d4d8d8a3b6
- Migrated monolithic main.py to feature-scoped routers in app/routers/ - Added GEMINI.md for project context and AI instructional guidelines - Updated README.md with a comprehensive modernization plan (SQL migration, robust scraping DSL, frontend modernization) - Improved authentication with cookie support and modular JS - Updated test suite and documentation
38 lines
1.3 KiB
Markdown
38 lines
1.3 KiB
Markdown
# Video Players (app/downloaders/video_players)
|
|
|
|
## OVERVIEW
|
|
File hosting extractors that extract direct download links from video player pages (Doodstream, Sibnet, VidMoly, etc.).
|
|
|
|
## WHERE TO LOOK
|
|
|
|
| Need | File |
|
|
|------|------|
|
|
| Base class | `base.py` - `BaseVideoPlayer` abstract class |
|
|
| Add new player | Create new `.py` file, inherit `BaseVideoPlayer`, add to `__init__.py` |
|
|
| URL detection logic | Each player's `can_handle()` method |
|
|
| Extract download link | Each player's `get_download_link()` method |
|
|
|
|
## 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]: ...
|
|
```
|
|
|
|
**File operation**: Always use `sanitize_filename()` on extracted filenames.
|
|
|
|
**HTTP client**: Use `self.client` (AsyncClient from base class). Always close via `await self.close()` when done.
|
|
|
|
**Return format**: `(download_url, filename)` tuple.
|
|
|
|
## ANTI-PATTERNS
|
|
|
|
- Do NOT hardcode User-Agent in each player (use base class headers)
|
|
- Do NOT forget to call `await self.close()` after extraction
|
|
- Do NOT return None for missing URLs, raise an exception
|
|
- Do NOT use sync `requests`, use async `httpx`
|
|
- Do NOT skip the `target_filename` parameter, even if unused
|