Commit Graph

146 Commits

Author SHA1 Message Date
Hitonabi e350523f7e Dashboard-Disc-Karte: Auto-Pre-Scan beim Einlegen — man SIEHT was drinliegt
Ampel / ampel (push) Successful in 41s
Commander-Befund: Disc wurde erkannt, aber das UI verriet nicht WAS.
- Watcher stoesst beim Einlegen (und beim Start mit bereits eingelegter
  Disc) automatisch den Pre-Scan an, Ergebnis landet im DISC_CACHE und
  im Log ("Disc erkannt: Titel (Jahr) [typ, Confidence]")
- GET /devices liefert das disc-Feld mit Titel/Jahr/Typ/Confidence/Poster
- UI: prominente Karte "Im Laufwerk erkannt" mit Poster (TMDB relativ
  oder OMDb absolut), Beschreibung und Rippen-Start (Ziel-Dialog)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 19:55:18 +02:00
Hitonabi dfef585ec8 Speicherziel-Wahl: Rip-Ziel pro Job frei waehlbar (Etappe 16 / Task 16)
Ampel / ampel (push) Successful in 28s
- POST /jobs nimmt target_dir (validiert unter /app/media, .. fliegt raus)
- GET /storage-targets: Verzeichnisse unter /app/media inkl. Mount-Flag
  und freiem Platz — NFS/SMB-Shares unter /srv/rippy/media erscheinen
  dank rslave-Bind automatisch
- jobs.target_dir (Mini-Migration via ADD COLUMN IF NOT EXISTS)
- Worker: rip_disc(target_dir) mit eigener Validierung; CD/Video/
  Transcode-Pfade legen im gewaehlten Ziel ab
- UI: "Rippen starten" oeffnet den Ziel-Dialog (Filme/Serien/Musik oder
  eigener Pfad); Modal-Bugfix: customPath wurde still ignoriert

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 16:20:36 +02:00
Hitonabi 2474b683e2 Transcode-Stufe: HandBrake komprimiert NACH dem MakeMKV-Rip + --noscan-Fix
Ampel / ampel (push) Successful in 34s
Commander-Entscheid 23.07.: 40-GB-Rohdateien sind kein brauchbares
Endprodukt. Architektur bleibt zweistufig, weil HandBrake AACS nicht
lesen kann: MakeMKV rippt verlustfrei nach /app/temp/raw, HandBrake
macht daraus x265 auf Arbeitsgroesse in /app/media, Roh-Verzeichnis
wird erst NACH komplettem Erfolg geloescht (keepOriginal behaelt es).

- Worker: handbrake-cli im Image, run_handbrake + _komprimiere,
  Job-Status "transcoding", Settings aus Postgres (transcodeEnabled/
  Preset/keepOriginal), Fortschritt je Datei aggregiert
- makemkvcon: --noscan im Kommando verankert — der Geraete-Scan haengt
  (1.18.4) bzw. crasht (1.17.7) im Container, mit --noscan + dev:-Pfad
  laeuft es (Befund 23.07., DRV-Zeile beweist Laufwerks-Erkennung)
- UI: Settings-Tab "Verarbeitung" (Toggle/Preset/Original behalten),
  Status-Badge "Komprimieren", LiveLog erkennt transcoding als aktiv
- KONZEPT/ROADMAP entsprechend aktualisiert; Tests fuer HandBrake-Cmd
  (arbeitet auf DATEI, nie am Geraet) und Progress-Regex

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:56:37 +02:00
Hitonabi 009898efae MakeMKV auf 1.17.7 gepinnt — 1.18.x haengt unter Linux beim Laufwerks-Scan
Ampel / ampel (push) Successful in 40s
Bei uns reproduziert (100% CPU, keine Ausgabe, auch mit sg-Knoten), im
MakeMKV-Forum vielfach bestaetigt (t=38128, t=38239, t=38249); Community-
Workaround ist 1.17.7. Bonus: exakt die Version, die spaeter die Firmware
flashen kann. MAKEMKV_URL_BASE als Build-Arg, weil makemkv.com gerade
per Cloudflare-525 down ist (Wayback-Snapshot als Ausweichquelle);
sha256 der Tarballs wird im Build-Log festgehalten.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:39:56 +02:00
Hitonabi bd6409038e UDF-Volume-Label-Leser (Blu-rays haben keine ISO-Bridge) + Etappe 12 (ARM)
Ampel / ampel (push) Successful in 35s
Praxis-Befund mit echter BD-50: reines UDF, der ISO-PVD-Leser griff nicht.
Jetzt ECMA-167-Weg (AVDP Sektor 256 -> Main VDS -> PVD Tag-ID 1 ->
Volume Identifier als d-string), mit Tests fuer das d-string-Parsing.

ROADMAP Etappe 12 aus der ARM-Vollanalyse: was wir uebernehmen
(Fingerprint-DB, bdmt_eng.xml, Suchdegradation, Manual Mode, Apprise,
Multi-Drive, Backup-Modus) und wo wir ARM schlagen (Serien-Episoden-
Matching, Main-Feature per Laufzeitabgleich).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:33:27 +02:00
Hitonabi 1aa51ca943 UI-Feinschliff: Settings-Tabs funktionieren, Details-Knopf tut etwas
Ampel / ampel (push) Successful in 33s
- Settings: Tabs waren reine Dekoration (kein onClick, isActive fest) —
  jetzt echte Tab-Navigation (Ripping/Verzeichnisse/APIs/Benachrichtigungen)
  + OMDb-Key-Feld im APIs-Tab
- Laufwerk-Details: aufklappbares Panel (Pfad/Modell/Seriennummer/Disc)
  mit "Rippen starten" (POST /jobs) und "Auswerfen" (Eject-Endpoint)
- Placebos raus: 4 tote Schnellaktionen, doppelte Geraete-Sektion mit
  zweitem totem Details-Knopf, toter Abmelden-Knopf

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:30:09 +02:00
Hitonabi 5528e0f652 Metadaten-Fallback OMDb + Pre-Scan repariert + Eject-Endpoint
- clients/omdb.py: OMDb als zweite Quelle (Fallback-Kette: TMDB exakt ->
  OMDb -> bester TMDB-Vorschlag mit niedriger Confidence -> unknown)
- Pre-Scan-Reparatur: Titel kam nie an — makemkvcon existiert nur im
  Worker, isosize war nirgends installiert (fiel still auf "DVD" zurueck).
  Jetzt: ISO-9660-Volume-Label direkt vom Medium + Label-Normalisierung
  (PULP_FICTION -> Pulp Fiction), Disc-Typ ueber zentrale detection.py
- POST /devices/{name}/eject (CDROMEJECT-ioctl) mit Job-Schutz (409 wenn
  auf dem Laufwerk gerade gerippt wird)
- OMDB_API_KEY in compose/.env.example; .env.example komplett ehrlich
  dokumentiert (JWT-Pflicht, MakeMKV-Beta-Key-Rhythmus)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:30:09 +02:00
Hitonabi 4aa237541f Fix: makemkvcon landete in /usr statt /usr/local — COPY nahm es nie mit
Ampel / ampel (push) Successful in 36s
Deploy-Befund 23.07.: Image frisch gebaut, GPL-Teile da, aber makemkvcon
fehlte — makemkv-bin installiert ohne PREFIX nach /usr, die Final-Stage
kopiert nur /usr/local. Jetzt PREFIX=/usr/local + test -x als Build-Beweis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:14:14 +02:00
Hitonabi ef84392848 Fix: .gitignore-Venv-Muster lib/ verschluckte docker/ui/src/lib/
Ampel / ampel (push) Successful in 30s
Der Ampel-Rot-Lauf 23 zeigte es: api.ts (der neue API-Client) kam nie im
Commit an — das Python-venv-Muster `lib/` galt fuer JEDES lib-Verzeichnis
im Baum. Jetzt auf Root verankert (/lib/), Datei nachgereicht.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:04:56 +02:00
Hitonabi f2da1ad525 UI: echter Build hinter nginx, relative API-Pfade, Logs-Seite ehrlich
Vorher lief der Vite-ENTWICKLUNGSSERVER als Produktion, und vier Dateien
riefen hartkodiert http://localhost:8000 auf — vom PC aus fragte der Browser
damit den PC selbst nach Laufwerken (deshalb blieb das UI immer leer);
Settings nutzte ein nie gesetztes VITE_API_URL. Die Logs-Seite zeigte fest
einprogrammierte Fantasie-Einträge ("The Matrix gerippt").

- lib/api.ts: axios-Instanz mit baseURL /api; nginx proxied /api → api:8000
  (ein Origin, kein CORS), SSE-tauglich (proxy_buffering off)
- Dockerfile: Vite-Build → nginx:alpine statt npm run dev
- Logs + LiveLog von echtem /logs-Endpoint; MetadataPreview: echte Laufwerke
  aus /devices statt erfundener /dev/bluray-Optionen, startet echten Job

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:02:39 +02:00
Hitonabi 28a12b2e06 API: Die Job-Kette existiert jetzt — POST /jobs, Watcher, Postgres, /logs
Vorher gab es KEINEN Code-Pfad, der je einen Rip ausgelöst hat: kein
POST /jobs, kein udev-Daemon (udev_daemon.py existierte nirgends), GET /jobs
gab hart [] zurück, Postgres lag komplett brach, der SSE-Stream konnte
strukturell nie senden (sse_connections wurde nie befüllt), udevadm lieferte
ohne udevd nichts.

- POST /jobs: legt Job-Zeile an, schickt worker.tasks.rip_disc via Celery
- GET /jobs aus Postgres (running→processing fürs UI)
- Disc-Watcher: 3s-ioctl-Poll statt udev, protokolliert Einwurf/Auswurf
- /devices über /sys (vendor/model) + ioctl-Status — ehrlich statt leer
- /logs + /settings (Settings-Seite sprach vorher gegen 404)
- SSE-Fix, udev aus dem API-Image entfernt, Import-Smoke-Test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:02:13 +02:00
Hitonabi 780d114fe4 Etappe 10: Worker rippt wirklich — MakeMKV 1.18.4 + ioctl-Disc-Erkennung
Vorher: Dockerfile unbaubar (makepkg ist ein Arch-Paket, existiert in Debian
nicht) und KEIN einziges Ripping-Tool im Image — jeder Rip endete sofort.
Disc-Erkennung via `file -L` konnte auf Block-Devices strukturell nie etwas
erkennen; ihr Test mockte sich die Ausgabe passend.

- makemkv-oss/bin 1.18.4 multi-stage (bookworm-gepinnt), EULA via
  tmp/eula_accepted, Beta-Key aus MAKEMKV_APP_KEY (entrypoint.sh)
- makemkvcon-Aufruf + PRGV-Parsing laut makemkv.com/developers/usage.txt
  (AGENTS Regel D), HandBrake raus aus dem Ripp-Pfad (KONZEPT: lossless=Muss)
- detection.py: CDROM_DISC_STATUS + BLKGETSIZE64 (cd/dvd/bluray), pure
  classify() mit ehrlichen Tests
- tasks.py: rip_disc als einziger Celery-Task, schreibt Status/Fortschritt
  nach Postgres (db.py), Ausgabe auf /app/media (Volume) statt totem /output

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:02:13 +02:00
Hitonabi b80b7681c5 fix: install udev in API container for udevadm device detection
Ampel / ampel (push) Successful in 30s
2026-07-23 13:41:06 +02:00
Hitonabi 68094f8b43 fix(api): detect direct devices /dev/sr0, /dev/cdrom
Ampel / ampel (push) Successful in 32s
- Get devices from /dev/disc/ (udev symlinks)
- Also check direct devices: /dev/sr0, /dev/cdrom, /dev/dvd
- Use udevadm to detect device type (cd/dvd/bluray)
- Extract model and serial for better identification
2026-07-23 12:59:09 +02:00
Hitonabi e9652a428c feat(ui): implement Discovery, Logs, and Live Log
Ampel / ampel (push) Successful in 29s
- DeviceDiscovery: auto device detection with type and status
- LogsPage: comprehensive logs view with filters and stats
- RipTargetModal: target directory selection wizard
- ConfirmDialog: generic confirmation dialog component
- LiveLogSection: real-time job progress and logs
- Update App.tsx to include new pages
2026-07-23 12:38:16 +02:00
Hitonabi 3e88c328db fix(worker): remove pyudev (needs libudev-dev, not in slim image)
Ampel / ampel (push) Successful in 30s
2026-07-23 12:27:21 +02:00
Hitonabi a456e8587c fix(worker): remove invalid udev package, use syslinux-utils for isoinfo
Ampel / ampel (push) Failing after 28s
2026-07-23 12:24:31 +02:00
Hitonabi 61af353559 fix(worker): mount host devices for disc detection
Ampel / ampel (push) Failing after 30s
- Add direct device mounts (cdrom, dvd, sr0) to worker
- Add SYS_ADMIN capability for udev access
- Install isoinfo and udev in worker container
- Add pyudev for device monitoring
- Update udev rules with correct paths
2026-07-23 12:15:55 +02:00
Hitonabi ad48276fdd Fix: Fortschritts-Regex toleriert Leerzeichen vor % (Testfund)
Ampel / ampel (push) Failing after 14m47s
Echtes HandBrake schreibt "45.50 %" mit Leerzeichen - die alte Regex
hat aus echter Ausgabe NIE einen Fortschritt geparst. Der neue Test
mit realistischer Zeile hat es sofort gefangen.
2026-07-22 19:39:35 +02:00
Hitonabi 0ea5f10b31 Fix-Runde nach Review: alle Befunde behoben + echte Tests
Ampel / ampel (push) Failing after 12m31s
- Metadaten-Preview WIEDERHERGESTELLT (Stub ueberschattete echte
  prescan-Implementierung), tote Altmodule geloescht
- Celery update_state statt Phantom-Task/erfundener API
- abcde-Kommando korrigiert (CD-Ripping war nie funktionsfaehig)
- JWT: fester Schluessel Pflicht, echtes Logout, Cleanup nur Abgelaufene
- main.py: crashende Endpoints (Path/secrets/api_keys), year-Bug,
  Admin-Login aus .env
- Ruff gruen (29 Funde), Tests: auth/cache_keys/ripping_helpers,
  Placebo-test_health raus
- SAVEPOINT: offene MakeMKV-Entscheidung SICHTBAR gemacht (Regel B)
2026-07-22 19:31:48 +02:00
Hitonabi 13c0c4b066 Ampel v2: universelle Vorlage (Fix: checkout braucht Node im Container)
Ampel / ampel (push) Failing after 12m54s
+ package-lock.json (fehlte komplett - Builds waren nie reproduzierbar)
2026-07-22 19:11:27 +02:00
Hitonabi 12c67aee27 fix: use dark class instead of data-theme for Tailwind 2026-07-22 17:12:32 +02:00
Hitonabi 85e072a7dd fix: use Tailwind dark: prefix instead of conditional classes 2026-07-22 17:11:02 +02:00
Hitonabi 886cf4398e fix: Dashboard.tsx useEffect syntax error 2026-07-22 17:04:18 +02:00
Hitonabi d2fb281342 fix: complete dark mode implementation with all UI components 2026-07-22 17:00:49 +02:00
Hitonabi 95c1f9b105 feat(ui): SoC Refactoring & Config Validation
- Theme Context ausgelagert (ThemeContext.tsx + useDarkMode.ts)
- Config Validation mit TMDB-API-Key Pflicht (config_validation.py)
- Cache Key Centralization (cache/keys.py)
- CD-Ripping mit abcde implementiert (Worker)
- Docker Compose mit Healthchecks & LOG_LEVEL
- ROADMAP.md & SAVEPOINT.md aktualisiert
2026-07-22 16:38:19 +02:00
Hitonabi 43dfce5233 feat(ui): implement dark mode with theme toggle
- Add global theme state in App.tsx with localStorage persistence
- Implement dark mode CSS variables in index.css
- Add theme toggle button in sidebar navigation
- Update Dashboard with dark mode support for stats cards and badges
- Update Settings page with dark mode for main layout and toggles

This implements the core dark mode functionality with separation of
concerns - theme state is managed globally in App.tsx and passed down
to child components as props.
2026-07-21 22:18:59 +02:00
Hitonabi ba2429612a rippy-ui-modern: API UI Modernisiert & Import-Fixes
- Doppelte Arcane-Einträge behoben (rippy statt Rippy) - Import-Fixes: relative → absolute imports in main.py, cache/__init__.py, prescan/__init__.py, clients/__init__.py - Neue Dateien: cache.py, prescan.py, Settings.tsx - API-Port 8000 in docker-compose.yml gemappt - UI mit Sidebar, Dark Mode, Einstellungen-Tabs

Fixes: #2978 (doppelte Einträge), #2888 (Import-Fehler)
2026-07-21 22:08:03 +02:00
Hitonabi e37aff2678 fix: jwt_secret_key hinzufügen 2026-07-21 17:53:59 +02:00
Hitonabi 7a61440d22 chore: worker .dockerignore for __pycache__ 2026-07-21 17:51:41 +02:00
Hitonabi 969a863835 fix: pydantic-settings import für v2 2026-07-21 17:49:16 +02:00
Hitonabi 08a985b989 fix: Package-Struktur für API-Container (app/) 2026-07-21 17:48:09 +02:00
Hitonabi 50f747d1e0 Dockerfiles: Korrektur für Arcane Build 2026-07-21 17:33:57 +02:00
Hitonabi efa642e676 Etappe 6: Sicherheit
- docker-compose.yml mit read_only: true, tmpfs, healthchecks
- API- und Worker-Dockerfiles mit minimalem Image
- requirements.txt für Python-Abhängigkeiten
2026-07-21 17:26:01 +02:00
Hitonabi 3e921fc0c9 Etappe 5: Auth + Rate-Limiting
- JWT-Auth (Access 15min/Refresh 7 Tage)
- Rate-Limiting (100/min pro Client/API-Key)
- API Key Management
- OAuth2 Password Scheme
2026-07-21 17:19:34 +02:00
Hitonabi 518155051f Etappe 3: Metadaten-Lookup + Pre-Scan
- SQLite-Cache für API-Rate-Limits (LRU, 10k Einträge)
- TMDB/MusicBrainz/TheTVDB Clients
- Pre-Scan-Modul für TOC-Lesung ohne Ripping
- Metadaten-Preview UI
- Jellyfin-Formatierung (NFO + Images)
- API Endpoints für Lookup, Confirm, Format
2026-07-21 17:17:35 +02:00
Hitonabi 0cf5413ac0 Merge remote-tracking branch 'origin/main' 2026-07-21 17:10:48 +02:00
Hitonabi a505415898 SAVEPOINT v1.2: UI läuft!
- Rippy UI auf Port 80
- Git Sync in Arcane
- Alle Container healthy
2026-07-21 17:07:54 +02:00
Arcane 25cba0e18d UI: Port 80 + lucide-react 2026-07-21 15:07:36 +00:00
Arcane 596ded1a4a postgres: Image von 16-slim auf 16 2026-07-21 14:58:22 +00:00
Hitonabi 4d1f613a1c Etappe 5: API + Auth + WebUI — Erste Implementierung
- React-UI: Dashboard mit Stats, Geräte, Jobs
- API: /jobs und /devices endpoints
- CORS aktiviert für UI-Kommunikation
2026-07-21 16:52:30 +02:00
Hitonabi 90e6f81d98 tasks.py: detect_disc_type wieder importieren 2026-07-21 16:49:01 +02:00
Hitonabi 719aa9408d tasks.py: detect_disc_type aus ripping.py importieren 2026-07-21 16:48:44 +02:00
Hitonabi 42f19a0806 ripping.py: HandBrakeCLI-Check + Typ-Erkennung 2026-07-21 16:48:32 +02:00
Hitonabi 9e73d065f9 Etappe 2: Ripping-Pipeline — Erste Implementierung
- DockerfileWorker: abcde, flac, ffmpeg, handbrake-cli installiert
- ripping.py: Ripping-Module für DVD/Blu-ray mit HandBrake
- tasks.py: Disc-Typ-Erkennung + passendes Ripping-Modul
- docker-compose.yml: Output-Verzeichnis /output hinzugefügt
- output/ Verzeichnis erstellt

WIP: CD-Ripping mit abcde noch nicht implementiert
2026-07-21 16:47:50 +02:00
Hitonabi 5d23b1e6c8 Etappe 1: Container-Infrastruktur + udev-Erkennung
- Docker Compose mit 5 Containern (api, worker, ui, postgres, redis)
- Basis-Dockerfiles für FastAPI, Celery, React/Vite, PostgreSQL, Redis
- udev-Regel + Python-Daemon für Disc-Einwurf-Erkennung
- Device-Resolver (UUID/Serial → /dev/disc/<uuid>)
- Celery-Worker mit Dummy-Job-Task (Disc-Erkennung)
- .env.example mit Umgebungsvariablen
- .gitignore für Docker, .env, node_modules
- README, SAVEPOINT, ROADMAP aktualisiert
2026-07-21 14:59:09 +02:00