浏览代码

Merge pull request #644 from thogil/split_series_missing_episodes_2

Missing episodes supports split series
Luke 11 年之前
父节点
当前提交
83f1fec902
共有 1 个文件被更改,包括 48 次插入34 次删除
  1. 48 34
      MediaBrowser.Providers/TV/SeriesPostScanTask.cs

+ 48 - 34
MediaBrowser.Providers/TV/SeriesPostScanTask.cs

@@ -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);
-
-            // Can't proceed without a tvdb id
-            if (string.IsNullOrEmpty(tvdbId))
+            foreach (var seriesGroup in series)
             {
             {
-                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)
-                    .ConfigureAwait(false);
+                foreach (var series in group)
+                {
+                    await series.RefreshMetadata(cancellationToken, true)
+                        .ConfigureAwait(false);
 
 
-                await series.ValidateChildren(new Progress<double>(), cancellationToken, true)
-                    .ConfigureAwait(false);
+                    await series.ValidateChildren(new Progress<double>(), cancellationToken, true)
+                        .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
-                .OfType<Episode>()
-                .ToList();
+            var existingEpisodes = series.SelectMany(s => s.RecursiveChildren.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
-                .OfType<Episode>()
-                .ToList();
+            var existingEpisodes = series.SelectMany(s => s.RecursiveChildren.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
-                .OfType<Season>()
-                .ToList();
+            var existingSeasons = series.SelectMany(s => s.Children.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);