using ErsatzTV.Core.Domain; namespace ErsatzTV.Application.Channels; /// /// Shared programme-metadata projection for guide output. Both the XMLTV cache builder /// () and the JSON guide query /// () resolve the display title/subtitle/category from a /// here so the two representations stay consistent. /// public static class ChannelGuideMetadata { public static string GetTitle(PlayoutItem playoutItem) { if (!string.IsNullOrWhiteSpace(playoutItem.CustomTitle)) { return playoutItem.CustomTitle; } return playoutItem.MediaItem switch { Movie m => m.MovieMetadata.HeadOrNone().Map(mm => mm.Title ?? string.Empty) .IfNone("[unknown movie]"), Episode e => e.Season.Show.ShowMetadata.HeadOrNone().Map(em => em.Title ?? string.Empty) .IfNone("[unknown show]"), MusicVideo mv => mv.Artist.ArtistMetadata.HeadOrNone().Map(am => am.Title ?? string.Empty) .IfNone("[unknown artist]"), OtherVideo ov => ov.OtherVideoMetadata.HeadOrNone().Map(vm => vm.Title ?? string.Empty) .IfNone("[unknown video]"), RemoteStream rs => rs.RemoteStreamMetadata.HeadOrNone().Map(vm => vm.Title ?? string.Empty) .IfNone("[unknown remote stream]"), _ => "[unknown]" }; } public static string GetSubtitle(PlayoutItem playoutItem) { if (!string.IsNullOrWhiteSpace(playoutItem.CustomTitle)) { return string.Empty; } return playoutItem.MediaItem switch { Episode e => e.EpisodeMetadata.HeadOrNone().Match( em => em.Title ?? string.Empty, () => string.Empty), MusicVideo mv => mv.MusicVideoMetadata.HeadOrNone().Match( mvm => mvm.Title ?? string.Empty, () => string.Empty), Song s => s.SongMetadata.HeadOrNone().Match( mvm => mvm.Title ?? string.Empty, () => string.Empty), _ => string.Empty }; } /// /// The primary guide category, mirroring the fixed <category> the XMLTV templates /// emit per media kind (Movie / Series / Music). Media kinds without a fixed category return null. /// public static string GetCategory(PlayoutItem playoutItem) => playoutItem.MediaItem switch { Movie => "Movie", Episode => "Series", MusicVideo => "Music", Song => "Music", _ => null }; }