Restefeger: Auth komplett raus, Serien-Flow + Episoden-Matching, Jellyfin-Refresh, Duplikat-Warnung, echtes Nur-Hauptfilm
Ampel / ampel (push) Successful in 55s

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>
This commit is contained in:
Hitonabi
2026-07-24 14:22:19 +02:00
parent e7a7d5fdb4
commit 8eb5653848
28 changed files with 934 additions and 892 deletions
+21 -4
View File
@@ -203,7 +203,8 @@ class PreScanResult:
year: int = None,
confidence: float = 0.0,
metadata: Dict = None,
tracks: List[Dict] = None
tracks: List[Dict] = None,
fingerprint: str = ""
):
self.disc_type = disc_type
self.title = title
@@ -211,6 +212,9 @@ class PreScanResult:
self.confidence = confidence
self.metadata = metadata or {}
self.tracks = tracks or []
# Fingerabdruck (Label|Größe) wandert mit ins Ergebnis — Basis der
# Duplikat-Warnung („diese Disc wurde schon gerippt")
self.fingerprint = fingerprint
def to_dict(self) -> Dict:
return {
@@ -219,7 +223,8 @@ class PreScanResult:
"year": self.year,
"confidence": self.confidence,
"metadata": self.metadata,
"tracks": self.tracks
"tracks": self.tracks,
"fingerprint": self.fingerprint
}
@@ -361,7 +366,8 @@ class PreScan:
disc_type="CD",
title=album,
tracks=toc["tracks"],
confidence=confidence
confidence=confidence,
fingerprint=toc.get("fingerprint", "")
)
cache_set(cache_key, result.to_dict())
return result
@@ -486,6 +492,16 @@ class PreScan:
"year": None
}
# Deutsche Texte für OMDb-Treffer nachladen (Commander-Wunsch 24.07.):
# OMDb kann nur Englisch — über die IMDb-ID liefert TMDB /find den
# deutschen Titel, die Beschreibung und oft ein besseres Poster.
if matched and metadata.get("source") == "omdb" and str(metadata.get("id", "")).startswith("tt"):
deutsch = self.tmdb.find_by_imdb(metadata["id"])
if deutsch:
for feld in ("title", "overview", "poster_path", "year", "type"):
if deutsch.get(feld):
metadata[feld] = deutsch[feld]
# Bei Treffer den sauberen API-Titel anzeigen statt des Disc-Titels
if matched and metadata.get("title"):
title = metadata["title"]
@@ -496,7 +512,8 @@ class PreScan:
year=metadata.get("year"),
confidence=confidence,
metadata=metadata,
tracks=toc.get("tracks", [])
tracks=toc.get("tracks", []),
fingerprint=toc.get("fingerprint", "")
)
# Nur ECHTE Treffer cachen: ein gecachtes "unknown" würde sonst auch
# nach Key-Eintrag/Fix ewig wieder serviert (Redis ist persistent).