Bläddra i källkod

only update episodes that have been changed

Luke Pulverenti 11 år sedan
förälder
incheckning
85928ea2b4

+ 1 - 1
MediaBrowser.Providers/MediaBrowser.Providers.csproj

@@ -82,7 +82,7 @@
     <Compile Include="Music\LastfmArtistProvider.cs" />
     <Compile Include="Music\LastfmBaseProvider.cs" />
     <Compile Include="Music\LastfmHelper.cs" />
-    <Compile Include="Music\MusicAlbumDynamicInfoProvider.cs" />
+    <Compile Include="Music\AlbumDynamicInfoProvider.cs" />
     <Compile Include="Music\MusicVideoXmlParser.cs" />
     <Compile Include="Music\SoundtrackPostScanTask.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />

+ 2 - 2
MediaBrowser.Providers/Music/MusicAlbumDynamicInfoProvider.cs → MediaBrowser.Providers/Music/AlbumDynamicInfoProvider.cs

@@ -13,14 +13,14 @@ namespace MediaBrowser.Providers.Music
     /// <summary>
     /// Class MusicAlbumDynamicInfoProvider
     /// </summary>
-    public class MusicAlbumDynamicInfoProvider : BaseMetadataProvider, IDynamicInfoProvider
+    public class AlbumDynamicInfoProvider : BaseMetadataProvider, IDynamicInfoProvider
     {
         /// <summary>
         /// Initializes a new instance of the <see cref="BaseMetadataProvider" /> class.
         /// </summary>
         /// <param name="logManager">The log manager.</param>
         /// <param name="configurationManager">The configuration manager.</param>
-        public MusicAlbumDynamicInfoProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
+        public AlbumDynamicInfoProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
             : base(logManager, configurationManager)
         {
         }

+ 82 - 8
MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using System.Collections.Generic;
+using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
@@ -127,7 +128,7 @@ namespace MediaBrowser.Providers.TV
             return base.NeedsRefreshInternal(item, providerInfo);
         }
 
-        protected override DateTime CompareDate(BaseItem item)
+        protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo)
         {
             var episode = (Episode)item;
 
@@ -136,17 +137,90 @@ namespace MediaBrowser.Providers.TV
             if (!string.IsNullOrEmpty(seriesId))
             {
                 // Process images
-                var seriesXmlPath = Path.Combine(RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId), ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower() + ".xml");
+                var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId);
 
-                var seriesXmlFileInfo = new FileInfo(seriesXmlPath);
+                var files = GetEpisodeXmlFiles(episode, seriesDataPath);
 
-                if (seriesXmlFileInfo.Exists)
+                if (files.Count > 0)
                 {
-                    return seriesXmlFileInfo.LastWriteTimeUtc;
+                    return files.Select(i => i.LastWriteTimeUtc).Max() > providerInfo.LastRefreshed;
                 }
             }
+            
+            return false;
+        }
+
+        /// <summary>
+        /// Gets the episode XML files.
+        /// </summary>
+        /// <param name="episode">The episode.</param>
+        /// <param name="seriesDataPath">The series data path.</param>
+        /// <returns>List{FileInfo}.</returns>
+        private List<FileInfo> GetEpisodeXmlFiles(Episode episode, string seriesDataPath)
+        {
+            var files = new List<FileInfo>();
+
+            if (episode.IndexNumber == null)
+            {
+                return files;
+            }
+
+            var episodeNumber = episode.IndexNumber.Value;
+            var seasonNumber = episode.ParentIndexNumber;
+
+            if (seasonNumber == null)
+            {
+                return files;
+            }
+
+            var file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
+
+            var fileInfo = new FileInfo(file);
+            var usingAbsoluteData = false;
+
+            if (fileInfo.Exists)
+            {
+                files.Add(fileInfo);
+            }
+            else
+            {
+                file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
+                fileInfo = new FileInfo(file);
+                if (fileInfo.Exists)
+                {
+                    files.Add(fileInfo);
+                    usingAbsoluteData = true;
+                }
+            }
+
+            var end = episode.IndexNumberEnd ?? episodeNumber;
+            episodeNumber++;
+
+            while (episodeNumber <= end)
+            {
+                if (usingAbsoluteData)
+                {
+                    file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
+                }
+                else
+                {
+                    file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
+                }
+
+                fileInfo = new FileInfo(file);
+                if (fileInfo.Exists)
+                {
+                    files.Add(fileInfo);
+                }
+                else
+                {
+                    break;
+                }
+
+                episodeNumber++;
+            }
 
-            return base.CompareDate(item);
+            return files;
         }
 
         /// <summary>
@@ -213,7 +287,7 @@ namespace MediaBrowser.Providers.TV
             }
 
             var episodeNumber = episode.IndexNumber.Value;
-            var seasonNumber = episode.ParentIndexNumber ?? TVUtils.GetSeasonNumberFromEpisodeFile(episode.Path);
+            var seasonNumber = episode.ParentIndexNumber;
 
             if (seasonNumber == null)
             {

+ 46 - 18
MediaBrowser.Providers/TV/RemoteSeriesProvider.cs

@@ -252,7 +252,7 @@ namespace MediaBrowser.Providers.TV
             // The prescan task will take care of updates so we don't need to re-download here
             if (!files.Contains("banners.xml", StringComparer.OrdinalIgnoreCase) || !files.Contains("actors.xml", StringComparer.OrdinalIgnoreCase) || !files.Contains(seriesXmlFilename, StringComparer.OrdinalIgnoreCase))
             {
-                await DownloadSeriesZip(seriesId, seriesDataPath, cancellationToken).ConfigureAwait(false);
+                await DownloadSeriesZip(seriesId, seriesDataPath, null, cancellationToken).ConfigureAwait(false);
             }
 
             // Examine if there's no local metadata, or save local is on (to get updates)
@@ -279,7 +279,7 @@ namespace MediaBrowser.Providers.TV
         /// <param name="seriesDataPath">The series data path.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
-        internal async Task DownloadSeriesZip(string seriesId, string seriesDataPath, CancellationToken cancellationToken)
+        internal async Task DownloadSeriesZip(string seriesId, string seriesDataPath, long? lastTvDbUpdateTime, CancellationToken cancellationToken)
         {
             var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, ConfigurationManager.Configuration.PreferredMetadataLanguage);
 
@@ -301,12 +301,14 @@ namespace MediaBrowser.Providers.TV
                 }
             }
 
-            foreach (var file in Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.AllDirectories).ToList())
+            // Sanitize all files, except for extracted episode files
+            foreach (var file in Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.AllDirectories).ToList()
+                .Where(i => !Path.GetFileName(i).StartsWith("episode-", StringComparison.OrdinalIgnoreCase)))
             {
                 await SanitizeXmlFile(file).ConfigureAwait(false);
             }
 
-            await ExtractEpisodes(seriesDataPath, Path.Combine(seriesDataPath, ConfigurationManager.Configuration.PreferredMetadataLanguage + ".xml")).ConfigureAwait(false);
+            await ExtractEpisodes(seriesDataPath, Path.Combine(seriesDataPath, ConfigurationManager.Configuration.PreferredMetadataLanguage + ".xml"), lastTvDbUpdateTime).ConfigureAwait(false);
         }
 
         /// <summary>
@@ -369,8 +371,9 @@ namespace MediaBrowser.Providers.TV
         /// </summary>
         /// <param name="seriesDataPath">The series data path.</param>
         /// <param name="xmlFile">The XML file.</param>
+        /// <param name="lastTvDbUpdateTime">The last tv db update time.</param>
         /// <returns>Task.</returns>
-        private async Task ExtractEpisodes(string seriesDataPath, string xmlFile)
+        private async Task ExtractEpisodes(string seriesDataPath, string xmlFile, long? lastTvDbUpdateTime)
         {
             var settings = new XmlReaderSettings
             {
@@ -398,7 +401,7 @@ namespace MediaBrowser.Providers.TV
                                     {
                                         var outerXml = reader.ReadOuterXml();
 
-                                        await SaveEpsiodeXml(seriesDataPath, outerXml).ConfigureAwait(false);
+                                        await SaveEpsiodeXml(seriesDataPath, outerXml, lastTvDbUpdateTime).ConfigureAwait(false);
                                         break;
                                     }
 
@@ -412,7 +415,7 @@ namespace MediaBrowser.Providers.TV
             }
         }
 
-        private async Task SaveEpsiodeXml(string seriesDataPath, string xml)
+        private async Task SaveEpsiodeXml(string seriesDataPath, string xml, long? lastTvDbUpdateTime)
         {
             var settings = new XmlReaderSettings
             {
@@ -425,6 +428,7 @@ namespace MediaBrowser.Providers.TV
             var seasonNumber = -1;
             var episodeNumber = -1;
             var absoluteNumber = -1;
+            var lastUpdateString = string.Empty;
 
             using (var streamReader = new StringReader(xml))
             {
@@ -440,6 +444,12 @@ namespace MediaBrowser.Providers.TV
                         {
                             switch (reader.Name)
                             {
+                                case "lastupdated":
+                                    {
+                                        lastUpdateString = reader.ReadElementContentAsString();
+                                        break;
+                                    }
+
                                 case "EpisodeNumber":
                                     {
                                         var val = reader.ReadElementContentAsString();
@@ -491,21 +501,21 @@ namespace MediaBrowser.Providers.TV
                 }
             }
 
-            var file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber, episodeNumber));
-
-            using (var writer = XmlWriter.Create(file, new XmlWriterSettings
-            {
-                Encoding = Encoding.UTF8,
-                Async = true
-            }))
+            var hasEpisodeChanged = true;
+            if (!string.IsNullOrEmpty(lastUpdateString) && lastTvDbUpdateTime.HasValue)
             {
-                await writer.WriteRawAsync(xml).ConfigureAwait(false);
+                long num;
+                if (long.TryParse(lastUpdateString, NumberStyles.Any, UsCulture, out num))
+                {
+                    hasEpisodeChanged = num >= lastTvDbUpdateTime.Value;
+                }
             }
 
-            if (absoluteNumber != -1)
-            {
-                file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", absoluteNumber));
+            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 || !File.Exists(file))
+            {
                 using (var writer = XmlWriter.Create(file, new XmlWriterSettings
                 {
                     Encoding = Encoding.UTF8,
@@ -515,6 +525,24 @@ namespace MediaBrowser.Providers.TV
                     await writer.WriteRawAsync(xml).ConfigureAwait(false);
                 }
             }
+
+            if (absoluteNumber != -1)
+            {
+                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 || !File.Exists(file))
+                {
+                    using (var writer = XmlWriter.Create(file, new XmlWriterSettings
+                    {
+                        Encoding = Encoding.UTF8,
+                        Async = true
+                    }))
+                    {
+                        await writer.WriteRawAsync(xml).ConfigureAwait(false);
+                    }
+                }
+            }
         }
 
         /// <summary>

+ 19 - 8
MediaBrowser.Providers/TV/TvdbPrescanTask.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using System.Globalization;
+using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Logging;
@@ -55,6 +56,8 @@ namespace MediaBrowser.Providers.TV
             _config = config;
         }
 
+        protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
         /// <summary>
         /// Runs the specified progress.
         /// </summary>
@@ -72,7 +75,7 @@ namespace MediaBrowser.Providers.TV
             var path = RemoteSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths);
 
             Directory.CreateDirectory(path);
-            
+
             var timestampFile = Path.Combine(path, "time.txt");
 
             var timestampFileInfo = new FileInfo(timestampFile);
@@ -106,7 +109,7 @@ namespace MediaBrowser.Providers.TV
                     newUpdateTime = GetUpdateTime(stream);
                 }
 
-                await UpdateSeries(existingDirectories, path, progress, cancellationToken).ConfigureAwait(false);
+                await UpdateSeries(existingDirectories, path, null, progress, cancellationToken).ConfigureAwait(false);
             }
             else
             {
@@ -114,7 +117,13 @@ namespace MediaBrowser.Providers.TV
 
                 newUpdateTime = seriesToUpdate.Item2;
 
-                await UpdateSeries(seriesToUpdate.Item1, path, progress, cancellationToken).ConfigureAwait(false);
+                long lastUpdateValue;
+
+                long.TryParse(lastUpdateTime, NumberStyles.Any, UsCulture, out lastUpdateValue);
+
+                var nullableUpdateValue = lastUpdateValue == 0 ? (long?)null : lastUpdateValue;
+
+                await UpdateSeries(seriesToUpdate.Item1, path, nullableUpdateValue, progress, cancellationToken).ConfigureAwait(false);
             }
 
             File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
@@ -251,10 +260,11 @@ namespace MediaBrowser.Providers.TV
         /// </summary>
         /// <param name="seriesIds">The series ids.</param>
         /// <param name="seriesDataPath">The series data path.</param>
+        /// <param name="lastTvDbUpdateTime">The last tv db update time.</param>
         /// <param name="progress">The progress.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
-        private async Task UpdateSeries(IEnumerable<string> seriesIds, string seriesDataPath, IProgress<double> progress, CancellationToken cancellationToken)
+        private async Task UpdateSeries(IEnumerable<string> seriesIds, string seriesDataPath, long? lastTvDbUpdateTime, IProgress<double> progress, CancellationToken cancellationToken)
         {
             var list = seriesIds.ToList();
             var numComplete = 0;
@@ -263,7 +273,7 @@ namespace MediaBrowser.Providers.TV
             {
                 try
                 {
-                    await UpdateSeries(seriesId, seriesDataPath, cancellationToken).ConfigureAwait(false);
+                    await UpdateSeries(seriesId, seriesDataPath, lastTvDbUpdateTime, cancellationToken).ConfigureAwait(false);
                 }
                 catch (HttpException ex)
                 {
@@ -289,9 +299,10 @@ namespace MediaBrowser.Providers.TV
         /// </summary>
         /// <param name="id">The id.</param>
         /// <param name="seriesDataPath">The series data path.</param>
+        /// <param name="lastTvDbUpdateTime">The last tv db update time.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
-        private Task UpdateSeries(string id, string seriesDataPath, CancellationToken cancellationToken)
+        private Task UpdateSeries(string id, string seriesDataPath, long? lastTvDbUpdateTime, CancellationToken cancellationToken)
         {
             _logger.Info("Updating series " + id);
 
@@ -299,7 +310,7 @@ namespace MediaBrowser.Providers.TV
 
             Directory.CreateDirectory(seriesDataPath);
 
-            return RemoteSeriesProvider.Current.DownloadSeriesZip(id, seriesDataPath, cancellationToken);
+            return RemoteSeriesProvider.Current.DownloadSeriesZip(id, seriesDataPath, lastTvDbUpdateTime, cancellationToken);
         }
     }
 }

+ 16 - 0
MediaBrowser.Server.Mono/Program.cs

@@ -11,6 +11,9 @@ using System.Diagnostics;
 using System.IO;
 using System.Threading;
 using System.Windows;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
 using Gtk;
 using Gdk;
 using System.Threading.Tasks;
@@ -90,12 +93,17 @@ namespace MediaBrowser.Server.Mono
 			}
 		}
 
+		private static RemoteCertificateValidationCallback _ignoreCertificates = new RemoteCertificateValidationCallback(delegate { return true; });
+
 		private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager)
 		{
 			// TODO: Show splash here
 
 			SystemEvents.SessionEnding += SystemEvents_SessionEnding;
 
+			// Allow all https requests
+			ServicePointManager.ServerCertificateValidationCallback = _ignoreCertificates;
+
 			_appHost = new ApplicationHost(appPaths, logManager);
 
 			var task = _appHost.Init();
@@ -264,4 +272,12 @@ namespace MediaBrowser.Server.Mono
 			Shutdown ();
 		}
 	}
+
+	class NoCheckCertificatePolicy : ICertificatePolicy
+	{
+		public bool CheckValidationResult (ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem)
+		{
+			return true;
+		}
+	}
 }