feat: Complete Sonarr integration with security enhancements
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>
This commit is contained in:
@@ -0,0 +1,484 @@
|
||||
# Sonarr Integration Guide
|
||||
|
||||
This guide explains how to integrate Ohm Stream Downloader with Sonarr for automatic anime downloads.
|
||||
|
||||
## Overview
|
||||
|
||||
The Sonarr integration allows you to automatically download anime episodes when Sonarr grabs new releases. This is done through webhooks that Sonarr sends when events occur.
|
||||
|
||||
## Features
|
||||
|
||||
- **Automatic Downloads**: Trigger anime downloads when Sonarr grabs episodes
|
||||
- **Series Mapping**: Map Sonarr series to anime providers (Anime-Sama, Neko-Sama, etc.)
|
||||
- **Quality Selection**: Download specific qualities (1080p, 720p, etc.)
|
||||
- **Language Support**: Choose between VOSTFR and VF versions
|
||||
- **HMAC Security**: Optional webhook signature verification
|
||||
- **Manual Trigger**: Manually trigger downloads using Sonarr information
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Configure Sonarr Webhook
|
||||
|
||||
1. Open Sonarr web interface
|
||||
2. Go to **Settings** > **Connect** > **+**
|
||||
3. Select **Sonarr** as the type
|
||||
4. Configure the webhook:
|
||||
- **Name**: Ohm Stream Downloader
|
||||
- **URL**: `http://your-server:3000/api/webhook/sonarr`
|
||||
- **Events**: Select which events to trigger (typically "Grab")
|
||||
5. (Optional) Add a HMAC secret for security
|
||||
6. Click **Test** to verify connectivity
|
||||
7. Save the configuration
|
||||
|
||||
### 2. Configure Ohm Stream Downloader
|
||||
|
||||
Use the API to configure Sonarr integration:
|
||||
|
||||
```bash
|
||||
# Enable webhooks and auto-download
|
||||
curl -X PUT http://localhost:3000/api/sonarr/config \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"webhook_enabled": true,
|
||||
"webhook_secret": "your-secret-key",
|
||||
"auto_download_enabled": true,
|
||||
"default_language": "vostfr",
|
||||
"default_quality": "1080p",
|
||||
"default_provider": "anime-sama",
|
||||
"verify_hmac": true,
|
||||
"log_webhooks": true
|
||||
}'
|
||||
```
|
||||
|
||||
### 3. Create Series Mappings
|
||||
|
||||
For each series you want to auto-download, create a mapping between Sonarr and the anime provider:
|
||||
|
||||
```bash
|
||||
# Search for anime
|
||||
curl http://localhost:3000/api/sonarr/search?q=naruto&provider=anime-sama&lang=vostfr
|
||||
|
||||
# Create mapping
|
||||
curl -X POST http://localhost:3000/api/sonarr/mappings \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"sonarr_series_id": 12345,
|
||||
"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
|
||||
}'
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Configuration
|
||||
|
||||
#### Get Configuration
|
||||
```http
|
||||
GET /api/sonarr/config
|
||||
```
|
||||
|
||||
Returns the current Sonarr configuration.
|
||||
|
||||
#### Update Configuration
|
||||
```http
|
||||
PUT /api/sonarr/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"webhook_enabled": true,
|
||||
"webhook_secret": "optional-secret",
|
||||
"auto_download_enabled": true,
|
||||
"default_language": "vostfr",
|
||||
"default_quality": "1080p",
|
||||
"default_provider": "anime-sama",
|
||||
"verify_hmac": false,
|
||||
"log_webhooks": true
|
||||
}
|
||||
```
|
||||
|
||||
### Mappings
|
||||
|
||||
#### Get All Mappings
|
||||
```http
|
||||
GET /api/sonarr/mappings
|
||||
```
|
||||
|
||||
Returns all Sonarr to anime mappings.
|
||||
|
||||
#### Get Specific Mapping
|
||||
```http
|
||||
GET /api/sonarr/mappings/{series_id}
|
||||
```
|
||||
|
||||
#### Create/Update Mapping
|
||||
```http
|
||||
POST /api/sonarr/mappings
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"sonarr_series_id": 12345,
|
||||
"sonarr_title": "Series Name",
|
||||
"anime_provider": "anime-sama",
|
||||
"anime_url": "https://anime-sama.si/catalogue/anime/saison1/vostfr/",
|
||||
"anime_title": "Anime Title",
|
||||
"lang": "vostfr",
|
||||
"quality_preference": "1080p",
|
||||
"auto_download": true
|
||||
}
|
||||
```
|
||||
|
||||
#### Delete Mapping
|
||||
```http
|
||||
DELETE /api/sonarr/mappings/{series_id}
|
||||
```
|
||||
|
||||
### Search & Discovery
|
||||
|
||||
#### Search Anime
|
||||
```http
|
||||
GET /api/sonarr/search?q=naruto&provider=anime-sama&lang=vostfr
|
||||
```
|
||||
|
||||
Search for anime on providers to find the correct URL for mapping.
|
||||
|
||||
#### Get Episodes
|
||||
```http
|
||||
GET /api/sonarr/episodes?url={anime_url}&provider=anime-sama&lang=vostfr
|
||||
```
|
||||
|
||||
Get episode list for an anime.
|
||||
|
||||
#### Suggest Mappings
|
||||
```http
|
||||
GET /api/sonarr/suggest?sonarr_title=Naruto&provider=anime-sama&lang=vostfr
|
||||
```
|
||||
|
||||
Get suggested anime matches based on Sonarr title with similarity scores.
|
||||
|
||||
### Webhooks
|
||||
|
||||
#### Main Webhook Endpoint
|
||||
```http
|
||||
POST /api/webhook/sonarr
|
||||
X-Sonarr-Event: sha256=signature
|
||||
```
|
||||
|
||||
Receives webhooks from Sonarr.
|
||||
|
||||
#### Test Webhook
|
||||
```http
|
||||
POST /api/webhook/test/sonarr
|
||||
```
|
||||
|
||||
Test endpoint for verifying webhook connectivity.
|
||||
|
||||
### Manual Download
|
||||
|
||||
#### Trigger Download
|
||||
```http
|
||||
POST /api/sonarr/download
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"sonarr_series_id": 12345,
|
||||
"sonarr_title": "Naruto Shippuden",
|
||||
"season_number": 1,
|
||||
"episode_number": 1,
|
||||
"quality": "1080p",
|
||||
"lang": "vostfr",
|
||||
"provider": "anime-sama"
|
||||
}
|
||||
```
|
||||
|
||||
Manually trigger a download using Sonarr series information.
|
||||
|
||||
## Workflow
|
||||
|
||||
### Automatic Download Flow
|
||||
|
||||
1. Sonarr grabs a new episode
|
||||
2. Sonarr sends webhook to Ohm Stream Downloader
|
||||
3. Ohm Stream Downloader receives webhook and verifies HMAC (if enabled)
|
||||
4. System looks up mapping for the series
|
||||
5. If mapping exists and auto_download is enabled:
|
||||
- Finds the matching episode on the anime provider
|
||||
- Creates a download task
|
||||
- Starts the download
|
||||
6. Returns response to Sonarr
|
||||
|
||||
### Manual Setup Flow
|
||||
|
||||
1. **Find Sonarr Series ID**:
|
||||
- Go to Sonarr web interface
|
||||
- Open series details
|
||||
- Find the TVDB ID in the series information
|
||||
|
||||
2. **Search for Anime**:
|
||||
```bash
|
||||
curl "http://localhost:3000/api/sonarr/search?q=Series+Name&provider=anime-sama&lang=vostfr"
|
||||
```
|
||||
|
||||
3. **Get Episodes** (optional, to verify):
|
||||
```bash
|
||||
curl "http://localhost:3000/api/sonarr/episodes?url={anime_url}&provider=anime-sama&lang=vostfr"
|
||||
```
|
||||
|
||||
4. **Create Mapping**:
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/sonarr/mappings \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"sonarr_series_id": 12345,
|
||||
"sonarr_title": "Series Name",
|
||||
"anime_provider": "anime-sama",
|
||||
"anime_url": "https://anime-sama.si/catalogue/series/saison1/vostfr/",
|
||||
"anime_title": "Anime Title",
|
||||
"lang": "vostfr"
|
||||
}'
|
||||
```
|
||||
|
||||
5. **Test with Manual Trigger**:
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/sonarr/download \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"sonarr_series_id": 12345,
|
||||
"season_number": 1,
|
||||
"episode_number": 1
|
||||
}'
|
||||
```
|
||||
|
||||
## Supported Providers
|
||||
|
||||
- **anime-sama**: Primary anime provider
|
||||
- **neko-sama**: Alternative anime provider
|
||||
- **anime-ultime**: French anime provider
|
||||
- **vostfree**: VOSTFR anime provider
|
||||
|
||||
## Event Types
|
||||
|
||||
Sonarr sends different event types:
|
||||
|
||||
- **Grab**: Triggered when Sonarr downloads a release (use this for auto-downloads)
|
||||
- **Download**: Triggered when download is completed
|
||||
- **Rename**: Triggered when files are renamed
|
||||
- **Delete**: Triggered when series/episodes are deleted
|
||||
- **Test**: Test webhook from Sonarr
|
||||
|
||||
## Security
|
||||
|
||||
### HMAC Verification
|
||||
|
||||
For enhanced security, enable HMAC verification:
|
||||
|
||||
1. Generate a secret key:
|
||||
```bash
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
2. Configure in both Sonarr and Ohm Stream Downloader:
|
||||
- Sonarr: Add the secret to webhook configuration
|
||||
- Ohm Stream Downloader: Set `webhook_secret` and `verify_hmac: true`
|
||||
|
||||
3. The webhook will verify all incoming requests using HMAC SHA256
|
||||
|
||||
### Recommendations
|
||||
|
||||
- Use HTTPS in production
|
||||
- Keep webhook secret secure
|
||||
- Monitor webhook logs
|
||||
- Use network restrictions to limit access
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Webhook Not Received
|
||||
|
||||
1. Check Ohm Stream Downloader logs:
|
||||
```bash
|
||||
tail -f logs/app.log | grep webhook
|
||||
```
|
||||
|
||||
2. Verify webhook is enabled:
|
||||
```bash
|
||||
curl http://localhost:3000/api/sonarr/config
|
||||
```
|
||||
|
||||
3. Test webhook from Sonarr:
|
||||
- Use Sonarr's test button
|
||||
- Check `/api/webhook/test/sonarr` endpoint
|
||||
|
||||
### Mapping Not Found
|
||||
|
||||
1. Check mapping exists:
|
||||
```bash
|
||||
curl http://localhost:3000/api/sonarr/mappings/{series_id}
|
||||
```
|
||||
|
||||
2. Verify series ID matches Sonarr TVDB ID
|
||||
|
||||
3. Check logs for error messages
|
||||
|
||||
### Episode Not Found
|
||||
|
||||
1. Verify anime URL is correct:
|
||||
```bash
|
||||
curl "http://localhost:3000/api/sonarr/episodes?url={url}&provider=anime-sama&lang=vostfr"
|
||||
```
|
||||
|
||||
2. Check episode number matches
|
||||
3. Verify season/episode format (Sonarr uses absolute numbering)
|
||||
|
||||
### Download Not Starting
|
||||
|
||||
1. Check download manager:
|
||||
```bash
|
||||
curl http://localhost:3000/api/downloads
|
||||
```
|
||||
|
||||
2. Verify auto-download is enabled:
|
||||
```bash
|
||||
curl http://localhost:3000/api/sonarr/config
|
||||
```
|
||||
|
||||
3. Check mapping has `auto_download: true`
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Setup Naruto Shippuden
|
||||
|
||||
```bash
|
||||
# 1. Search for Naruto Shippuden
|
||||
curl "http://localhost:3000/api/sonarr/search?q=naruto+shippuden&provider=anime-sama&lang=vostfr"
|
||||
|
||||
# 2. Create mapping (using TVDB ID 79644)
|
||||
curl -X POST http://localhost:3000/api/sonarr/mappings \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"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
|
||||
}'
|
||||
|
||||
# 3. Test with manual download
|
||||
curl -X POST http://localhost:3000/api/sonarr/download \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"sonarr_series_id": 79644,
|
||||
"season_number": 1,
|
||||
"episode_number": 1
|
||||
}'
|
||||
```
|
||||
|
||||
### Example 2: Enable with Security
|
||||
|
||||
```bash
|
||||
# Generate secret
|
||||
SECRET=$(openssl rand -hex 32)
|
||||
|
||||
# Configure Ohm Stream Downloader
|
||||
curl -X PUT http://localhost:3000/api/sonarr/config \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"webhook_enabled\": true,
|
||||
\"webhook_secret\": \"$SECRET\",
|
||||
\"verify_hmac\": true,
|
||||
\"auto_download_enabled\": true,
|
||||
\"log_webhooks\": true
|
||||
}"
|
||||
|
||||
# Use same secret in Sonarr webhook configuration
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Custom Provider Configuration
|
||||
|
||||
You can specify different providers per mapping:
|
||||
|
||||
```json
|
||||
{
|
||||
"sonarr_series_id": 12345,
|
||||
"sonarr_title": "One Piece",
|
||||
"anime_provider": "neko-sama",
|
||||
"anime_url": "https://neko-sama.fr/anime/one-piece",
|
||||
"anime_title": "One Piece",
|
||||
"lang": "vostfr",
|
||||
"quality_preference": "1080p"
|
||||
}
|
||||
```
|
||||
|
||||
### Multiple Languages
|
||||
|
||||
Create separate mappings for different languages:
|
||||
|
||||
```bash
|
||||
# VOSTFR version
|
||||
curl -X POST http://localhost:3000/api/sonarr/mappings \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"sonarr_series_id": 12345,
|
||||
"sonarr_title": "Anime Name",
|
||||
"anime_provider": "anime-sama",
|
||||
"anime_url": "https://anime-sama.si/catalogue/anime/saison1/vostfr/",
|
||||
"anime_title": "Anime Name VOSTFR",
|
||||
"lang": "vostfr"
|
||||
}'
|
||||
|
||||
# VF version
|
||||
curl -X POST http://localhost:3000/api/sonarr/mappings \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"sonarr_series_id": 12346,
|
||||
"sonarr_title": "Anime Name",
|
||||
"anime_provider": "anime-sama",
|
||||
"anime_url": "https://anime-sama.si/catalogue/anime/saison1/vf/",
|
||||
"anime_title": "Anime Name VF",
|
||||
"lang": "vf"
|
||||
}'
|
||||
```
|
||||
|
||||
## Configuration Files
|
||||
|
||||
Configuration is stored in `config/sonarr.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"webhook_enabled": true,
|
||||
"webhook_secret": "your-secret-key",
|
||||
"auto_download_enabled": true,
|
||||
"default_language": "vostfr",
|
||||
"default_quality": "1080p",
|
||||
"default_provider": "anime-sama",
|
||||
"verify_hmac": true,
|
||||
"log_webhooks": true
|
||||
}
|
||||
```
|
||||
|
||||
Mappings are stored in `config/sonarr_mappings.json`:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"sonarr_series_id": 12345,
|
||||
"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,
|
||||
"created_at": "2024-01-01T00:00:00",
|
||||
"updated_at": "2024-01-01T00:00:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
Reference in New Issue
Block a user