Aniworld/infrastructure.md

7.1 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

Request Models:

  • DownloadRequest: serie_id (key, primary identifier), serie_folder (filesystem path), serie_name (display), episodes, priority

Response Models:

  • DownloadItem: id, serie_id (key), serie_folder (metadata), serie_name, episode, status, progress
  • QueueStatus: is_running, is_paused, active_downloads, pending_queue, completed_downloads, failed_downloads

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

Series Identifier in Messages: All series-related WebSocket events include key as the primary identifier in their data payload:

{
    "type": "download_progress",
    "timestamp": "2025-10-17T10:30:00.000Z",
    "data": {
        "download_id": "abc123",
        "key": "attack-on-titan",
        "folder": "Attack on Titan (2013)",
        "percent": 45.2,
        "speed_mbps": 2.5,
        "eta_seconds": 180
    }
}

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