from abc import ABC, abstractmethod from typing import Any, Dict, List class Loader(ABC): """Abstract base class for anime data loaders/providers.""" @abstractmethod def subscribe_download_progress(self, handler): """Subscribe a handler to the download_progress event. Args: handler: Callable to be called with progress dict. """ @abstractmethod def unsubscribe_download_progress(self, handler): """Unsubscribe a handler from the download_progress event. Args: handler: Callable previously subscribed. """ @abstractmethod def search(self, word: str) -> List[Dict[str, Any]]: """Search for anime series by name. Args: word: Search term to look for Returns: List of found series as dictionaries containing series information """ @abstractmethod def is_language( self, season: int, episode: int, key: str, language: str = "German Dub", ) -> bool: """Check if episode exists in specified language. Args: season: Season number (1-indexed) episode: Episode number (1-indexed) key: Unique series identifier/key language: Language to check (default: German Dub) Returns: True if episode exists in specified language, False otherwise """ @abstractmethod def download( self, base_directory: str, serie_folder: str, season: int, episode: int, key: str, language: str = "German Dub" ) -> bool: """Download episode to specified directory. Args: base_directory: Base directory for downloads serie_folder: Series folder name within base directory season: Season number (0 for movies, 1+ for series) episode: Episode number within season key: Unique series identifier/key language: Language version to download (default: German Dub) Returns: True if download successful, False otherwise """ @abstractmethod def get_site_key(self) -> str: """Get the site key/identifier for this provider. Returns: Site key string (e.g., 'aniworld.to', 'voe.com') """ @abstractmethod def get_title(self, key: str) -> str: """Get the human-readable title of a series. Args: key: Unique series identifier/key Returns: Series title string """ @abstractmethod def get_season_episode_count(self, slug: str) -> Dict[int, int]: """Get season and episode counts for a series. Args: slug: Series slug/key identifier Returns: Dictionary mapping season number (int) to episode count (int) """