Files
ohm_streaming/AGENTS.md
T
2026-02-28 09:22:57 +00:00

10 KiB

AGENTS.md - Agentic Coding Guidelines

This file provides guidance for AI agents working in this repository.

Quick Start

# Setup
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt

# Run dev server
uvicorn main:app --reload --host 0.0.0.0 --port 3000

Build, Lint & Test Commands

Running Tests

# All tests
pytest

# With coverage (HTML report in htmlcov/)
pytest --cov=app --cov-report=html

# Unit only (fast)
pytest -m "unit"

# Integration tests only
pytest -m "integration"

# Exclude slow tests
pytest -m "not slow"

# Exclude network tests (mocked only)
pytest -m "not network"

# Verbose with print debugging
pytest -v -s

# Generate HTML report
pytest --html=report.html --self-contained-html

# Timeout per test (seconds)
pytest --timeout=30

Running Single Tests

# Specific file
pytest tests/test_sonarr.py -v

# Specific class
pytest tests/test_sonarr.py::TestSonarrHandler -v

# Specific test
pytest tests/test_sonarr.py::TestSonarrHandler::test_add_mapping -v

# Pattern match
pytest -k "test_download" -v

Code Style

Imports (PEP 8 order)

  1. Standard library (os, json, asyncio)
  2. Third-party (httpx, beautifulsoup4, fastapi)
  3. Local app (app.config, app.utils)
import os
import asyncio
from typing import Optional

import httpx
from fastapi import APIRouter, HTTPException

from app.config import get_settings
from app.models import DownloadTask, DownloadStatus

Formatting

  • Line length: 120 chars max
  • Indentation: 4 spaces
  • Blank lines: 2 between top-level, 1 between inline

Type Annotations

  • Use explicit types
  • Use Optional[X] not X | None
  • Use list[X], dict[X, Y]
# Good
async def get_download_link(url: str, target_filename: Optional[str] = None) -> tuple[str, str]:
    results: list[dict[str, str]] = []

# Avoid
async def get_download_link(url, target_filename=None):
    results = []

Naming Conventions

Element Convention Example
Modules snake_case download_manager.py
Classes PascalCase DownloadManager
Functions snake_case get_download_link()
Constants UPPER_SNAKE MAX_PARALLEL_DOWNLOADS
Variables snake_case download_task
Enums PascalCase DownloadStatus
Enum values UPPER_SNAKE DownloadStatus.PENDING

Async/Await

  • Always use for I/O operations
  • Close clients properly to avoid leaks
async def close(self):
    await self.client.aclose()

Error Handling

  • Use try/except for recoverable errors
  • Raise specific exceptions (HTTPException, ValueError)
  • Never use empty except blocks
  • Log errors appropriately
try:
    result = await client.get(url)
except httpx.TimeoutException:
    logger.warning(f"Request timeout for {url}")
    raise HTTPException(status_code=504, detail="Request timeout")

File Operations

  • Always sanitize filenames: app.utils.sanitize_filename()
  • Validate paths: app.utils.is_safe_filename()

Testing

  • Use pytest with pytest-asyncio
  • Mark tests: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.network
  • Tests in test_api.py are auto-marked as integration, others as unit
  • Use fixtures from tests/conftest.py
@pytest.mark.unit
@pytest.mark.asyncio
async def test_download_manager():
    manager = DownloadManager(max_parallel=3)
    assert manager.max_parallel == 3

# Mark slow tests
@pytest.mark.slow
async def test_full_download_flow():
    ...

# Mark tests requiring network
@pytest.mark.network
async def test_external_api():
    ...

Security

  • Never hardcode secrets - use environment variables
  • Validate all inputs (URLs, filenames)
  • Use HMAC for webhook verification when configured
  • Limit CORS origins - never use * in production

Architecture Patterns

Three-Tier Downloader Architecture

The project uses a three-tier downloader system:

  1. Anime Catalogs (app/downloaders/anime_sites/)

    • animesama.py - Anime-Sama (primary)
    • animeultime.py - Anime-Ultime
    • nekosama.py - Neko-Sama
    • vostfree.py - Vostfree
    • frenchmanga.py - French-Manga
  2. Series Catalogs (app/downloaders/series_sites/)

    • fs7.py - French Stream
  3. Video Players (app/downloaders/video_players/)

    • sibnet.py, doodstream.py, vidmoly.py, uqload.py
    • uptobox.py, unfichier.py, rapidfile.py
    • sendvid.py, lpayer.py, vidzy.py, luluv.py
    • oneupload.py, smoothpre.py

Each tier has a base class and factory pattern. When adding providers:

  1. Inherit from appropriate base class (base.py)
  2. Implement required methods (search_anime, get_episodes, get_download_link)
  3. Register in app/providers.py
  4. Add URL detection patterns

URL Convention: Pipe-separated format preserves metadata:

video_url|anime_page_url|episode_title

Core Modules

Module Purpose
app/watchlist.py Episode tracking & auto-download
app/auto_download_scheduler.py APScheduler for periodic checks
app/episode_checker.py New episode detection
app/sonarr_handler.py Sonarr webhook integration
app/recommendation_engine.py Personalized anime recommendations
app/favorites.py User favorites management
app/auth.py JWT authentication
app/download_manager.py Download queue management

Key Files

File Purpose
main.py FastAPI app, all API endpoints
app/config.py Pydantic Settings configuration
app/download_manager.py Download queue & task management
app/utils.py sanitize_filename, is_safe_filename
app/auth.py JWT auth, user management
app/providers.py Provider definitions & URL detection
app/models/__init__.py Core Pydantic models
app/models/watchlist.py Watchlist models
app/models/sonarr.py Sonarr integration models
app/models/auth.py Authentication models

Frontend Architecture

JavaScript Modules (static/js/)

Module Purpose
main.js Application entry point
api.js API client functions
auth.js Authentication handling
tabs.js Tab navigation
anime.js Anime search & display
anime-details.js Anime detail views
watchlist.js Watchlist API calls
watchlist-ui.js Watchlist UI rendering
downloads.js Download management UI
recommendations.js Recommendations display
series-search.js TV series search
utils.js Utility functions

Templates (templates/)

Template Purpose
base.html Base layout with CSS/JS imports
index.html Main SPA interface
login.html Login/register page
watchlist.html Watchlist management page
player.html Video player page
components/ Reusable HTML components

Configuration

  • Use .env from .env.example
  • JWT_SECRET_KEY must change in production
  • Config files stored in config/:
    • users.json - User database
    • watchlist.json - Watchlist data
    • watchlist_settings.json - Auto-download settings
    • sonarr.json - Sonarr integration config
    • sonarr_mappings.json - Series to anime mappings

API Endpoints Overview

Authentication

  • POST /api/auth/register - Register new user
  • POST /api/auth/login - Login, get JWT token
  • GET /api/auth/me - Get current user info
  • POST /api/auth/logout - Logout (client-side)

Downloads

  • POST /api/download - Create download task
  • GET /api/downloads - List all downloads
  • GET /api/download/{task_id} - Get download status
  • POST /api/download/{task_id}/pause - Pause download
  • POST /api/download/{task_id}/resume - Resume download
  • DELETE /api/download/{task_id} - Cancel/delete download
  • GET /api/download/{task_id}/file - Download completed file

Anime Search & Metadata

  • GET /api/anime/search - Search across all anime providers
  • GET /api/series/search - Search TV series providers
  • GET /api/anime/metadata - Get detailed anime metadata
  • GET /api/anime/episodes - Get episode list
  • GET /api/anime/seasons - Get available seasons
  • POST /api/anime/download-season - Download all episodes

Watchlist

  • GET /api/watchlist - List watchlist items
  • POST /api/watchlist - Add to watchlist
  • PUT /api/watchlist/{item_id} - Update watchlist item
  • DELETE /api/watchlist/{item_id} - Remove from watchlist
  • GET /api/watchlist/settings - Get auto-download settings
  • PUT /api/watchlist/settings - Update settings
  • POST /api/watchlist/check - Trigger manual episode check

Favorites

  • GET /api/favorites - List favorites
  • POST /api/favorites - Add to favorites
  • DELETE /api/favorites/{anime_id} - Remove from favorites
  • POST /api/favorites/toggle - Toggle favorite status

Recommendations

  • GET /api/recommendations - Get personalized recommendations
  • GET /api/releases/latest - Get latest releases
  • GET /api/releases/seasonal - Get seasonal anime

Sonarr Integration

  • POST /api/sonarr/webhook - Receive Sonarr webhooks
  • GET /api/sonarr/mappings - List Sonarr mappings
  • POST /api/sonarr/mappings - Create mapping
  • DELETE /api/sonarr/mappings/{series_id} - Delete mapping

Dependencies

Core

  • fastapi - Web framework
  • uvicorn - ASGI server
  • httpx - Async HTTP client
  • aiohttp - Alternative HTTP client
  • pydantic / pydantic-settings - Data validation & settings

Scraping & Parsing

  • beautifulsoup4 - HTML parsing
  • lxml - XML/HTML parser
  • jieba - Chinese text segmentation

Authentication

  • python-jose - JWT handling
  • passlib[bcrypt] - Password hashing

Scheduler

  • apscheduler - Job scheduling for auto-downloads

Cryptography

  • pycryptodome - AES decryption for video players

Testing

  • pytest + pytest-asyncio - Async test support
  • pytest-cov - Coverage reporting
  • pytest-mock - Mocking utilities
  • pytest-timeout - Test timeout protection
  • pytest-html - HTML test reports