feat: Complete watchlist & auto-download system with UI
Implement comprehensive watchlist system with automatic episode detection
and downloading. Features include per-user watchlists, scheduler-based
periodic checks, and a modern web UI.
**Backend Components:**
- WatchlistManager: JSON-based storage with multi-tenant support
- EpisodeChecker: Detects and downloads new episodes automatically
- AutoDownloadScheduler: APScheduler-based periodic task execution
- Complete REST API for CRUD operations and scheduler control
**Frontend Components:**
- Modern watchlist page with dark theme and animations
- Real-time status updates and progress tracking
- Scheduler controls with next-run display
- Add anime directly from search results
**Models & Configuration:**
- WatchlistItem with status, quality, and auto-download settings
- WatchlistSettings for global configuration
- Per-user statistics and provider tracking
**API Endpoints:**
- GET/POST /api/watchlist - List and add items
- PUT/DELETE /api/watchlist/{id} - Update and delete
- POST /api/watchlist/{id}/check - Manual check trigger
- POST /api/watchlist/check-all - Check all due items
- GET/PUT /api/watchlist/settings - Global settings
- GET /api/watchlist/stats - Statistics
- GET/POST /api/watchlist/scheduler/* - Scheduler control
**Configuration Files:**
- config/watchlist.json - User watchlist data
- config/watchlist_settings.json - Global settings
Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -281,7 +281,54 @@ The downloaders are organized into three categories with separate base classes:
|
||||
- Provides enriched metadata (synopsis, genres, ratings, poster images)
|
||||
- Used as fallback when provider metadata is incomplete
|
||||
|
||||
### 10. Pydantic Models (`app/models/`)
|
||||
### 10. Watchlist & Auto-Download System
|
||||
|
||||
**WatchlistManager** (`app/watchlist.py`):
|
||||
- JSON-based storage in `config/watchlist.json`
|
||||
- Per-user watchlist management (multi-tenant)
|
||||
- CRUD operations for tracked anime
|
||||
- Statistics and queries
|
||||
- Settings management in `config/watchlist_settings.json`
|
||||
|
||||
**EpisodeChecker** (`app/episode_checker.py`):
|
||||
- Checks for new episodes for anime in watchlist
|
||||
- Downloads episodes automatically when detected
|
||||
- Integrates with existing downloaders
|
||||
- Handles errors and retries
|
||||
- Lazy initialization to avoid circular imports
|
||||
|
||||
**AutoDownloadScheduler** (`app/auto_download_scheduler.py`):
|
||||
- APScheduler-based periodic checking
|
||||
- Configurable intervals (1-168 hours)
|
||||
- Start/stop control via API
|
||||
- Next run tracking
|
||||
- Background task execution
|
||||
|
||||
**Watchlist Models** (`app/models/watchlist.py`):
|
||||
- `WatchlistItem` - Tracked anime with settings
|
||||
- `WatchlistStatus` - ACTIVE, PAUSED, COMPLETED, ARCHIVED
|
||||
- `QualityPreference` - AUTO, 1080p, 720p, 480p
|
||||
- `WatchlistSettings` - Global configuration
|
||||
- `AutoDownloadResult` - Operation results
|
||||
|
||||
**Watchlist Endpoints:**
|
||||
- `GET /api/watchlist` - List user's watchlist (with status filter)
|
||||
- `POST /api/watchlist` - Add anime to watchlist
|
||||
- `GET /api/watchlist/{item_id}` - Get specific item
|
||||
- `PUT /api/watchlist/{item_id}` - Update watchlist item
|
||||
- `DELETE /api/watchlist/{item_id}` - Remove from watchlist
|
||||
- `POST /api/watchlist/{item_id}/check` - Check specific anime
|
||||
- `POST /api/watchlist/check-all` - Check all due items
|
||||
- `POST /api/watchlist/{item_id}/pause` - Pause tracking
|
||||
- `POST /api/watchlist/{item_id}/resume` - Resume tracking
|
||||
- `GET /api/watchlist/settings` - Get global settings
|
||||
- `PUT /api/watchlist/settings` - Update settings
|
||||
- `GET /api/watchlist/stats` - Get watchlist statistics
|
||||
- `GET /api/watchlist/scheduler/status` - Get scheduler status
|
||||
- `POST /api/watchlist/scheduler/start` - Start scheduler
|
||||
- `POST /api/watchlist/scheduler/stop` - Stop scheduler
|
||||
|
||||
### 11. Pydantic Models (`app/models/`)
|
||||
- **`__init__.py`** - Core models:
|
||||
- `DownloadStatus` - Enum for task states (PENDING, DOWNLOADING, PAUSED, COMPLETED, FAILED, CANCELLED)
|
||||
- `HostType` - Enum for file host types (RAPIDFILE, UNFICHIER, DOODSTREAM, OTHER)
|
||||
@@ -294,6 +341,17 @@ The downloaders are organized into three categories with separate base classes:
|
||||
- `SonarrEventType` - Enum for event types (Grab, Download, Rename, Delete, Test)
|
||||
- `SonarrMapping` - Mapping between Sonarr series and anime providers
|
||||
- `SonarrConfig` - Webhook configuration (enabled, secret, auto-download, etc.)
|
||||
- **`auth.py`** - Authentication models:
|
||||
- `UserCreate` - User registration request
|
||||
- `UserLogin` - Login request
|
||||
- `User` - User profile
|
||||
- `Token` - JWT token response
|
||||
- **`watchlist.py`** - Watchlist models:
|
||||
- `WatchlistItem` - Tracked anime item
|
||||
- `WatchlistItemCreate` - Create request
|
||||
- `WatchlistItemUpdate` - Update request
|
||||
- `WatchlistStatus` - Status enum
|
||||
- `WatchlistSettings` - Global settings
|
||||
|
||||
## Test Structure
|
||||
|
||||
@@ -521,6 +579,8 @@ JWT_SECRET_KEY=change-me-in-production # JWT signing key for auth
|
||||
- `config/users.json` - User authentication database (created automatically)
|
||||
- `config/sonarr.json` - Sonarr webhook configuration (created automatically)
|
||||
- `config/sonarr_mappings.json` - Sonarr to anime provider mappings (created automatically)
|
||||
- `config/watchlist.json` - User watchlist items (created automatically)
|
||||
- `config/watchlist_settings.json` - Watchlist global settings (created automatically)
|
||||
- `config/.gitkeep` - Ensures config directory is tracked in git
|
||||
- Example files: `config/sonarr.example.json`, `config/sonarr_mappings.example.json`
|
||||
|
||||
@@ -530,6 +590,27 @@ JWT_SECRET_KEY=change-me-in-production # JWT signing key for auth
|
||||
- `docs/SONARR_INTEGRATION.md` - Complete Sonarr setup guide
|
||||
- `docs/SONARR_IMPLEMENTATION.md` - Technical implementation summary
|
||||
- `docs/IMPROVEMENTS_2024-01-24.md` - Recent security and quality improvements
|
||||
- `docs/WATCHLIST_AUTO_DOWNLOAD.md` - Watchlist system documentation
|
||||
|
||||
## Security
|
||||
|
||||
**Filename Sanitization (`app/utils.py`):**
|
||||
- `sanitize_filename()` - Removes dangerous characters (`\ / : * ? " < > |`)
|
||||
- `is_safe_filename()` - Validates against path traversal patterns
|
||||
- Used throughout the codebase for all file operations
|
||||
- Prevents `../../../etc/passwd` style attacks
|
||||
- Limits filename length to 255 characters
|
||||
|
||||
**CORS Configuration:**
|
||||
- Restricted origins (not `*`) in production
|
||||
- Specific allowed methods (GET, POST, PUT, DELETE, PATCH, OPTIONS)
|
||||
- Configured in `main.py` via environment variables
|
||||
|
||||
**Authentication:**
|
||||
- JWT token-based authentication with 7-day expiration
|
||||
- bcrypt password hashing with passlib
|
||||
- Passwords truncated to 72 bytes (bcrypt limitation)
|
||||
- Credentials stored in `config/users.json`
|
||||
|
||||
## Key Implementation Details
|
||||
|
||||
@@ -570,9 +651,14 @@ JWT_SECRET_KEY=change-me-in-production # JWT signing key for auth
|
||||
- beautifulsoup4, lxml - HTML parsing
|
||||
- aiofiles - Async file operations
|
||||
- jieba - Chinese text segmentation for fuzzy search
|
||||
- passlib[bcrypt] - Password hashing
|
||||
- python-jose[cryptography] - JWT token handling
|
||||
- apscheduler - Task scheduling for auto-download
|
||||
|
||||
**Testing:**
|
||||
- pytest - Test framework
|
||||
- pytest-asyncio - Async test support
|
||||
- pytest-cov - Coverage reporting
|
||||
- pytest-mock - Mocking support
|
||||
- pytest-timeout - Test timeout handling
|
||||
- pytest-html - HTML test reports
|
||||
|
||||
Reference in New Issue
Block a user