From 1a9497675272ad538c99892fa160d83b10a26f5e Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Sat, 1 Jun 2024 18:40:59 -0400 Subject: [PATCH] Backport pull request #11806 from jellyfin/release-10.9.z Return missing episodes for series when no user defined Original-merge: ae584beaac0123f6a722f341a4e12b8f8fbcaf34 Merged-by: crobibero Backported-by: Joshua M. Boniface --- .../Session/SessionManager.cs | 3 +- Jellyfin.Api/Controllers/TvShowsController.cs | 7 +++-- MediaBrowser.Controller/Entities/TV/Season.cs | 19 ++++++------ MediaBrowser.Controller/Entities/TV/Series.cs | 30 +++++++------------ .../TV/SeriesMetadataService.cs | 2 +- 5 files changed, 27 insertions(+), 34 deletions(-) diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 10d5b4f97f..3dda5fdee7 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1202,7 +1202,8 @@ namespace Emby.Server.Implementations.Session new DtoOptions(false) { EnableImages = false - }) + }, + user.DisplayMissingEpisodes) .Where(i => !i.IsVirtualItem) .SkipWhile(i => !i.Id.Equals(episode.Id)) .ToList(); diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index 68b4b6b8b0..4264026670 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -231,6 +231,7 @@ public class TvShowsController : BaseJellyfinApiController var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); + var shouldIncludeMissingEpisodes = (user is not null && user.DisplayMissingEpisodes) || User.GetIsApiKey(); if (seasonId.HasValue) // Season id was supplied. Get episodes by season id. { @@ -240,7 +241,7 @@ public class TvShowsController : BaseJellyfinApiController return NotFound("No season exists with Id " + seasonId); } - episodes = seasonItem.GetEpisodes(user, dtoOptions); + episodes = seasonItem.GetEpisodes(user, dtoOptions, shouldIncludeMissingEpisodes); } else if (season.HasValue) // Season number was supplied. Get episodes by season number { @@ -256,7 +257,7 @@ public class TvShowsController : BaseJellyfinApiController episodes = seasonItem is null ? new List() - : ((Season)seasonItem).GetEpisodes(user, dtoOptions); + : ((Season)seasonItem).GetEpisodes(user, dtoOptions, shouldIncludeMissingEpisodes); } else // No season number or season id was supplied. Returning all episodes. { @@ -265,7 +266,7 @@ public class TvShowsController : BaseJellyfinApiController return NotFound("Series not found"); } - episodes = series.GetEpisodes(user, dtoOptions).ToList(); + episodes = series.GetEpisodes(user, dtoOptions, shouldIncludeMissingEpisodes).ToList(); } // Filter after the fact in case the ui doesn't want them diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index c29cefc15e..083f12746e 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -159,7 +159,7 @@ namespace MediaBrowser.Controller.Entities.TV Func filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); - var items = GetEpisodes(user, query.DtoOptions).Where(filter); + var items = GetEpisodes(user, query.DtoOptions, true).Where(filter); return PostFilterAndSort(items, query, false); } @@ -169,30 +169,31 @@ namespace MediaBrowser.Controller.Entities.TV /// /// The user. /// The options to use. + /// If missing episodes should be included. /// Set of episodes. - public List GetEpisodes(User user, DtoOptions options) + public List GetEpisodes(User user, DtoOptions options, bool shouldIncludeMissingEpisodes) { - return GetEpisodes(Series, user, options); + return GetEpisodes(Series, user, options, shouldIncludeMissingEpisodes); } - public List GetEpisodes(Series series, User user, DtoOptions options) + public List GetEpisodes(Series series, User user, DtoOptions options, bool shouldIncludeMissingEpisodes) { - return GetEpisodes(series, user, null, options); + return GetEpisodes(series, user, null, options, shouldIncludeMissingEpisodes); } - public List GetEpisodes(Series series, User user, IEnumerable allSeriesEpisodes, DtoOptions options) + public List GetEpisodes(Series series, User user, IEnumerable allSeriesEpisodes, DtoOptions options, bool shouldIncludeMissingEpisodes) { - return series.GetSeasonEpisodes(this, user, allSeriesEpisodes, options); + return series.GetSeasonEpisodes(this, user, allSeriesEpisodes, options, shouldIncludeMissingEpisodes); } public List GetEpisodes() { - return Series.GetSeasonEpisodes(this, null, null, new DtoOptions(true)); + return Series.GetSeasonEpisodes(this, null, null, new DtoOptions(true), true); } public override List GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { - return GetEpisodes(user, new DtoOptions(true)); + return GetEpisodes(user, new DtoOptions(true), true); } protected override bool GetBlockUnratedValue(User user) diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 8b4108b692..76fe7389e9 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -250,7 +250,7 @@ namespace MediaBrowser.Controller.Entities.TV return LibraryManager.GetItemsResult(query); } - public IEnumerable GetEpisodes(User user, DtoOptions options) + public IEnumerable GetEpisodes(User user, DtoOptions options, bool shouldIncludeMissingEpisodes) { var seriesKey = GetUniqueSeriesKey(this); @@ -260,20 +260,16 @@ namespace MediaBrowser.Controller.Entities.TV SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { BaseItemKind.Episode, BaseItemKind.Season }, OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }, - DtoOptions = options + DtoOptions = options, + IsMissing = shouldIncludeMissingEpisodes }; - if (user is null || !user.DisplayMissingEpisodes) - { - query.IsMissing = false; - } - var allItems = LibraryManager.GetItemList(query); var allSeriesEpisodes = allItems.OfType().ToList(); var allEpisodes = allItems.OfType() - .SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes, options)) + .SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes, options, shouldIncludeMissingEpisodes)) .Reverse(); // Specials could appear twice based on above - once in season 0, once in the aired season @@ -348,7 +344,7 @@ namespace MediaBrowser.Controller.Entities.TV await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false); } - public List GetSeasonEpisodes(Season parentSeason, User user, DtoOptions options) + public List GetSeasonEpisodes(Season parentSeason, User user, DtoOptions options, bool shouldIncludeMissingEpisodes) { var queryFromSeries = ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons; @@ -363,26 +359,20 @@ namespace MediaBrowser.Controller.Entities.TV SeriesPresentationUniqueKey = queryFromSeries ? seriesKey : null, IncludeItemTypes = new[] { BaseItemKind.Episode }, OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }, - DtoOptions = options + DtoOptions = options, + IsMissing = shouldIncludeMissingEpisodes }; - if (user is not null) - { - if (!user.DisplayMissingEpisodes) - { - query.IsMissing = false; - } - } var allItems = LibraryManager.GetItemList(query); - return GetSeasonEpisodes(parentSeason, user, allItems, options); + return GetSeasonEpisodes(parentSeason, user, allItems, options, shouldIncludeMissingEpisodes); } - public List GetSeasonEpisodes(Season parentSeason, User user, IEnumerable allSeriesEpisodes, DtoOptions options) + public List GetSeasonEpisodes(Season parentSeason, User user, IEnumerable allSeriesEpisodes, DtoOptions options, bool shouldIncludeMissingEpisodes) { if (allSeriesEpisodes is null) { - return GetSeasonEpisodes(parentSeason, user, options); + return GetSeasonEpisodes(parentSeason, user, options, shouldIncludeMissingEpisodes); } var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons); diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs index 99c4e0f1b0..41c6bd8f20 100644 --- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs @@ -128,7 +128,7 @@ namespace MediaBrowser.Providers.TV private void RemoveObsoleteEpisodes(Series series) { - var episodes = series.GetEpisodes(null, new DtoOptions()).OfType().ToList(); + var episodes = series.GetEpisodes(null, new DtoOptions(), true).OfType().ToList(); var numberOfEpisodes = episodes.Count; // TODO: O(n^2), but can it be done faster without overcomplicating it? for (var i = 0; i < numberOfEpisodes; i++)