Eine Mediathek für alles, was in keinem Katalog steht

Urlaubsaufnahmen, Mitschnitte, Vorträge. Jedes Verfahren, das bei Filmen
richtig ist, wäre hier falsch: „Sommer 2019 Teil 2" ist kein Film von 2019,
zwei Aufnahmen desselben Tages sind nicht zwei Fassungen derselben Sache,
und in keinem Katalog steht, was da liegt.

Die neue Art `Videos` nimmt den Dateinamen als Titel, zerlegt nichts, legt
nichts zusammen und fragt niemanden. Der Pfad ist dabei der
Vergleichsschlüssel, nicht der Name — zwei Dateien „Ausflug.mp4" in zwei
Ordnern sind zwei Ausflüge.

**Der Unterordner wird zur Kategorie.** Statt eine eigene Gruppierung zu
bauen, bekommt jedes Video den Namen seines Ordners als Genre. Damit
greifen Filter, Kategorienansicht und Suche, ohne dass es in der Oberfläche
etwas Neues gibt. Eine zweite Gruppierung daneben hiesse: zwei Wege für
dasselbe, und einer davon wäre überall sonst ungepflegt.

Die Anreicherung übergeht jetzt alles, was `MatchLocked` trägt. Das galt
bisher nur für von Hand korrigierte Zuordnungen und gilt damit auch hier —
eine Suche nach „Abend am Feuer" fände irgendeinen fremden Film, und der
stünde danach mit Plakat und Beschreibung in der Urlaubsmediathek.

Geprüft: vier Dateien in zwei Ordnern ergeben vier Titel mit ihren
Dateinamen, keine Jahre, keinen fremden Treffer — und genau zwei
Kategorien, denn was direkt in der Wurzel liegt, bekommt keine.

742 Tests grün, davon zwei neue.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-08 21:36:06 +02:00
co-authored by Claude Opus 5
parent af2b844d65
commit c13d1e78d2
7 changed files with 240 additions and 5 deletions
@@ -561,6 +561,84 @@ public class MetadataTests
}
/// <summary>Eine Videomediathek nimmt den Dateinamen und fragt niemanden.</summary>
///
/// <remarks>
/// <para>
/// <b>Für alles, was in keinem Katalog steht.</b> Urlaubsaufnahmen,
/// Mitschnitte, Vorträge. Jedes der Verfahren, die bei Filmen richtig
/// sind, wäre hier falsch: „Sommer 2019 Teil 2" ist kein Film von 2019,
/// und zwei Aufnahmen desselben Tages sind nicht zwei Fassungen
/// derselben Sache.
/// </para>
/// <para>
/// <b>Der Unterordner wird zur Kategorie</b> — damit greifen Filter und
/// Kategorienansicht, ohne dass es dort etwas Neues gibt.
/// </para>
/// </remarks>
[Test]
public async Task Eine_Videomediathek_nimmt_den_Dateinamen_als_Titel()
{
Datei("Ferien 2019/Ausflug zum See.mp4");
Datei("Ferien 2019/Abend am Feuer.mp4");
Datei("Vortraege/Wie Dateisysteme altern.mp4");
Datei("Direkt daneben.mp4");
// Die Quelle würde antworten — gefragt werden darf sie trotzdem nicht.
var anbieter = new VorgegebenerAnbieter
{
Film = new MovieMetadata(999, "Irgendein fremder Film", 1999, null, null, null),
};
using var server = MitAnbieter(anbieter);
var (client, bibliothek) = await Einrichten(server, "Videos");
await Scannen(client, bibliothek);
var filme = await client.GetFromJsonAsync<Page<MovieResponse>>("/api/v1/movies");
var titel = filme!.Items.Select(f => f.Title).ToList();
Assert.Multiple(() =>
{
Assert.That(titel, Is.EquivalentTo(new[]
{
"Ausflug zum See", "Abend am Feuer", "Wie Dateisysteme altern", "Direkt daneben",
}));
Assert.That(filme.Items.All(f => f.Year is null), Is.True,
"der Ordnername Ferien 2019 ist kein Erscheinungsjahr");
Assert.That(titel, Has.No.Member("Irgendein fremder Film"),
"die Metadatenquelle wird hier nicht gefragt");
});
var kategorien = await client.GetFromJsonAsync<List<string>>(
$"/api/v1/libraries/{bibliothek}/genres");
Assert.That(kategorien, Is.EquivalentTo(new[] { "Ferien 2019", "Vortraege" }),
"die Unterordner werden zu Kategorien; was direkt in der Wurzel liegt, bekommt keine");
}
/// <summary>Zwei gleichnamige Dateien in zwei Ordnern sind zwei Einträge.</summary>
///
/// <remarks>
/// Bei Filmen sucht der Scanner einen vorhandenen Eintrag und hängt die
/// Datei dort an — so finden zwei Fassungen zusammen. Hier wäre das
/// falsch: zwei „Ausflug.mp4" in zwei Ordnern sind zwei Ausflüge.
/// </remarks>
[Test]
public async Task Gleichnamige_Videos_werden_nicht_zusammengelegt()
{
Datei("Mai/Ausflug.mp4");
Datei("Juni/Ausflug.mp4");
using var server = MitAnbieter(new VorgegebenerAnbieter());
var (client, bibliothek) = await Einrichten(server, "Videos");
await Scannen(client, bibliothek);
var filme = await client.GetFromJsonAsync<Page<MovieResponse>>("/api/v1/movies");
Assert.That(filme!.Items, Has.Count.EqualTo(2),
"zwei Dateien gleichen Namens in zwei Ordnern sind zwei Aufnahmen");
}
/// <summary>Eine abgehakte Gruppe verlässt die Liste — und kommt zurück, wenn eine Datei dazukommt.</summary>
///
/// <remarks>