From 0c07d4efc74a1ed2eaefce850b40532d2a33f97a Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Sun, 4 Oct 2026 21:14:55 +0200 Subject: [PATCH] Ein falscher Treffer verhinderte seine eigene Korrektur MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit „Doctor Strange" war fälschlich auf ein Making-of von 2022 gelaufen. Beim Korrigieren hängte die Vorschlagssuche `year=2022` an — aus genau der Zuordnung, die weg sollte — und lieferte nur noch Titel von 2022. Der richtige Film von 2016 konnte gar nicht erscheinen, egal wie oft man suchte. An TMDB nachgemessen: query='Doctor Strange' ohne Jahr → 2016 Doctor Strange, 2022 Multiverse … query='Doctor Strange' mit year=2022 → genau die drei Treffer aus der Meldung Gesucht wird jetzt mit dem Jahr aus dem Dateinamen, nie mit dem aus dem Treffer. Die Oberfläche trägt ebenfalls keines mehr vor: das angezeigte stammt aus derselben falschen Zuordnung. Co-Authored-By: Claude Opus 5 --- .../src/Flaro.Api/Endpoints/MatchEndpoints.cs | 15 ++++++- server/tests/Flaro.Api.Tests/MetadataTests.cs | 42 ++++++++++++++++++- web/app/src/card.ts | 7 +++- web/app/src/views/admin.ts | 3 +- web/app/src/zuordnung.ts | 5 ++- 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/server/src/Flaro.Api/Endpoints/MatchEndpoints.cs b/server/src/Flaro.Api/Endpoints/MatchEndpoints.cs index 153da53..b95b44c 100644 --- a/server/src/Flaro.Api/Endpoints/MatchEndpoints.cs +++ b/server/src/Flaro.Api/Endpoints/MatchEndpoints.cs @@ -132,7 +132,16 @@ public static class MatchEndpoints // Ohne eigene Suchworte das, was aus dem Dateinamen gelesen wurde // — nicht der angezeigte Titel, der ja gerade der falsche ist. var vorschläge = await anbieter.SearchMoviesAsync( - string.IsNullOrWhiteSpace(query) ? film.ParsedTitle : query.Trim(), year ?? film.Year); + string.IsNullOrWhiteSpace(query) ? film.ParsedTitle : query.Trim(), + // **Das Jahr aus dem Dateinamen, nicht das aus der Zuordnung.** + // + // Hier stand `film.Year` — und das kommt von genau der + // Zuordnung, die gerade korrigiert werden soll. „Doctor + // Strange" war fälschlich auf ein Making-of von 2022 + // gelaufen; die Suche hängte daraufhin `year=2022` an, und der + // richtige Film von 2016 konnte gar nicht mehr auftauchen. Ein + // falscher Treffer verhinderte so seine eigene Korrektur. + year ?? film.ParsedYear); return Results.Ok(vorschläge.Select(v => new MatchCandidate(v.ProviderId, v.Title, v.Year, v.Overview, v.Poster?.Url)).ToList()); @@ -161,7 +170,9 @@ public static class MatchEndpoints if (serie is null) return Results.NotFound(); var vorschläge = await anbieter.SearchSeriesAsync( - string.IsNullOrWhiteSpace(query) ? serie.ParsedTitle : query.Trim(), year ?? serie.Year); + string.IsNullOrWhiteSpace(query) ? serie.ParsedTitle : query.Trim(), + // Siehe oben: aus dem Dateinamen, nicht aus der Zuordnung. + year ?? serie.ParsedYear); return Results.Ok(vorschläge.Select(v => new MatchCandidate(v.ProviderId, v.Title, v.Year, v.Overview, v.Poster?.Url)).ToList()); diff --git a/server/tests/Flaro.Api.Tests/MetadataTests.cs b/server/tests/Flaro.Api.Tests/MetadataTests.cs index 95660f7..899e93c 100644 --- a/server/tests/Flaro.Api.Tests/MetadataTests.cs +++ b/server/tests/Flaro.Api.Tests/MetadataTests.cs @@ -55,7 +55,9 @@ public sealed class VorgegebenerAnbieter : IMetadataProvider public Task> SearchMoviesAsync(string t, int? j, CancellationToken ct = default) { - Gefragt.Add($"suchFilm:{t}"); + // Mit Jahr: genau daran hing der Fehler, dass ein falscher Treffer + // seine eigene Korrektur verhinderte. + Gefragt.Add($"suchFilm:{t}:{j}"); return Task.FromResult>(Film is null ? [] : [Film]); } @@ -314,6 +316,44 @@ public class MetadataTests Assert.That(nachher!.Items[0].Title, Is.EqualTo("Von Hand")); } + /// Eine falsche Zuordnung darf ihre eigene Korrektur nicht verhindern. + /// + /// + /// Aus dem echten Bestand. „Doctor Strange" war fälschlich auf ein + /// Making-of von 2022 gelaufen. Beim Korrigieren hängte die Suche + /// year=2022 an — aus genau der Zuordnung, die gerade weg sollte — + /// und lieferte nur noch Titel von 2022. Der richtige Film von 2016 konnte + /// gar nicht erscheinen. Gesucht wird deshalb mit dem Jahr aus dem + /// Dateinamen, nie mit dem aus dem Treffer. + /// + [Test] + public async Task Die_Vorschlagssuche_nimmt_das_Jahr_aus_dem_Dateinamen() + { + Datei("Doctor Strange (2016).mkv"); + var anbieter = new VorgegebenerAnbieter + { + // Der falsche Treffer: anderes Jahr als im Dateinamen. + Film = new MovieMetadata(980017, "Das Making of", 2022, null, null, null) + { + Language = "de-DE", + }, + }; + + using var server = MitAnbieter(anbieter); + var (client, bibliothek) = await Einrichten(server, "Movies"); + await Scannen(client, bibliothek); + + var filme = await client.GetFromJsonAsync>("/api/v1/movies"); + Assert.That(filme!.Items[0].Year, Is.EqualTo(2022), "Der falsche Treffer sitzt."); + + anbieter.Gefragt.Clear(); + await client.GetFromJsonAsync>( + $"/api/v1/movies/{filme.Items[0].Id}/matches"); + + Assert.That(anbieter.Gefragt, Does.Contain("suchFilm:Doctor Strange:2016"), + "Gesucht wird mit 2016 aus dem Dateinamen, nicht mit 2022 aus dem Treffer."); + } + [Test] public async Task Ein_Film_ohne_Treffer_behaelt_seinen_Dateinamen() { diff --git a/web/app/src/card.ts b/web/app/src/card.ts index 39e8408..4d155f6 100644 --- a/web/app/src/card.ts +++ b/web/app/src/card.ts @@ -284,8 +284,11 @@ function kachelpunkte( icon: 'suche', // **Hier und nicht nur auf der Detailseite.** Wer zwanzig falsch // erkannte Titel vor sich hat, soll sie hier geradeziehen können. - tun: () => zuordnungsdialog(art, k.id, k.titel, - k.zweite && /^\d{4}$/.test(k.zweite) ? Number(k.zweite) : null, + // **Ohne Jahr.** Das angezeigte stammt aus der Zuordnung, die gerade + // korrigiert werden soll — bei einem falschen Treffer grenzt es die + // Suche auf genau das falsche Jahr ein. Ohne Angabe nimmt der Server + // das aus dem Dateinamen. + tun: () => zuordnungsdialog(art, k.id, k.titel, null, // **Nur die Kachel, nicht die Seite.** `location.reload()` warf // Bildlauf, Filter und offene Reiter weg — für einen Titel, der sich // geändert hat. Bei zwanzig Korrekturen hintereinander ist das diff --git a/web/app/src/views/admin.ts b/web/app/src/views/admin.ts index d518fdd..b76a61e 100644 --- a/web/app/src/views/admin.ts +++ b/web/app/src/views/admin.ts @@ -342,7 +342,8 @@ function pruefbereich(geaendert: () => void): HTMLElement { { text: 'Bilder bearbeiten', icon: 'stift', tun: () => bilddialog(art, e.id, e.title) }, { text: 'Zuordnung korrigieren', icon: 'suche', - tun: () => zuordnungsdialog(art, e.id, e.title, e.year, () => void laden()) }, + // Ohne Jahr — siehe card.ts: das der falschen Zuordnung grenzt falsch ein. + tun: () => zuordnungsdialog(art, e.id, e.title, null, () => void laden()) }, ]; mehr.onclick = () => menueAnZiel(mehr, punkte()); kontextmenue(mehr, punkte); diff --git a/web/app/src/zuordnung.ts b/web/app/src/zuordnung.ts index 43181ef..c774bb0 100644 --- a/web/app/src/zuordnung.ts +++ b/web/app/src/zuordnung.ts @@ -72,7 +72,10 @@ export function zuordnungsdialog( const suche = feld('Anderer Suchbegriff'); suche.value = titel; - const jahrfeld = feld('Jahr', 'number'); + // Leer heisst: der Server nimmt das Jahr aus dem Dateinamen. Hier etwas + // vorzutragen, das aus der zu korrigierenden Zuordnung stammt, hiesse die + // Suche auf genau den falschen Jahrgang einzugrenzen. + const jahrfeld = feld('Jahr (aus dem Dateinamen)', 'number'); if (jahr) jahrfeld.value = String(jahr); const suchen = knopf('Suchen', 'btn');