Skip to content

Commit

Permalink
fix: Custom logo selection
Browse files Browse the repository at this point in the history
  • Loading branch information
carlreid committed Feb 19, 2025
1 parent 7bf8157 commit a32defb
Show file tree
Hide file tree
Showing 9 changed files with 523 additions and 515 deletions.
23 changes: 21 additions & 2 deletions src/StreamMaster.Application/EPG/Commands/XMLTVBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System.Collections.Concurrent;
using System;
using System.Collections.Concurrent;
using System.Globalization;

using Microsoft.AspNetCore.Http;

using StreamMaster.Domain.Crypto;
using StreamMaster.Domain.XML;
using StreamMaster.Domain.XmltvXml;

namespace StreamMaster.Application.EPG.Commands;

Expand Down Expand Up @@ -248,7 +250,7 @@ private void ProcessCustomPlaylists(XMLTV xmlTv, List<VideoStreamConfig> customC

channels.Add(channel);

List<XmltvProgramme> newProgrammes = logoService.GetXmltvProgrammeForPeriod(config, SMDT.UtcNow, sdSettingsMonitor.CurrentValue.SDEPGDays, config.BaseUrl);
List<XmltvProgramme> newProgrammes = GetXmltvProgrammeForPeriod(config, SMDT.UtcNow, sdSettingsMonitor.CurrentValue.SDEPGDays, config.BaseUrl);
foreach (XmltvProgramme programme in newProgrammes)
{
programme.Channel = config.OutputProfile!.Id;
Expand All @@ -261,6 +263,23 @@ private void ProcessCustomPlaylists(XMLTV xmlTv, List<VideoStreamConfig> customC
xmlTv.Programs.AddRange(programs);
}

public List<XmltvProgramme> GetXmltvProgrammeForPeriod(VideoStreamConfig videoStreamConfig, DateTime startDate, int days, string baseUrl)
{
List<(Movie Movie, DateTime StartTime, DateTime EndTime)> moviesForPeriod = customPlayListBuilder.GetMoviesForPeriod(videoStreamConfig.Name, startDate, days);
List<XmltvProgramme> ret = [];
foreach ((Movie Movie, DateTime StartTime, DateTime EndTime) x in moviesForPeriod)
{
var xmltvProgramme = XmltvProgrammeConverter.ConvertMovieToXmltvProgramme(x.Movie, videoStreamConfig.EPGId, x.StartTime, x.EndTime);
if (x.Movie.Thumb is not null && !string.IsNullOrEmpty(x.Movie.Thumb.Text))
{
string src = $"/api/files/smChannelLogo/{videoStreamConfig.ChannelNumber}";
xmltvProgramme.Icons = [new XmltvIcon { Src = src }];
}
ret.Add(xmltvProgramme);
}
return ret;
}

private (List<XmltvChannel> xmltvChannels, List<XmltvProgramme> programs) ProcessXML(XMLTV xml, List<VideoStreamConfig> videoStreamConfigs)
{
string baseUrl = GetUrlWithPath();
Expand Down
10 changes: 0 additions & 10 deletions src/StreamMaster.Domain/Services/ILogoService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,8 @@ public interface ILogoService

Task<(FileStream? fileStream, string? FileName, string? ContentType)> GetLogoAsync(string fileName, CancellationToken cancellationToken);

//Task<(FileStream? fileStream, string? FileName, string? ContentType)> GetLogoFromCacheAsync(string source, SMFileTypes fileType, CancellationToken cancellationToken);
Task<(FileStream? fileStream, string? FileName, string? ContentType)> GetLogoForChannelAsync(int SMChannelId, CancellationToken cancellationToken);

//string GetLogoUrl2(string logoSource, SMFileTypes logoType);
List<XmltvProgramme> GetXmltvProgrammeForPeriod(VideoStreamConfig videoStreamConfig, DateTime startDate, int days, string baseUrl);

/// <summary>
/// Adds a new logo based on the specified artwork URI and title.
/// </summary>
Expand All @@ -42,12 +38,6 @@ void AddLogoToCache(
SMFileTypes sMFileType,
bool HashSource = false);

/// <summary>
/// Adds a new logo using the specified <see cref="LogoFileDto"/>.
/// </summary>
/// <param name="logoFile">The logo file DTO containing logo details.</param>
void CacheLogo(CustomLogoDto logoFile, bool OG = false);

/// <summary>
/// Builds the logo cache using the current streams asynchronously.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -605,9 +605,11 @@ public async Task<APIResponse> SetSMChannelLogo(int SMChannelId, string logo)
string.IsNullOrWhiteSpace(logo) ||
!(
logo.StartsWithIgnoreCase("http") ||
logo.StartsWithIgnoreCase("/images/") ||
logo.StartsWithIgnoreCase("/images/") ||
logo.StartsWithIgnoreCase("data:") ||
logo.StartsWithIgnoreCase("/api/files/cu/")
logo.StartsWithIgnoreCase("/api/files/lc/") ||
logo.StartsWithIgnoreCase("/api/files/cu/") ||
logo.StartsWithIgnoreCase("/api/files/tv/")
)
)
{
Expand Down Expand Up @@ -638,11 +640,12 @@ public async Task<APIResponse> SetSMChannelLogo(int SMChannelId, string logo)
channel.Logo = logo;

Update(channel);
_ = await SaveChangesAsync();
await SaveChangesAsync();

return APIResponse.Success;
}


public async Task<APIResponse> SetSMChannelName(int sMChannelId, string name)
{
SMChannel? channel = GetSMChannel(sMChannelId);
Expand Down
192 changes: 77 additions & 115 deletions src/StreamMaster.Infrastructure/Services/LogoService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Web;

Expand All @@ -20,16 +19,12 @@
using StreamMaster.Domain.Extensions;
using StreamMaster.Domain.Helpers;
using StreamMaster.Domain.Repository;
using StreamMaster.Domain.Services;
using StreamMaster.Domain.XmltvXml;
using StreamMaster.PlayList;
using StreamMaster.PlayList.Models;
using StreamMaster.SchedulesDirect.Domain.Interfaces;

namespace StreamMaster.Infrastructure.Services;

public class LogoService(ICustomPlayListBuilder customPlayListBuilder,
IHttpContextAccessor httpContextAccessor,
public class LogoService(IHttpContextAccessor httpContextAccessor,
IOptionsMonitor<Setting> settings,
IOptionsMonitor<CustomLogoDict> customLogos,
IImageDownloadService imageDownloadService,
Expand All @@ -45,23 +40,6 @@ public class LogoService(ICustomPlayListBuilder customPlayListBuilder,
private ConcurrentDictionary<string, CustomLogoDto> Logos { get; } = [];
private static readonly SemaphoreSlim scantvLogoSemaphore = new(1, 1);

public List<XmltvProgramme> GetXmltvProgrammeForPeriod(VideoStreamConfig videoStreamConfig, DateTime startDate, int days, string baseUrl)
{
List<(Movie Movie, DateTime StartTime, DateTime EndTime)> movies = customPlayListBuilder.GetMoviesForPeriod(videoStreamConfig.Name, startDate, days);
List<XmltvProgramme> ret = [];
foreach ((Movie Movie, DateTime StartTime, DateTime EndTime) x in movies)
{
XmltvProgramme programme = XmltvProgrammeConverter.ConvertMovieToXmltvProgramme(x.Movie, videoStreamConfig.EPGId, x.StartTime, x.EndTime);
if (x.Movie.Thumb is not null && !string.IsNullOrEmpty(x.Movie.Thumb.Text))
{
string src = $"/api/files/smChannelLogo/{videoStreamConfig.ChannelNumber}";// GetLogoUrl(x.Movie.Thumb.Text, baseUrl, SMStreamTypeEnum.CustomPlayList);
programme.Icons = [new XmltvIcon { Src = src }];
}
ret.Add(programme);
}
return ret;
}

#region Custom Logo

public string AddCustomLogo(string Name, string Source)
Expand Down Expand Up @@ -428,17 +406,6 @@ private string GetContentType(string fileName)
return string.IsNullOrEmpty(fullPath) ? null : !File.Exists(fullPath) ? null : fullPath;
}

public void CacheLogo(CustomLogoDto logoFile, bool OG = false)
{
if (!OG)
{
string url = $"/api/files/5/{logoFile.Source}";
logoFile.Source = url;
}

Logos.TryAdd(logoFile.Source, logoFile);
}

public void AddLogoToCache(string source, string title, SMFileTypes sMFileType)
{
AddLogoToCache(source, source, title, sMFileType, false);
Expand Down Expand Up @@ -489,112 +456,114 @@ public void ClearLogos()
{
string url = HttpUtility.UrlDecode(URL);

if (fileType == SMFileTypes.CustomLogo)
switch (fileType)
{
string LogoReturnName = Path.GetFileName(url);
string? cachedFile = GetCachedFile(url, fileType);
return cachedFile != null
? new ImagePath
case SMFileTypes.Logo:
{
ReturnName = LogoReturnName,
FullPath = cachedFile,
SMFileType = SMFileTypes.CustomLogo
string logoReturnName = Path.GetFileName(url);
string? cachedFile = GetCachedFile(url, fileType);
return cachedFile != null
? new ImagePath
{
ReturnName = logoReturnName,
FullPath = cachedFile,
SMFileType = SMFileTypes.Logo
}
: null;
}
: null;
}

if (fileType == SMFileTypes.ProgramLogo)
{
string LogoReturnName = Path.GetFileName(url);
string? cachedFile = GetCachedFile(url, fileType);
return cachedFile != null
? new ImagePath
case SMFileTypes.CustomLogo:
{
ReturnName = LogoReturnName,
FullPath = cachedFile,
SMFileType = SMFileTypes.Logo
string logoReturnName = Path.GetFileName(url);
string? cachedFile = GetCachedFile(url, fileType);
return cachedFile != null
? new ImagePath
{
ReturnName = logoReturnName,
FullPath = cachedFile,
SMFileType = SMFileTypes.CustomLogo
}
: null;
}
: null;
}

if (fileType == SMFileTypes.Logo)
{
string LogoReturnName = Path.GetFileName(url);
string? cachedFile = GetCachedFile(url, fileType);
return cachedFile != null
? new ImagePath
case SMFileTypes.CustomPlayList:
case SMFileTypes.CustomPlayListLogo:
{
ReturnName = LogoReturnName,
FullPath = cachedFile,
SMFileType = SMFileTypes.Logo
string fullPath = BuildInfo.CustomPlayListFolder + URL;
return File.Exists(fullPath)
? new ImagePath
{
ReturnName = Path.GetFileName(fullPath),
FullPath = fullPath,
SMFileType = SMFileTypes.CustomPlayListLogo
}
: null;
}
: null;
}

if (fileType is SMFileTypes.CustomPlayListLogo or SMFileTypes.CustomPlayList)
{
string fullPath = BuildInfo.CustomPlayListFolder + URL;
return File.Exists(fullPath)
? new ImagePath
case SMFileTypes.ProgramLogo:
{
ReturnName = Path.GetFileName(fullPath),
FullPath = fullPath,
SMFileType = SMFileTypes.CustomPlayListLogo
string logoReturnName = Path.GetFileName(url);
string? cachedFile = GetCachedFile(url, fileType);
return cachedFile != null
? new ImagePath
{
ReturnName = logoReturnName,
FullPath = cachedFile,
SMFileType = SMFileTypes.Logo
}
: null;
}
: null;
}

if (fileType is SMFileTypes.TvLogo)
{
string fullPath = BuildInfo.TVLogoFolder + "/" + URL;
return File.Exists(fullPath)
? new ImagePath
case SMFileTypes.TvLogo:
{
ReturnName = Path.GetFileName(fullPath),
FullPath = fullPath,
SMFileType = SMFileTypes.TvLogo
string fullPath = BuildInfo.TVLogoFolder + "/" + URL;
return File.Exists(fullPath)
? new ImagePath
{
ReturnName = Path.GetFileName(fullPath),
FullPath = fullPath,
SMFileType = SMFileTypes.TvLogo
}
: null;
}
: null;
}

string returnName;
// Handle logo cache lookup
if (Logos.TryGetValue(url, out CustomLogoDto? cache))
{
returnName = cache.Value;
string tvLogosFileName = Path.Combine(BuildInfo.TVLogoFolder, returnName);
string path = cache.Value;
string tvLogosFileName = Path.Combine(BuildInfo.TVLogoFolder, path);
return new ImagePath
{
ReturnName = returnName,
ReturnName = path,
FullPath = tvLogosFileName,
SMFileType = SMFileTypes.TvLogo
};
}

Stopwatch sw = Stopwatch.StartNew();
CustomLogoDto? logo = GetLogoBySource(url);
//_ = GetValidImagePath(baseUrl, fileType);
//_ = GetValidImagePath(baseUrl, SMFileTypes.SDImage);
if (logo is null)
// Try to get logo by source
Stopwatch stopwatch = Stopwatch.StartNew();
CustomLogoDto? logoBySource = GetLogoBySource(url);
if (logoBySource == null)
{
sw.Stop();
if (sw.ElapsedMilliseconds > 10)
stopwatch.Stop();
if (stopwatch.ElapsedMilliseconds > 10)
{
logger.LogInformation("GetValidImagePath GetIcBySource took {ElapsedMilliseconds}ms", sw.ElapsedMilliseconds);
logger.LogInformation("GetValidImagePath GetIcBySource took {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
}
return null;
}

FileDefinition fd = FileDefinitions.Logo;

returnName = $"{logo.Name}";
string fileName = Path.Combine(fd.DirectoryLocation, returnName);
FileDefinition logo = FileDefinitions.Logo;
string returnName = logoBySource.Name ?? "";
string fileName = Path.Combine(logo.DirectoryLocation, returnName);

return File.Exists(fileName)
? new ImagePath
{
ReturnName = returnName,
SMFileType = SMFileTypes.Logo,
FullPath = fileName,
FullPath = fileName
}
: null;
}
Expand Down Expand Up @@ -681,21 +650,12 @@ public async Task UpdateTVLogosFromDirectoryAsync(DirectoryInfo dirInfo, string
continue;
}
string basename = basePath.Replace(Path.DirectorySeparatorChar, ' ');
string title = $"{basename}-{name}";

string source = $"{basename}-{name}";
string title = basename + " " + name.Replace('-', ' ');
string url = Path.Combine(basePath, file.Name).ToUrlSafeBase64String();
url += Path.GetExtension(file.Name);

string realUrl = $"/api/files/tv/{url}";

CustomLogoDto tvLogo = new()
{
Source = realUrl,
Value = realUrl,
Name = title
};

CacheLogo(tvLogo, true);
AddLogoToCache(url, title, SMFileTypes.TvLogo);
}

foreach (DirectoryInfo newDir in dirInfo.GetDirectories())
Expand Down Expand Up @@ -727,7 +687,9 @@ public async Task<DataResponse<bool>> CacheEPGChannelLogosAsync(CancellationToke
foreach (EPGFile epgFile in await epgService.GetEPGFilesAsync())
{
if (cancellationToken.IsCancellationRequested)
{
return DataResponse.True;
}

string epgPath = Path.Combine(FileDefinitions.EPG.DirectoryLocation, epgFile.Source);
List<XmltvChannel> channelsFromXml = await fileUtilService.GetChannelsFromXmlAsync(epgPath, cancellationToken);
Expand Down
Loading

0 comments on commit a32defb

Please sign in to comment.