mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-02 20:30:10 +00:00
Add multi-download-client support and UI management
Implements support for configuring both qBittorrent and SABnzbd simultaneously, including migration from legacy config, protocol-aware routing, and protocol filtering. Adds new CRUD API routes for download clients, new UI management components, and updates setup and settings flows to use the new multi-client architecture. Updates documentation to describe the new structure and usage.
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
- **Full pipeline overview** → [phase3/README.md](phase3/README.md)
|
||||
- **Search via Prowlarr (torrents + NZBs)** → [phase3/prowlarr.md](phase3/prowlarr.md)
|
||||
- **Torrent ranking/selection** → [phase3/ranking-algorithm.md](phase3/ranking-algorithm.md)
|
||||
- **Multi-download-client support (qBittorrent + SABnzbd)** → [phase3/download-clients.md](phase3/download-clients.md)
|
||||
- **qBittorrent integration (torrents)** → [phase3/qbittorrent.md](phase3/qbittorrent.md)
|
||||
- **SABnzbd integration (Usenet/NZB)** → [phase3/sabnzbd.md](phase3/sabnzbd.md)
|
||||
- **File organization, seeding** → [phase3/file-organization.md](phase3/file-organization.md)
|
||||
@@ -102,8 +103,10 @@
|
||||
|
||||
## Feature-Specific Lookups
|
||||
**"How do I add a new audiobook?"** → [integrations/audible.md](integrations/audible.md) (scraping), [phase3/README.md](phase3/README.md) (automation)
|
||||
**"How do I configure multiple download clients?"** → [phase3/download-clients.md](phase3/download-clients.md)
|
||||
**"How do torrent downloads work?"** → [phase3/qbittorrent.md](phase3/qbittorrent.md), [backend/services/jobs.md](backend/services/jobs.md)
|
||||
**"How do Usenet/NZB downloads work?"** → [phase3/sabnzbd.md](phase3/sabnzbd.md), [backend/services/jobs.md](backend/services/jobs.md)
|
||||
**"Can I use both qBittorrent and SABnzbd?"** → [phase3/download-clients.md](phase3/download-clients.md)
|
||||
**"How does Plex matching work?"** → [integrations/plex.md](integrations/plex.md)
|
||||
**"How does e-book sidecar work?"** → [integrations/ebook-sidecar.md](integrations/ebook-sidecar.md)
|
||||
**"How do I enable e-book downloads?"** → [integrations/ebook-sidecar.md](integrations/ebook-sidecar.md), [settings-pages.md](settings-pages.md)
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
# Multi-Download-Client Support
|
||||
|
||||
**Status:** ✅ Implemented | Simultaneous qBittorrent + SABnzbd support
|
||||
|
||||
## Overview
|
||||
Users can configure both qBittorrent (torrents) and SABnzbd (Usenet) simultaneously. System selects best release across all indexer types regardless of protocol.
|
||||
|
||||
**Constraint:** 1 client per type (torrent/usenet) for now; architecture supports future expansion.
|
||||
|
||||
## Key Details
|
||||
|
||||
### Configuration Structure
|
||||
**Key:** `download_clients` (JSON array, replaces legacy flat keys)
|
||||
|
||||
```typescript
|
||||
interface DownloadClientConfig {
|
||||
id: string; // UUID
|
||||
type: 'qbittorrent' | 'sabnzbd';
|
||||
name: string; // User-friendly name
|
||||
enabled: boolean;
|
||||
url: string;
|
||||
username?: string; // qBittorrent only
|
||||
password: string; // Password or API key
|
||||
disableSSLVerify: boolean;
|
||||
remotePathMappingEnabled: boolean;
|
||||
remotePath?: string;
|
||||
localPath?: string;
|
||||
category?: string; // Default: 'readmeabook'
|
||||
}
|
||||
```
|
||||
|
||||
### Download Client Manager Service
|
||||
**File:** `src/lib/services/download-client-manager.service.ts`
|
||||
|
||||
**Methods:**
|
||||
- `getClientForProtocol(protocol: 'torrent' | 'usenet')` - Get client by protocol
|
||||
- `hasClientForProtocol(protocol)` - Check if protocol configured
|
||||
- `getAllClients()` - List all configs
|
||||
- `testConnection(config)` - Test specific config
|
||||
- `invalidate()` - Clear cache on config change
|
||||
- `getClientServiceForProtocol(protocol)` - Get instantiated service
|
||||
|
||||
**Singleton Pattern:** Uses caching with invalidation on config changes.
|
||||
|
||||
### Protocol Filtering
|
||||
**File:** `src/lib/integrations/prowlarr.service.ts:379`
|
||||
|
||||
**Logic:**
|
||||
- Both clients configured: Return all results (mixed torrent + NZB)
|
||||
- Only torrent client: Filter for torrent results only
|
||||
- Only usenet client: Filter for NZB results only
|
||||
- No clients: Return empty
|
||||
|
||||
### Download Routing
|
||||
**File:** `src/lib/processors/download-torrent.processor.ts:44`
|
||||
|
||||
**Logic:**
|
||||
1. Detect protocol from result (`ProwlarrService.isNZBResult()`)
|
||||
2. Get appropriate client via manager (`getClientForProtocol()`)
|
||||
3. Route to qBittorrent or SABnzbd service
|
||||
4. Create download history record
|
||||
|
||||
### Migration
|
||||
**Auto-migration** from legacy single-client config to new JSON array format on first access:
|
||||
- Reads legacy keys: `download_client_type`, `download_client_url`, etc.
|
||||
- Converts to single-client array
|
||||
- Saves as `download_clients` JSON
|
||||
- Legacy keys remain for backward compatibility (cleaned up on migration)
|
||||
|
||||
## API Routes
|
||||
|
||||
**GET /api/admin/settings/download-clients** - List all configured clients
|
||||
**POST /api/admin/settings/download-clients** - Add new client
|
||||
**PUT /api/admin/settings/download-clients/[id]** - Update client by ID
|
||||
**DELETE /api/admin/settings/download-clients/[id]** - Delete client by ID
|
||||
**POST /api/admin/settings/download-clients/test** - Test connection
|
||||
|
||||
**Validation:**
|
||||
- Only 1 client per type allowed (enforced on add)
|
||||
- Test connection required before save
|
||||
- Password masking in responses (`********`)
|
||||
|
||||
## UI Components
|
||||
|
||||
**Directory:** `src/components/admin/download-clients/`
|
||||
|
||||
| Component | Purpose |
|
||||
|-----------|---------|
|
||||
| `DownloadClientManagement.tsx` | Container with add buttons + configured cards |
|
||||
| `DownloadClientCard.tsx` | Card with name, type badge, edit/delete |
|
||||
| `DownloadClientModal.tsx` | Add/edit modal with type-specific fields |
|
||||
|
||||
**UI Flow:**
|
||||
1. **Add Client Section:** Two cards (qBittorrent, SABnzbd) with "Add" button or "Already configured" badge
|
||||
2. **Configured Clients:** Grid of cards showing name, type, URL, status
|
||||
3. **Modal:** Type-specific fields, SSL toggle, path mapping, test connection
|
||||
|
||||
## Integration Points
|
||||
|
||||
### Settings Tab
|
||||
**File:** `src/app/admin/settings/tabs/DownloadTab/DownloadTab.tsx`
|
||||
|
||||
Replaced legacy form with `<DownloadClientManagement mode="settings" />`
|
||||
|
||||
### Wizard Step
|
||||
**File:** `src/app/setup/steps/DownloadClientStep.tsx`
|
||||
|
||||
Replaced single-client form with `<DownloadClientManagement mode="wizard" />`
|
||||
|
||||
**Validation:** At least 1 enabled client required to proceed
|
||||
|
||||
### Setup Complete API
|
||||
**File:** `src/app/api/setup/complete/route.ts`
|
||||
|
||||
Accepts both legacy single client and new array format:
|
||||
- Legacy: Converts to array on save
|
||||
- New: Saves directly as `download_clients` JSON
|
||||
|
||||
## Edge Cases
|
||||
|
||||
**Single client:** Works exactly as before (protocol filtering active)
|
||||
**No clients:** Wizard requires one; settings shows warning
|
||||
**Client disabled:** Results for that protocol filtered out
|
||||
**Connection failure:** Per-download error handling (existing)
|
||||
**Mixed results:** Best release selected regardless of protocol when both clients configured
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. **Migration:** Existing single-client users see config as card after update
|
||||
2. **Single client:** Configure only qBittorrent → only torrent results shown
|
||||
3. **Both clients:** Configure both → mixed results, best selected across protocols
|
||||
4. **Download routing:** Torrent result → qBittorrent; NZB result → SABnzbd
|
||||
5. **Wizard:** Must add at least one client to proceed
|
||||
6. **Settings:** Can add/edit/delete/test clients; changes persist
|
||||
|
||||
## Critical Files
|
||||
|
||||
| File | Changes |
|
||||
|------|---------|
|
||||
| `src/lib/services/download-client-manager.service.ts` | **NEW** - Core multi-client service |
|
||||
| `src/lib/integrations/prowlarr.service.ts:379` | Protocol filtering logic (both clients = all results) |
|
||||
| `src/lib/processors/download-torrent.processor.ts:44` | Download routing (detect protocol → route) |
|
||||
| `src/app/api/admin/settings/download-clients/*` | **NEW** - CRUD API routes |
|
||||
| `src/components/admin/download-clients/*` | **NEW** - UI components (card-based) |
|
||||
| `src/app/admin/settings/tabs/DownloadTab/DownloadTab.tsx` | Replaced with management component |
|
||||
| `src/app/setup/steps/DownloadClientStep.tsx` | Replaced with management component |
|
||||
| `src/app/api/setup/complete/route.ts` | Save as JSON array, support legacy |
|
||||
|
||||
## Related
|
||||
|
||||
- [qBittorrent Integration](./qbittorrent.md) - Torrent client details
|
||||
- [SABnzbd Integration](./sabnzbd.md) - Usenet client details
|
||||
- [Prowlarr Integration](./prowlarr.md) - Indexer search
|
||||
Reference in New Issue
Block a user