mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-06 11:34:57 +02:00
Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser
This commit is contained in:
commit
9dff8e9d38
1 changed files with 48 additions and 34 deletions
|
@ -50,14 +50,20 @@ namespace MediaBrowser.Providers.TV
|
||||||
.OfType<Series>()
|
.OfType<Series>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
var seriesGroups = from series in seriesList
|
||||||
|
let tvdbId = series.GetProviderId(MetadataProviders.Tvdb)
|
||||||
|
where !string.IsNullOrEmpty(tvdbId)
|
||||||
|
group series by tvdbId into g
|
||||||
|
select g;
|
||||||
|
|
||||||
|
await new MissingEpisodeProvider(_logger, _config).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var numComplete = 0;
|
var numComplete = 0;
|
||||||
|
|
||||||
foreach (var series in seriesList)
|
foreach (var series in seriesList)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
await new MissingEpisodeProvider(_logger, _config).Run(series, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var episodes = series.RecursiveChildren
|
var episodes = series.RecursiveChildren
|
||||||
.OfType<Episode>()
|
.OfType<Episode>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
@ -100,15 +106,17 @@ namespace MediaBrowser.Providers.TV
|
||||||
_config = config;
|
_config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Run(Series series, CancellationToken cancellationToken)
|
public async Task Run(IEnumerable<IGrouping<string, Series>> series, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var tvdbId = series.GetProviderId(MetadataProviders.Tvdb);
|
foreach (var seriesGroup in series)
|
||||||
|
|
||||||
// Can't proceed without a tvdb id
|
|
||||||
if (string.IsNullOrEmpty(tvdbId))
|
|
||||||
{
|
{
|
||||||
return;
|
await Run(seriesGroup, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Run(IGrouping<string, Series> group, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var tvdbId = group.Key;
|
||||||
|
|
||||||
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId);
|
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId);
|
||||||
|
|
||||||
|
@ -142,33 +150,36 @@ namespace MediaBrowser.Providers.TV
|
||||||
.Where(i => i.Item1 != -1 && i.Item2 != -1)
|
.Where(i => i.Item1 != -1 && i.Item2 != -1)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var anySeasonsRemoved = await RemoveObsoleteOrMissingSeasons(series, episodeLookup, cancellationToken)
|
var anySeasonsRemoved = await RemoveObsoleteOrMissingSeasons(group, episodeLookup, cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var anyEpisodesRemoved = await RemoveObsoleteOrMissingEpisodes(series, episodeLookup, cancellationToken)
|
var anyEpisodesRemoved = await RemoveObsoleteOrMissingEpisodes(group, episodeLookup, cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var hasNewEpisodes = false;
|
var hasNewEpisodes = false;
|
||||||
var hasNewSeasons = false;
|
var hasNewSeasons = false;
|
||||||
|
|
||||||
if (series.ContainsEpisodesWithoutSeasonFolders)
|
foreach (var series in group.Where(s => s.ContainsEpisodesWithoutSeasonFolders))
|
||||||
{
|
{
|
||||||
hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false);
|
hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_config.Configuration.EnableInternetProviders)
|
if (_config.Configuration.EnableInternetProviders)
|
||||||
{
|
{
|
||||||
hasNewEpisodes = await AddMissingEpisodes(series, seriesDataPath, episodeLookup, cancellationToken)
|
hasNewEpisodes = await AddMissingEpisodes(group, seriesDataPath, episodeLookup, cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasNewSeasons || hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved)
|
if (hasNewSeasons || hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved)
|
||||||
{
|
{
|
||||||
await series.RefreshMetadata(cancellationToken, true)
|
foreach (var series in group)
|
||||||
.ConfigureAwait(false);
|
{
|
||||||
|
await series.RefreshMetadata(cancellationToken, true)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await series.ValidateChildren(new Progress<double>(), cancellationToken, true)
|
await series.ValidateChildren(new Progress<double>(), cancellationToken, true)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,11 +225,9 @@ namespace MediaBrowser.Providers.TV
|
||||||
/// <param name="episodeLookup">The episode lookup.</param>
|
/// <param name="episodeLookup">The episode lookup.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
private async Task<bool> AddMissingEpisodes(Series series, string seriesDataPath, IEnumerable<Tuple<int, int>> episodeLookup, CancellationToken cancellationToken)
|
private async Task<bool> AddMissingEpisodes(IEnumerable<Series> series, string seriesDataPath, IEnumerable<Tuple<int, int>> episodeLookup, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var existingEpisodes = series.RecursiveChildren
|
var existingEpisodes = series.SelectMany(s => s.RecursiveChildren.OfType<Episode>()).ToList();
|
||||||
.OfType<Episode>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var hasChanges = false;
|
var hasChanges = false;
|
||||||
|
|
||||||
|
@ -251,21 +260,23 @@ namespace MediaBrowser.Providers.TV
|
||||||
}
|
}
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
|
var targetSeries = DetermineAppropriateSeries(series, tuple.Item1);
|
||||||
|
|
||||||
if (airDate.Value < now)
|
if (airDate.Value < now)
|
||||||
{
|
{
|
||||||
// tvdb has a lot of nearly blank episodes
|
// tvdb has a lot of nearly blank episodes
|
||||||
_logger.Info("Creating virtual missing episode {0} {1}x{2}", series.Name, tuple.Item1, tuple.Item2);
|
_logger.Info("Creating virtual missing episode {0} {1}x{2}", targetSeries.Name, tuple.Item1, tuple.Item2);
|
||||||
|
|
||||||
await AddEpisode(series, tuple.Item1, tuple.Item2, cancellationToken).ConfigureAwait(false);
|
await AddEpisode(targetSeries, tuple.Item1, tuple.Item2, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
hasChanges = true;
|
hasChanges = true;
|
||||||
}
|
}
|
||||||
else if (airDate.Value > now)
|
else if (airDate.Value > now)
|
||||||
{
|
{
|
||||||
// tvdb has a lot of nearly blank episodes
|
// tvdb has a lot of nearly blank episodes
|
||||||
_logger.Info("Creating virtual unaired episode {0} {1}x{2}", series.Name, tuple.Item1, tuple.Item2);
|
_logger.Info("Creating virtual unaired episode {0} {1}x{2}", targetSeries.Name, tuple.Item1, tuple.Item2);
|
||||||
|
|
||||||
await AddEpisode(series, tuple.Item1, tuple.Item2, cancellationToken).ConfigureAwait(false);
|
await AddEpisode(targetSeries, tuple.Item1, tuple.Item2, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
hasChanges = true;
|
hasChanges = true;
|
||||||
}
|
}
|
||||||
|
@ -274,14 +285,19 @@ namespace MediaBrowser.Providers.TV
|
||||||
return hasChanges;
|
return hasChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Series DetermineAppropriateSeries(IEnumerable<Series> series, int seasonNumber)
|
||||||
|
{
|
||||||
|
return series.FirstOrDefault(s => s.RecursiveChildren.OfType<Season>().Any(season => season.IndexNumber == seasonNumber)) ??
|
||||||
|
series.FirstOrDefault(s => s.RecursiveChildren.OfType<Season>().Any(season => season.IndexNumber == 1)) ??
|
||||||
|
series.OrderBy(s => s.RecursiveChildren.OfType<Season>().Select(season => season.IndexNumber).Min()).First();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes the virtual entry after a corresponding physical version has been added
|
/// Removes the virtual entry after a corresponding physical version has been added
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<bool> RemoveObsoleteOrMissingEpisodes(Series series, IEnumerable<Tuple<int, int>> episodeLookup, CancellationToken cancellationToken)
|
private async Task<bool> RemoveObsoleteOrMissingEpisodes(IEnumerable<Series> series, IEnumerable<Tuple<int, int>> episodeLookup, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var existingEpisodes = series.RecursiveChildren
|
var existingEpisodes = series.SelectMany(s => s.RecursiveChildren.OfType<Episode>()).ToList();
|
||||||
.OfType<Episode>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var physicalEpisodes = existingEpisodes
|
var physicalEpisodes = existingEpisodes
|
||||||
.Where(i => i.LocationType != LocationType.Virtual)
|
.Where(i => i.LocationType != LocationType.Virtual)
|
||||||
|
@ -324,7 +340,7 @@ namespace MediaBrowser.Providers.TV
|
||||||
|
|
||||||
foreach (var episodeToRemove in episodesToRemove)
|
foreach (var episodeToRemove in episodesToRemove)
|
||||||
{
|
{
|
||||||
_logger.Info("Removing missing/unaired episode {0} {1}x{2}", series.Name, episodeToRemove.ParentIndexNumber, episodeToRemove.IndexNumber);
|
_logger.Info("Removing missing/unaired episode {0} {1}x{2}", episodeToRemove.Series.Name, episodeToRemove.ParentIndexNumber, episodeToRemove.IndexNumber);
|
||||||
|
|
||||||
await episodeToRemove.Parent.RemoveChild(episodeToRemove, cancellationToken).ConfigureAwait(false);
|
await episodeToRemove.Parent.RemoveChild(episodeToRemove, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -341,11 +357,9 @@ namespace MediaBrowser.Providers.TV
|
||||||
/// <param name="episodeLookup">The episode lookup.</param>
|
/// <param name="episodeLookup">The episode lookup.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{System.Boolean}.</returns>
|
/// <returns>Task{System.Boolean}.</returns>
|
||||||
private async Task<bool> RemoveObsoleteOrMissingSeasons(Series series, IEnumerable<Tuple<int, int>> episodeLookup, CancellationToken cancellationToken)
|
private async Task<bool> RemoveObsoleteOrMissingSeasons(IEnumerable<Series> series, IEnumerable<Tuple<int, int>> episodeLookup, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var existingSeasons = series.Children
|
var existingSeasons = series.SelectMany(s => s.Children.OfType<Season>()).ToList();
|
||||||
.OfType<Season>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var physicalSeasons = existingSeasons
|
var physicalSeasons = existingSeasons
|
||||||
.Where(i => i.LocationType != LocationType.Virtual)
|
.Where(i => i.LocationType != LocationType.Virtual)
|
||||||
|
@ -385,7 +399,7 @@ namespace MediaBrowser.Providers.TV
|
||||||
|
|
||||||
foreach (var seasonToRemove in seasonsToRemove)
|
foreach (var seasonToRemove in seasonsToRemove)
|
||||||
{
|
{
|
||||||
_logger.Info("Removing virtual season {0} {1}", series.Name, seasonToRemove.IndexNumber);
|
_logger.Info("Removing virtual season {0} {1}", seasonToRemove.Series.Name, seasonToRemove.IndexNumber);
|
||||||
|
|
||||||
await seasonToRemove.Parent.RemoveChild(seasonToRemove, cancellationToken).ConfigureAwait(false);
|
await seasonToRemove.Parent.RemoveChild(seasonToRemove, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue