Aniworld/infrastructure.md
Lukas ff5b364852 Task 4.1: Update Anime API Endpoints to use key as primary identifier
- Updated AnimeSummary model with enhanced documentation:
  - key as primary identifier (unique series identifier)
  - folder as metadata only (not used for lookups)
  - Added Field descriptions for all attributes

- Updated AnimeDetail model:
  - Replaced 'id' field with 'key' field
  - Added 'folder' field as metadata
  - Enhanced documentation and JSON schema example

- Updated get_anime() endpoint:
  - Primary lookup by 'key' (preferred)
  - Fallback lookup by 'folder' (backward compatibility)
  - Updated docstring to clarify identifier usage

- Updated add_series() endpoint:
  - Extracts key from link URL (/anime/stream/{key})
  - Returns both key and folder in response
  - Enhanced docstring with parameter descriptions

- Updated _perform_search():
  - Uses key as primary identifier
  - Extracts key from link URL if not present
  - Enhanced docstring with return value details

- Updated list_anime() and search endpoint docstrings:
  - Clarified key as primary identifier
  - Documented folder as metadata only

- Updated instructions.md:
  - Marked Task 4.1 as completed
  - Updated task tracking section

- Updated infrastructure.md:
  - Updated API endpoints documentation
  - Added response model details

All anime API tests passing (11/11)
All unit tests passing (604/604)
2025-11-27 19:02:19 +01:00

6.3 KiB

Aniworld Web Application Infrastructure

conda activate AniWorld

Project Structure

src/
├── core/                  # Core application logic
│   ├── SeriesApp.py       # Main application class
│   ├── SerieScanner.py    # Directory scanner
│   ├── entities/          # Domain entities (series.py, SerieList.py)
│   ├── interfaces/        # Abstract interfaces (providers.py, callbacks.py)
│   ├── providers/         # Content providers (aniworld, streaming)
│   └── exceptions/        # Custom exceptions
├── server/                # FastAPI web application
│   ├── fastapi_app.py     # Main FastAPI application
│   ├── controllers/       # Route controllers (health, page, error)
│   ├── api/               # API routes (auth, config, anime, download, websocket)
│   ├── models/            # Pydantic models
│   ├── services/          # Business logic services
│   ├── database/          # SQLAlchemy ORM layer
│   ├── utils/             # Utilities (dependencies, templates, security)
│   └── web/               # Frontend (templates, static assets)
├── cli/                   # CLI application
data/                      # Config, database, queue state
logs/                      # Application logs
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

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)")

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

Configuration (/api/config)

  • 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

Response Models:

  • 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

WebSocket (/ws/connect)

Real-time updates for downloads, scans, and queue operations.

Rooms: downloads, download_progress, scan_progress

Message Types: download_progress, download_complete, download_failed, queue_status, scan_progress, scan_complete, scan_failed

Database Models

Model Purpose
AnimeSeries Series metadata (key, name, folder, etc)
Episode Episodes linked to series
DownloadQueueItem Queue items with status and progress
UserSession JWT sessions with expiry

Mixins: TimestampMixin (created_at, updated_at), SoftDeleteMixin

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

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

Frontend

Static Files

  • 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:

const socket = io();
socket.join('download_progress');
socket.on('download_progress', (data) => { /* ... */ });

Authentication

JWT tokens stored in localStorage, included as Authorization: Bearer <token>.

Testing

# All tests
conda run -n AniWorld python -m pytest tests/ -v

# Unit tests only
conda run -n AniWorld python -m pytest tests/unit/ -v

# API tests
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

Multi-Process Deployment

  • Switch to PostgreSQL/MySQL
  • Move WebSocket registry to Redis
  • Use distributed locking for queue operations
  • Consider Redis for session/cache storage