using System.Reflection; using ErsatzTV.Core; namespace ErsatzTV.Services.RunOnce; public class ResourceExtractorService : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await Task.Yield(); if (!Directory.Exists(FileSystemLayout.ResourcesCacheFolder)) { Directory.CreateDirectory(FileSystemLayout.ResourcesCacheFolder); } Assembly assembly = typeof(ResourceExtractorService).GetTypeInfo().Assembly; await ExtractResource(assembly, "_background.png", stoppingToken); await ExtractResource(assembly, "_song_album_cover_512.png", stoppingToken); await ExtractResource(assembly, "_song_background_1.png", stoppingToken); await ExtractResource(assembly, "_song_background_2.png", stoppingToken); await ExtractResource(assembly, "_song_background_3.png", stoppingToken); await ExtractResource(assembly, "song_progress_overlay.png", stoppingToken); await ExtractResource(assembly, "song_progress_overlay_43.png", stoppingToken); await ExtractResource(assembly, "ErsatzTV.png", stoppingToken); await ExtractResource(assembly, "sequential-schedule.schema.json", stoppingToken); await ExtractResource(assembly, "sequential-schedule-import.schema.json", stoppingToken); await ExtractResource(assembly, "test.avs", stoppingToken); await ExtractFontResource(assembly, "Sen.ttf", stoppingToken); await ExtractFontResource(assembly, "Roboto-Regular.ttf", stoppingToken); await ExtractFontResource(assembly, "OPTIKabel-Heavy.otf", stoppingToken); await ExtractTemplateResource( assembly, "_default.ass.sbntxt", FileSystemLayout.MusicVideoCreditsTemplatesFolder, stoppingToken); await ExtractTemplateResource( assembly, "_ArtistTitle_LeftMiddle.sbntxt", FileSystemLayout.MusicVideoCreditsTemplatesFolder, stoppingToken); await ExtractTemplateResource( assembly, "_ArtistTitleAlbum_CenterTop.sbntxt", FileSystemLayout.MusicVideoCreditsTemplatesFolder, stoppingToken); await ExtractTemplateResource( assembly, "_channel.sbntxt", FileSystemLayout.ChannelGuideTemplatesFolder, stoppingToken); await ExtractTemplateResource( assembly, "_movie.sbntxt", FileSystemLayout.ChannelGuideTemplatesFolder, stoppingToken); await ExtractTemplateResource( assembly, "_episode.sbntxt", FileSystemLayout.ChannelGuideTemplatesFolder, stoppingToken); await ExtractTemplateResource( assembly, "_musicVideo.sbntxt", FileSystemLayout.ChannelGuideTemplatesFolder, stoppingToken); await ExtractTemplateResource( assembly, "_song.sbntxt", FileSystemLayout.ChannelGuideTemplatesFolder, stoppingToken); await ExtractTemplateResource( assembly, "_otherVideo.sbntxt", FileSystemLayout.ChannelGuideTemplatesFolder, stoppingToken); await ExtractTemplateResource( assembly, "_remoteStream.sbntxt", FileSystemLayout.ChannelGuideTemplatesFolder, stoppingToken); await ExtractScriptResource( assembly, "_threePartEpisodes.js", FileSystemLayout.MultiEpisodeShuffleTemplatesFolder, stoppingToken); await ExtractScriptResource( assembly, "_episode.js", FileSystemLayout.AudioStreamSelectorScriptsFolder, stoppingToken); await ExtractScriptResource( assembly, "_movie.js", FileSystemLayout.AudioStreamSelectorScriptsFolder, stoppingToken); await ExtractMpegTsScriptResource( assembly, "run.sh", FileSystemLayout.DefaultMpegTsScriptFolder, stoppingToken); await ExtractMpegTsScriptResource( assembly, "run.bat", FileSystemLayout.DefaultMpegTsScriptFolder, stoppingToken); await ExtractMpegTsScriptResource( assembly, "mpegts.yml", FileSystemLayout.DefaultMpegTsScriptFolder, stoppingToken); } private static async Task ExtractResource(Assembly assembly, string name, CancellationToken cancellationToken) { await using Stream resource = assembly.GetManifestResourceStream($"ErsatzTV.Resources.{name}"); if (resource != null) { await using FileStream fs = File.Create(Path.Combine(FileSystemLayout.ResourcesCacheFolder, name)); await resource.CopyToAsync(fs, cancellationToken); } } private static async Task ExtractFontResource(Assembly assembly, string name, CancellationToken cancellationToken) { await using Stream resource = assembly.GetManifestResourceStream($"ErsatzTV.Resources.Fonts.{name}"); if (resource != null) { await using FileStream fs = File.Create(Path.Combine(FileSystemLayout.ResourcesCacheFolder, name)); await resource.CopyToAsync(fs, cancellationToken); resource.Position = 0; await using FileStream fontCacheFileStream = File.Create(Path.Combine(FileSystemLayout.FontsCacheFolder, name)); await resource.CopyToAsync(fontCacheFileStream, cancellationToken); } } private static async Task ExtractTemplateResource( Assembly assembly, string name, string targetFolder, CancellationToken cancellationToken) { await using Stream resource = assembly.GetManifestResourceStream($"ErsatzTV.Resources.Templates.{name}"); if (resource != null) { await using FileStream fs = File.Create(Path.Combine(targetFolder, name)); await resource.CopyToAsync(fs, cancellationToken); } } private static async Task ExtractScriptResource( Assembly assembly, string name, string targetFolder, CancellationToken cancellationToken) { await using Stream resource = assembly.GetManifestResourceStream($"ErsatzTV.Resources.Scripts.{name}"); if (resource != null) { await using FileStream fs = File.Create(Path.Combine(targetFolder, name)); await resource.CopyToAsync(fs, cancellationToken); } } private static async Task ExtractMpegTsScriptResource( Assembly assembly, string name, string targetFolder, CancellationToken cancellationToken) { await using Stream resource = assembly.GetManifestResourceStream($"ErsatzTV.Resources.Scripts.MpegTs.{name}"); if (resource != null) { await using FileStream fs = File.Create(Path.Combine(targetFolder, name)); await resource.CopyToAsync(fs, cancellationToken); } } }