Introduces SABnzbd as a supported download client for Usenet/NZB alongside qBittorrent, including service implementation, setup wizard and admin settings UI updates, and protocol-specific job processor logic. Updates documentation, PRD, and database schema to support NZB downloads, adds comprehensive technical details and testing strategies, and fixes Audible integration issues related to search and ASIN extraction.
7.2 KiB
SABnzbd Integration
Status: ✅ Implemented
Free, open-source Usenet/NZB download client with comprehensive Web API. Industry standard for automation workflows.
Key Features
- Protocol: Usenet/NZB downloads (not torrents)
- Post-Processing: Automatic par2 repair, rar/zip extraction, cleanup
- Category Support: Per-category download paths
- API: RESTful JSON API with API key authentication
- Status: No hash extraction needed (NZB ID returned immediately)
API Endpoints
Base: http://sabnzbd:8080/api
Auth: API key parameter (apikey={key})
Format: All requests use output=json for JSON responses
GET /api?mode=version&output=json&apikey={key} - Get SABnzbd version GET /api?mode=addurl&name={url}&cat={category}&output=json&apikey={key} - Add NZB by URL GET /api?mode=queue&output=json&apikey={key} - Get active downloads GET /api?mode=history&limit=100&output=json&apikey={key} - Get completed/failed downloads GET /api?mode=pause&value={nzbId}&output=json&apikey={key} - Pause download GET /api?mode=resume&value={nzbId}&output=json&apikey={key} - Resume download GET /api?mode=queue&name=delete&value={nzbId}&del_files={0|1}&output=json&apikey={key} - Delete download GET /api?mode=get_config&output=json&apikey={key} - Get configuration (categories) GET /api?mode=set_config§ion=categories&keyword={cat}&value={path}&output=json&apikey={key} - Create/update category
Config
Required (database only, no env fallbacks):
download_client_type- Must be 'sabnzbd'download_client_url- SABnzbd Web UI URL (supports HTTP and HTTPS)download_client_password- API key (reuses password field)download_dir- Download save path (passed to SABnzbd category)
Optional (SSL/TLS):
download_client_disable_ssl_verify- Disable SSL certificate verification (boolean as string "true"/"false", default: "false")- Use when connecting to SABnzbd with self-signed certificates
- ⚠️ Security warning: Only use on trusted private networks
Optional (Remote Path Mapping):
download_client_remote_path_mapping_enabled- Enable path mapping (boolean)download_client_remote_path- Remote path prefix from SABnzbddownload_client_local_path- Local path prefix for ReadMeABook
Optional (SABnzbd-specific):
sabnzbd_category- Category name (default: 'readmeabook')
Validation: All required fields checked before service initialization. Path mapping fields validated when enabled.
Singleton Invalidation: Service uses singleton pattern. When settings change, singleton invalidated to force reload:
invalidateSABnzbdService()called after updating settings- Forces service to re-read database config
- Ensures category and credentials are always current
Category Management
Category: readmeabook (auto-created for all downloads)
Save Path Synchronization:
- Category created on first download if not exists
- Category path set to
download_dirconfig value - Unlike qBittorrent, SABnzbd categories are less frequently updated (set once at creation)
Post-Processing
Automatic (Built-in SABnzbd Features):
- Par2 Repair: Verifies and repairs damaged downloads
- Archive Extraction: Extracts .rar, .zip, .7z archives automatically
- Cleanup: Deletes .par2, .nfo, .nzb files after extraction
- Result:
downloadPathpoints to extracted directory (ready for file organizer)
Configuration: Post-processing level set to pp=3 (Repair + Unpack + Delete) on all downloads
Data Models
interface NZBInfo {
nzbId: string; // SABnzbd NZB ID
name: string;
size: number; // bytes
progress: number; // 0.0-1.0
status: NZBStatus;
downloadSpeed: number; // bytes/s
timeLeft: number; // seconds
category: string;
downloadPath?: string; // Available after completion
completedAt?: Date;
errorMessage?: string;
}
type NZBStatus = 'downloading' | 'queued' | 'paused' | 'extracting' | 'completed' | 'failed' | 'repairing';
interface QueueItem {
nzbId: string;
name: string;
size: number; // MB
sizeLeft: number; // MB
percentage: number; // 0-100
status: string; // "Downloading", "Paused", "Queued"
timeLeft: string; // "0:15:30" format
category: string;
priority: string;
}
interface HistoryItem {
nzbId: string;
name: string;
category: string;
status: string; // "Completed", "Failed"
bytes: string; // Size in bytes (as string)
failMessage: string;
storage: string; // Download path
completedTimestamp: string; // Unix timestamp
downloadTime: string; // Seconds
}
NZB ID vs Torrent Hash
Key Difference: SABnzbd returns NZB ID immediately (no extraction needed)
qBittorrent:
- Returns "Ok." without hash
- Requires parsing magnet link or .torrent file
- Hash extraction needed for tracking
SABnzbd:
- Returns
nzo_idsarray immediately - NZB ID format:
SABnzbd_nzo_abc123xyz - No extraction needed, can track immediately
Database Storage:
- qBittorrent:
torrent_hashfield - SABnzbd:
nzb_idfield (new) - Both nullable, exactly one must be set
Status Tracking
Queue vs History:
- Queue: Active downloads (downloading, queued, paused)
- History: Completed or failed downloads
Monitoring Flow:
- Check queue for NZB ID
- If found: Parse progress, status, speed
- If not in queue: Check history
- If in history: Parse completion status or error
States:
Downloading→ Active downloadQueued→ Waiting in queuePaused→ Manually pausedExtracting/Unpacking→ Post-processing extractionRepairing/Verifying→ Post-processing par2 repairCompleted→ Successfully downloaded and extractedFailed→ Download or post-processing failed
Remote Path Mapping
Use Case: SABnzbd runs on different machine/container with different filesystem perspective.
Example Scenario:
- SABnzbd reports:
/remote/usenet/complete/Audiobook.Name - ReadMeABook needs:
/downloads/Audiobook.Name - Mapping: Remote
/remote/usenet/complete→ Local/downloads
Implementation: Same as qBittorrent (uses PathMapper utility)
Fixed Issues ✅
1. API Key Authentication - Uses apikey parameter (not username/password)
2. Immediate NZB ID - No hash extraction needed (returned by API)
3. Post-Processing Tracking - Monitors extracting/repairing states
4. Queue vs History Logic - Checks queue first, falls back to history
5. SSL Certificate Errors - Optional SSL verification disable for self-signed certs
Comparison: SABnzbd vs qBittorrent
| Feature | SABnzbd | qBittorrent |
|---|---|---|
| Protocol | Usenet/NZB | BitTorrent |
| Auth | API key only | Username + Password |
| ID Format | NZB ID (immediate) | Torrent hash (extracted) |
| Post-Processing | Automatic (par2, extraction) | None (manual) |
| Seeding | N/A (Usenet is not P2P) | Required (tracker) |
| Categories | Path-based | Path + tag-based |
| File Handling | Auto-extracts archives | Downloads as-is |
Tech Stack
- axios (HTTP client)
- Node.js https (SSL/TLS agent)
- JSON API responses
Related
- See File Organization for post-download processing
- See qBittorrent Integration for torrent alternative