# Anime Sites (app/downloaders/anime_sites/) ## OVERVIEW Handlers for French anime streaming catalogs that provide metadata and episode listings, delegating actual video extraction to video player handlers. ## WHERE TO LOOK | File | Purpose | |------|---------| | `base.py` | Abstract `BaseAnimeSite` class defining the interface | | `animesama.py` | Primary provider — dynamic domain switching, multiple video player extraction | | `nekosama.py` | Neko-Sama / Gupy integration (metadata-only, no direct downloads) | | `animeultime.py` | Anime-Ultime catalog handler | | `vostfree.py` | Vostfree catalog handler | | `frenchmanga.py` | French-Manga catalog handler | ## CONVENTIONS **Interface contract** — each site implements from `BaseAnimeSite`: - `can_handle(url)` — URL pattern matching - `search_anime(query, lang)` → `[{title, url, cover_image}]` - `get_episodes(anime_url, lang)` → `[{episode_number, url, title, host}]` - `get_anime_metadata(anime_url)` → `{synopsis, genres, rating, release_year, studio, poster_image, total_episodes, status}` - `get_download_link(url)` → `(video_player_url, filename)` **Key patterns**: - Pipe-separated URLs: `video_url|anime_page_url|episode_title` - Language param: `lang="vostfr"` or `"vf"` - Video player delegation: returns player URLs (vidmoly, sendvid, etc.), NOT direct downloads - Filename format: `{anime_name} - S{season} - {episode}.mp4` - Browser UA + referer headers required **Domain detection**: `AnimeSamaDownloader` fetches current domain from `anime-sama.pw` dynamically. Uses fallback chain for video extraction. **Error handling**: Raise `Exception` with descriptive message. Log at `debug` for expected failures, `error` for unexpected. Validate URLs with `_test_video_url()` before returning. ## ANTI-PATTERNS - Do NOT return direct download URLs from anime sites — return player URLs - Do NOT skip URL validation — use `_test_video_url()` - 5 empty `except:` blocks in `animesama.py` — known tech debt, silently swallow failures