# 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//`). - 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.