From 372c1681d8272c6fa8f120a132bc40351067fb10 Mon Sep 17 00:00:00 2001 From: Daniel Țuțuianu Date: Sat, 23 May 2026 23:29:25 +0300 Subject: Refresh Live TV channel icons on every guide update. Guide refresh skipped channel logos once a primary image existed, so stale EPG/tuner icons never got replaced. --- src/Jellyfin.LiveTv/Channels/ChannelManager.cs | 4 +-- src/Jellyfin.LiveTv/Guide/GuideManager.cs | 14 +++-------- src/Jellyfin.LiveTv/LiveTvChannelImageHelper.cs | 33 +++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 src/Jellyfin.LiveTv/LiveTvChannelImageHelper.cs (limited to 'src') diff --git a/src/Jellyfin.LiveTv/Channels/ChannelManager.cs b/src/Jellyfin.LiveTv/Channels/ChannelManager.cs index ed02fe6a1d..e421601092 100644 --- a/src/Jellyfin.LiveTv/Channels/ChannelManager.cs +++ b/src/Jellyfin.LiveTv/Channels/ChannelManager.cs @@ -14,6 +14,7 @@ using Jellyfin.Database.Implementations.Entities; using Jellyfin.Database.Implementations.Enums; using Jellyfin.Extensions; using Jellyfin.Extensions.Json; +using Jellyfin.LiveTv; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; @@ -1109,9 +1110,8 @@ namespace Jellyfin.LiveTv.Channels item.Path = mediaSource?.Path; } - if (!string.IsNullOrEmpty(info.ImageUrl) && !item.HasImage(ImageType.Primary)) + if (LiveTvChannelImageHelper.UpdateChannelImageIfNeeded(item, null, info.ImageUrl)) { - item.SetImagePath(ImageType.Primary, info.ImageUrl); _logger.LogDebug("Forcing update due to ImageUrl {0}", item.Name); forceUpdate = true; } diff --git a/src/Jellyfin.LiveTv/Guide/GuideManager.cs b/src/Jellyfin.LiveTv/Guide/GuideManager.cs index 556516674b..b8545cbb64 100644 --- a/src/Jellyfin.LiveTv/Guide/GuideManager.cs +++ b/src/Jellyfin.LiveTv/Guide/GuideManager.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Enums; using Jellyfin.Extensions; +using Jellyfin.LiveTv; using Jellyfin.LiveTv.Configuration; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Dto; @@ -448,18 +449,9 @@ public class GuideManager : IGuideManager item.Name = channelInfo.Name; - if (!item.HasImage(ImageType.Primary)) + if (LiveTvChannelImageHelper.UpdateChannelImageIfNeeded(item, channelInfo.ImagePath, channelInfo.ImageUrl)) { - if (!string.IsNullOrWhiteSpace(channelInfo.ImagePath)) - { - item.SetImagePath(ImageType.Primary, channelInfo.ImagePath); - forceUpdate = true; - } - else if (!string.IsNullOrWhiteSpace(channelInfo.ImageUrl)) - { - item.SetImagePath(ImageType.Primary, channelInfo.ImageUrl); - forceUpdate = true; - } + forceUpdate = true; } if (isNew) diff --git a/src/Jellyfin.LiveTv/LiveTvChannelImageHelper.cs b/src/Jellyfin.LiveTv/LiveTvChannelImageHelper.cs new file mode 100644 index 0000000000..a590193b5f --- /dev/null +++ b/src/Jellyfin.LiveTv/LiveTvChannelImageHelper.cs @@ -0,0 +1,33 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; + +namespace Jellyfin.LiveTv; + +/// +/// Helpers for keeping Live TV channel icons in sync with guide data. +/// +internal static class LiveTvChannelImageHelper +{ + /// + /// Applies the channel icon from guide or tuner metadata. + /// Called on each guide refresh so remote icons are re-downloaded even when the URL is unchanged. + /// + /// The channel item. + /// The local image path from the tuner, if any. + /// The remote image URL from the guide provider, if any. + /// true when the item image metadata was updated. + internal static bool UpdateChannelImageIfNeeded(BaseItem item, string? imagePath, string? imageUrl) + { + var newImageSource = !string.IsNullOrWhiteSpace(imagePath) + ? imagePath + : imageUrl; + + if (string.IsNullOrWhiteSpace(newImageSource)) + { + return false; + } + + item.SetImagePath(ImageType.Primary, newImageSource); + return true; + } +} -- cgit v1.2.3 From e41f41559426a5996bc58a28af5e82f432557ea4 Mon Sep 17 00:00:00 2001 From: Breno Alvim Date: Tue, 23 Jun 2026 23:13:33 -0300 Subject: Use Convert.ToHexStringLower for Schedules Direct password hash --- Jellyfin.Api/Controllers/LiveTvController.cs | 4 +--- src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 113298c251..1c570daf21 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -1002,9 +1002,7 @@ public class LiveTvController : BaseJellyfinApiController { if (!string.IsNullOrEmpty(pw)) { - // TODO: remove ToLower when Convert.ToHexString supports lowercase - // Schedules Direct requires the hex to be lowercase - listingsProviderInfo.Password = Convert.ToHexString(SHA1.HashData(Encoding.UTF8.GetBytes(pw))).ToLowerInvariant(); + listingsProviderInfo.Password = Convert.ToHexStringLower(SHA1.HashData(Encoding.UTF8.GetBytes(pw))); } return await _listingsManager.SaveListingProvider(listingsProviderInfo, validateLogin, validateListings).ConfigureAwait(false); diff --git a/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs b/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs index c1ccb24bf4..d456bea469 100644 --- a/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs +++ b/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs @@ -748,9 +748,7 @@ namespace Jellyfin.LiveTv.Listings #pragma warning disable CA5350 // SchedulesDirect is always SHA1. var hashedPasswordBytes = SHA1.HashData(Encoding.ASCII.GetBytes(password)); #pragma warning restore CA5350 - // TODO: remove ToLower when Convert.ToHexString supports lowercase - // Schedules Direct requires the hex to be lowercase - string hashedPassword = Convert.ToHexString(hashedPasswordBytes).ToLowerInvariant(); + string hashedPassword = Convert.ToHexStringLower(hashedPasswordBytes); options.Content = new StringContent("{\"username\":\"" + username + "\",\"password\":\"" + hashedPassword + "\"}", Encoding.UTF8, MediaTypeNames.Application.Json); var root = await Request(options, false, null, cancellationToken).ConfigureAwait(false); -- cgit v1.2.3