mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-03 21:00:09 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# qBittorrent Integration
|
||||
|
||||
**Status:** ✅ Implemented
|
||||
|
||||
Free, open-source BitTorrent client with comprehensive Web API.
|
||||
|
||||
## Enterprise Torrent Addition
|
||||
|
||||
**Challenge:** `/api/v2/torrents/add` returns only "Ok." without torrent hash.
|
||||
|
||||
**Solution (Professional):**
|
||||
|
||||
**Magnet Links:**
|
||||
1. Extract `info_hash` from magnet URI (deterministic)
|
||||
2. Upload via `urls` parameter
|
||||
3. Return extracted hash immediately
|
||||
|
||||
**Torrent Files:**
|
||||
1. Download .torrent file to memory
|
||||
2. Parse with `parse-torrent` (bencode decoder)
|
||||
3. Extract `info_hash` (SHA-1 of info dict)
|
||||
4. Upload file content via `torrents` parameter (multipart/form-data)
|
||||
5. Return extracted hash immediately
|
||||
|
||||
**Benefits:** Deterministic, no race conditions, works with Docker networking, handles expired URLs
|
||||
|
||||
## API Endpoints
|
||||
|
||||
**Base:** `http://qbittorrent:8080/api/v2`
|
||||
**Auth:** Cookie-based (login required)
|
||||
|
||||
**POST /auth/login** - Get session cookie
|
||||
**POST /torrents/add** - Add torrent (supports `urls` and `torrents` params)
|
||||
**GET /torrents/info?hashes={hash}** - Get status/progress
|
||||
**POST /torrents/pause** - Pause torrent
|
||||
**POST /torrents/resume** - Resume
|
||||
**POST /torrents/delete** - Delete torrent
|
||||
**GET /torrents/files** - Get file list
|
||||
**POST /torrents/setCategory** - Set category
|
||||
|
||||
## Config
|
||||
|
||||
**Required (database only, no env fallbacks):**
|
||||
- `qbittorrent_url`
|
||||
- `qbittorrent_username`
|
||||
- `qbittorrent_password`
|
||||
- `paths_downloads`
|
||||
|
||||
Validation: All fields checked before service initialization.
|
||||
|
||||
## Data Models
|
||||
|
||||
```typescript
|
||||
interface TorrentInfo {
|
||||
hash: string;
|
||||
name: string;
|
||||
size: number;
|
||||
progress: number; // 0.0-1.0
|
||||
dlspeed: number; // bytes/s
|
||||
upspeed: number;
|
||||
eta: number; // seconds
|
||||
state: TorrentState;
|
||||
category: string;
|
||||
savePath: string;
|
||||
completionDate: number;
|
||||
}
|
||||
|
||||
type TorrentState = 'downloading' | 'uploading' | 'stalledDL' |
|
||||
'pausedDL' | 'queuedDL' | 'checkingDL' | 'error' | 'missingFiles';
|
||||
```
|
||||
|
||||
## Fixed Issues ✅
|
||||
|
||||
**1. Naive torrent identification** - Fixed with deterministic hash extraction
|
||||
**2. Docker networking issues** - Fixed by downloading .torrent ourselves
|
||||
**3. Duplicate detection** - Check if hash exists before adding
|
||||
**4. Config fallbacks to env** - Removed, database only
|
||||
**5. Unclear error messages** - List missing fields explicitly
|
||||
**6. Race condition on torrent availability** - Fixed with 3s initial delay + exponential backoff retry (500ms, 1s, 2s)
|
||||
**7. Error logging during duplicate check** - Removed console.error in getTorrent() during expected "not found" cases (duplicate checking)
|
||||
**8. Prowlarr magnet link redirects** - Some indexers return HTTP URLs that redirect to magnet: links. Fixed by intercepting 3xx redirects before axios follows them, extracting the Location header, and routing to magnet flow if target is a magnet: link
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- axios (HTTP + cookie mgmt)
|
||||
- parse-torrent (bencode + hash extraction)
|
||||
- form-data (multipart uploads)
|
||||
|
||||
## Related
|
||||
|
||||
- See [File Organization](./file-organization.md) for seeding support
|
||||
Reference in New Issue
Block a user