Add SABnzbd Usenet/NZB integration and documentation

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.
This commit is contained in:
kikootwo
2026-01-07 02:40:11 -05:00
parent 23881eb670
commit e008744df1
21 changed files with 2378 additions and 254 deletions
+4 -1
View File
@@ -26,13 +26,16 @@ Evaluates and scores torrents to automatically select best audiobook download.
**Stage 2: Title Matching (0-35 pts)**
- Only scored if Stage 1 passes
- **Tries full title first, then required title (without parentheses)** if no match
- Example: "We Are Legion (We Are Bob)" tries both full title and "We Are Legion"
- Handles torrents that include subtitle AND those that omit it
- Complete title match requirements (both must be true):
- No significant words BEFORE matched title (prevents "This Inevitable Ruin Dungeon Crawler Carl, Book 7")
- Followed by metadata markers: " by", " [", " -", " (", " {", " :", ","
- Complete match → 35 pts
- Title has prefix/suffix words OR continues with more words → fuzzy similarity (partial credit)
- Prevents series confusion: "The Housemaid" vs "The Housemaid's Secret", "Dungeon Crawler Carl" vs "Book 7"
- No substring match → fuzzy similarity (partial credit)
- No substring match → fuzzy similarity (best score from full or required title)
**Stage 3: Author Matching (0-15 pts)**
- Exact substring match → proportional credit
+203
View File
@@ -0,0 +1,203 @@
# 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&section=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 SABnzbd
- `download_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_dir` config 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:** `downloadPath` points to extracted directory (ready for file organizer)
**Configuration:** Post-processing level set to `pp=3` (Repair + Unpack + Delete) on all downloads
## Data Models
```typescript
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_ids` array immediately
- NZB ID format: `SABnzbd_nzo_abc123xyz`
- No extraction needed, can track immediately
**Database Storage:**
- qBittorrent: `torrent_hash` field
- SABnzbd: `nzb_id` field (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:**
1. Check queue for NZB ID
2. If found: Parse progress, status, speed
3. If not in queue: Check history
4. If in history: Parse completion status or error
**States:**
- `Downloading` → Active download
- `Queued` → Waiting in queue
- `Paused` → Manually paused
- `Extracting/Unpacking` → Post-processing extraction
- `Repairing/Verifying` → Post-processing par2 repair
- `Completed` → Successfully downloaded and extracted
- `Failed` → 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](./file-organization.md) for post-download processing
- See [qBittorrent Integration](./qbittorrent.md) for torrent alternative