namespace Halo.Api.Endpoints; // Was über die Leitung geht. Bewusst eigene Typen und nicht die der Domäne: // sonst wandert jede Umbenennung im Datenmodell ungefragt in die Schnittstelle // und bricht Clients, die niemand mehr aktualisiert. public sealed record SystemInfo(string Version, bool NeedsSetup); public sealed record SetupRequest(string UserName, string Password); public sealed record LoginRequest(string UserName, string Password, string DeviceName, string DeviceId); public sealed record AuthenticatedUser(Guid Id, string UserName, bool IsAdministrator); public sealed record LoginResponse(string Token, AuthenticatedUser User); public sealed record CodeRequest(string DeviceName, string DeviceId); /// Was der Fernseher nach dem Anfordern bekommt. /// /// /// Der Handle ist das Geheimnis und wird nicht angezeigt — der /// Code ist das, was auf dem Bildschirm steht. /// public sealed record CodeResponse(string Code, string Handle, DateTimeOffset ExpiresAt); public sealed record CodeState(string State, LoginResponse? Login); public sealed record CreateUserRequest(string UserName, string Password, bool IsAdministrator); public sealed record LibraryResponse(Guid Id, string Name, string Kind, string Path); public sealed record CreateLibraryRequest(string Name, string Kind, string Path); // --- Stufe 2: Bibliothek ------------------------------------------------- public sealed record ScanProblem(string Path, string Reason); public sealed record ScanStatus( string State, DateTimeOffset? StartedAt, DateTimeOffset? FinishedAt, int? FilesFound, int? Added, int? Updated, int? Removed, int? Unrecognised, int? Probed, IReadOnlyList? Problems, string? Error, MetadataProgress? Metadata); /// Was das Nachschlagen bei der Metadatenquelle ergeben hat. public sealed record MetadataProgress( int MoviesMatched, int SeriesMatched, int EpisodesMatched, bool Skipped, string? Error); /// Eine Spur in einer Datei. public sealed record MediaStreamResponse( int Index, string Kind, string? Codec, string? Language, string? Title, bool IsDefault, bool IsForced, int? Channels, int? Width, int? Height); /// Eine Datei hinter einem Titel — eine Fassung also. /// /// /// Nur der Dateiname, nicht der Pfad. Der Pfad verriete jedem /// Angemeldeten den Aufbau des Servers, und gebraucht wird er nirgends: die /// App spricht Dateien über ihre Kennung an. Zum Unterscheiden zweier /// Fassungen genügt der Name. /// public sealed record MediaFileResponse( Guid Id, string FileName, long SizeBytes, string? Container, double? DurationSeconds, IReadOnlyList Streams); public sealed record MovieResponse( Guid Id, string Title, int? Year, string? Overview, string? PosterImage, string? BackdropImage, IReadOnlyList Files); public sealed record SeriesResponse( Guid Id, string Title, int? Year, string? Overview, string? PosterImage, string? BackdropImage, int EpisodeCount, IReadOnlyList Seasons); public sealed record EpisodeResponse( Guid Id, int Season, int Episode, string? Title, string? Overview, string? StillImage, IReadOnlyList Files); public sealed record Page(IReadOnlyList Items, int Total); public sealed record MetadataSettingsResponse(bool HasApiKey, string Language); public sealed record MetadataSettingsRequest(string? ApiKey, string? Language); // --- Stufe 3: Ausliefern ------------------------------------------------- /// Was mit einer Datei geschehen wird, bevor sie hinausgeht. /// /// /// Damit vorher feststeht, was man bekommt. Drei Gigabyte /// herunterzuladen und erst danach zu merken, dass die Untertitel fehlen oder /// die falsche Tonspur drin ist, war der Anlass für dieses ganze Projekt. /// public sealed record DeliveryInfo( string Method, IReadOnlyList Reasons, IReadOnlyList AudioToEncode, IReadOnlyList SubtitlesDropped, string PackageState, double Progress, string? Error);