This commit is contained in:
Lukas 2025-11-27 19:02:55 +01:00
parent ff5b364852
commit da4973829e
4 changed files with 79 additions and 83 deletions

View File

@ -17,7 +17,7 @@
"keep_days": 30 "keep_days": 30
}, },
"other": { "other": {
"master_password_hash": "$pbkdf2-sha256$29000$AsCYU2pNCYHwHoPwnlPqXQ$uHLpvUnvj9GmNFgkAAgk3Yvvp2WzLyMNUBwKMyH79CQ", "master_password_hash": "$pbkdf2-sha256$29000$AQAAAKAUImRsTSlFCGFMaQ$farZvo8fZCY9ZX7UiGFXTMtdduNvfSSVP8iDNwSWqfo",
"anime_directory": "/mnt/server/serien/Serien/" "anime_directory": "/mnt/server/serien/Serien/"
}, },
"version": "1.0.0" "version": "1.0.0"

View File

@ -1,27 +1,6 @@
{ {
"pending": [ "pending": [],
{
"id": "03bfbf39-60b7-4790-ae9e-a158f654dafa",
"serie_id": "a-star-brighter-than-the-sun",
"serie_folder": "Ein Stern, heller als die Sonne (2025)",
"serie_name": "A Star Brighter Than the Sun",
"episode": {
"season": 1,
"episode": 8,
"title": null
},
"status": "cancelled",
"priority": "NORMAL",
"added_at": "2025-11-22T16:36:10.705099Z",
"started_at": "2025-11-22T16:36:16.078860Z",
"completed_at": "2025-11-22T16:37:02.340465Z",
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
}
],
"active": [], "active": [],
"failed": [], "failed": [],
"timestamp": "2025-11-22T16:37:02.340599+00:00" "timestamp": "2025-11-27T17:59:24.301867+00:00"
} }

View File

@ -32,56 +32,62 @@ tests/ # Test suites
## Technology Stack ## Technology Stack
| Layer | Technology | | Layer | Technology |
| ---------- | --------------------------------------------------- | | --------- | ---------------------------------------------- |
| Backend | FastAPI, Uvicorn, SQLAlchemy, SQLite, Pydantic | | Backend | FastAPI, Uvicorn, SQLAlchemy, SQLite, Pydantic |
| Frontend | HTML5, CSS3, Vanilla JS, Bootstrap 5, HTMX | | Frontend | HTML5, CSS3, Vanilla JS, Bootstrap 5, HTMX |
| Security | JWT (python-jose), bcrypt (passlib) | | Security | JWT (python-jose), bcrypt (passlib) |
| Real-time | Native WebSocket | | Real-time | Native WebSocket |
## Series Identifier Convention ## Series Identifier Convention
Throughout the codebase, two identifiers are used for anime series: Throughout the codebase, two identifiers are used for anime series:
- **`key`**: Primary identifier (provider-assigned, URL-safe, e.g., `"attack-on-titan"`) - **`key`**: Primary identifier (provider-assigned, URL-safe, e.g., `"attack-on-titan"`)
- **`folder`**: Display/filesystem metadata only (e.g., `"Attack on Titan (2013)"`) - **`folder`**: Display/filesystem metadata only (e.g., `"Attack on Titan (2013)"`)
All lookups, events, and API operations use `key`. The `folder` is metadata for display purposes. All lookups, events, and API operations use `key`. The `folder` is metadata for display purposes.
## API Endpoints ## API Endpoints
### Authentication (`/api/auth`) ### Authentication (`/api/auth`)
- `POST /login` - Master password authentication (returns JWT)
- `POST /logout` - Invalidate session - `POST /login` - Master password authentication (returns JWT)
- `GET /status` - Check authentication status - `POST /logout` - Invalidate session
- `GET /status` - Check authentication status
### Configuration (`/api/config`) ### Configuration (`/api/config`)
- `GET /` - Get configuration
- `PUT /` - Update configuration - `GET /` - Get configuration
- `POST /validate` - Validate without applying - `PUT /` - Update configuration
- `GET /backups` - List backups - `POST /validate` - Validate without applying
- `POST /backups/{name}/restore` - Restore backup - `GET /backups` - List backups
- `POST /backups/{name}/restore` - Restore backup
### Anime (`/api/anime`) ### Anime (`/api/anime`)
- `GET /` - List anime with missing episodes (returns `key` as identifier)
- `GET /{anime_id}` - Get anime details (accepts `key` or `folder` for backward compatibility) - `GET /` - List anime with missing episodes (returns `key` as identifier)
- `POST /search` - Search for anime (returns `key` as identifier) - `GET /{anime_id}` - Get anime details (accepts `key` or `folder` for backward compatibility)
- `POST /add` - Add new series (extracts `key` from link URL) - `POST /search` - Search for anime (returns `key` as identifier)
- `POST /rescan` - Trigger library rescan - `POST /add` - Add new series (extracts `key` from link URL)
- `POST /rescan` - Trigger library rescan
**Response Models:** **Response Models:**
- `AnimeSummary`: `key` (primary identifier), `name`, `site`, `folder` (metadata), `missing_episodes`, `link`
- `AnimeDetail`: `key` (primary identifier), `title`, `folder` (metadata), `episodes`, `description` - `AnimeSummary`: `key` (primary identifier), `name`, `site`, `folder` (metadata), `missing_episodes`, `link`
- `AnimeDetail`: `key` (primary identifier), `title`, `folder` (metadata), `episodes`, `description`
### Download Queue (`/api/queue`) ### Download Queue (`/api/queue`)
- `GET /status` - Queue status and statistics
- `POST /add` - Add episodes to queue - `GET /status` - Queue status and statistics
- `DELETE /{item_id}` - Remove item - `POST /add` - Add episodes to queue
- `POST /start` | `/stop` | `/pause` | `/resume` - Queue control - `DELETE /{item_id}` - Remove item
- `POST /retry` - Retry failed downloads - `POST /start` | `/stop` | `/pause` | `/resume` - Queue control
- `DELETE /completed` - Clear completed items - `POST /retry` - Retry failed downloads
- `DELETE /completed` - Clear completed items
### WebSocket (`/ws/connect`) ### WebSocket (`/ws/connect`)
Real-time updates for downloads, scans, and queue operations. Real-time updates for downloads, scans, and queue operations.
**Rooms**: `downloads`, `download_progress`, `scan_progress` **Rooms**: `downloads`, `download_progress`, `scan_progress`
@ -102,40 +108,48 @@ Real-time updates for downloads, scans, and queue operations.
## Core Services ## Core Services
### SeriesApp (`src/core/SeriesApp.py`) ### SeriesApp (`src/core/SeriesApp.py`)
Main engine for anime series management with async support, progress callbacks, and cancellation. Main engine for anime series management with async support, progress callbacks, and cancellation.
### Callback System (`src/core/interfaces/callbacks.py`) ### Callback System (`src/core/interfaces/callbacks.py`)
- `ProgressCallback`, `ErrorCallback`, `CompletionCallback`
- Context classes include `key` + optional `folder` fields - `ProgressCallback`, `ErrorCallback`, `CompletionCallback`
- Thread-safe `CallbackManager` for multiple callback registration - Context classes include `key` + optional `folder` fields
- Thread-safe `CallbackManager` for multiple callback registration
### Services (`src/server/services/`) ### Services (`src/server/services/`)
| Service | Purpose | | Service | Purpose |
| ----------------- | ------------------------------------------- | | ---------------- | ----------------------------------------- |
| AnimeService | Series management, scans (uses SeriesApp) | | AnimeService | Series management, scans (uses SeriesApp) |
| DownloadService | Queue management, download execution | | DownloadService | Queue management, download execution |
| ScanService | Library scan operations with callbacks | | ScanService | Library scan operations with callbacks |
| ProgressService | Centralized progress tracking + WebSocket | | ProgressService | Centralized progress tracking + WebSocket |
| WebSocketService | Real-time connection management | | WebSocketService | Real-time connection management |
| AuthService | JWT authentication, rate limiting | | AuthService | JWT authentication, rate limiting |
| ConfigService | Configuration persistence with backups | | ConfigService | Configuration persistence with backups |
## Frontend ## Frontend
### Static Files ### Static Files
- CSS: `styles.css` (Fluent UI design), `ux_features.css` (accessibility)
- JS: `app.js`, `queue.js`, `websocket_client.js`, accessibility modules - CSS: `styles.css` (Fluent UI design), `ux_features.css` (accessibility)
- JS: `app.js`, `queue.js`, `websocket_client.js`, accessibility modules
### WebSocket Client ### WebSocket Client
Native WebSocket wrapper with Socket.IO-compatible API: Native WebSocket wrapper with Socket.IO-compatible API:
```javascript ```javascript
const socket = io(); const socket = io();
socket.join('download_progress'); socket.join("download_progress");
socket.on('download_progress', (data) => { /* ... */ }); socket.on("download_progress", (data) => {
/* ... */
});
``` ```
### Authentication ### Authentication
JWT tokens stored in localStorage, included as `Authorization: Bearer <token>`. JWT tokens stored in localStorage, included as `Authorization: Bearer <token>`.
## Testing ## Testing
@ -154,12 +168,14 @@ conda run -n AniWorld python -m pytest tests/api/ -v
## Production Notes ## Production Notes
### Current (Single-Process) ### Current (Single-Process)
- SQLite with WAL mode
- In-memory WebSocket connections - SQLite with WAL mode
- File-based config and queue persistence - In-memory WebSocket connections
- File-based config and queue persistence
### Multi-Process Deployment ### Multi-Process Deployment
- Switch to PostgreSQL/MySQL
- Move WebSocket registry to Redis - Switch to PostgreSQL/MySQL
- Use distributed locking for queue operations - Move WebSocket registry to Redis
- Consider Redis for session/cache storage - Use distributed locking for queue operations
- Consider Redis for session/cache storage

View File

@ -187,13 +187,14 @@ For each task completed:
**Completed:** November 27, 2025 **Completed:** November 27, 2025
Updated `src/server/api/anime.py` to standardize all endpoints to use `key` as the primary series identifier: Updated `src/server/api/anime.py` to standardize all endpoints to use `key` as the primary series identifier:
- Updated `AnimeSummary` model with proper documentation (key as primary identifier)
- Updated `AnimeDetail` model with `key` field (replaced `id` field) - Updated `AnimeSummary` model with proper documentation (key as primary identifier)
- Updated `get_anime()` endpoint with key-first lookup and folder fallback - Updated `AnimeDetail` model with `key` field (replaced `id` field)
- Updated `add_series()` endpoint to extract key from link URL - Updated `get_anime()` endpoint with key-first lookup and folder fallback
- Updated `_perform_search()` to use key as identifier - Updated `add_series()` endpoint to extract key from link URL
- All docstrings updated to clarify identifier usage - Updated `_perform_search()` to use key as identifier
- All anime API tests pass (11/11) - All docstrings updated to clarify identifier usage
- All anime API tests pass (11/11)
--- ---