# Video Players (app/downloaders/video_players/)

## OVERVIEW
File hosting extractors that extract direct download links from video player pages (Doodstream, Sibnet, VidMoly, Uptobox, etc.).

## WHERE TO LOOK

| File | Purpose |
|------|---------|
| `base.py` | `BaseVideoPlayer` abstract class |
| `unfichier.py` | 1fichier.com |
| `doodstream.py` | Doodstream |
| `vidmoly.py` | VidMoly (requires Playwright for extraction) |
| `uptobox.py` | Uptobox |
| `sendvid.py` | SendVid |
| `sibnet.py` | Sibnet |
| `rapidfile.py` | Rapidfile |
| `uqload.py` | Uqload |
| `lpayer.py` | Lplayer |
| `vidzy.py` | Vidzy |
| `luluv.py` | LuLuvid |
| `smoothpre.py` | Smoothpre |
| `oneupload.py` | OneUpload |

## CONVENTIONS

**Class naming**: `{Provider}Downloader` (e.g., `DoodStreamDownloader`)

**Required methods**:
```python
def can_handle(self, url: str) -> bool: ...
async def get_download_link(self, url: str, target_filename: str = None) -> tuple[str, str]: ...
```

**Return format**: `(download_url, filename)` tuple.

**HTTP client**: Use `self.client` (AsyncClient from base class). Always close via `await self.close()`.

**File operation**: Always `sanitize_filename()` on extracted filenames.

## ANTI-PATTERNS

- Do NOT hardcode User-Agent per player — use base class headers
- Do NOT forget `await self.close()` — resource leak
- Do NOT return None for missing URLs — raise an exception
- Do NOT use sync `requests` — use async `httpx`
- Do NOT skip `target_filename` parameter — required for anime/series site compatibility
- 8 empty `except:` blocks across players — known tech debt
