mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
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 <cody@robibe.ro> Backported-by: Joshua M. Boniface <joshua@boniface.me>
This commit is contained in:
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…
x
Reference in New Issue
Block a user