From da4973829e6439fa0cf077aefe16d0360cb866bb Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 27 Nov 2025 19:02:55 +0100 Subject: [PATCH] backup --- data/config.json | 2 +- data/download_queue.json | 25 +------- infrastructure.md | 120 ++++++++++++++++++++++----------------- instructions.md | 15 ++--- 4 files changed, 79 insertions(+), 83 deletions(-) diff --git a/data/config.json b/data/config.json index cb9e2f3..03643ca 100644 --- a/data/config.json +++ b/data/config.json @@ -17,7 +17,7 @@ "keep_days": 30 }, "other": { - "master_password_hash": "$pbkdf2-sha256$29000$AsCYU2pNCYHwHoPwnlPqXQ$uHLpvUnvj9GmNFgkAAgk3Yvvp2WzLyMNUBwKMyH79CQ", + "master_password_hash": "$pbkdf2-sha256$29000$AQAAAKAUImRsTSlFCGFMaQ$farZvo8fZCY9ZX7UiGFXTMtdduNvfSSVP8iDNwSWqfo", "anime_directory": "/mnt/server/serien/Serien/" }, "version": "1.0.0" diff --git a/data/download_queue.json b/data/download_queue.json index 81445d3..c68def4 100644 --- a/data/download_queue.json +++ b/data/download_queue.json @@ -1,27 +1,6 @@ { - "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 - } - ], + "pending": [], "active": [], "failed": [], - "timestamp": "2025-11-22T16:37:02.340599+00:00" + "timestamp": "2025-11-27T17:59:24.301867+00:00" } \ No newline at end of file diff --git a/infrastructure.md b/infrastructure.md index 2008b9e..d2e7fda 100644 --- a/infrastructure.md +++ b/infrastructure.md @@ -32,56 +32,62 @@ tests/ # Test suites ## Technology Stack -| Layer | Technology | -| ---------- | --------------------------------------------------- | -| Backend | FastAPI, Uvicorn, SQLAlchemy, SQLite, Pydantic | -| Frontend | HTML5, CSS3, Vanilla JS, Bootstrap 5, HTMX | -| Security | JWT (python-jose), bcrypt (passlib) | -| Real-time | Native WebSocket | +| Layer | Technology | +| --------- | ---------------------------------------------- | +| Backend | FastAPI, Uvicorn, SQLAlchemy, SQLite, Pydantic | +| Frontend | HTML5, CSS3, Vanilla JS, Bootstrap 5, HTMX | +| Security | JWT (python-jose), bcrypt (passlib) | +| Real-time | Native WebSocket | ## Series Identifier Convention Throughout the codebase, two identifiers are used for anime series: -- **`key`**: Primary identifier (provider-assigned, URL-safe, e.g., `"attack-on-titan"`) -- **`folder`**: Display/filesystem metadata only (e.g., `"Attack on Titan (2013)"`) +- **`key`**: Primary identifier (provider-assigned, URL-safe, e.g., `"attack-on-titan"`) +- **`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. ## API Endpoints ### Authentication (`/api/auth`) -- `POST /login` - Master password authentication (returns JWT) -- `POST /logout` - Invalidate session -- `GET /status` - Check authentication status + +- `POST /login` - Master password authentication (returns JWT) +- `POST /logout` - Invalidate session +- `GET /status` - Check authentication status ### Configuration (`/api/config`) -- `GET /` - Get configuration -- `PUT /` - Update configuration -- `POST /validate` - Validate without applying -- `GET /backups` - List backups -- `POST /backups/{name}/restore` - Restore backup + +- `GET /` - Get configuration +- `PUT /` - Update configuration +- `POST /validate` - Validate without applying +- `GET /backups` - List backups +- `POST /backups/{name}/restore` - Restore backup ### 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) -- `POST /search` - Search for anime (returns `key` as identifier) -- `POST /add` - Add new series (extracts `key` from link URL) -- `POST /rescan` - Trigger library rescan + +- `GET /` - List anime with missing episodes (returns `key` as identifier) +- `GET /{anime_id}` - Get anime details (accepts `key` or `folder` for backward compatibility) +- `POST /search` - Search for anime (returns `key` as identifier) +- `POST /add` - Add new series (extracts `key` from link URL) +- `POST /rescan` - Trigger library rescan **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`) -- `GET /status` - Queue status and statistics -- `POST /add` - Add episodes to queue -- `DELETE /{item_id}` - Remove item -- `POST /start` | `/stop` | `/pause` | `/resume` - Queue control -- `POST /retry` - Retry failed downloads -- `DELETE /completed` - Clear completed items + +- `GET /status` - Queue status and statistics +- `POST /add` - Add episodes to queue +- `DELETE /{item_id}` - Remove item +- `POST /start` | `/stop` | `/pause` | `/resume` - Queue control +- `POST /retry` - Retry failed downloads +- `DELETE /completed` - Clear completed items ### WebSocket (`/ws/connect`) + Real-time updates for downloads, scans, and queue operations. **Rooms**: `downloads`, `download_progress`, `scan_progress` @@ -102,40 +108,48 @@ Real-time updates for downloads, scans, and queue operations. ## Core Services ### SeriesApp (`src/core/SeriesApp.py`) + Main engine for anime series management with async support, progress callbacks, and cancellation. ### Callback System (`src/core/interfaces/callbacks.py`) -- `ProgressCallback`, `ErrorCallback`, `CompletionCallback` -- Context classes include `key` + optional `folder` fields -- Thread-safe `CallbackManager` for multiple callback registration + +- `ProgressCallback`, `ErrorCallback`, `CompletionCallback` +- Context classes include `key` + optional `folder` fields +- Thread-safe `CallbackManager` for multiple callback registration ### Services (`src/server/services/`) -| Service | Purpose | -| ----------------- | ------------------------------------------- | -| AnimeService | Series management, scans (uses SeriesApp) | -| DownloadService | Queue management, download execution | -| ScanService | Library scan operations with callbacks | -| ProgressService | Centralized progress tracking + WebSocket | -| WebSocketService | Real-time connection management | -| AuthService | JWT authentication, rate limiting | -| ConfigService | Configuration persistence with backups | +| Service | Purpose | +| ---------------- | ----------------------------------------- | +| AnimeService | Series management, scans (uses SeriesApp) | +| DownloadService | Queue management, download execution | +| ScanService | Library scan operations with callbacks | +| ProgressService | Centralized progress tracking + WebSocket | +| WebSocketService | Real-time connection management | +| AuthService | JWT authentication, rate limiting | +| ConfigService | Configuration persistence with backups | ## Frontend ### 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 + Native WebSocket wrapper with Socket.IO-compatible API: + ```javascript const socket = io(); -socket.join('download_progress'); -socket.on('download_progress', (data) => { /* ... */ }); +socket.join("download_progress"); +socket.on("download_progress", (data) => { + /* ... */ +}); ``` ### Authentication + JWT tokens stored in localStorage, included as `Authorization: Bearer `. ## Testing @@ -154,12 +168,14 @@ conda run -n AniWorld python -m pytest tests/api/ -v ## Production Notes ### Current (Single-Process) -- SQLite with WAL mode -- In-memory WebSocket connections -- File-based config and queue persistence + +- SQLite with WAL mode +- In-memory WebSocket connections +- File-based config and queue persistence ### Multi-Process Deployment -- Switch to PostgreSQL/MySQL -- Move WebSocket registry to Redis -- Use distributed locking for queue operations -- Consider Redis for session/cache storage + +- Switch to PostgreSQL/MySQL +- Move WebSocket registry to Redis +- Use distributed locking for queue operations +- Consider Redis for session/cache storage diff --git a/instructions.md b/instructions.md index fa1011e..a426567 100644 --- a/instructions.md +++ b/instructions.md @@ -187,13 +187,14 @@ For each task completed: **Completed:** November 27, 2025 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 `get_anime()` endpoint with key-first lookup and folder fallback -- Updated `add_series()` endpoint to extract key from link URL -- Updated `_perform_search()` to use key as identifier -- All docstrings updated to clarify identifier usage -- All anime API tests pass (11/11) + +- Updated `AnimeSummary` model with proper documentation (key as primary identifier) +- Updated `AnimeDetail` model with `key` field (replaced `id` field) +- Updated `get_anime()` endpoint with key-first lookup and folder fallback +- Updated `add_series()` endpoint to extract key from link URL +- Updated `_perform_search()` to use key as identifier +- All docstrings updated to clarify identifier usage +- All anime API tests pass (11/11) ---