chore: update watchlist features and fixes
This commit is contained in:
@@ -21,17 +21,29 @@ uvicorn main:app --reload --host 0.0.0.0 --port 3000
|
||||
# All tests
|
||||
pytest
|
||||
|
||||
# With coverage
|
||||
# With coverage (HTML report in htmlcov/)
|
||||
pytest --cov=app --cov-report=html
|
||||
|
||||
# Unit only (fast)
|
||||
pytest -m "unit"
|
||||
|
||||
# Integration tests only
|
||||
pytest -m "integration"
|
||||
|
||||
# Exclude slow tests
|
||||
pytest -m "not slow"
|
||||
|
||||
# Exclude network tests (mocked only)
|
||||
pytest -m "not network"
|
||||
|
||||
# Verbose with print debugging
|
||||
pytest -v -s
|
||||
|
||||
# Generate HTML report
|
||||
pytest --html=report.html --self-contained-html
|
||||
|
||||
# Timeout per test (seconds)
|
||||
pytest --timeout=30
|
||||
```
|
||||
|
||||
### Running Single Tests
|
||||
@@ -130,7 +142,8 @@ except httpx.TimeoutException:
|
||||
|
||||
### Testing
|
||||
- Use pytest with pytest-asyncio
|
||||
- Mark tests: `@pytest.mark.unit`, `@pytest.mark.integration`
|
||||
- Mark tests: `@pytest.mark.unit`, `@pytest.mark.integration`, `@pytest.mark.slow`, `@pytest.mark.network`
|
||||
- Tests in `test_api.py` are auto-marked as integration, others as unit
|
||||
- Use fixtures from `tests/conftest.py`
|
||||
|
||||
```python
|
||||
@@ -139,6 +152,16 @@ except httpx.TimeoutException:
|
||||
async def test_download_manager():
|
||||
manager = DownloadManager(max_parallel=3)
|
||||
assert manager.max_parallel == 3
|
||||
|
||||
# Mark slow tests
|
||||
@pytest.mark.slow
|
||||
async def test_full_download_flow():
|
||||
...
|
||||
|
||||
# Mark tests requiring network
|
||||
@pytest.mark.network
|
||||
async def test_external_api():
|
||||
...
|
||||
```
|
||||
|
||||
### Security
|
||||
@@ -149,34 +172,182 @@ async def test_download_manager():
|
||||
|
||||
## Architecture Patterns
|
||||
|
||||
**Three-Tier Downloader:**
|
||||
1. `app/downloaders/anime_sites/` - Anime catalogs
|
||||
2. `app/downloaders/series_sites/` - TV series catalogs
|
||||
3. `app/downloaders/video_players/` - File hosting
|
||||
### Three-Tier Downloader Architecture
|
||||
|
||||
Each has base class and factory. When adding providers:
|
||||
1. Inherit from appropriate base class
|
||||
2. Implement required methods
|
||||
3. Register in factory
|
||||
4. Add to providers config in `app/providers.py`
|
||||
The project uses a three-tier downloader system:
|
||||
|
||||
1. **Anime Catalogs** (`app/downloaders/anime_sites/`)
|
||||
- `animesama.py` - Anime-Sama (primary)
|
||||
- `animeultime.py` - Anime-Ultime
|
||||
- `nekosama.py` - Neko-Sama
|
||||
- `vostfree.py` - Vostfree
|
||||
- `frenchmanga.py` - French-Manga
|
||||
|
||||
2. **Series Catalogs** (`app/downloaders/series_sites/`)
|
||||
- `fs7.py` - French Stream
|
||||
|
||||
3. **Video Players** (`app/downloaders/video_players/`)
|
||||
- `sibnet.py`, `doodstream.py`, `vidmoly.py`, `uqload.py`
|
||||
- `uptobox.py`, `unfichier.py`, `rapidfile.py`
|
||||
- `sendvid.py`, `lpayer.py`, `vidzy.py`, `luluv.py`
|
||||
- `oneupload.py`, `smoothpre.py`
|
||||
|
||||
Each tier has a base class and factory pattern. When adding providers:
|
||||
1. Inherit from appropriate base class (`base.py`)
|
||||
2. Implement required methods (`search_anime`, `get_episodes`, `get_download_link`)
|
||||
3. Register in `app/providers.py`
|
||||
4. Add URL detection patterns
|
||||
|
||||
**URL Convention**: Pipe-separated format preserves metadata:
|
||||
```
|
||||
video_url|anime_page_url|episode_title
|
||||
```
|
||||
|
||||
### Core Modules
|
||||
|
||||
| Module | Purpose |
|
||||
|--------|---------|
|
||||
| `app/watchlist.py` | Episode tracking & auto-download |
|
||||
| `app/auto_download_scheduler.py` | APScheduler for periodic checks |
|
||||
| `app/episode_checker.py` | New episode detection |
|
||||
| `app/sonarr_handler.py` | Sonarr webhook integration |
|
||||
| `app/recommendation_engine.py` | Personalized anime recommendations |
|
||||
| `app/favorites.py` | User favorites management |
|
||||
| `app/auth.py` | JWT authentication |
|
||||
| `app/download_manager.py` | Download queue management |
|
||||
|
||||
## Key Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `main.py` | FastAPI app, endpoints |
|
||||
| `app/config.py` | Pydantic Settings |
|
||||
| `app/download_manager.py` | Download queue |
|
||||
| `app/utils.py` | sanitize_filename |
|
||||
| `app/auth.py` | JWT auth |
|
||||
| `app/models/__init__.py` | Pydantic models |
|
||||
| `main.py` | FastAPI app, all API endpoints |
|
||||
| `app/config.py` | Pydantic Settings configuration |
|
||||
| `app/download_manager.py` | Download queue & task management |
|
||||
| `app/utils.py` | `sanitize_filename`, `is_safe_filename` |
|
||||
| `app/auth.py` | JWT auth, user management |
|
||||
| `app/providers.py` | Provider definitions & URL detection |
|
||||
| `app/models/__init__.py` | Core Pydantic models |
|
||||
| `app/models/watchlist.py` | Watchlist models |
|
||||
| `app/models/sonarr.py` | Sonarr integration models |
|
||||
| `app/models/auth.py` | Authentication models |
|
||||
|
||||
## Frontend Architecture
|
||||
|
||||
### JavaScript Modules (`static/js/`)
|
||||
| Module | Purpose |
|
||||
|--------|---------|
|
||||
| `main.js` | Application entry point |
|
||||
| `api.js` | API client functions |
|
||||
| `auth.js` | Authentication handling |
|
||||
| `tabs.js` | Tab navigation |
|
||||
| `anime.js` | Anime search & display |
|
||||
| `anime-details.js` | Anime detail views |
|
||||
| `watchlist.js` | Watchlist API calls |
|
||||
| `watchlist-ui.js` | Watchlist UI rendering |
|
||||
| `downloads.js` | Download management UI |
|
||||
| `recommendations.js` | Recommendations display |
|
||||
| `series-search.js` | TV series search |
|
||||
| `utils.js` | Utility functions |
|
||||
|
||||
### Templates (`templates/`)
|
||||
| Template | Purpose |
|
||||
|----------|---------|
|
||||
| `base.html` | Base layout with CSS/JS imports |
|
||||
| `index.html` | Main SPA interface |
|
||||
| `login.html` | Login/register page |
|
||||
| `watchlist.html` | Watchlist management page |
|
||||
| `player.html` | Video player page |
|
||||
| `components/` | Reusable HTML components |
|
||||
|
||||
## Configuration
|
||||
|
||||
- Use `.env` from `.env.example`
|
||||
- JWT_SECRET_KEY must change in production
|
||||
- `JWT_SECRET_KEY` must change in production
|
||||
- Config files stored in `config/`:
|
||||
- `users.json` - User database
|
||||
- `watchlist.json` - Watchlist data
|
||||
- `watchlist_settings.json` - Auto-download settings
|
||||
- `sonarr.json` - Sonarr integration config
|
||||
- `sonarr_mappings.json` - Series to anime mappings
|
||||
|
||||
## API Endpoints Overview
|
||||
|
||||
### Authentication
|
||||
- `POST /api/auth/register` - Register new user
|
||||
- `POST /api/auth/login` - Login, get JWT token
|
||||
- `GET /api/auth/me` - Get current user info
|
||||
- `POST /api/auth/logout` - Logout (client-side)
|
||||
|
||||
### Downloads
|
||||
- `POST /api/download` - Create download task
|
||||
- `GET /api/downloads` - List all downloads
|
||||
- `GET /api/download/{task_id}` - Get download status
|
||||
- `POST /api/download/{task_id}/pause` - Pause download
|
||||
- `POST /api/download/{task_id}/resume` - Resume download
|
||||
- `DELETE /api/download/{task_id}` - Cancel/delete download
|
||||
- `GET /api/download/{task_id}/file` - Download completed file
|
||||
|
||||
### Anime Search & Metadata
|
||||
- `GET /api/anime/search` - Search across all anime providers
|
||||
- `GET /api/series/search` - Search TV series providers
|
||||
- `GET /api/anime/metadata` - Get detailed anime metadata
|
||||
- `GET /api/anime/episodes` - Get episode list
|
||||
- `GET /api/anime/seasons` - Get available seasons
|
||||
- `POST /api/anime/download-season` - Download all episodes
|
||||
|
||||
### Watchlist
|
||||
- `GET /api/watchlist` - List watchlist items
|
||||
- `POST /api/watchlist` - Add to watchlist
|
||||
- `PUT /api/watchlist/{item_id}` - Update watchlist item
|
||||
- `DELETE /api/watchlist/{item_id}` - Remove from watchlist
|
||||
- `GET /api/watchlist/settings` - Get auto-download settings
|
||||
- `PUT /api/watchlist/settings` - Update settings
|
||||
- `POST /api/watchlist/check` - Trigger manual episode check
|
||||
|
||||
### Favorites
|
||||
- `GET /api/favorites` - List favorites
|
||||
- `POST /api/favorites` - Add to favorites
|
||||
- `DELETE /api/favorites/{anime_id}` - Remove from favorites
|
||||
- `POST /api/favorites/toggle` - Toggle favorite status
|
||||
|
||||
### Recommendations
|
||||
- `GET /api/recommendations` - Get personalized recommendations
|
||||
- `GET /api/releases/latest` - Get latest releases
|
||||
- `GET /api/releases/seasonal` - Get seasonal anime
|
||||
|
||||
### Sonarr Integration
|
||||
- `POST /api/sonarr/webhook` - Receive Sonarr webhooks
|
||||
- `GET /api/sonarr/mappings` - List Sonarr mappings
|
||||
- `POST /api/sonarr/mappings` - Create mapping
|
||||
- `DELETE /api/sonarr/mappings/{series_id}` - Delete mapping
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Core
|
||||
- `fastapi` - Web framework
|
||||
- `uvicorn` - ASGI server
|
||||
- `httpx` - Async HTTP client
|
||||
- `aiohttp` - Alternative HTTP client
|
||||
- `pydantic` / `pydantic-settings` - Data validation & settings
|
||||
|
||||
### Scraping & Parsing
|
||||
- `beautifulsoup4` - HTML parsing
|
||||
- `lxml` - XML/HTML parser
|
||||
- `jieba` - Chinese text segmentation
|
||||
|
||||
### Authentication
|
||||
- `python-jose` - JWT handling
|
||||
- `passlib[bcrypt]` - Password hashing
|
||||
|
||||
### Scheduler
|
||||
- `apscheduler` - Job scheduling for auto-downloads
|
||||
|
||||
### Cryptography
|
||||
- `pycryptodome` - AES decryption for video players
|
||||
|
||||
### Testing
|
||||
- `pytest` + `pytest-asyncio` - Async test support
|
||||
- `pytest-cov` - Coverage reporting
|
||||
- `pytest-mock` - Mocking utilities
|
||||
- `pytest-timeout` - Test timeout protection
|
||||
- `pytest-html` - HTML test reports
|
||||
Reference in New Issue
Block a user