Python API for accessing and downloading content from JMComic with Cloudflare bypass and plugin system.
—
Flexible configuration system supporting YAML/JSON files, environment variables, and programmatic configuration. Enables comprehensive customization of download behavior, client settings, plugin options, and file organization rules.
from typing import Dict, Any, List, Optional, Union, CallableCentral configuration class that manages all download options, client settings, and plugin configurations.
class JmOption:
"""
Central configuration class for download options and client settings.
Attributes:
- download: Dict[str, Any] - Download-related settings
- client: Dict[str, Any] - Client configuration options
- plugins: Dict[str, Any] - Plugin configurations
- dir_rule: DirRule - Directory naming and organization rules
- cache: CacheRegistry - Client caching configuration
Class Methods:
- default(): Create default configuration
- from_file(filepath): Load configuration from YAML/JSON file
- construct(data): Create from dictionary data
- merge(other): Merge with another JmOption instance
Instance Methods:
- to_dict(): Convert to dictionary
- to_file(filepath): Save configuration to file
- validate(): Validate configuration settings
"""
@classmethod
def default(cls) -> 'JmOption':
"""
Create default configuration with standard settings.
Returns:
JmOption - Default configuration instance
"""
@classmethod
def from_file(cls, filepath: str) -> 'JmOption':
"""
Load configuration from YAML or JSON file.
Parameters:
- filepath: str - Path to configuration file
Returns:
JmOption - Configuration loaded from file
"""
@classmethod
def construct(cls, data: Dict[str, Any]) -> 'JmOption':
"""
Create configuration from dictionary data.
Parameters:
- data: dict - Configuration data
Returns:
JmOption - Configuration instance
"""
def merge(self, other: 'JmOption') -> 'JmOption':
"""
Merge with another configuration instance.
Parameters:
- other: JmOption - Configuration to merge
Returns:
JmOption - New merged configuration
"""
def to_dict(self) -> Dict[str, Any]:
"""
Convert configuration to dictionary.
Returns:
dict - Configuration as dictionary
"""
def to_file(self, filepath: str):
"""
Save configuration to YAML file.
Parameters:
- filepath: str - Target file path
"""
def validate(self) -> bool:
"""
Validate configuration settings.
Returns:
bool - True if configuration is valid
Raises:
ValueError - If configuration is invalid
"""Usage examples:
# Create default configuration
option = JmOption.default()
# Load from file
option = JmOption.from_file("config.yml")
# Create from dictionary
config_data = {
"download": {
"base_dir": "/downloads",
"max_threads": 4
},
"client": {
"retry_count": 3,
"timeout": 30
}
}
option = JmOption.construct(config_data)
# Merge configurations
default_option = JmOption.default()
custom_option = JmOption.from_file("custom.yml")
merged_option = default_option.merge(custom_option)
# Save configuration
option.to_file("saved_config.yml")Configuration for file and directory naming and organization patterns.
class DirRule:
"""
File and directory naming and organization rules.
Attributes:
- base_dir: str - Base download directory
- album_dir_rule: str - Album directory naming pattern
- photo_dir_rule: str - Photo directory naming pattern
- image_filename_rule: str - Image filename pattern
- create_album_dir: bool - Whether to create album directories
- create_photo_dir: bool - Whether to create photo directories
Methods:
- format_album_dir(album): Generate album directory name
- format_photo_dir(photo): Generate photo directory name
- format_image_filename(image): Generate image filename
- validate_rules(): Validate naming rules
"""
def __init__(self,
base_dir: str = "./downloads",
album_dir_rule: str = "{album_id} - {title}",
photo_dir_rule: str = "{photo_id} - {title}",
image_filename_rule: str = "{index:03d}.{ext}"):
"""
Initialize directory rules.
Parameters:
- base_dir: str - Base download directory
- album_dir_rule: str - Album directory naming pattern
- photo_dir_rule: str - Photo directory naming pattern
- image_filename_rule: str - Image filename pattern
"""
def format_album_dir(self, album: 'JmAlbumDetail') -> str:
"""
Generate album directory name using the configured rule.
Parameters:
- album: JmAlbumDetail - Album entity
Returns:
str - Formatted directory name
"""
def format_photo_dir(self, photo: 'JmPhotoDetail') -> str:
"""
Generate photo directory name using the configured rule.
Parameters:
- photo: JmPhotoDetail - Photo entity
Returns:
str - Formatted directory name
"""
def format_image_filename(self, image: 'JmImageDetail') -> str:
"""
Generate image filename using the configured rule.
Parameters:
- image: JmImageDetail - Image entity
Returns:
str - Formatted filename
"""Usage examples:
# Create custom directory rules
dir_rule = DirRule(
base_dir="/home/user/comics",
album_dir_rule="{title} [{album_id}]",
photo_dir_rule="Chapter {index:02d} - {title}",
image_filename_rule="page_{index:03d}.{ext}"
)
# Use in configuration
option = JmOption.default()
option.dir_rule = dir_rule
# Generate paths
album = JmAlbumDetail(id="123456", title="Sample Album")
album_dir = dir_rule.format_album_dir(album) # "Sample Album [123456]"Caching mechanism for client operations to improve performance and reduce redundant requests.
class CacheRegistry:
"""
Client caching mechanism for improved performance.
Attributes:
- enabled: bool - Whether caching is enabled
- cache_dir: str - Directory for cache files
- max_cache_size: int - Maximum cache size in MB
- ttl: int - Cache time-to-live in seconds
Methods:
- get(key): Retrieve cached value
- set(key, value): Store value in cache
- clear(): Clear all cached data
- cleanup(): Remove expired cache entries
"""
def __init__(self,
enabled: bool = True,
cache_dir: str = "./cache",
max_cache_size: int = 100,
ttl: int = 3600):
"""
Initialize cache registry.
Parameters:
- enabled: bool - Enable/disable caching
- cache_dir: str - Cache directory path
- max_cache_size: int - Max cache size in MB
- ttl: int - Cache TTL in seconds
"""
def get(self, key: str) -> Optional[Any]:
"""
Retrieve cached value by key.
Parameters:
- key: str - Cache key
Returns:
Any or None - Cached value if exists and valid
"""
def set(self, key: str, value: Any):
"""
Store value in cache.
Parameters:
- key: str - Cache key
- value: Any - Value to cache
"""
def clear(self):
"""Clear all cached data."""
def cleanup(self):
"""Remove expired cache entries."""Utility functions for creating configuration instances from various sources.
def create_option_by_file(filepath: str) -> JmOption:
"""
Create configuration from YAML or JSON file.
Parameters:
- filepath: str - Path to configuration file
Returns:
JmOption - Configuration instance
"""
def create_option_by_env(env_name: str = 'JM_OPTION_PATH') -> JmOption:
"""
Create configuration from environment variable path.
Parameters:
- env_name: str - Environment variable name containing file path
Returns:
JmOption - Configuration instance
Raises:
ValueError - If environment variable is not set
"""
def create_option_by_str(text: str, mode: Optional[str] = None) -> JmOption:
"""
Create configuration from string content.
Parameters:
- text: str - YAML or JSON configuration text
- mode: str, optional - Parse mode ('yml' or 'json')
Returns:
JmOption - Configuration instance
"""
# Alias for convenience
create_option = create_option_by_fileUsage examples:
# Load from file
option = create_option_by_file("config.yml")
# Load from environment variable
import os
os.environ['JM_OPTION_PATH'] = "/path/to/config.yml"
option = create_option_by_env()
# Load from string
yaml_config = """
download:
base_dir: /downloads
max_threads: 4
client:
retry_count: 3
"""
option = create_option_by_str(yaml_config)
# Using alias
option = create_option("config.yml")A typical configuration file structure:
# Download settings
download:
base_dir: "/home/user/downloads"
max_threads: 4
create_album_dir: true
create_photo_dir: true
# Directory naming rules
dir_rule:
album_dir_rule: "{title} [{album_id}]"
photo_dir_rule: "Chapter {index:02d}"
image_filename_rule: "{index:03d}.{ext}"
# Client settings
client:
retry_count: 3
timeout: 30
user_agent: "Custom User Agent"
headers:
"Accept": "image/*"
# Caching
cache:
enabled: true
cache_dir: "./cache"
max_cache_size: 100
ttl: 3600
# Plugin configurations
plugins:
JmLoginPlugin:
username: "user@example.com"
password: "password"
ZipPlugin:
enabled: true
password: "archive_password"For complex scenarios, configurations can be programmatically modified:
# Start with default configuration
option = JmOption.default()
# Modify specific settings
option.download['max_threads'] = 8
option.dir_rule.base_dir = "/custom/path"
option.cache.enabled = False
# Add plugin configuration
option.plugins['ZipPlugin'] = {
'enabled': True,
'password': 'my_password'
}
# Validate and save
option.validate()
option.to_file("custom_config.yml")Install with Tessl CLI
npx tessl i tessl/pypi-jmcomic