Ampel / ampel (push) Failing after 1m20s
metadaten/: discmerkmale.ts (BDMT-Studio-Titel, ISO-9660- und UDF-Volume-Label direkt vom Medium — OHNE koffi, ueber fs auf \.\G: —, Label-Normalisierung, Fingerabdruck, progressive Titel-Kandidaten), tmdb.ts (v3-Key UND v4-Token, de-DE, /find fuer deutsche Texte zu OMDb-Treffern), omdb.ts, zuordnung.ts (die Confidence-Kaskade 0,95/0,90/0,80/0,60/0,30 aus prescan.py). ablage/poster.ts. Kern meldet 'disc-info' beim Einlegen; die Pipeline benennt den fertigen Ordner '<Titel> (Jahr)', schreibt movie.nfo/tvshow.nfo mit echten Metadaten und laedt das Poster. Fenster zeigt 'sehr wahrscheinlich: … · 95 %'. ZWEI Kaskaden-Schwaechen LIVE GEFUNDEN und gehaertet (gegen die echten APIs gemessen, Keys aus den Docker-Settings der VM, nicht persistiert): 1. 'Spartacus Gods Of The Arena' wurde zum FILM 'Spartacus' (1960) — der stark gekuerzte Kandidat traf woertlich, bevor die volle Anfrage als spezifische SERIE galt. Kaskade jetzt JE KANDIDAT woertlich→spezifisch (spezifisch nur fuer die volle Anfrage, auch fuer Serien). Nachgemessen: jetzt Serie, 90 %. 2. OMDbs t=-Suche machte aus dem Label 'Bd Evg D2' selbstbewusst 'BD Scream 5' — jetzt Wort-Jaccard-Gate >= 0,5. Nachgemessen: der Fall ist jetzt ein ehrlicher 60-%-Vorschlag, den das UI nachfragt. Messwerte: Akira→95% · Evangelion 2.22→80% (der dokumentierte Fund) · Spartacus GotA→Serie 90% · Bd Evg D2→Vorschlag 60%. Dazu ein neuer Quelltext-Hygiene-Waechter (keine rohen Steuerbytes — zweimal beim Schreiben passiert, einmal haette ein Test dadurch anders gemessen als gelesen). 165 Tests gruen, Smoke gruen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
31 lines
1.1 KiB
TypeScript
31 lines
1.1 KiB
TypeScript
// Poster/Fanart neben den Film legen (KONZEPT § 6.10) — Regeln aus
|
|
// medien.py: relative TMDb-Pfade bekommen das w500-Präfix; ein fehlendes
|
|
// Poster darf einen gelungenen Rip NIE kippen (best effort, aber die
|
|
// Meldung sagt was passiert ist).
|
|
import { writeFileSync } from 'node:fs'
|
|
|
|
export function posterUrl(posterPfad: string): string {
|
|
if (posterPfad.length === 0) return ''
|
|
if (posterPfad.startsWith('http')) return posterPfad
|
|
return `https://image.tmdb.org/t/p/w500${posterPfad}`
|
|
}
|
|
|
|
export async function posterSpeichern(
|
|
posterPfad: string,
|
|
zielDatei: string,
|
|
holen: typeof fetch = fetch,
|
|
): Promise<string> {
|
|
const url = posterUrl(posterPfad)
|
|
if (url.length === 0) return ''
|
|
try {
|
|
const antwort = await holen(url, { signal: AbortSignal.timeout(15_000) })
|
|
if (antwort.status !== 200) return `Poster: HTTP ${antwort.status}`
|
|
const daten = Buffer.from(await antwort.arrayBuffer())
|
|
if (daten.length === 0) return 'Poster: leere Antwort'
|
|
writeFileSync(zielDatei, daten)
|
|
return 'poster.jpg gespeichert'
|
|
} catch (fehler) {
|
|
return `Poster fehlgeschlagen: ${String(fehler)}`
|
|
}
|
|
}
|