diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 017f3dead1..9f345e06d8 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -75,6 +75,7 @@
+
diff --git a/MediaBrowser.Controller/Providers/TV/RemoteSeriesProvider.cs b/MediaBrowser.Controller/Providers/TV/RemoteSeriesProvider.cs
index 62cc21510a..cf3bcbd70a 100644
--- a/MediaBrowser.Controller/Providers/TV/RemoteSeriesProvider.cs
+++ b/MediaBrowser.Controller/Providers/TV/RemoteSeriesProvider.cs
@@ -228,15 +228,13 @@ namespace MediaBrowser.Controller.Providers.TV
cancellationToken.ThrowIfCancellationRequested();
- var status = ProviderRefreshStatus.Success;
-
if (!string.IsNullOrEmpty(seriesId))
{
series.SetProviderId(MetadataProviders.Tvdb, seriesId);
var seriesDataPath = GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId);
- status = await FetchSeriesData(series, seriesId, seriesDataPath, cancellationToken).ConfigureAwait(false);
+ await FetchSeriesData(series, seriesId, seriesDataPath, cancellationToken).ConfigureAwait(false);
}
BaseProviderInfo data;
@@ -247,8 +245,8 @@ namespace MediaBrowser.Controller.Providers.TV
}
data.Data = GetComparisonData(item);
-
- SetLastRefreshed(item, DateTime.UtcNow, status);
+
+ SetLastRefreshed(item, DateTime.UtcNow);
return true;
}
@@ -260,10 +258,8 @@ namespace MediaBrowser.Controller.Providers.TV
/// The series data path.
/// The cancellation token.
/// Task{System.Boolean}.
- private async Task FetchSeriesData(Series series, string seriesId, string seriesDataPath, CancellationToken cancellationToken)
+ private async Task FetchSeriesData(Series series, string seriesId, string seriesDataPath, CancellationToken cancellationToken)
{
- var status = ProviderRefreshStatus.Success;
-
var files = Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.TopDirectoryOnly).Select(Path.GetFileName).ToArray();
var seriesXmlFilename = ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower() + ".xml";
@@ -299,24 +295,6 @@ namespace MediaBrowser.Controller.Providers.TV
await _providerManager.SaveToLibraryFilesystem(series, Path.Combine(series.MetaLocation, LocalMetaFileName), ms, cancellationToken).ConfigureAwait(false);
}
}
-
- // Process images
- var imagesXmlPath = Path.Combine(seriesDataPath, "banners.xml");
-
- try
- {
- var xmlDoc = new XmlDocument();
- xmlDoc.Load(imagesXmlPath);
-
- await FetchImages(series, xmlDoc, cancellationToken).ConfigureAwait(false);
- }
- catch (HttpException)
- {
- // Have the provider try again next time, but don't let it fail here
- status = ProviderRefreshStatus.CompletedWithErrors;
- }
-
- return status;
}
///
@@ -329,7 +307,7 @@ namespace MediaBrowser.Controller.Providers.TV
internal async Task DownloadSeriesZip(string seriesId, string seriesDataPath, CancellationToken cancellationToken)
{
var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, ConfigurationManager.Configuration.PreferredMetadataLanguage);
-
+
using (var zipStream = await HttpClient.Get(new HttpRequestOptions
{
Url = url,
@@ -486,66 +464,6 @@ namespace MediaBrowser.Controller.Providers.TV
///
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
- ///
- /// Fetches the images.
- ///
- /// The series.
- /// The images.
- /// The cancellation token.
- /// Task.
- private async Task FetchImages(Series series, XmlDocument images, CancellationToken cancellationToken)
- {
- if (ConfigurationManager.Configuration.RefreshItemImages || !series.HasImage(ImageType.Primary))
- {
- var n = images.SelectSingleNode("//Banner[BannerType='poster']");
- if (n != null)
- {
- n = n.SelectSingleNode("./BannerPath");
- if (n != null)
- {
- series.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, TvDbResourcePool, cancellationToken).ConfigureAwait(false);
- }
- }
- }
-
- if (ConfigurationManager.Configuration.DownloadSeriesImages.Banner && (ConfigurationManager.Configuration.RefreshItemImages || !series.HasImage(ImageType.Banner)))
- {
- var n = images.SelectSingleNode("//Banner[BannerType='series']");
- if (n != null)
- {
- n = n.SelectSingleNode("./BannerPath");
- if (n != null)
- {
- var bannerImagePath = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "banner" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, TvDbResourcePool, cancellationToken);
-
- series.SetImage(ImageType.Banner, bannerImagePath);
- }
- }
- }
-
- if (series.BackdropImagePaths.Count < ConfigurationManager.Configuration.MaxBackdrops)
- {
- var bdNo = series.BackdropImagePaths.Count;
- var xmlNodeList = images.SelectNodes("//Banner[BannerType='fanart']");
- if (xmlNodeList != null)
- {
- foreach (XmlNode b in xmlNodeList)
- {
- var p = b.SelectSingleNode("./BannerPath");
-
- if (p != null)
- {
- var bdName = "backdrop" + (bdNo > 0 ? bdNo.ToString(UsCulture) : "");
- series.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + p.InnerText, bdName + Path.GetExtension(p.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, TvDbResourcePool, cancellationToken).ConfigureAwait(false));
- bdNo++;
- }
-
- if (series.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops) break;
- }
- }
- }
- }
-
///
/// Determines whether [has local meta] [the specified item].
///
diff --git a/MediaBrowser.Controller/Providers/TV/TvdbSeriesImageProvider.cs b/MediaBrowser.Controller/Providers/TV/TvdbSeriesImageProvider.cs
new file mode 100644
index 0000000000..423e90efb3
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/TV/TvdbSeriesImageProvider.cs
@@ -0,0 +1,280 @@
+using System.Globalization;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace MediaBrowser.Controller.Providers.TV
+{
+ public class TvdbSeriesImageProvider : BaseMetadataProvider
+ {
+ ///
+ /// Gets the HTTP client.
+ ///
+ /// The HTTP client.
+ protected IHttpClient HttpClient { get; private set; }
+
+ ///
+ /// The _provider manager
+ ///
+ private readonly IProviderManager _providerManager;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The HTTP client.
+ /// The log manager.
+ /// The configuration manager.
+ /// The provider manager.
+ /// httpClient
+ public TvdbSeriesImageProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
+ : base(logManager, configurationManager)
+ {
+ if (httpClient == null)
+ {
+ throw new ArgumentNullException("httpClient");
+ }
+ HttpClient = httpClient;
+ _providerManager = providerManager;
+ }
+
+ ///
+ /// Supportses the specified item.
+ ///
+ /// The item.
+ /// true if XXXX, false otherwise
+ public override bool Supports(BaseItem item)
+ {
+ return item is Series;
+ }
+
+ ///
+ /// Gets the priority.
+ ///
+ /// The priority.
+ public override MetadataProviderPriority Priority
+ {
+ // Run after fanart
+ get { return MetadataProviderPriority.Fourth; }
+ }
+
+ ///
+ /// Gets a value indicating whether [requires internet].
+ ///
+ /// true if [requires internet]; otherwise, false.
+ public override bool RequiresInternet
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Returns true or false indicating if the provider should refresh when the contents of it's directory changes
+ ///
+ /// true if [refresh on file system stamp change]; otherwise, false.
+ protected override bool RefreshOnFileSystemStampChange
+ {
+ get
+ {
+ return ConfigurationManager.Configuration.SaveLocalMeta;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether [refresh on version change].
+ ///
+ /// true if [refresh on version change]; otherwise, false.
+ protected override bool RefreshOnVersionChange
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Gets the provider version.
+ ///
+ /// The provider version.
+ protected override string ProviderVersion
+ {
+ get
+ {
+ return "1";
+ }
+ }
+
+ ///
+ /// Needses the refresh internal.
+ ///
+ /// The item.
+ /// The provider info.
+ /// true if XXXX, false otherwise
+ protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
+ {
+ if (GetComparisonData(item) != providerInfo.Data)
+ {
+ return true;
+ }
+
+ return base.NeedsRefreshInternal(item, providerInfo);
+ }
+
+ ///
+ /// Gets the comparison data.
+ ///
+ /// The item.
+ /// Guid.
+ private Guid GetComparisonData(BaseItem item)
+ {
+ var seriesId = item.GetProviderId(MetadataProviders.Tvdb);
+
+ if (!string.IsNullOrEmpty(seriesId))
+ {
+ // Process images
+ var imagesXmlPath = Path.Combine(RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId), "banners.xml");
+
+ var imagesFileInfo = new FileInfo(imagesXmlPath);
+
+ return GetComparisonData(imagesFileInfo);
+ }
+
+ return Guid.Empty;
+ }
+
+ ///
+ /// Gets the comparison data.
+ ///
+ /// The images file info.
+ /// Guid.
+ private Guid GetComparisonData(FileInfo imagesFileInfo)
+ {
+ var date = imagesFileInfo.Exists ? imagesFileInfo.LastWriteTimeUtc : DateTime.MinValue;
+
+ var key = date.Ticks + imagesFileInfo.FullName;
+
+ return key.GetMD5();
+ }
+
+ ///
+ /// Fetches metadata and returns true or false indicating if any work that requires persistence was done
+ ///
+ /// The item.
+ /// if set to true [force].
+ /// The cancellation token.
+ /// Task{System.Boolean}.
+ public override async Task FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var series = (Series)item;
+ var seriesId = series.GetProviderId(MetadataProviders.Tvdb);
+
+ if (!string.IsNullOrEmpty(seriesId))
+ {
+ // Process images
+ var imagesXmlPath = Path.Combine(RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId), "banners.xml");
+
+ var imagesFileInfo = new FileInfo(imagesXmlPath);
+
+ if (imagesFileInfo.Exists)
+ {
+ if (!series.HasImage(ImageType.Primary) || !series.HasImage(ImageType.Banner) || series.BackdropImagePaths.Count == 0)
+ {
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(imagesXmlPath);
+
+ await FetchImages(series, xmlDoc, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ BaseProviderInfo data;
+ if (!item.ProviderData.TryGetValue(Id, out data))
+ {
+ data = new BaseProviderInfo();
+ item.ProviderData[Id] = data;
+ }
+
+ data.Data = GetComparisonData(imagesFileInfo);
+
+ SetLastRefreshed(item, DateTime.UtcNow);
+ return true;
+ }
+
+ return false;
+ }
+
+ protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+ ///
+ /// Fetches the images.
+ ///
+ /// The series.
+ /// The images.
+ /// The cancellation token.
+ /// Task.
+ private async Task FetchImages(Series series, XmlDocument images, CancellationToken cancellationToken)
+ {
+ if (ConfigurationManager.Configuration.RefreshItemImages || !series.HasImage(ImageType.Primary))
+ {
+ var n = images.SelectSingleNode("//Banner[BannerType='poster']");
+ if (n != null)
+ {
+ n = n.SelectSingleNode("./BannerPath");
+ if (n != null)
+ {
+ series.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false);
+ }
+ }
+ }
+
+ if (ConfigurationManager.Configuration.DownloadSeriesImages.Banner && (ConfigurationManager.Configuration.RefreshItemImages || !series.HasImage(ImageType.Banner)))
+ {
+ var n = images.SelectSingleNode("//Banner[BannerType='series']");
+ if (n != null)
+ {
+ n = n.SelectSingleNode("./BannerPath");
+ if (n != null)
+ {
+ var bannerImagePath = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "banner" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken);
+
+ series.SetImage(ImageType.Banner, bannerImagePath);
+ }
+ }
+ }
+
+ if (series.BackdropImagePaths.Count < ConfigurationManager.Configuration.MaxBackdrops)
+ {
+ var bdNo = series.BackdropImagePaths.Count;
+ var xmlNodeList = images.SelectNodes("//Banner[BannerType='fanart']");
+ if (xmlNodeList != null)
+ {
+ foreach (XmlNode b in xmlNodeList)
+ {
+ var p = b.SelectSingleNode("./BannerPath");
+
+ if (p != null)
+ {
+ var bdName = "backdrop" + (bdNo > 0 ? bdNo.ToString(UsCulture) : "");
+ series.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + p.InnerText, bdName + Path.GetExtension(p.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false));
+ bdNo++;
+ }
+
+ if (series.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops) break;
+ }
+ }
+ }
+ }
+ }
+}