Add category filtering, default to copy mode, split dev/prod compose
- Default MOVE_MODE changed to copy so qBit can continue seeding - Add QBIT_CATEGORY env var (default "Stash") to filter torrents - Split compose into dev (build from source) and prod (pre-built image) - Fix Dockerfile COPY glob needing trailing slash - Update README and summary docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+6
-4
@@ -4,7 +4,7 @@
|
||||
|
||||
## Purpose
|
||||
|
||||
StashHandler sits between qBittorrent and Stash (both running in Docker). It polls qBit's API for completed torrents, hashes media files, deduplicates them via a SQLite database, and moves new files into Stash's import directory.
|
||||
StashHandler sits between qBittorrent and Stash (both running in Docker). It polls qBit's API for completed torrents filtered by category, hashes media files, deduplicates them via a SQLite database, and copies new files into Stash's import directory (preserving originals for continued seeding).
|
||||
|
||||
**Problems solved:**
|
||||
1. Deleted files in Stash don't get reimported (hash DB remembers them)
|
||||
@@ -33,7 +33,8 @@ Designed for Docker Swarm — no host-local config files, everything via env var
|
||||
| `hasher.py` | Streaming file hashing (sha256 default, blake3 optional) in 64KB chunks |
|
||||
| `qbit_client.py` | qBittorrent API client — login, session cookies, auto re-auth on 403 |
|
||||
| `Dockerfile` | python:3.12-slim, entrypoint is `stash_handler.py`, default command `daemon` |
|
||||
| `docker-compose.yaml` | Example compose with stash-handler, qbittorrent, stash services |
|
||||
| `docker-compose.yaml` | Dev compose — builds from source, includes qbittorrent + stash, DEBUG logging |
|
||||
| `docker-compose.prod.example.yaml` | Prod compose template — pulls from `git.fabledsword.com/bvandeusen/stashhandler:latest`, stash-handler only |
|
||||
| `requirements.txt` | `requests` (only dependency) |
|
||||
|
||||
## Modes of Operation
|
||||
@@ -44,7 +45,7 @@ docker run stash-handler
|
||||
# or: python stash_handler.py daemon
|
||||
```
|
||||
- Polls qBit API at `POLL_INTERVAL` seconds
|
||||
- Fetches completed torrents via `/api/v2/torrents/info?filter=completed`
|
||||
- Fetches completed torrents via `/api/v2/torrents/info?filter=completed&category=<QBIT_CATEGORY>`
|
||||
- Skips already-processed torrents (by info_hash in `processed_torrents` table)
|
||||
- For each new torrent: walks media files, hashes, deduplicates, transfers new files to import dir
|
||||
- Clean shutdown on SIGINT/SIGTERM (1-second sleep granularity)
|
||||
@@ -71,7 +72,8 @@ docker exec stash-handler python stash_handler.py scan [--import] [path]
|
||||
| `POLL_INTERVAL` | `60` | Seconds between qBit API polls |
|
||||
| `MEDIA_EXTENSIONS` | `.mp4,.mkv,.avi,.wmv,.mov,.webm,.flv,.m4v` | Comma-separated list of media file extensions |
|
||||
| `HASH_ALGORITHM` | `sha256` | Hash algorithm (`sha256` or `blake3`) |
|
||||
| `MOVE_MODE` | `move` | File transfer mode: `move`, `hardlink`, or `copy` |
|
||||
| `MOVE_MODE` | `copy` | File transfer mode: `copy`, `hardlink`, or `move` |
|
||||
| `QBIT_CATEGORY` | `Stash` | qBit category to filter torrents by (shared qBit instance support) |
|
||||
| `LOG_LEVEL` | `INFO` | Python logging level |
|
||||
|
||||
## Database Schema
|
||||
|
||||
Reference in New Issue
Block a user