namespace Halo.Core.Library;
/// Eine Datei auf der Platte, so wie der Scan sie vorgefunden hat.
///
///
///
/// Die Datei zeigt auf den Titel, nicht umgekehrt. Das sieht
/// herumgedreht aus und ist Absicht: ein Film liegt oft zweimal vor, als 4K
/// und als 1080p. Trüge der Film den Verweis auf seine eine Datei, wäre die
/// zweite Fassung ein Umbau am Datenmodell — so ist sie eine Zeile mehr.
///
///
/// Genau dasselbe gilt für Folgen.
///
///
public sealed class MediaFile
{
public Guid Id { get; init; } = Guid.CreateVersion7();
public required Guid LibraryId { get; init; }
/// Der Pfad, wie der Server ihn sieht — im Container, nicht auf dem Wirt.
public required string Path { get; set; }
public long SizeBytes { get; set; }
public DateTimeOffset ModifiedAt { get; set; }
/// Wann der letzte Scan diese Datei noch vorgefunden hat.
///
///
/// Daran hängt das Aufräumen: Was ein Lauf nicht gesehen hat, liegt nicht
/// mehr da. Ohne diese Angabe müsste der Scan sich merken, was er gesehen
/// hat, und das wächst mit dem Bestand.
///
public DateTimeOffset SeenAt { get; set; }
public Guid? MovieId { get; set; }
public Guid? EpisodeId { get; set; }
// --- Was ffprobe gelesen hat -----------------------------------------
/// Die Schachtel: mkv, mp4, ts …
public string? Container { get; set; }
public TimeSpan? Duration { get; set; }
public long? BitRate { get; set; }
/// Wann zuletzt untersucht — null, solange nie.
///
///
/// Daran hängt, ob der nächste Scan die Datei erneut untersucht. Ein
/// Durchgang kostet rund fünfzig Millisekunden; bei vierzigtausend Dateien
/// sind das über eine halbe Stunde, und die will niemand bei jedem Lauf
/// erneut aufbringen.
///
public DateTimeOffset? ProbedAt { get; set; }
}
public sealed class Movie
{
public Guid Id { get; init; } = Guid.CreateVersion7();
public required Guid LibraryId { get; init; }
/// Der Titel, wie er aus dem Dateinamen gelesen wurde.
///
///
/// Daran ordnet der Scan zu, nicht an . Der
/// angezeigte Titel kommt nach dem ersten Lauf von der Metadatenquelle und
/// ändert sich dabei — aus „The Matrix" wird „Matrix". Würde der nächste
/// Scan darauf suchen, fände er nichts, legte den Film ein zweites Mal an,
/// und die Mediathek wüchse bei jedem Lauf. Dieses Feld ändert sich nie.
///
public required string ParsedTitle { get; init; }
public required string Title { get; set; }
/// Ohne führenden Artikel — siehe .
public required string SortTitleValue { get; set; }
public int? Year { get; set; }
public string? Overview { get; set; }
/// Die Kennung bei TMDB, sobald zugeordnet.
public int? TmdbId { get; set; }
/// Schlüssel des zwischengespeicherten Plakats — siehe Bildablage.
///
///
/// Der Schlüssel, nicht die Adresse bei TMDB. Würde die App dort unmittelbar
/// laden, bräuchte sie Internet für ein Plakat, das zehn Zentimeter weiter
/// auf der Platte liegt — und TMDB erführe, wer wann was ansieht.
///
public string? PosterImage { get; set; }
public string? BackdropImage { get; set; }
public DateTimeOffset AddedAt { get; init; } = DateTimeOffset.UtcNow;
}
public sealed class Series
{
public Guid Id { get; init; } = Guid.CreateVersion7();
public required Guid LibraryId { get; init; }
/// Der Titel, wie er aus dem Dateinamen gelesen wurde.
///
///
/// Daran ordnet der Scan zu, nicht an . Der
/// angezeigte Titel kommt nach dem ersten Lauf von der Metadatenquelle und
/// ändert sich dabei — aus „The Matrix" wird „Matrix". Würde der nächste
/// Scan darauf suchen, fände er nichts, legte den Film ein zweites Mal an,
/// und die Mediathek wüchse bei jedem Lauf. Dieses Feld ändert sich nie.
///
public required string ParsedTitle { get; init; }
public required string Title { get; set; }
public required string SortTitleValue { get; set; }
public int? Year { get; set; }
public string? Overview { get; set; }
public int? TmdbId { get; set; }
/// Schlüssel des zwischengespeicherten Plakats — siehe Bildablage.
///
///
/// Der Schlüssel, nicht die Adresse bei TMDB. Würde die App dort unmittelbar
/// laden, bräuchte sie Internet für ein Plakat, das zehn Zentimeter weiter
/// auf der Platte liegt — und TMDB erführe, wer wann was ansieht.
///
public string? PosterImage { get; set; }
public string? BackdropImage { get; set; }
public DateTimeOffset AddedAt { get; init; } = DateTimeOffset.UtcNow;
}
public sealed class Episode
{
public Guid Id { get; init; } = Guid.CreateVersion7();
public required Guid SeriesId { get; init; }
public required int SeasonNumber { get; init; }
public required int EpisodeNumber { get; init; }
public string? Title { get; set; }
public string? Overview { get; set; }
/// Das Standbild der Folge.
public string? StillImage { get; set; }
public DateTimeOffset AddedAt { get; init; } = DateTimeOffset.UtcNow;
}