Files

123 lines
7.1 KiB
Markdown

# Project Context & System Architecture Blueprint
**Repository:** `qbittorrent-performer-sorter`
**Gitea Remote:** `http://truenas.local:30008/david/qbittorrent-performer-sorter.git`
**Working Workspace:** `/home/david` & `/home/david/github/qbittorrent-performer-sorter`
**Primary App Port:** `8000` (`http://localhost:8000`)
**Stash GraphQL Endpoint:** `http://servervm.local:9999/graphql` (Internal `/data` maps to `/mnt/isolation/videos`)
---
## 1. Executive Summary & Purpose
This application is a unified web-based media organizer, AI intelligence engine, video stream previewer, and Stash media server control center. It bridges qBittorrent, local/SMB filesystem storage (TrueNAS), and Stash GraphQL API to provide automated performer sorting, duplicate scene analysis, Stash database tag/performer normalization, and transcode optimization.
---
## 2. Key Architecture & File Structure
```
qbittorrent-performer-sorter/
├── server.py # Python 3 standard-library HTTP & API server
├── qbittorrent_performer_sorter.html # Single-Page Application (HTML5, Vanilla JS, CSS3)
├── mount_isolation.sh # Auto-mount helper script for TrueNAS SMB shares
├── performer_sorter.db # SQLite persistent caching & audit log database
├── README.md # Quick start and feature overview
└── CONTEXT.md # LLM Session Save Point & Deep Architecture Spec
```
### Zero-Dependency Python Architecture
`server.py` relies exclusively on Python standard library modules (`http.server`, `socketserver`, `sqlite3`, `urllib.request`, `urllib.parse`, `json`, `re`, `os`, `shutil`, `threading`, `time`, `mimetypes`). No external pip dependencies are required.
---
## 3. UI Tab Layout & Feature Modules
1. **Tab 1: 📡 qBittorrent Sorter**
- Direct integration with qBittorrent WebUI (`/qb-proxy/api/v2/...`).
- Analyzes torrent files, multi-file torrent hierarchies, and moves seeding torrents using `torrents/setLocation` without breaking active seeding.
- AI performer parsing with multi-candidate pill selectors.
2. **Tab 2: 📂 SMB Video Sorter**
- Direct filesystem scanner for TrueNAS video shares (`/mnt/isolation/videos/videodownloader` & `/mnt/isolation/videos/unsorted`).
- Categorizes, cleans filenames, and relocates files to performer destination folders (`/mnt/isolation/videos/<performer>/`).
- Automatic SMB auto-mount detection and auto-recovery.
3. **Tab 3: 🖼️ Stash Image Review**
- Performer avatar manager, gallery browser, and quick-tagging studio.
- Hover cards and image zoom preview modals.
4. **Tab 4: 📜 Relocation History & Analytics**
- Persistent SQLite audit log tracking moves, size changes, timestamps, and performer classifications.
- One-click rollback and undo support.
5. **Tab 5: ⚡ Stash Tasks & Tool Control**
- **Section A: 👥 Performer Merge & Deduplication Studio**: Scans fuzzy and punctuation duplicate performer profiles (`cory.chase` vs `Cory Chase`) and merges them via Stash GraphQL `performerMerge`. Includes 1-Click Batch Merge All.
- **Section B: 📡 Missing Metadata Radar**: Scans scenes lacking studios, performers, or tags with quick autotag triggers.
- **Section C: 🏷️ Tag Normalizer & Deduplication**: Identifies tag casing/alias duplicates and merges them via `tagsMerge`. Includes 1-Click Batch Merge All.
- **Section D: 🔀 Stash Transcode Correlator & Storage Saver**:
- Scans generated transcodes in `/mnt/isolation/stashapp/generated/transcodes/`.
- Matches OSHash filenames against Stash library database paths.
- Side-by-side **🎬 Orig** vs **⚡ Transcode** in-browser video streaming comparisons.
- True physical storage savings metrics ($\text{Freed} = \text{Original File Size}$).
- Atomic replacement: Staging copy $\to$ size validation $\to$ `os.replace` $\to$ cache deletion $\to$ background directory metadata rescan.
- Embedded Real-Time Live Execution Terminal Console (`#transcode-terminal-wrapper`) with auto-scroll and status monitoring.
- **Section E: 🔍 Duplicate Scene Comparator & Plugin Hub**:
- Visual side-by-side comparison of duplicate scenes with resolution/codec/bitrate badges and stream previews.
- Direct triggers for Stash plugins (`DupFileManager`, `phashDuplicateTagger`).
- **Section F: ⚡ Task Manager**:
- Live polling of active/queued background Stash jobs (`findJobStatus`).
- Library Scan, Identify/Auto-tag, Clean, and Generate task starters with instant job cancellation (`stopJob` / `stopAllJobs`).
---
## 4. Path Mapping & Filesystem Translation Rules
| Context | Stash Container Path | Local TrueNAS Mount Path |
| :--- | :--- | :--- |
| **Main Videos Share** | `/data/...` | `/mnt/isolation/videos/...` |
| **Generated Transcodes** | `/generated/transcodes/...` or `/media/stashapp/generated/...` | `/mnt/isolation/stashapp/generated/transcodes/...` |
| **Download Incomplete** | `/downloads/...` | `/mnt/isolation/incomplete/...` or `/mnt/isolation/videos/unsorted/...` |
### Streaming Path Translation (`resolve_stream_video_path` in `server.py`)
- Accepts any Stash GraphQL path (e.g. `/data/performer/scene.mp4`) or local path and resolves to the actual local mount path on disk before serving HTTP 206 partial content chunks.
---
## 5. GraphQL Mutation Conventions (Stash v0.31+ Compliance)
Stash v0.31+ strict GraphQL schema rejects variable declarations in mutations with `HTTP 422: GRAPHQL_PARSE_FAILED`.
**Standard**: All mutations must be constructed using `build_stash_mutation(mutation_name, input_obj, fields)`:
- Keys are unquoted in GraphQL literals.
- String filters like `performers`, `studios`, `tags` in `metadataAutoTag` require string array filters (e.g. `["*"]`).
---
## 6. Database Schema (`performer_sorter.db`)
### `ai_cache` Table
- `item_key` (TEXT PRIMARY KEY) - Torrent hash or SMB file path.
- `item_name` (TEXT)
- `performer_result` (TEXT) - Primary chosen performer slug.
- `candidates_json` (TEXT) - JSON list of multi-performer candidate names.
- `source_type` (TEXT) - `'qb'` or `'smb'`.
- `move_status` (TEXT) - `'unmoved'` or `'moved'`.
- `target_path` (TEXT)
- `updated_at` (TIMESTAMP)
### `relocation_history` Table
- `id` (INTEGER PRIMARY KEY AUTOINCREMENT)
- `source_type` (TEXT) - `'qb'`, `'smb'`, or `'stash_transcode'`.
- `item_key` (TEXT)
- `item_name` (TEXT)
- `source_path` (TEXT)
- `target_path` (TEXT)
- `performer` (TEXT)
- `file_size` (INTEGER)
- `timestamp` (TIMESTAMP)
---
## 7. Operational Guidelines for Future AI Sessions
1. **Syncing Changes**: Always ensure modifications to `server.py` and `qbittorrent_performer_sorter.html` in `/home/david` are mirrored to `/home/david/github/qbittorrent-performer-sorter`, committed with semantic messages, and pushed to `http://truenas.local:30008/david/qbittorrent-performer-sorter.git`.
2. **Standard Library Integrity**: Keep `server.py` free of external pip packages.
3. **HTTP Range 206 Streaming**: Maintain HTTP Range handling in `handle_stream_video` for smooth seeking in the web player.
4. **Safety Verification in File Ops**: Always maintain atomic staging (`.tmp` $\to$ verify size $\to$ `os.replace`) when modifying or replacing media files.