Files
ohm_streaming/AGENTS.md
T
root 2482a1fe58 feat: Add AGENTS.md and new downloaders with metadata enrichment
- Add AGENTS.md for agentic coding guidelines
- Add Oneupload and Smoothpre video player downloaders
- Add MetadataEnrichment service with Kitsu API fallback
- Add tests for metadata enrichment and provider detection
- Update .gitignore to ignore runtime config files
2026-02-24 20:14:31 +00:00

4.2 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
pytest --cov=app --cov-report=html

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

# Exclude slow tests
pytest -m "not slow"

# Verbose with print debugging
pytest -v -s

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

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:

  1. app/downloaders/anime_sites/ - Anime catalogs
  2. app/downloaders/series_sites/ - TV series catalogs
  3. app/downloaders/video_players/ - File hosting

Each has base class and factory. When adding providers:

  1. Inherit from appropriate base class
  2. Implement required methods
  3. Register in factory
  4. Add to providers config in app/providers.py

URL Convention: Pipe-separated format preserves metadata:

video_url|anime_page_url|episode_title

Key Files

File Purpose
main.py FastAPI app, endpoints
app/config.py Pydantic Settings
app/download_manager.py Download queue
app/utils.py sanitize_filename
app/auth.py JWT auth
app/models/__init__.py Pydantic models

Configuration

  • Use .env from .env.example
  • JWT_SECRET_KEY must change in production