Просмотр исходного кода

encapsulate validity in tv providers

Luke Pulverenti 9 лет назад
Родитель
Сommit
0c7e06648c

+ 13 - 8
MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs

@@ -47,6 +47,8 @@ namespace MediaBrowser.Providers.TV
 
         public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken)
         {
+            var seriesProviderIds = searchInfo.SeriesProviderIds;
+
             var list = new List<RemoteSearchResult>();
 
             var identity = Identity.ParseIdentity(searchInfo.GetProviderId(FullIdKey));
@@ -59,14 +61,17 @@ namespace MediaBrowser.Providers.TV
 
             if (identity != null)
             {
-                await TvdbSeriesProvider.Current.EnsureSeriesInfo(identity.Value.SeriesId, searchInfo.MetadataLanguage,
-                        cancellationToken).ConfigureAwait(false);
+                seriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+                seriesProviderIds[MetadataProviders.Tvdb.ToString()] = identity.Value.SeriesId;
+            }
 
-                var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, identity.Value.SeriesId);
+            if (TvdbSeriesProvider.IsValidSeries(seriesProviderIds))
+            {
+                var seriesDataPath = await TvdbSeriesProvider.Current.EnsureSeriesInfo(seriesProviderIds, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
 
                 try
                 {
-                    var metadataResult = FetchEpisodeData(searchInfo, identity.Value, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
+                    var metadataResult = FetchEpisodeData(searchInfo, identity, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
 
                     if (metadataResult.HasMetadata)
                     {
@@ -247,11 +252,11 @@ namespace MediaBrowser.Providers.TV
         /// <param name="seriesProviderIds">The series provider ids.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{System.Boolean}.</returns>
-        private MetadataResult<Episode> FetchEpisodeData(EpisodeInfo id, Identity identity, string seriesDataPath, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
+        private MetadataResult<Episode> FetchEpisodeData(EpisodeInfo id, Identity? identity, string seriesDataPath, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
         {
-            var episodeNumber = identity.EpisodeNumber;
+            var episodeNumber = identity.HasValue ? (identity.Value.EpisodeNumber) : id.IndexNumber.Value;
             var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(seriesProviderIds) ?? 0;
-            var seasonNumber = identity.SeasonIndex + seasonOffset;
+            var seasonNumber = identity.HasValue ? (identity.Value.SeasonIndex + seasonOffset) : id.ParentIndexNumber;
             
             string file;
             var usingAbsoluteData = false;
@@ -294,7 +299,7 @@ namespace MediaBrowser.Providers.TV
                 usingAbsoluteData = true;
             }
 
-            var end = identity.EpisodeNumberEnd ?? episodeNumber;
+            var end = identity.HasValue ? (identity.Value.EpisodeNumberEnd ?? episodeNumber) : (id.IndexNumberEnd ?? episodeNumber);
             episodeNumber++;
 
             while (episodeNumber <= end)

+ 18 - 12
MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs

@@ -66,24 +66,30 @@ namespace MediaBrowser.Providers.TV
             var season = (Season)item;
             var series = season.Series;
 
-            var identity = TvdbSeasonIdentityProvider.ParseIdentity(season.GetProviderId(TvdbSeasonIdentityProvider.FullIdKey));
-            if (identity == null && series != null && season.IndexNumber.HasValue)
+            if (series != null && season.IndexNumber.HasValue && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
             {
-                identity = new TvdbSeasonIdentity(series.GetProviderId(MetadataProviders.Tvdb), season.IndexNumber.Value);
-            }
+                var seriesProviderIds = series.ProviderIds;
+                var seasonNumber = season.IndexNumber.Value;
 
-            if (identity != null && series != null)
-            {
-                var id = identity.Value;
-                await TvdbSeriesProvider.Current.EnsureSeriesInfo(id.SeriesId, series.GetPreferredMetadataLanguage(), cancellationToken).ConfigureAwait(false);
+                var identity = TvdbSeasonIdentityProvider.ParseIdentity(season.GetProviderId(TvdbSeasonIdentityProvider.FullIdKey));
+                if (identity == null)
+                {
+                    identity = new TvdbSeasonIdentity(series.GetProviderId(MetadataProviders.Tvdb), seasonNumber);
+                }
 
-                // Process images
-                var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, id.SeriesId);
+                if (identity != null)
+                {
+                    var id = identity.Value;
+                    seasonNumber = AdjustForSeriesOffset(series, id.Index);
+
+                    seriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+                    seriesProviderIds[MetadataProviders.Tvdb.ToString()] = id.SeriesId;
+                }
+
+                var seriesDataPath = await TvdbSeriesProvider.Current.EnsureSeriesInfo(seriesProviderIds, series.GetPreferredMetadataLanguage(), cancellationToken).ConfigureAwait(false);
 
                 var path = Path.Combine(seriesDataPath, "banners.xml");
 
-                var seasonNumber = AdjustForSeriesOffset(series, id.Index);
-                
                 try
                 {
                     return GetImages(path, item.GetPreferredMetadataLanguage(), seasonNumber, cancellationToken);

+ 3 - 9
MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs

@@ -62,23 +62,17 @@ namespace MediaBrowser.Providers.TV
 
         public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
         {
-            var series = (Series)item;
-            var seriesId = series.GetProviderId(MetadataProviders.Tvdb);
-
-            if (!string.IsNullOrEmpty(seriesId))
+            if (TvdbSeriesProvider.IsValidSeries(item.ProviderIds))
             {
                 var language = item.GetPreferredMetadataLanguage();
 
-                await TvdbSeriesProvider.Current.EnsureSeriesInfo(seriesId, language, cancellationToken).ConfigureAwait(false);
-
-                // Process images
-                var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId);
+                var seriesDataPath = await TvdbSeriesProvider.Current.EnsureSeriesInfo(item.ProviderIds, language, cancellationToken).ConfigureAwait(false);
 
                 var path = Path.Combine(seriesDataPath, "banners.xml");
 
                 try
                 {
-                    var seriesOffset = TvdbSeriesProvider.GetSeriesOffset(series.ProviderIds);
+                    var seriesOffset = TvdbSeriesProvider.GetSeriesOffset(item.ProviderIds);
                     if (seriesOffset != null && seriesOffset.Value != 0)
                         return TvdbSeasonImageProvider.GetImages(path, language, seriesOffset.Value + 1, cancellationToken);
                     

+ 111 - 76
MediaBrowser.Providers/TV/TvdbSeriesProvider.cs

@@ -59,56 +59,48 @@ namespace MediaBrowser.Providers.TV
 
         public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
         {
-            var seriesId = searchInfo.GetProviderId(MetadataProviders.Tvdb);
-
-            if (string.IsNullOrWhiteSpace(seriesId))
+            if (IsValidSeries(searchInfo.ProviderIds))
             {
-                return await FindSeries(searchInfo.Name, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
-            }
-
-            var metadata = await GetMetadata(searchInfo, cancellationToken).ConfigureAwait(false);
-
-            var list = new List<RemoteSearchResult>();
+                var metadata = await GetMetadata(searchInfo, cancellationToken).ConfigureAwait(false);
 
-            if (metadata.HasMetadata)
-            {
-                var res = new RemoteSearchResult
+                if (metadata.HasMetadata)
                 {
-                    Name = metadata.Item.Name,
-                    PremiereDate = metadata.Item.PremiereDate,
-                    ProductionYear = metadata.Item.ProductionYear,
-                    ProviderIds = metadata.Item.ProviderIds,
-                    SearchProviderName = Name
-                };
-
-                list.Add(res);
+                    return new List<RemoteSearchResult>
+                    {
+                        new RemoteSearchResult
+                        {
+                            Name = metadata.Item.Name,
+                            PremiereDate = metadata.Item.PremiereDate,
+                            ProductionYear = metadata.Item.ProductionYear,
+                            ProviderIds = metadata.Item.ProviderIds,
+                            SearchProviderName = Name
+                        }
+                    };
+                }
             }
 
-            return list;
+            return await FindSeries(searchInfo.Name, searchInfo.Year, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
         }
 
         public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo itemId, CancellationToken cancellationToken)
         {
             var result = new MetadataResult<Series>();
 
-            var seriesId = itemId.GetProviderId(MetadataProviders.Tvdb);
-
-            if (string.IsNullOrWhiteSpace(seriesId))
+            if (!IsValidSeries(itemId.ProviderIds))
             {
                 await Identify(itemId).ConfigureAwait(false);
-                seriesId = itemId.GetProviderId(MetadataProviders.Tvdb);
             }
-            
+
             cancellationToken.ThrowIfCancellationRequested();
 
-            if (!string.IsNullOrWhiteSpace(seriesId))
+            if (IsValidSeries(itemId.ProviderIds))
             {
-                await EnsureSeriesInfo(seriesId, itemId.MetadataLanguage, cancellationToken).ConfigureAwait(false);
+                await EnsureSeriesInfo(itemId.ProviderIds, itemId.MetadataLanguage, cancellationToken).ConfigureAwait(false);
 
                 result.Item = new Series();
                 result.HasMetadata = true;
 
-                FetchSeriesData(result, seriesId, cancellationToken);
+                FetchSeriesData(result, itemId.GetProviderId(MetadataProviders.Tvdb), cancellationToken);
                 await FindAnimeSeriesIndex(result.Item, itemId).ConfigureAwait(false);
             }
 
@@ -168,7 +160,7 @@ namespace MediaBrowser.Providers.TV
             cancellationToken.ThrowIfCancellationRequested();
 
             result.ResetPeople();
-            
+
             FetchActors(result, actorsXmlPath);
         }
 
@@ -239,7 +231,7 @@ namespace MediaBrowser.Providers.TV
 
             if (!string.Equals(downloadLangaugeXmlFile, saveAsLanguageXmlFile, StringComparison.OrdinalIgnoreCase))
             {
-				_fileSystem.CopyFile(downloadLangaugeXmlFile, saveAsLanguageXmlFile, true);
+                _fileSystem.CopyFile(downloadLangaugeXmlFile, saveAsLanguageXmlFile, true);
             }
 
             await ExtractEpisodes(seriesDataPath, downloadLangaugeXmlFile, lastTvDbUpdateTime).ConfigureAwait(false);
@@ -250,62 +242,94 @@ namespace MediaBrowser.Providers.TV
             return _config.GetConfiguration<TvdbOptions>("tvdb");
         }
 
-        private readonly Task _cachedTask = Task.FromResult(true);
-        internal Task EnsureSeriesInfo(string seriesId, string preferredMetadataLanguage, CancellationToken cancellationToken)
+        internal static bool IsValidSeries(Dictionary<string, string> seriesProviderIds)
         {
-            var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesId);
-
-			_fileSystem.CreateDirectory(seriesDataPath);
+            string id;
+            if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id))
+            {
+                return true;
+            }
+            //if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id))
+            //{
+            //    return true;
+            //}
+            return false;
+        }
 
-			var files = _fileSystem.GetFiles(seriesDataPath)
-                .ToList();
+        internal async Task<string> EnsureSeriesInfo(Dictionary<string,string> seriesProviderIds, string preferredMetadataLanguage, CancellationToken cancellationToken)
+        {
+            string seriesId;
+            if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesId))
+            {
+                var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesId);
 
-            var seriesXmlFilename = preferredMetadataLanguage + ".xml";
+                // Only download if not already there
+                // The post-scan task will take care of updates so we don't need to re-download here
+                if (!IsCacheValid(seriesDataPath, preferredMetadataLanguage))
+                {
+                    await DownloadSeriesZip(seriesId, seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
+                }
 
-            var download = false;
-            var automaticUpdatesEnabled = GetTvDbOptions().EnableAutomaticUpdates;
+                return seriesDataPath;
+            }
 
-            const int cacheDays = 2;
+            return null;
+        }
 
-            var seriesFile = files.FirstOrDefault(i => string.Equals(seriesXmlFilename, i.Name, StringComparison.OrdinalIgnoreCase));
-            // No need to check age if automatic updates are enabled
-            if (seriesFile == null || !seriesFile.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(seriesFile)).TotalDays > cacheDays))
+        private bool IsCacheValid(string seriesDataPath, string preferredMetadataLanguage)
+        {
+            try
             {
-                download = true;
-            }
+                var files = _fileSystem.GetFiles(seriesDataPath)
+                    .ToList();
 
-            var actorsXml = files.FirstOrDefault(i => string.Equals("actors.xml", i.Name, StringComparison.OrdinalIgnoreCase));
-            // No need to check age if automatic updates are enabled
-            if (actorsXml == null || !actorsXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(actorsXml)).TotalDays > cacheDays))
-            {
-                download = true;
-            }
+                var seriesXmlFilename = preferredMetadataLanguage + ".xml";
+
+                var automaticUpdatesEnabled = GetTvDbOptions().EnableAutomaticUpdates;
+
+                const int cacheDays = 2;
+
+                var seriesFile = files.FirstOrDefault(i => string.Equals(seriesXmlFilename, i.Name, StringComparison.OrdinalIgnoreCase));
+                // No need to check age if automatic updates are enabled
+                if (seriesFile == null || !seriesFile.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(seriesFile)).TotalDays > cacheDays))
+                {
+                    return false;
+                }
 
-            var bannersXml = files.FirstOrDefault(i => string.Equals("banners.xml", i.Name, StringComparison.OrdinalIgnoreCase));
-            // No need to check age if automatic updates are enabled
-            if (bannersXml == null || !bannersXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(bannersXml)).TotalDays > cacheDays))
+                var actorsXml = files.FirstOrDefault(i => string.Equals("actors.xml", i.Name, StringComparison.OrdinalIgnoreCase));
+                // No need to check age if automatic updates are enabled
+                if (actorsXml == null || !actorsXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(actorsXml)).TotalDays > cacheDays))
+                {
+                    return false;
+                }
+
+                var bannersXml = files.FirstOrDefault(i => string.Equals("banners.xml", i.Name, StringComparison.OrdinalIgnoreCase));
+                // No need to check age if automatic updates are enabled
+                if (bannersXml == null || !bannersXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(bannersXml)).TotalDays > cacheDays))
+                {
+                    return false;
+                }
+                return true;
+            }
+            catch (DirectoryNotFoundException)
             {
-                download = true;
+                return false;
             }
-
-            // Only download if not already there
-            // The post-scan task will take care of updates so we don't need to re-download here
-            if (download)
+            catch (FileNotFoundException)
             {
-                return DownloadSeriesZip(seriesId, seriesDataPath, null, preferredMetadataLanguage, cancellationToken);
+                return false;
             }
-
-            return _cachedTask;
         }
 
         /// <summary>
         /// Finds the series.
         /// </summary>
         /// <param name="name">The name.</param>
+        /// <param name="year">The year.</param>
         /// <param name="language">The language.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{System.String}.</returns>
-        private async Task<IEnumerable<RemoteSearchResult>> FindSeries(string name, string language, CancellationToken cancellationToken)
+        private async Task<IEnumerable<RemoteSearchResult>> FindSeries(string name, int? year, string language, CancellationToken cancellationToken)
         {
             var results = (await FindSeriesInternal(name, language, cancellationToken).ConfigureAwait(false)).ToList();
 
@@ -320,7 +344,16 @@ namespace MediaBrowser.Providers.TV
                 }
             }
 
-            return results;
+            return results.Where(i =>
+            {
+                if (year.HasValue && i.ProductionYear.HasValue)
+                {
+                    // Allow one year tolerance
+                    return Math.Abs(year.Value - i.ProductionYear.Value) <= 1;
+                }
+
+                return true;
+            });
         }
 
         private async Task<IEnumerable<RemoteSearchResult>> FindSeriesInternal(string name, string language, CancellationToken cancellationToken)
@@ -1108,7 +1141,7 @@ namespace MediaBrowser.Providers.TV
             var file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber, episodeNumber));
 
             // Only save the file if not already there, or if the episode has changed
-			if (hasEpisodeChanged || !_fileSystem.FileExists(file))
+            if (hasEpisodeChanged || !_fileSystem.FileExists(file))
             {
                 using (var writer = XmlWriter.Create(file, new XmlWriterSettings
                 {
@@ -1125,7 +1158,7 @@ namespace MediaBrowser.Providers.TV
                 file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", absoluteNumber));
 
                 // Only save the file if not already there, or if the episode has changed
-				if (hasEpisodeChanged || !_fileSystem.FileExists(file))
+                if (hasEpisodeChanged || !_fileSystem.FileExists(file))
                 {
                     using (var writer = XmlWriter.Create(file, new XmlWriterSettings
                     {
@@ -1242,17 +1275,19 @@ namespace MediaBrowser.Providers.TV
 
         public async Task Identify(SeriesInfo info)
         {
-            if (string.IsNullOrEmpty(info.GetProviderId(MetadataProviders.Tvdb)))
+            if (!string.IsNullOrWhiteSpace(info.GetProviderId(MetadataProviders.Tvdb)))
             {
-                var srch = await FindSeries(info.Name, info.MetadataLanguage, CancellationToken.None).ConfigureAwait(false);
+                return;
+            }
 
-                var entry = srch.FirstOrDefault();
+            var srch = await FindSeries(info.Name, info.Year, info.MetadataLanguage, CancellationToken.None).ConfigureAwait(false);
 
-                if (entry != null)
-                {
-                    var id = entry.GetProviderId(MetadataProviders.Tvdb);
-                    info.SetProviderId(MetadataProviders.Tvdb, id);
-                }
+            var entry = srch.FirstOrDefault();
+
+            if (entry != null)
+            {
+                var id = entry.GetProviderId(MetadataProviders.Tvdb);
+                info.SetProviderId(MetadataProviders.Tvdb, id);
             }
         }
 

+ 10 - 0
MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs

@@ -607,8 +607,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
                 throw new ArgumentNullException("timer");
             }
 
+            if (string.IsNullOrWhiteSpace(timer.ProgramId))
+            {
+                throw new InvalidOperationException("timer.ProgramId is null. Cannot record.");
+            }
+
             var info = GetProgramInfoFromCache(timer.ChannelId, timer.ProgramId);
 
+            if (info == null)
+            {
+                throw new InvalidOperationException(string.Format("Program with Id {0} not found", timer.ProgramId));
+            }
+
             var recordPath = RecordingPath;
 
             if (info.IsMovie)