diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index cde4854f..512404ce 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -17,5 +17,5 @@ jobs: call: uses: jellyfin/jellyfin-meta-plugins/.github/workflows/build.yaml@master with: - dotnet-version: "9.0.*" - dotnet-target: "net9.0" + dotnet-version: "10.0.*" + dotnet-target: "net10.0" diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 8312960b..c5a18c20 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -10,8 +10,8 @@ jobs: build: uses: jellyfin/jellyfin-meta-plugins/.github/workflows/build.yaml@master with: - dotnet-version: "9.0.*" - dotnet-target: "net9.0" + dotnet-version: "10.0.*" + dotnet-target: "net10.0" upload: runs-on: ubuntu-latest needs: diff --git a/.github/workflows/scan-codeql.yaml b/.github/workflows/scan-codeql.yaml index 119a7dfd..72c745bf 100644 --- a/.github/workflows/scan-codeql.yaml +++ b/.github/workflows/scan-codeql.yaml @@ -9,5 +9,5 @@ jobs: call: uses: jellyfin/jellyfin-meta-plugins/.github/workflows/scan-codeql.yaml@master with: - dotnet-version: "9.0.*" + dotnet-version: "10.0.*" repository-name: Kevinjil/Jellyfin.Xtream diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 368fbd33..d1f20ee8 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -17,4 +17,4 @@ jobs: call: uses: jellyfin/jellyfin-meta-plugins/.github/workflows/test.yaml@master with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x diff --git a/Jellyfin.Xtream/CatchupChannel.cs b/Jellyfin.Xtream/CatchupChannel.cs index 4ce63184..7fbe095f 100644 --- a/Jellyfin.Xtream/CatchupChannel.cs +++ b/Jellyfin.Xtream/CatchupChannel.cs @@ -198,6 +198,7 @@ private async Task GetStreams(int categoryId, int channelId, new() { ContentType = ChannelMediaContentType.TvExtra, + DateModified = StreamService.MediaSourceRevision, Id = StreamService.ToGuid(StreamService.CatchupStreamPrefix, channelId, 0, day).ToString(), IsLiveStream = false, MediaSources = [ @@ -226,6 +227,7 @@ private async Task GetStreams(int categoryId, int channelId, { ContentType = ChannelMediaContentType.TvExtra, DateCreated = epg.Start, + DateModified = StreamService.MediaSourceRevision, Id = StreamService.ToGuid(StreamService.CatchupStreamPrefix, channel.StreamId, epg.Id, day).ToString(), IsLiveStream = false, MediaSources = sources, diff --git a/Jellyfin.Xtream/Jellyfin.Xtream.csproj b/Jellyfin.Xtream/Jellyfin.Xtream.csproj index 85beee3b..d7340de8 100644 --- a/Jellyfin.Xtream/Jellyfin.Xtream.csproj +++ b/Jellyfin.Xtream/Jellyfin.Xtream.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 Jellyfin.Xtream 0.8.1.0 0.8.1.0 @@ -13,8 +13,8 @@ - - + + diff --git a/Jellyfin.Xtream/SeriesChannel.cs b/Jellyfin.Xtream/SeriesChannel.cs index fdfcfc15..67ea60ea 100644 --- a/Jellyfin.Xtream/SeriesChannel.cs +++ b/Jellyfin.Xtream/SeriesChannel.cs @@ -217,6 +217,7 @@ private ChannelItemInfo CreateChannelItemInfo(SeriesStreamInfo series, Season? s { ContentType = ChannelMediaContentType.Episode, DateCreated = episode.Added, + DateModified = StreamService.MediaSourceRevision, Genres = GetGenres(serie.Genre), Id = StreamService.ToGuid(StreamService.EpisodePrefix, 0, 0, episode.EpisodeId).ToString(), IndexNumber = episode.EpisodeNum, diff --git a/Jellyfin.Xtream/Service/StreamService.cs b/Jellyfin.Xtream/Service/StreamService.cs index b09b2bcf..ed97dba9 100644 --- a/Jellyfin.Xtream/Service/StreamService.cs +++ b/Jellyfin.Xtream/Service/StreamService.cs @@ -91,6 +91,13 @@ public partial class StreamService(IXtreamClient xtreamClient) /// public const int EpgPrefix = 0x5d774c3f; + /// + /// The time the media sources of channel items last changed shape. + /// Jellyfin only rewrites the sources it saved for a channel item when the item changes, + /// so channel media items carry this as their modification date. + /// + public static readonly DateTime MediaSourceRevision = new(2026, 9, 28, 0, 0, 0, DateTimeKind.Utc); + private static readonly Regex _tagRegex = TagRegex(); /// @@ -399,7 +406,9 @@ public MediaSourceInfo GetMediaSourceInfo( { Container = extension, EncoderProtocol = MediaProtocol.Http, - Id = ToGuid(MediaSourcePrefix, (int)type, id, 0).ToString(), + // Jellyfin gives a channel source without an id the id of its item, which it requires since 12.0. + // Live TV keeps its own id, which identifies the restream to share. + Id = isLive ? ToGuid(MediaSourcePrefix, (int)type, id, 0).ToString() : null, IsInfiniteStream = isLive, IsRemote = true, MediaStreams = diff --git a/Jellyfin.Xtream/VodChannel.cs b/Jellyfin.Xtream/VodChannel.cs index b08397f3..a42eb817 100644 --- a/Jellyfin.Xtream/VodChannel.cs +++ b/Jellyfin.Xtream/VodChannel.cs @@ -131,6 +131,7 @@ private Task CreateChannelItemInfo(StreamInfo stream) { ContentType = ChannelMediaContentType.Movie, DateCreated = DateTimeOffset.FromUnixTimeSeconds(added).DateTime, + DateModified = StreamService.MediaSourceRevision, Id = $"{StreamService.StreamPrefix}{stream.StreamId}", ImageUrl = stream.StreamIcon, IsLiveStream = false, diff --git a/build.yaml b/build.yaml index 642cd10c..55d3c96f 100644 --- a/build.yaml +++ b/build.yaml @@ -2,8 +2,8 @@ name: "Jellyfin Xtream" guid: "5d774c35-8567-46d3-a950-9bb8227a0c5d" version: "0.8.1.0" -targetAbi: "10.11.0.0" -framework: "net9.0" +targetAbi: "12.0.0.0" +framework: "net10.0" overview: "Stream content from an Xtream-compatible server." description: > Stream Live IPTV, Video On-Demand, and Series from an Xtream-compatible server using this plugin. diff --git a/jellyfin.ruleset b/jellyfin.ruleset index d6994a1c..a1bae001 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -100,6 +100,8 @@ + +