Backport pull request #11806 from jellyfin/release-10.9.z

Return missing episodes for series when no user defined

Original-merge: ae584beaac

Merged-by: crobibero <cody@robibe.ro>

Backported-by: Joshua M. Boniface <joshua@boniface.me>
master
Shadowghost 4 weeks ago committed by Joshua M. Boniface
parent 407dc9272c
commit 1a94976752

@ -1202,7 +1202,8 @@ namespace Emby.Server.Implementations.Session
new DtoOptions(false) new DtoOptions(false)
{ {
EnableImages = false EnableImages = false
}) },
user.DisplayMissingEpisodes)
.Where(i => !i.IsVirtualItem) .Where(i => !i.IsVirtualItem)
.SkipWhile(i => !i.Id.Equals(episode.Id)) .SkipWhile(i => !i.Id.Equals(episode.Id))
.ToList(); .ToList();

@ -231,6 +231,7 @@ public class TvShowsController : BaseJellyfinApiController
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(User) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .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. 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); 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 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 ? episodes = seasonItem is null ?
new List<BaseItem>() new List<BaseItem>()
: ((Season)seasonItem).GetEpisodes(user, dtoOptions); : ((Season)seasonItem).GetEpisodes(user, dtoOptions, shouldIncludeMissingEpisodes);
} }
else // No season number or season id was supplied. Returning all episodes. 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"); 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 // Filter after the fact in case the ui doesn't want them

@ -159,7 +159,7 @@ namespace MediaBrowser.Controller.Entities.TV
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); Func<BaseItem, bool> 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); return PostFilterAndSort(items, query, false);
} }
@ -169,30 +169,31 @@ namespace MediaBrowser.Controller.Entities.TV
/// </summary> /// </summary>
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
/// <param name="options">The options to use.</param> /// <param name="options">The options to use.</param>
/// <param name="shouldIncludeMissingEpisodes">If missing episodes should be included.</param>
/// <returns>Set of episodes.</returns> /// <returns>Set of episodes.</returns>
public List<BaseItem> GetEpisodes(User user, DtoOptions options) public List<BaseItem> GetEpisodes(User user, DtoOptions options, bool shouldIncludeMissingEpisodes)
{ {
return GetEpisodes(Series, user, options); return GetEpisodes(Series, user, options, shouldIncludeMissingEpisodes);
} }
public List<BaseItem> GetEpisodes(Series series, User user, DtoOptions options) public List<BaseItem> GetEpisodes(Series series, User user, DtoOptions options, bool shouldIncludeMissingEpisodes)
{ {
return GetEpisodes(series, user, null, options); return GetEpisodes(series, user, null, options, shouldIncludeMissingEpisodes);
} }
public List<BaseItem> GetEpisodes(Series series, User user, IEnumerable<Episode> allSeriesEpisodes, DtoOptions options) public List<BaseItem> GetEpisodes(Series series, User user, IEnumerable<Episode> allSeriesEpisodes, DtoOptions options, bool shouldIncludeMissingEpisodes)
{ {
return series.GetSeasonEpisodes(this, user, allSeriesEpisodes, options); return series.GetSeasonEpisodes(this, user, allSeriesEpisodes, options, shouldIncludeMissingEpisodes);
} }
public List<BaseItem> GetEpisodes() public List<BaseItem> GetEpisodes()
{ {
return Series.GetSeasonEpisodes(this, null, null, new DtoOptions(true)); return Series.GetSeasonEpisodes(this, null, null, new DtoOptions(true), true);
} }
public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) public override List<BaseItem> 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) protected override bool GetBlockUnratedValue(User user)

@ -250,7 +250,7 @@ namespace MediaBrowser.Controller.Entities.TV
return LibraryManager.GetItemsResult(query); return LibraryManager.GetItemsResult(query);
} }
public IEnumerable<BaseItem> GetEpisodes(User user, DtoOptions options) public IEnumerable<BaseItem> GetEpisodes(User user, DtoOptions options, bool shouldIncludeMissingEpisodes)
{ {
var seriesKey = GetUniqueSeriesKey(this); var seriesKey = GetUniqueSeriesKey(this);
@ -260,20 +260,16 @@ namespace MediaBrowser.Controller.Entities.TV
SeriesPresentationUniqueKey = seriesKey, SeriesPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] { BaseItemKind.Episode, BaseItemKind.Season }, IncludeItemTypes = new[] { BaseItemKind.Episode, BaseItemKind.Season },
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }, 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 allItems = LibraryManager.GetItemList(query);
var allSeriesEpisodes = allItems.OfType<Episode>().ToList(); var allSeriesEpisodes = allItems.OfType<Episode>().ToList();
var allEpisodes = allItems.OfType<Season>() var allEpisodes = allItems.OfType<Season>()
.SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes, options)) .SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes, options, shouldIncludeMissingEpisodes))
.Reverse(); .Reverse();
// Specials could appear twice based on above - once in season 0, once in the aired season // 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); await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
} }
public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, DtoOptions options) public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, DtoOptions options, bool shouldIncludeMissingEpisodes)
{ {
var queryFromSeries = ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons; var queryFromSeries = ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons;
@ -363,26 +359,20 @@ namespace MediaBrowser.Controller.Entities.TV
SeriesPresentationUniqueKey = queryFromSeries ? seriesKey : null, SeriesPresentationUniqueKey = queryFromSeries ? seriesKey : null,
IncludeItemTypes = new[] { BaseItemKind.Episode }, IncludeItemTypes = new[] { BaseItemKind.Episode },
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }, 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); var allItems = LibraryManager.GetItemList(query);
return GetSeasonEpisodes(parentSeason, user, allItems, options); return GetSeasonEpisodes(parentSeason, user, allItems, options, shouldIncludeMissingEpisodes);
} }
public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, IEnumerable<BaseItem> allSeriesEpisodes, DtoOptions options) public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, IEnumerable<BaseItem> allSeriesEpisodes, DtoOptions options, bool shouldIncludeMissingEpisodes)
{ {
if (allSeriesEpisodes is null) if (allSeriesEpisodes is null)
{ {
return GetSeasonEpisodes(parentSeason, user, options); return GetSeasonEpisodes(parentSeason, user, options, shouldIncludeMissingEpisodes);
} }
var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons); var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);

@ -128,7 +128,7 @@ namespace MediaBrowser.Providers.TV
private void RemoveObsoleteEpisodes(Series series) private void RemoveObsoleteEpisodes(Series series)
{ {
var episodes = series.GetEpisodes(null, new DtoOptions()).OfType<Episode>().ToList(); var episodes = series.GetEpisodes(null, new DtoOptions(), true).OfType<Episode>().ToList();
var numberOfEpisodes = episodes.Count; var numberOfEpisodes = episodes.Count;
// TODO: O(n^2), but can it be done faster without overcomplicating it? // TODO: O(n^2), but can it be done faster without overcomplicating it?
for (var i = 0; i < numberOfEpisodes; i++) for (var i = 0; i < numberOfEpisodes; i++)

Loading…
Cancel
Save