# Downloaders (app/downloaders/)

## OVERVIEW
3-tier scraper architecture: anime catalogs → series catalogs → video players. Factory pattern routes URLs through each tier.

## STRUCTURE
```
downloaders/
├── __init__.py          # get_downloader(url) — 3-tier factory + GenericDownloader
├── base.py              # Legacy BaseDownloader (kept for compat)
├── anime_sites/         # Anime streaming catalogs (see anime_sites/AGENTS.md)
│   ├── __init__.py      # get_anime_site(url) factory
│   ├── base.py          # BaseAnimeSite abstract class
│   └── *.py             # 5 anime providers
├── series_sites/        # TV series catalogs (see series_sites/AGENTS.md)
│   ├── __init__.py      # get_series_site(url) factory
│   ├── base.py          # BaseSeriesSite abstract class
│   └── fs7.py           # 1 series provider
└── video_players/       # File hosting extractors (see video_players/AGENTS.md)
    ├── __init__.py      # get_video_player(url) factory
    ├── base.py          # BaseVideoPlayer abstract class
    └── *.py             # 13 video player handlers
```

## WHERE TO LOOK

| Need | File | Notes |
|------|------|-------|
| Route URL to downloader | `__init__.py:32` | `get_downloader(url)` tries anime→series→video→generic |
| Add anime provider | `anime_sites/` | Inherit BaseAnimeSite, register in anime_sites/__init__.py |
| Add series provider | `series_sites/` | Inherit BaseSeriesSite, register in series_sites/__init__.py |
| Add video player | `video_players/` | Inherit BaseVideoPlayer, register in video_players/__init__.py |
| Provider domains/icons | `app/providers.py` | Separate from downloader code |

## CONVENTIONS

**URL pipe format**: `video_url|anime_page_url|episode_title` — metadata preserved through tiers. Anime/series sites return player URLs (not direct downloads). Video players extract final download links.

**Factory chain**: `get_downloader()` → `get_anime_site()` → `get_series_site()` → `get_video_player()` → `GenericDownloader`.

**New provider checklist**: 1) Create .py inheriting base class, 2) Implement required methods, 3) Add to `__init__.py` factory list, 4) Add to `app/providers.py`.

## ANTI-PATTERNS

- Do NOT return None from `get_download_link()` — raise Exception
- Do NOT use sync `requests` — always `httpx.AsyncClient`
- Do NOT forget `await self.close()` — causes resource leaks
- Do NOT skip `sanitize_filename()` on extracted filenames
- Do NOT hardcode User-Agent per player — use base class headers
