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 sessionGET /status- Check authentication status
Configuration (/api/config)
GET /- Get configurationPUT /- Update configurationPOST /validate- Validate without applyingGET /backups- List backupsPOST /backups/{name}/restore- Restore backup
Anime (/api/anime)
GET /- List anime with missing episodes (returnskeyas identifier)GET /{anime_id}- Get anime details (acceptskeyorfolderfor backward compatibility)POST /search- Search for anime (returnskeyas identifier)POST /add- Add new series (extractskeyfrom link URL)POST /rescan- Trigger library rescan
Response Models:
AnimeSummary:key(primary identifier),name,site,folder(metadata),missing_episodes,linkAnimeDetail:key(primary identifier),title,folder(metadata),episodes,description
Download Queue (/api/queue)
GET /status- Queue status and statisticsPOST /add- Add episodes to queueDELETE /{item_id}- Remove itemPOST /start|/stop|/pause|/resume- Queue controlPOST /retry- Retry failed downloadsDELETE /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,progressQueueStatus: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+ optionalfolderfields - Thread-safe
CallbackManagerfor 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