Aus dem Weitergabe-Review. Kein Verhaltenswechsel fuer den Ursprungs-Host
(alle Defaults = bisheriges Verhalten):
Portabilitaet:
- Laufwerk-Geraeteknoten via .env parametrisiert (OPTICAL_SR/OPTICAL_SG,
Defaults sr0/sg1) - der #1-Blocker: auf Fremdhosts liegt das sg-Node woanders.
- deploy.sh generisch (RIPPY_VM/RIPPY_REPO_URL/... aus der Umgebung) - keine
festen Besitzer-Adressen (interne IP + DDNS) mehr im Repo.
- POSTGRES_PASSWORD in compose durchverdrahtet (Default rippy) - war No-op.
Aufraeumen (toter/irrefuehrender Code):
- udev/ entfernt (fehlende Regeldatei, falscher Container-Name; durch ioctl-
Polling ersetzt - reine Altlast).
- docker/postgres/*, docker/redis/*, init.sql entfernt (nie eingebunden).
Onboarding:
- FirstRunWizard verdrahtet: App.tsx fragt GET /setup und zeigt den
Einrichtungs-Assistenten beim ersten Start (war gebaut, aber nie gerendert).
Doku:
- README: Laufwerk-Abschnitt auf .env, ENV-Tabelle (OPTICAL_*/POSTGRES),
rshared-Anleitung, neuer Abschnitt "Haertung fuer fremde/exponierte Netze".
- config_validation.py: TMDB Pflicht->empfohlen, Zeichensalat-Tippfehler gefixt.
- .env.example: TMDB-Wording, OPTICAL_*-Variablen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Commander-Einwand: .vbs ist abgekuendigt (Win11 24H2 Feature-on-Demand) und
wird oft als gefaehrlich geflaggt. Loesung: echte .exe.
- RippyWorkerSetup.exe (50 KB): install-gui.ps1 via ps2exe kompiliert —
eingebettetes Rippy-Disc-Icon (deploy/worker-windows/rippy.ico), kein
Konsolenfenster (-noConsole), WinForms (-STA). E2E getestet: Fenster
oeffnet, conhost-Zaehler unveraendert (kein Konsolenfenster).
Vorgebaut auf Windows (build-exe.ps1) + committet — eine Windows-.exe
kann nicht von Linux (Rippy-Host) gebaut werden. WICHTIG: friert KEINE
Versionen ein — HandBrake wird zur Laufzeit (GitHub latest) und der
Worker-Code live von Rippy geholt; nur bei GUI-Aenderungen neu bauen.
- API: GET /worker-setup/windows-exe (FileResponse); Dockerfile kopiert die
.exe ins Image. .gitattributes: *.exe/*.ico als binary.
- UI (Worker -> Windows): 'Installer herunterladen (.exe)' als Haupt-Weg
(generisch, GUI fragt Adresse ab; die einzutragende IP wird als Hinweis
angezeigt). .vbs-Erzeugung entfernt. CLI bleibt Profi-Alternative.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Commander-Wunsch: kein Konsolenfenster + Icon.
- Starter ist jetzt eine .vbs (statt .bat): wscript startet PowerShell mit
Fensterstil 0 = KOMPLETT versteckt, kein Konsolenfenster. Nur das
WinForms-Installer-Fenster erscheint. Download-Datei: rippy-worker-setup.vbs
(weiter CLIENT-seitig mit eingetragener LAN-IP erzeugt).
- install-gui.ps1: Fenster-Icon = Rippy-Disc (zur Laufzeit gezeichnet,
Indigo-Kreis + weisses Loch) — erscheint in Titelleiste + Taskleiste.
(Die Datei selbst kann Windows-bedingt kein Icon tragen — nur .exe/.lnk.)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Commander-Wunsch: die CLI-Installation ist grausam. Jetzt:
- install-gui.ps1 (WinForms, ASCII-only): Fenster mit Feldern (Rippy-IP,
Worker-Name, Autostart-Checkbox), Install-Knopf mit Live-Log, danach
'Worker starten'-Knopf. Gleiche Schritte wie der CLI-Installer
(Worker-Code + HandBrake latest + venv + Tray/Start/Uninstall).
Braucht nur Python 3.10+, keine externe GUI-Runtime.
- API: GET /worker-setup/windows-gui serviert die GUI; Dockerfile kopiert
sie ins worker_dist/.
- UI (Worker-Tab, Windows): 'Grafischen Installer herunterladen (.bat)' als
Haupt-Weg — die .bat wird CLIENT-seitig mit der eingetragenen LAN-IP
erzeugt (Blob-Download), Doppelklick laedt+startet die GUI von Rippy.
Der CLI-Befehl bleibt als Profi-Alternative.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Commander-Wunsch: das UI soll die Werkzeug-Versionslage genau so zeigen,
wie sie ist. Klarstellung im System-Tab:
- Hinweis bei 'Installierte Werkzeuge': MakeMKV aktuell haltbar (wichtig
wegen Schluessel-DB), HandBrake im Docker-Worker bewusst Debian-stabil
(kein separates Update), native Worker holen die neueste.
- Update-Check: MakeMKV mit gruenem '✓ aktuell' bzw. Update-Befehl (echtes
To-do). HandBrake NICHT mehr als 'Update noetig' alarmieren — neutral als
'Debian-Version, bewusst so' + Info, dass die nativen Worker die neueste
nutzen.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1) Speicher-Mounts robust (Befund: toter CIFS-Mount nach NAS-Ausfall/Rebuild —
mounted:false, verschwand aus 'Verfuegbare Ziele', Neu-Anlegen -> 409, man
sass fest):
- mounts.py: ist_erreichbar() (listdir, soft-Mount bricht schnell ab),
ist_gemountet() faengt OSError toter Mounts, aushaengen() mit
umount -l Fallback, reparieren() (lazy abhaengen + frisch mounten).
- /storage-mounts liefert 'reachable'; POST bei existierendem Namen:
aktiv -> 409, tot -> automatische Reparatur mit neuen Angaben;
neuer POST /storage-mounts/{name}/repair (gespeicherte Zugangsdaten).
- /storage-targets crasht nicht mehr an totem Mount (os.path.ismount
OSError abgefangen).
- UI: eigene 'Netzwerk-Mounts'-Liste mit Status (aktiv/nicht erreichbar/
getrennt) + Reparieren- und Entfernen-Knopf — tote Mounts sind sichtbar
und wiederherstellbar statt zu verschwinden.
2) HandBrake-Versionen konsistent (Befund: Docker 1.6.1, Windows-Skript
fest 1.9.2, Update-Check meldet 1.11.2 — verwirrend):
- Windows-Installer zieht jetzt DYNAMISCH die neueste Version (GitHub
latest, Fallback 1.11.2) — passt zum Update-Check.
- Update-UI erklaert klar: Docker = stabiles Debian-Paket (bewusst aelter,
kein Fehler), Windows = neueste. MakeMKV-Update zeigt den Befehl.
3) Encoder-/Worker-Auswahl beim Rip (Feature):
- Celery worker_direct=True: jeder Worker konsumiert zusaetzlich seine
Direkt-Queue. API-Helper transcode_queue(node) routet gezielt an den
gewaehlten Worker, faellt aber sicher auf die geteilte transcode-Queue
zurueck, wenn er offline ist (kein Haengenbleiben).
- /capabilities liefert den Celery-Node je Worker; POST /jobs nimmt
transcode_node (-> Job-meta); rip_disc + retry-transcode routen danach.
- Rip-Dialog: Encoder-/Worker-Dropdown, sichtbar ab 2 Online-Workern.
- ping_worker-Task zum Verifizieren des gezielten Routings.
- Nebenfund gefixt: DeviceDiscovery leitete die Titel-Auswahl (titles)
gar nicht an die API weiter — jetzt titles + transcode_node.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Befund (Commander, Screenshot): Das Feld 'Rippy-Adresse' fuellte sich
automatisch mit window.location.hostname — also der Adresse, ueber die man
das UI geoeffnet hat (bei ihm die eigene PC-IP hinter einem Forward/Proxy,
192.168.178.98). Das ist NICHT zwingend die direkte LAN-IP der
Rippy-Maschine, die der Worker fuer Redis/Postgres (6379/5432) braucht —
der generierte Befehl zeigte damit auf den falschen Host ('Verbindung
verweigert').
Fix:
- Kein Auto-Default mehr (Feld leer); leeres Feld -> sichtbarer
Platzhalter <RIPPY-IP> im Befehl (erkennbar unvollstaendig statt still
falsch).
- Label auf 'LAN-IP der Rippy-Maschine (Docker-Host)' geschaerft +
dauerhaft sichtbarer Hilfetext: die IP der Rippy-Maschine, NICHT dieses
PCs, und auch dann die direkte LAN-IP wenn das UI ueber Domain/Proxy
geoeffnet wurde.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- tray.py (nur nativer Windows-Worker; Docker unberuehrt): pystray+Pillow-
Tray neben der Uhr — Status, Worker starten/stoppen, Rippy oeffnen,
Log anzeigen, Beenden (stoppt den Worker mit). Celery laeuft als
Kind-Prozess ohne Konsolenfenster (CREATE_NO_WINDOW), Log in worker.log.
- install.ps1 erzeugt jetzt start-tray.bat (pythonw, empfohlen),
start-worker.bat (Konsole/Debug) und uninstall.ps1: stoppt alle
Prozesse aus dem Ordner, loescht die Autostart-Aufgabe, meldet den
Worker per DELETE /workers/{name} in Rippy ab und entfernt den Ordner
komplett. -Autostart registriert die Tray-Variante (onlogon).
- UI-Beschreibung + Anleitung entsprechend ergaenzt.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1. Update-Erkennung (Commander-Frage 'wie kriegen wir Updates mit?'):
GET /system/updates vergleicht installierte Versionen (Worker-Info) mit
makemkv.com (Versionsnummer der Download-Seite) und der HandBrake-
GitHub-Release-API (releases/latest), 12 h gecacht. Einstellungen ->
System: 'Auf Updates prüfen' + fertiger Update-Befehl bei MakeMKV.
Selbst-Update gibt es bewusst NICHT (waere Docker-Socket-Zugriff);
dafuer ist MAKEMKV_VERSION jetzt per .env uebersteuerbar — Update ohne
Code-Aenderung. HandBrake-Abweichung wird als Info dargestellt
(Debian-Paket hinkt der offiziellen Version bewusst hinterher).
2. Worker-Anbindung: editierbares Adressfeld statt stillschweigend
window.location.hostname — Befund: ueber die externe Domain kopierte
Befehle liefen in den Reverse-Proxy (401) und Worker koennen Redis/
Postgres eh nur im Heimnetz erreichen. Amber-Warnung bei oeffentlich
aussehender Adresse, Anleitung ergaenzt.
3. 'Einstellungen speichern' ist im Worker-Tab ausgeblendet — dort gibt
es nichts zu speichern, der Knopf verwirrte nur.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Volle Titel-Auswahl vor dem Rip (Etappe-12-Rest):
- worker.tasks.scan_tracks: makemkvcon info -> Titel-Liste (Dauer/Groesse/
Kapitel, apdefs-Attr 8/9/11) in die settings-Tabelle 'tracks:<device>';
API: POST /devices/{n}/scan-tracks + GET /devices/{n}/tracks (Polling).
- Rip-Dialog: 'Disc scannen' -> Tabelle mit Checkboxen, Vorauswahl ab
5 min, Groessen-Summe; gewaehlte Titel als meta.titles in den Job.
- rip_titel_auswahl: ein makemkvcon-Aufruf je Titel (mkv kann nur einen
Titel oder all), Fortschritt anteilig. Parser-Tests dabei.
Nativer Windows-Worker OHNE Docker (Commander-Wunsch):
- Die Rippy-Instanz versorgt sich selbst: GET /worker-setup/windows
liefert install.ps1, /worker-setup/paket den Worker-Code als Zip
(api-Dockerfile kopiert docker/worker/*.py als worker_dist/ ins Image).
- install.ps1: Python-Check, venv + requirements, HandBrakeCLI 1.9.2 vom
offiziellen GitHub-Release (URL per HEAD verifiziert), start-worker.bat
mit celery -Q transcode --pool=solo (Celery-Doku: Windows nur solo),
optional -Autostart via schtasks onlogon.
- tasks.py laedt jetzt auch ohne fcntl (Import-Guard) — rip_disc ist auf
solchen Workern hart verriegelt (Klartext-Fehler statt Crash).
- Einstellungen -> Worker: Varianten-Umschalter Linux(Docker)/Windows(nativ)
mit passenden Copy-Paste-Befehlen.
Anleitungs-Tab: Rippy erklaert sich selbst (Disc-Weg, Serien, NAS,
Media-Server, Benachrichtigungen, Key, Worker, Downloads, FAQ).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AUTH ENTFERNT (Commander-Entscheid 24.07., KONZEPT §10): /token- und
/api-keys-Endpoints, auth.py, test_auth.py, passlib/bcrypt/PyJWT/
python-multipart, JWT_SECRET_KEY-Pflicht. Heimnetz-only, das UI hatte nie
einen Login — die Auth-Oberflaeche war Placebo und die passlib/bcrypt-
Falle brach die Ampel. Rate-Limit pro IP bleibt. Schnellstart laeuft
jetzt ganz ohne .env-Pflichtwerte.
Serien-Flow (Etappe-12-Kern, ARM-Wunde #395):
- Rip-Dialog: Serienname + Staffel -> Ablage <Serie>/Season NN
(jellyfin.org/docs Naming-Schema); tvshow.nfo + poster.jpg im
Serien-Ordner, bei Staffel 2 nicht ueberschrieben.
- Episoden-Matching per Laufzeitabgleich: HandBrakeCLI --scan
('+ duration:', handbrake.fr/docs) je MKV gegen TMDB-Staffel-Laufzeiten
(GET /metadata/tv/{id}/season/{n}; tv-season-details-API).
Ordnungserhaltend; komplette Staffel auf einer Disc klappt auch bei
uniformen Anime-Laufzeiten (Sequenz-Stufe). Umbenannt wird NUR bei
eindeutiger Zuordnung — sonst ehrliches Log. Mit Tests.
Weitere Punkte:
- Jellyfin/Emby-Bibliotheks-Refresh nach jedem fertigen Rip
(POST /Library/Refresh, X-Emby-Token lt. jellyfin.org/docs) —
URL/Key + Test-Knopf in Einstellungen -> Ripping.
- Duplikat-Warnung: Disc-Fingerabdruck (jetzt Teil des Prescan-Ergebnisses
+ der Job-Metadaten) gegen die Historie; Karte zeigt 'bereits gerippt',
Vollautomatik ueberspringt Duplikate.
- 'Nur Hauptfilm' ECHT: makemkvcon info -> TINFO-Attr-9-Laufzeiten
(usage.txt) -> laengster Titel -> mkv dev:X <nr>. Vorher wirkungsloses
Setting; pro Rip im Dialog uebersteuerbar. Mit Tests.
- OMDb-Treffer eingedeutscht via TMDB /find (external_source=imdb_id,
de-DE; find-by-id-API).
- Dashboard: Speicherplatz-Anzeige (amber < 60 GB) + CSV-Export
(GET /jobs/export, Semikolon+BOM fuer deutsches Excel).
- Metadaten-Seite entfernt (Abnahme durch Commander-Auftrag) inkl.
Placebo-Endpoints /metadata/lookup (scannte Dummy-Device) und
/metadata/confirm (schrieb nie gelesenen Cache-Key).
- Doppel-Jahr-Fix: 'X (2009) (2009)' in Log und Ordnernamen.
- Remote-Worker-Blocker: redis (6379) + postgres (5432) waren NIE
veroeffentlicht — kein Remote-Worker konnte sich je verbinden. Ports
jetzt offen (Heimnetz-Kompromiss, kommentiert) + API_URL fuer Worker.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Zwei bewiesene Bug-Fixes:
- SMB-Mount 'Unable to apply new capability set': mount.cifs hebt
CAP_DAC_READ_SEARCH an, die in Dockers Default-Caps fehlt (auf der VM
reproduziert: Bounding-Set a82425fb ohne Bit 2; mit der Capability
verschwindet der Fehler). Fix: cap_add DAC_READ_SEARCH fuer den
api-Container.
- TMDB fiel still aus: Client konnte nur v4-Bearer-Tokens, der uebliche
32-Hex-v3-Key bekam 401 und die Suche lieferte nur OMDb. Jetzt beide
Key-Arten (ist_v4_token + api_key-Query-Param lt.
developer.themoviedb.org, mit Tests) — damit kommen auch die deutschen
Texte an (language=de-DE war ueberall schon gesetzt). Neu:
GET /metadata/status + 'Verbindung pruefen' in Einstellungen -> APIs
(Live-Check am Cache vorbei).
Features aus dem Commander-Feedback:
- 4K UHD als eigener Disc-Typ: classify >= 55 GiB (BD-66/BD-100; BD-50
bleibt bluray), beide detection.py + Tests, eigene Badge-Farbe in
Dashboard/Laufwerken, Prescan-Label '4K UHD'. UHD-Rip-Fehler 'Failed to
open disc' (Code 11) bekommt Klartext: LibreDrive-Firmware noetig.
- Vollautomatik (Setting autoRipStart): Disc erkannt -> Rip startet ohne
Popup in den Schnellwahl-Ordner (Serie->Serien, sonst Filme, CD->Musik).
- Job-Verwaltung: 'Neu komprimieren' nur noch mit can_retry (Rohdaten
liegen wirklich da), DELETE /jobs/{id} + 'Erledigte aufraeumen'
(Dateien bleiben immer), 'Alle herunterladen' im Job-Detail
(gestaffelte Einzel-Downloads statt Server-Zip von 40-GB-Dateien).
- Worker zuordenbar: WORKER_NAME-Env als stabiler Anzeigename (fixt auch
die Offline-Leichen nach Rebuilds), info.hostname/ip gemeldet,
Online-Abgleich ueber hostname, DELETE /workers/{name} + Papierkorb im
UI, Quelle-Anzeige an der Disc-Karte ('Quelle: TMDB - 99 % sicher').
- Ripping-Tab nach Medium gegliedert (Video/Audio-CD/Allgemein) +
Untertitel-Klartext (--all-audio/--all-subtitles bleiben komplett),
CD -> Musik-Vorauswahl im Ziel-Dialog, Ordner-Verwaltung beschriftet
und standardmaessig eingeklappt.
- Docs: SAVEPOINT v3.3, ROADMAP Etappe 14 + Ideen (nativer
Windows-Worker, deutsche OMDb-Texte via TMDB-Find), README.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- GET /jobs/{id}/files: Dateiliste aus job.output_path (Name + Groesse)
- GET /jobs/{id}/files/{name}: FileResponse-Stream; Validierung strikt —
output_path muss unter /app/media liegen, nackter Dateiname (kein
Slash/.., kein Dotfile), realpath-Check gegen Symlink-Ausbrueche.
Mit Test (test_dateiname_validierung_blockt_pfad_tricks).
- UI: 'Download'-Knopf in der Aktion-Spalte bei fertigen Jobs; die
Dateiliste mit Groessen + Download-Links lebt im Job-Detail-Popup
(ein Dropdown wuerde im overflow-x-auto-Tabellencontainer clippen).
- nginx: proxy_buffering off + proxy_read_timeout 3600s waren fuer SSE
schon gesetzt — grosse Downloads brauchen keine Aenderung.
Wunsch aus der Uebernahme-Session (Commander-Sammelliste 24.07.).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Commander-Wuensche (23.07. Nacht):
- "Nicht korrekt?!"-Knopf direkt an der Disc-Karte: Korrektur-Suche als
Popup (MetadataKorrektur) — kein Seitenwechsel mehr noetig; Wahl gilt
per Disc-Fingerabdruck weiter 30 Tage
- Einstellungen -> Worker: verbundene Encoding-Maschinen mit ECHTER
Erreichbarkeit (Celery-Ping + minuetlicher Herzschlag/last_seen),
Encoder-Badges, Copy-Paste-Anbindung fuer neue Maschinen
(Linux/Docker + Docker Desktop; SSH-Ein-Klick als Ausbaustufe)
- JSX-0-Falle gefixt: {0 && ...} renderte nackte "0" unter GENRE/LAUFZEIT
- ruff.toml: Regelsatz gepinnt — lokal aktualisierte Ruff-Version zog
ploetzlich Stilregeln und faerbte den Baum rot; Ampel und lokal
urteilen jetzt identisch
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Commander-Befunde (23.07. spaet):
- MANUELLE KORREKTUR (KONZEPT Schritt 5 endlich komplett): Metadaten-Seite
hat jetzt Titelsuche ueber ALLE Quellen (GET /metadata/search) mit
Poster-Kacheln; ein Klick uebernimmt den Treffer (POST /metadata/override)
fuer Karte, Jobs UND merkt ihn sich 30 Tage per Disc-Fingerabdruck —
dieselbe Disc wird beim naechsten Einlegen sofort richtig erkannt
- PC/NAS per Klick: SMB-Freigaben eines Rechners auflisten
(GET /storage-mounts/shares via smbclient) statt //host/share raten
- Berechtigungs-PRUEFUNG beim Einhaengen: Schreibtest, Warnung bei
nur-lesbaren Zielen (API + UI + Log)
- "Standard-Unterordner" verstaendlich gemacht: heisst jetzt "Schnellwahl
beim Rippen" mit Erklaertext; kryptisches Basis-Feld raus
- Preview zeigt Poster; Fingerprint fuer Cache/Override vereinheitlicht
(billiges Label+Groesse statt Mount-Titel)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Commander-Befunde (Screenshots 23.07. abends):
- Jikan (MyAnimeList, kostenlos OHNE Key) als Anime-Quelle vor OMDb —
waehlt per Titel-Aehnlichkeit (SequenceMatcher, Schwelle 0.55) statt
blind Treffer 1; damit trifft "Evangelion 2.22" den exakten Film
- Job-Titel: POST /jobs uebernimmt den erkannten Disc-Titel aus dem
DISC_CACHE — Schluss mit "Unbekannt" in der Queue
- Kooperativer Job-Abbruch: POST /jobs/{id}/cancel setzt canceling,
der Worker prueft das Flag bei jedem Fortschritts-Update und killt
den Encoder-Prozess sauber (RipAbbruch); UI-Knopf "Abbrechen" fuer
laufende, Status-Badge "Wird abgebrochen"
- Dark-Mode: Job-Zeilen-Hover war hart hell (hover:bg-slate-50)
- Speicherziele: lokaler Ordner-Browser mit "Ordner anlegen"
(GET /browse + POST /browse/mkdir, nur unter /app/media)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Commander-Befunde 23.07. abends:
1. Metadaten "klappen nicht": Wurzel = kryptisches Volume-Label + kein
TMDB-Key. Jetzt: API mountet die Disc read-only (CAP_SYS_ADMIN ist da)
und liest den KLARTEXT-Titel aus BDMV/META/DL/bdmt_*.xml; dazu
progressive Suchdegradation (Titel-Varianten) und OMDb-Unscharf-Suche
(s= + imdbID-Nachladen) — mit dem vorhandenen OMDb-Key gibt es damit
Titel/Jahr/Poster auch ohne TMDB
2. Weisses Fenster beim Pre-Scan: Lucide-Icons sind forwardRef —
Direktaufruf getIcon(...)({size}) crashte die Seite; als JSX gerendert
3. Dashboard sortiert: System-Leiste (Encoder + aktiver Job) oben,
Disc/Geraete -> Stats -> Jobs, Live-Log ans Ende
4. Ziel-Dialog mit ORDNER-BROWSER (GET /browse, nur unter /app/media);
Schnellwahl nutzt die Settings-Unterordner statt Hartkodierung;
Tab "Verzeichnisse" in "Speicherziele" aufgegangen (redundant)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
- 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>
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>
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>
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>
- 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
- 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.