Python API for accessing and downloading content from JMComic with Cloudflare bypass and plugin system.
—
Comprehensive download management system with support for callbacks, progress tracking, exception handling, and specialized download behaviors. Provides fine-grained control over the download process with various downloader implementations.
from typing import Callable, List, Any, Optional, Dict, UnionThe primary downloader class that handles album, photo, and image downloads with comprehensive error handling and callback support.
class JmDownloader:
"""
Main downloader class with comprehensive download functionality.
Attributes:
- option: JmOption - Configuration options for the downloader
- client: JmcomicClient - Client instance for API/web operations
- exception_list: List[Exception] - List of exceptions encountered during download
- callback: DownloadCallback - Callback handler for download events
Methods:
- download_album(album_id): Download complete album with all episodes
- download_photo(photo_id): Download single photo with all images
- download_image(image): Download individual image
- has_exception(): Check if any exceptions occurred
- raise_if_has_exception(): Raise PartialDownloadFailedException if errors exist
- clear_exception(): Clear the exception list
"""
def __init__(self, option: 'JmOption'):
"""
Initialize downloader with configuration options.
Parameters:
- option: JmOption - Configuration for download behavior
"""
def download_album(self, album_id: Union[str, int]) -> 'JmAlbumDetail':
"""
Download a complete album including all episodes and images.
Parameters:
- album_id: str or int - Album ID to download
Returns:
JmAlbumDetail - Downloaded album with all metadata and episodes
"""
def download_photo(self, photo_id: Union[str, int]) -> 'JmPhotoDetail':
"""
Download a single photo/chapter with all images.
Parameters:
- photo_id: str or int - Photo ID to download
Returns:
JmPhotoDetail - Downloaded photo with all metadata and images
"""
def download_image(self, image: 'JmImageDetail') -> bool:
"""
Download an individual image.
Parameters:
- image: JmImageDetail - Image entity to download
Returns:
bool - True if download successful, False otherwise
"""
def has_exception(self) -> bool:
"""
Check if any exceptions occurred during download.
Returns:
bool - True if exceptions exist, False otherwise
"""
def raise_if_has_exception(self):
"""
Raise PartialDownloadFailedException if any exceptions occurred.
Raises:
PartialDownloadFailedException - If exception_list is not empty
"""
def clear_exception(self):
"""Clear all recorded exceptions."""Usage examples:
# Create and use downloader
option = create_option_by_file("config.yml")
downloader = JmDownloader(option)
# Download album
album = downloader.download_album("123456")
# Check for errors
if downloader.has_exception():
print(f"Errors occurred: {len(downloader.exception_list)}")
for exc in downloader.exception_list:
print(f" {type(exc).__name__}: {exc}")
# Raise errors if any
try:
downloader.raise_if_has_exception()
except PartialDownloadFailedException as e:
print(f"Download failed: {e}")Specialized downloader implementations for testing and development purposes.
class DoNotDownloadImage(JmDownloader):
"""
Test downloader that skips actual image downloads.
Useful for testing metadata extraction and API functionality
without downloading large image files.
"""
class JustDownloadSpecificCountImage(JmDownloader):
"""
Test downloader that downloads only a specific number of images.
Useful for testing download functionality with limited data transfer.
Attributes:
- count: int - Maximum number of images to download
"""
def __init__(self, option: 'JmOption', count: int = 1):
"""
Initialize with download count limit.
Parameters:
- option: JmOption - Configuration options
- count: int - Maximum number of images to download
"""Usage examples:
# Test without downloading images
option = create_option_by_file("config.yml")
test_downloader = DoNotDownloadImage(option)
album = test_downloader.download_album("123456") # Only metadata, no images
# Test with limited image downloads
limited_downloader = JustDownloadSpecificCountImage(option, count=5)
album = limited_downloader.download_album("123456") # Only first 5 imagesCallback interface for monitoring and responding to download events.
class DownloadCallback:
"""
Callback interface for download progress and event monitoring.
Methods:
- on_album_start(album): Called when album download starts
- on_album_complete(album): Called when album download completes
- on_photo_start(photo): Called when photo download starts
- on_photo_complete(photo): Called when photo download completes
- on_image_start(image): Called when image download starts
- on_image_complete(image): Called when image download completes
- on_error(exception, context): Called when errors occur
"""
def on_album_start(self, album: 'JmAlbumDetail'):
"""
Called when album download starts.
Parameters:
- album: JmAlbumDetail - Album being downloaded
"""
def on_album_complete(self, album: 'JmAlbumDetail'):
"""
Called when album download completes.
Parameters:
- album: JmAlbumDetail - Completed album
"""
def on_photo_start(self, photo: 'JmPhotoDetail'):
"""
Called when photo download starts.
Parameters:
- photo: JmPhotoDetail - Photo being downloaded
"""
def on_photo_complete(self, photo: 'JmPhotoDetail'):
"""
Called when photo download completes.
Parameters:
- photo: JmPhotoDetail - Completed photo
"""
def on_image_start(self, image: 'JmImageDetail'):
"""
Called when image download starts.
Parameters:
- image: JmImageDetail - Image being downloaded
"""
def on_image_complete(self, image: 'JmImageDetail'):
"""
Called when image download completes.
Parameters:
- image: JmImageDetail - Completed image
"""
def on_error(self, exception: Exception, context: Dict[str, Any]):
"""
Called when errors occur during download.
Parameters:
- exception: Exception - The error that occurred
- context: dict - Additional context about the error
"""Usage examples:
# Custom callback implementation
class MyDownloadCallback(DownloadCallback):
def on_album_start(self, album):
print(f"Starting download: {album.title}")
def on_photo_complete(self, photo):
print(f"Completed chapter: {photo.title}")
def on_error(self, exception, context):
print(f"Error: {exception} in {context}")
# Use callback with downloader
callback = MyDownloadCallback()
option = create_option_by_file("config.yml")
downloader = JmDownloader(option)
downloader.callback = callback
album = downloader.download_album("123456")Decorator for exception handling in download operations.
def catch_exception(func: Callable) -> Callable:
"""
Decorator for catching and logging exceptions in download operations.
Parameters:
- func: callable - Function to wrap with exception handling
Returns:
callable - Wrapped function with exception handling
"""Usage examples:
# Apply exception handling to custom functions
@catch_exception
def custom_download_operation():
# Custom download logic here
pass
# Exception is caught and logged automatically
custom_download_operation()The typical download flow follows this pattern:
JmDownloader with JmOption configurationdownload_album() which:
exception_listDownloaders can be used as context managers for automatic resource cleanup:
with new_downloader(option) as downloader:
album = downloader.download_album("123456")
# Automatic cleanup on exitInstall with Tessl CLI
npx tessl i tessl/pypi-jmcomic