This commit adds comprehensive Sonarr webhook integration and implements critical security improvements identified in code review. ## Sonarr Integration - Full webhook support for Grab, Download, Rename, Delete, and Test events - HMAC SHA256 signature verification for webhook authentication - Series mapping system (Sonarr TVDB ID → Anime Provider URL) - 11 new API endpoints for configuration, mappings, search, and downloads - Comprehensive test suite (31 tests, all passing) - Complete documentation in docs/SONARR_INTEGRATION.md ## Security Enhancements - CORS restricted to specific origins (user's IP: 192.168.1.204:3000) - Path traversal prevention via sanitize_filename() and is_safe_filename() - Structured logging infrastructure (replaced all print() statements) - Environment-based configuration with .env support - Filename sanitization prevents malicious path attacks ## New Features - Lpayer and Sibnet downloader support - Kitsu API integration for anime metadata - Recommendation engine based on download history - Latest releases endpoint for new anime - Modular web interface with component-based templates ## Configuration - Centralized settings via app/config.py with pydantic-settings - Sonarr config auto-created in config/ directory - Example configurations provided for easy setup ## Tests - 31 Sonarr integration tests (23 functionality + 9 security) - 100+ tests passing in core test files - Security utilities fully tested ## Documentation - Updated CLAUDE.md with Sonarr and testing info - Added IMPROVEMENTS_2024-01-24.md analysis - Added SONARR_IMPLEMENTATION.md technical summary Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
14 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Ohm Stream Downloader is a FastAPI-based web application for downloading anime episodes and media files from various file hosting services (1fichier, Doodstream, Rapidfile, Uptobox, VidMoly, SendVid, Sibnet, Lpayer) and anime streaming platforms (Anime-Sama, Neko-Sama, Anime-Ultime, Vostfree). It features a modern web interface, parallel downloads, pause/resume support, video streaming, personalized recommendations, and Sonarr webhook integration for automated downloads.
Development Commands
# Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Run development server (auto-reload)
uvicorn main:app --reload --host 0.0.0.0 --port 3000
# Access web interface
# Open http://localhost:3000/web in browser
# Run all tests
pytest
# Run tests with coverage report
pytest --cov=app --cov-report=html
# Run only unit tests (fast, isolated)
pytest -m "unit"
# Run only integration tests
pytest -m "integration"
# Exclude slow tests
pytest -m "not slow"
# Verbose output
pytest -v
# Show print debugging
pytest -s
Architecture
Directory Structure:
Ohm_streaming/
├── main.py # FastAPI application & API endpoints
├── app/
│ ├── models/ # Pydantic models (DownloadTask, AnimeMetadata, Sonarr, etc.)
│ ├── downloaders/ # Host-specific downloaders
│ │ ├── base.py # BaseDownloader abstract class
│ │ ├── unfichier.py # 1fichier.com handler
│ │ ├── doodstream.py # Doodstream handler
│ │ ├── rapidfile.py # Rapidfile handler
│ │ ├── uptobox.py # Uptobox handler
│ │ ├── vidmoly.py # VidMoly handler
│ │ ├── sendvid.py # SendVid handler
│ │ ├── sibnet.py # Sibnet handler
│ │ ├── lpayer.py # Lpayer handler
│ │ ├── vidmoly_old.py # Old VidMoly implementation (deprecated)
│ │ ├── animesama.py # Anime-Sama (anime provider)
│ │ ├── animeultime.py # Anime-Ultime (anime provider)
│ │ ├── nekosama.py # Neko-Sama (anime provider)
│ │ ├── vostfree.py # Vostfree (anime provider)
│ │ └── __init__.py # Factory function and registry
│ ├── providers.py # Provider configuration (domains, icons, colors)
│ ├── download_manager.py # Manages download queue, progress, parallel downloads
│ ├── favorites.py # Favorites management system (JSON-based)
│ ├── recommendation_engine.py # Analyzes download history for recommendations
│ ├── recommendations.py # Fetches latest releases from anime sources
│ ├── kitsu_api.py # Kitsu API integration for metadata
│ ├── sonarr_handler.py # Sonarr webhook integration handler
│ └── models/
│ └── sonarr.py # Sonarr Pydantic models
├── downloads/ # Downloaded files storage
├── templates/
│ ├── index.html # Main web interface
│ ├── player.html # Video player page
│ └── base.html # Base template
├── static/ # Static assets (CSS, JS, images)
└── tests/ # Test suite with fixtures
Core Components:
1. DownloadManager (app/download_manager.py)
- Manages all download tasks with parallel download limit (default: 3 concurrent)
- Handles pause/resume/cancel operations
- Tracks progress, speed, and file chunks for resume support
- Uses
asyncio.Semaphoreto limit concurrent downloads - Auto-restores completed downloads from disk on server startup
2. Downloaders (app/downloaders/)
Factory Pattern:
get_downloader(url)in__init__.pyselects appropriate downloader- Each downloader inherits from
BaseDownloaderabstract class - Order matters: anime providers checked first, then file hosts
- Falls back to
GenericDownloaderif no match
BaseDownloader Interface:
can_handle(url)- Check if downloader supports the URLget_download_link(url)- Extract direct download link and filenamesearch_anime(query, lang)- Search anime (anime providers only)get_episodes(anime_url, lang)- Get episode list (anime providers only)get_anime_metadata(anime_url)- Get metadata dict (anime providers only) - Note: not in base.py, implemented by anime providers
Key Patterns:
- All downloaders use httpx.AsyncClient for HTTP requests
- BeautifulSoup with lxml for HTML parsing
- Async/await throughout for non-blocking I/O
- Fuzzy search using jieba for Chinese text segmentation and typo tolerance
3. Provider Configuration (app/providers.py)
ANIME_PROVIDERS- Anime streaming sites configurationFILE_HOSTS- File hosting services configuration- Each provider has: name, domains, icon, color, url_pattern
detect_provider_from_url(url)- Identify provider from URL
4. API Endpoints
Download Management:
POST /api/download- Create new download taskGET /api/downloads- List all download tasksGET /api/download/{task_id}- Get task detailsPOST /api/download/{task_id}/pause- Pause downloadPOST /api/download/{task_id}/resume- Resume downloadDELETE /api/download/{task_id}- Delete task (keeps completed files)GET /api/download/{task_id}/file- Download completed file
Anime Features:
GET /api/anime/search- Unified search across all providersGET /api/anime/metadata- Get anime metadataGET /api/anime/episodes- Get episode listPOST /api/anime/download- Download single episodePOST /api/anime/download-season- Download entire season
Video Streaming:
GET /video/{task_id}- Stream video with Range supportGET /stream/{filename}- Stream by filenameGET /player/{task_id}- Video player pageGET /watch/{filename}- Player by filename
Recommendations & Favorites:
GET /api/recommendations- Personalized recommendationsGET /api/releases/latest- Latest anime releasesGET /api/favorites- List favoritesPOST /api/favorites- Add favoriteDELETE /api/favorites/{anime_id}- Remove favorite
Sonarr Integration:
POST /api/webhook/sonarr- Receive Sonarr webhooksGET /api/sonarr/config- Get Sonarr configurationPUT /api/sonarr/config- Update Sonarr configurationGET /api/sonarr/mappings- List Sonarr to anime mappingsPOST /api/sonarr/mappings- Create/update mappingDELETE /api/sonarr/mappings/{series_id}- Delete mappingGET /api/sonarr/search- Search anime for mappingGET /api/sonarr/episodes- Get episode listGET /api/sonarr/suggest- Suggest anime matchesPOST /api/sonarr/download- Manually trigger download
5. Web Interface
- Single-page app at
/web(templates/index.html) - Auto-refreshes every second to show progress
- Video player with seeking support (HTTP Range headers)
- Dark theme with gradients and animations
Test Structure
Test Organization (tests/):
conftest.py- Pytest configuration and fixturestest_models.py- Pydantic model teststest_downloaders.py- Downloader teststest_download_manager.py- DownloadManager teststest_favorites.py- Favorites system teststest_api.py- FastAPI endpoint teststest_sonarr.py- Sonarr integration tests (23 tests, all passing)
Fixtures in conftest.py:
temp_dir- Temporary directorytemp_download_dir- Temporary download directorydownload_manager- DownloadManager instancefavorites_manager- FavoritesManager instancemock_httpx_client- Mock for httpx.AsyncClientsample_download_task- Sample task datasample_anime_metadata- Sample metadata
Test Markers:
unit- Unit tests (isolated, fast) - auto-appliedintegration- Integration tests (API endpoints) - auto-appliedasyncio- Async tests - auto-appliedslow- Slow tests - manualnetwork- Requires network - manual
Running Single Test:
# Run specific test file
pytest tests/test_sonarr.py -v
# Run specific test class
pytest tests/test_sonarr.py::TestSonarrHandler -v
# Run specific test
pytest tests/test_sonarr.py::TestSonarrHandler::test_add_mapping -v
Adding New Host Support
To add support for a new file hosting service:
- Create new file in
app/downloaders/(e.g.,myhost.py) - Inherit from
BaseDownloader - Implement required methods
- Add to imports in
app/downloaders/__init__.py - Add to
downloaderslist inget_downloader() - Add configuration to
FILE_HOSTSinapp/providers.py
Example:
from .base import BaseDownloader
from bs4 import BeautifulSoup
class MyHostDownloader(BaseDownloader):
def can_handle(self, url: str) -> bool:
return "myhost.com" in url.lower()
async def get_download_link(self, url: str) -> tuple[str, str]:
soup = BeautifulSoup(await self._fetch_page(url), 'lxml')
# ... extraction logic ...
return download_url, filename
def close(self):
# IMPORTANT: Always close the HTTP client
await self.client.aclose()
Important: Always close the HTTP client in your downloader to avoid resource leaks.
Sonarr Integration
The application includes full Sonarr webhook support for automated anime downloads.
Architecture
SonarrHandler (app/sonarr_handler.py):
- Processes incoming webhooks from Sonarr
- Manages series mappings (Sonarr TVDB ID → Anime Provider URL)
- Supports HMAC SHA256 signature verification for security
- Auto-triggers downloads on Grab events
- Provides search and suggestion APIs for mapping setup
Sonarr Models (app/models/sonarr.py):
SonarrWebhookPayload- Complete webhook payload schemaSonarrEventType- Enum for event types (Grab, Download, Rename, Delete, Test)SonarrMapping- Mapping between Sonarr series and anime providersSonarrConfig- Webhook configuration (enabled, secret, auto-download, etc.)
Workflow
-
Setup in Sonarr:
- Configure webhook: Settings > Connect > Sonarr > Webhook
- URL:
http://your-server:3000/api/webhook/sonarr - Enable "Grab" event
-
Create Mappings:
- Get Sonarr series TVDB ID from series details
- Search anime:
GET /api/sonarr/search?q={title} - Create mapping:
POST /api/sonarr/mappings
-
Automatic Download:
- Sonarr grabs new episode → Sends webhook
- Ohm Stream Downloader receives webhook
- Looks up mapping by TVDB ID
- Finds matching episode on anime provider
- Creates and starts download task
Configuration Files
config/sonarr.json- Webhook configurationconfig/sonarr_mappings.json- Series mappings
Example Mapping
{
"sonarr_series_id": 79644,
"sonarr_title": "Naruto Shippuden",
"anime_provider": "anime-sama",
"anime_url": "https://anime-sama.si/catalogue/naruto-shippuden/saison1/vostfr/",
"anime_title": "Naruto Shippuden",
"lang": "vostfr",
"quality_preference": "1080p",
"auto_download": true
}
Security
- Optional HMAC SHA256 signature verification
- Configure secret in both Sonarr and Ohm Stream Downloader
- Enable with
verify_hmac: truein config
Testing
- Test endpoint:
POST /api/webhook/test/sonarr - Manual trigger:
POST /api/sonarr/download - Get suggestions:
GET /api/sonarr/suggest?sonarr_title={title}
Documentation: See docs/SONARR_INTEGRATION.md for complete setup guide.
Adding New Anime Provider
To add a new anime streaming provider:
- Create downloader inheriting from
BaseDownloader - Implement anime-specific methods:
search_anime(query, lang)- Return list of anime with title, url, cover_imageget_episodes(anime_url, lang)- Return list of episodesget_anime_metadata(anime_url)- Return metadata dict
- Add to
ANIME_PROVIDERSinapp/providers.py - Add to factory in
app/downloaders/__init__.py - Update
main.pyto include in unified search
Metadata should include:
- synopsis, genres, rating, release_year, studio, poster_image, total_episodes, status
Configuration
Edit main.py to configure:
max_parallel- Maximum concurrent downloads (default: 3)download_dir- Storage location (default: "downloads")
Configuration Files:
config/sonarr.json- Sonarr webhook configuration (created automatically)config/sonarr_mappings.json- Sonarr to anime provider mappings (created automatically)config/.gitkeep- Ensures config directory is tracked in git- Example files:
config/sonarr.example.json,config/sonarr_mappings.example.json
Documentation:
README.md- User-facing features and roadmapCLAUDE.md- This file (developer guide)docs/SONARR_INTEGRATION.md- Complete Sonarr setup guidedocs/SONARR_IMPLEMENTATION.md- Technical implementation summary
Key Implementation Details
Resume Support:
- Downloads use HTTP Range headers to resume from last byte
- Files downloaded in 1MB chunks
- Partial files cleaned up on cancel
- Resume position tracked in
downloaded_bytesfield
Domain Handling:
- Anime providers use dynamic domain detection (e.g., Anime-Sama fetches current domain from anime-sama.pw)
- Multiple domains per provider supported in configuration
- Domain detection via
detect_provider_from_url(url)in providers.py
Task Lifecycle:
- PENDING → DOWNLOADING → PAUSED / COMPLETED / CANCELLED / FAILED
- Active downloads tracked in
active_downloadsdict - All tasks stored in
tasksdict with UUID keys - Completed files preserved when deleting tasks (only partial files removed)
Video Streaming:
- Range header support for seeking in video player
- Serves from
/downloadsdirectory via StaticFiles - Video extensions: .mp4, .mkv, .avi, .mov, .wmv, .flv, .webm
Error Handling:
- Graceful degradation with status tracking
- Network errors caught and reported in task status
- Automatic retry on resume
- Downloads > 1MB considered complete to skip small error files
Dependencies
Core:
- fastapi - Web framework
- uvicorn - ASGI server
- httpx - Async HTTP client
- beautifulsoup4, lxml - HTML parsing
- aiofiles - Async file operations
- jieba - Chinese text segmentation for fuzzy search
Testing:
- pytest - Test framework
- pytest-asyncio - Async test support
- pytest-cov - Coverage reporting
- pytest-mock - Mocking support