diff --git a/MediaBrowser.Api/RemoteImageService.cs b/MediaBrowser.Api/RemoteImageService.cs index c5f1005c75..e64badd050 100644 --- a/MediaBrowser.Api/RemoteImageService.cs +++ b/MediaBrowser.Api/RemoteImageService.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Api [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] public string Id { get; set; } - [ApiMember(Name = "Type", Description = "The image type", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + [ApiMember(Name = "Type", Description = "The image type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public ImageType? Type { get; set; } /// diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 4f0f2a7d93..128db86b25 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -114,9 +114,10 @@ - - - + + + + diff --git a/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs b/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs index b66d9faf52..06115a6dee 100644 --- a/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/ManualFanartSeasonProvider.cs @@ -245,7 +245,7 @@ namespace MediaBrowser.Providers.TV public int Priority { - get { return 1; } + get { return 0; } } } } diff --git a/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs b/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs index 21b8e278c7..718e7849e2 100644 --- a/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/ManualFanartSeriesProvider.cs @@ -303,7 +303,7 @@ namespace MediaBrowser.Providers.TV public int Priority { - get { return 1; } + get { return 0; } } } } diff --git a/MediaBrowser.Providers/TV/ManualTvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbEpisodeImageProvider.cs index 003b40f6da..1b6d37639d 100644 --- a/MediaBrowser.Providers/TV/ManualTvdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/TV/ManualTvdbEpisodeImageProvider.cs @@ -52,9 +52,9 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(seriesId)) { // Process images - var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId); + var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId); - var files = RemoteEpisodeProvider.Current.GetEpisodeXmlFiles(episode, seriesDataPath); + var files = TvdbEpisodeProvider.Current.GetEpisodeXmlFiles(episode, seriesDataPath); var result = files.Select(i => GetImageInfo(i, cancellationToken)).Where(i => i != null); diff --git a/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs index 211ec5a84a..9c4b31d096 100644 --- a/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/TV/ManualTvdbSeasonImageProvider.cs @@ -59,7 +59,7 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(seriesId) && season.IndexNumber.HasValue) { // Process images - var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId); + var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId); var path = Path.Combine(seriesDataPath, "banners.xml"); @@ -279,10 +279,14 @@ namespace MediaBrowser.Providers.TV ProviderName = Name, Language = language, Width = width, - Height = height, - ThumbnailUrl = thumbnailUrl + Height = height }; + if (!string.IsNullOrEmpty(thumbnailUrl)) + { + imageInfo.ThumbnailUrl = TVUtils.BannerUrl + thumbnailUrl; + } + if (string.Equals(bannerType, "season", StringComparison.OrdinalIgnoreCase)) { if (string.Equals(bannerType2, "season", StringComparison.OrdinalIgnoreCase)) @@ -307,7 +311,7 @@ namespace MediaBrowser.Providers.TV public int Priority { - get { return 0; } + get { return 1; } } } } diff --git a/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs new file mode 100644 index 0000000000..fa09681e79 --- /dev/null +++ b/MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs @@ -0,0 +1,312 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; + +namespace MediaBrowser.Providers.TV +{ + public class ManualTvdbSeriesImageProvider : IImageProvider + { + private readonly IServerConfigurationManager _config; + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + + public ManualTvdbSeriesImageProvider(IServerConfigurationManager config) + { + _config = config; + } + + public string Name + { + get { return ProviderName; } + } + + public static string ProviderName + { + get { return "TvDb"; } + } + + public bool Supports(BaseItem item) + { + return item is Series; + } + + public async Task> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + { + var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); + + return images.Where(i => i.Type == imageType); + } + + public Task> GetAllImages(BaseItem item, CancellationToken cancellationToken) + { + var seriesId = item.GetProviderId(MetadataProviders.Tvdb); + + if (!string.IsNullOrEmpty(seriesId)) + { + // Process images + var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId); + + var path = Path.Combine(seriesDataPath, "banners.xml"); + + try + { + var result = GetImages(path, cancellationToken); + + return Task.FromResult(result); + } + catch (FileNotFoundException) + { + // No tvdb data yet. Don't blow up + } + } + + return Task.FromResult>(new RemoteImageInfo[] { }); + } + + private IEnumerable GetImages(string xmlPath, CancellationToken cancellationToken) + { + var settings = new XmlReaderSettings + { + CheckCharacters = false, + IgnoreProcessingInstructions = true, + IgnoreComments = true, + ValidationType = ValidationType.None + }; + + var list = new List(); + + using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8)) + { + // Use XmlReader for best performance + using (var reader = XmlReader.Create(streamReader, settings)) + { + reader.MoveToContent(); + + // Loop through each element + while (reader.Read()) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Banner": + { + using (var subtree = reader.ReadSubtree()) + { + AddImage(subtree, list); + } + break; + } + default: + reader.Skip(); + break; + } + } + } + } + } + + var language = _config.Configuration.PreferredMetadataLanguage; + + var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); + + return list.OrderByDescending(i => + { + if (string.Equals(language, i.Language, StringComparison.OrdinalIgnoreCase)) + { + return 3; + } + if (!isLanguageEn) + { + if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase)) + { + return 2; + } + } + if (string.IsNullOrEmpty(i.Language)) + { + return isLanguageEn ? 3 : 2; + } + return 0; + }) + .ThenByDescending(i => i.CommunityRating ?? 0) + .ToList(); + } + + private void AddImage(XmlReader reader, List images) + { + reader.MoveToContent(); + + string bannerType = null; + string url = null; + int? bannerSeason = null; + int? width = null; + int? height = null; + string language = null; + double? rating = null; + int? voteCount = null; + string thumbnailUrl = null; + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Rating": + { + var val = reader.ReadElementContentAsString() ?? string.Empty; + + double rval; + + if (double.TryParse(val, NumberStyles.Any, _usCulture, out rval)) + { + rating = rval; + } + + break; + } + + case "RatingCount": + { + var val = reader.ReadElementContentAsString() ?? string.Empty; + + int rval; + + if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval)) + { + voteCount = rval; + } + + break; + } + + case "Language": + { + language = reader.ReadElementContentAsString() ?? string.Empty; + break; + } + + case "ThumbnailPath": + { + thumbnailUrl = reader.ReadElementContentAsString() ?? string.Empty; + break; + } + + case "BannerType": + { + bannerType = reader.ReadElementContentAsString() ?? string.Empty; + + break; + } + + case "BannerPath": + { + url = reader.ReadElementContentAsString() ?? string.Empty; + break; + } + + case "BannerType2": + { + var bannerType2 = reader.ReadElementContentAsString() ?? string.Empty; + + // Sometimes the resolution is stuffed in here + var resolutionParts = bannerType2.Split('x'); + + if (resolutionParts.Length == 2) + { + int rval; + + if (int.TryParse(resolutionParts[0], NumberStyles.Integer, _usCulture, out rval)) + { + width = rval; + } + + if (int.TryParse(resolutionParts[1], NumberStyles.Integer, _usCulture, out rval)) + { + height = rval; + } + + } + + break; + } + + case "Season": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + bannerSeason = int.Parse(val); + } + break; + } + + + default: + reader.Skip(); + break; + } + } + } + + if (!string.IsNullOrEmpty(url) && !bannerSeason.HasValue) + { + var imageInfo = new RemoteImageInfo + { + RatingType = RatingType.Score, + CommunityRating = rating, + VoteCount = voteCount, + Url = TVUtils.BannerUrl + url, + ProviderName = Name, + Language = language, + Width = width, + Height = height + }; + + if (!string.IsNullOrEmpty(thumbnailUrl)) + { + imageInfo.ThumbnailUrl = TVUtils.BannerUrl + thumbnailUrl; + } + + if (string.Equals(bannerType, "poster", StringComparison.OrdinalIgnoreCase)) + { + imageInfo.Type = ImageType.Primary; + images.Add(imageInfo); + } + else if (string.Equals(bannerType, "series", StringComparison.OrdinalIgnoreCase)) + { + imageInfo.Type = ImageType.Banner; + images.Add(imageInfo); + } + else if (string.Equals(bannerType, "fanart", StringComparison.OrdinalIgnoreCase)) + { + imageInfo.Type = ImageType.Backdrop; + images.Add(imageInfo); + } + } + + } + + public int Priority + { + get { return 1; } + } + } +} diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs index 22ff917618..7ad564d0fe 100644 --- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs @@ -111,7 +111,7 @@ namespace MediaBrowser.Providers.TV return; } - var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId); + var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId); var episodeFiles = Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.TopDirectoryOnly) .Select(Path.GetFileNameWithoutExtension) diff --git a/MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs similarity index 97% rename from MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs rename to MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs index 63b755bf90..c47640ad96 100644 --- a/MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.TV /// /// Class RemoteEpisodeProvider /// - class RemoteEpisodeProvider : BaseMetadataProvider + class TvdbEpisodeProvider : BaseMetadataProvider { /// /// The _provider manager @@ -39,16 +39,16 @@ namespace MediaBrowser.Providers.TV protected IHttpClient HttpClient { get; private set; } private readonly IFileSystem _fileSystem; - internal static RemoteEpisodeProvider Current; + internal static TvdbEpisodeProvider Current; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The HTTP client. /// The log manager. /// The configuration manager. /// The provider manager. - public RemoteEpisodeProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem) + public TvdbEpisodeProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem) : base(logManager, configurationManager) { HttpClient = httpClient; @@ -149,7 +149,7 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(seriesId)) { // Process images - var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId); + var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId); var files = GetEpisodeXmlFiles(episode, seriesDataPath); @@ -254,7 +254,7 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(seriesId)) { - var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId); + var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId); try { @@ -438,7 +438,7 @@ namespace MediaBrowser.Providers.TV { var url = TVUtils.BannerUrl + val; - await _providerManager.SaveImage(item, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); + await _providerManager.SaveImage(item, url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); } catch (HttpException) { diff --git a/MediaBrowser.Providers/TV/TvdbPersonImageProvider.cs b/MediaBrowser.Providers/TV/TvdbPersonImageProvider.cs index 10ca47c413..5882d74cfb 100644 --- a/MediaBrowser.Providers/TV/TvdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbPersonImageProvider.cs @@ -107,7 +107,7 @@ namespace MediaBrowser.Providers.TV /// Task. private async Task DownloadImageFromSeries(BaseItem item, Series series, CancellationToken cancellationToken) { - var tvdbPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, series.GetProviderId(MetadataProviders.Tvdb)); + var tvdbPath = TvdbSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, series.GetProviderId(MetadataProviders.Tvdb)); var actorXmlPath = Path.Combine(tvdbPath, "actors.xml"); @@ -117,7 +117,7 @@ namespace MediaBrowser.Providers.TV { url = TVUtils.BannerUrl + url; - await _providerManager.SaveImage(item, url, RemoteSeriesProvider.Current.TvDbResourcePool, + await _providerManager.SaveImage(item, url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs index d77698725a..df5c39b65f 100644 --- a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs +++ b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs @@ -77,7 +77,7 @@ namespace MediaBrowser.Providers.TV return; } - var path = RemoteSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths); + var path = TvdbSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths); Directory.CreateDirectory(path); @@ -107,7 +107,7 @@ namespace MediaBrowser.Providers.TV Url = ServerTimeUrl, CancellationToken = cancellationToken, EnableHttpCompression = true, - ResourcePool = RemoteSeriesProvider.Current.TvDbResourcePool + ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool }).ConfigureAwait(false)) { @@ -195,7 +195,7 @@ namespace MediaBrowser.Providers.TV Url = string.Format(UpdatesUrl, lastUpdateTime), CancellationToken = cancellationToken, EnableHttpCompression = true, - ResourcePool = RemoteSeriesProvider.Current.TvDbResourcePool + ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool }).ConfigureAwait(false)) { @@ -315,7 +315,7 @@ namespace MediaBrowser.Providers.TV Directory.CreateDirectory(seriesDataPath); - return RemoteSeriesProvider.Current.DownloadSeriesZip(id, seriesDataPath, lastTvDbUpdateTime, cancellationToken); + return TvdbSeriesProvider.Current.DownloadSeriesZip(id, seriesDataPath, lastTvDbUpdateTime, cancellationToken); } } } diff --git a/MediaBrowser.Providers/TV/RemoteSeasonProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs similarity index 88% rename from MediaBrowser.Providers/TV/RemoteSeasonProvider.cs rename to MediaBrowser.Providers/TV/TvdbSeasonProvider.cs index 7444698473..77a432add6 100644 --- a/MediaBrowser.Providers/TV/RemoteSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.TV /// /// Class RemoteSeasonProvider /// - class RemoteSeasonProvider : BaseMetadataProvider + class TvdbSeasonProvider : BaseMetadataProvider { /// /// The _provider manager @@ -28,13 +28,13 @@ namespace MediaBrowser.Providers.TV private readonly IFileSystem _fileSystem; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The log manager. /// The configuration manager. /// The provider manager. /// httpClient - public RemoteSeasonProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem) + public TvdbSeasonProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem) : base(logManager, configurationManager) { _providerManager = providerManager; @@ -113,7 +113,7 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(seriesId)) { // Process images - var imagesXmlPath = Path.Combine(RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId), "banners.xml"); + var imagesXmlPath = Path.Combine(TvdbSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId), "banners.xml"); var imagesFileInfo = new FileInfo(imagesXmlPath); @@ -145,7 +145,7 @@ namespace MediaBrowser.Providers.TV { cancellationToken.ThrowIfCancellationRequested(); - var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualFanartSeriesImageProvider.ProviderName).ConfigureAwait(false); + var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualTvdbSeasonImageProvider.ProviderName).ConfigureAwait(false); const int backdropLimit = 1; @@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.TV if (image != null) { - await _providerManager.SaveImage(item, image.Url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken) + await _providerManager.SaveImage(item, image.Url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken) .ConfigureAwait(false); } } @@ -174,7 +174,7 @@ namespace MediaBrowser.Providers.TV if (image != null) { - await _providerManager.SaveImage(item, image.Url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Banner, null, cancellationToken) + await _providerManager.SaveImage(item, image.Url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Banner, null, cancellationToken) .ConfigureAwait(false); } } @@ -192,7 +192,7 @@ namespace MediaBrowser.Providers.TV continue; } - await _providerManager.SaveImage(item, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, bdNo, cancellationToken).ConfigureAwait(false); + await _providerManager.SaveImage(item, url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, bdNo, cancellationToken).ConfigureAwait(false); bdNo++; diff --git a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs index 5fc7b50f9e..42118c0633 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs @@ -3,20 +3,17 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Providers; using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; -using System.Xml; namespace MediaBrowser.Providers.TV { @@ -125,7 +122,7 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(seriesId)) { // Process images - var imagesXmlPath = Path.Combine(RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId), "banners.xml"); + var imagesXmlPath = Path.Combine(TvdbSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId), "banners.xml"); var imagesFileInfo = new FileInfo(imagesXmlPath); @@ -158,64 +155,36 @@ namespace MediaBrowser.Providers.TV { cancellationToken.ThrowIfCancellationRequested(); - var series = (Series)item; - var seriesId = series.GetProviderId(MetadataProviders.Tvdb); + var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualTvdbSeriesImageProvider.ProviderName).ConfigureAwait(false); - if (!string.IsNullOrEmpty(seriesId)) - { - // Process images - var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId); - - var imagesXmlPath = Path.Combine(seriesDataPath, "banners.xml"); - - var backdropLimit = ConfigurationManager.Configuration.MaxBackdrops; - - if (!series.HasImage(ImageType.Primary) || !series.HasImage(ImageType.Banner) || series.BackdropImagePaths.Count < backdropLimit) - { - Directory.CreateDirectory(seriesDataPath); - - try - { - var fanartData = FetchFanartXmlData(imagesXmlPath, backdropLimit, cancellationToken); - await DownloadImages(item, fanartData, backdropLimit, cancellationToken).ConfigureAwait(false); - } - catch (FileNotFoundException) - { - // No biggie. Not all series have images - } - } + const int backdropLimit = 1; - SetLastRefreshed(item, DateTime.UtcNow); - return true; - } + await DownloadImages(item, images.ToList(), backdropLimit, cancellationToken).ConfigureAwait(false); - return false; + SetLastRefreshed(item, DateTime.UtcNow); + return true; } - protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - private async Task DownloadImages(BaseItem item, FanartXmlData data, int backdropLimit, CancellationToken cancellationToken) + private async Task DownloadImages(BaseItem item, List images, int backdropLimit, CancellationToken cancellationToken) { if (!item.HasImage(ImageType.Primary)) { - var url = data.LanguagePoster ?? data.Poster; - if (!string.IsNullOrEmpty(url)) - { - url = TVUtils.BannerUrl + url; + var image = images.FirstOrDefault(i => i.Type == ImageType.Primary); - await _providerManager.SaveImage(item, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken) + if (image != null) + { + await _providerManager.SaveImage(item, image.Url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken) .ConfigureAwait(false); } } if (ConfigurationManager.Configuration.DownloadSeriesImages.Banner && !item.HasImage(ImageType.Banner)) { - var url = data.LanguageBanner ?? data.Banner; - if (!string.IsNullOrEmpty(url)) - { - url = TVUtils.BannerUrl + url; + var image = images.FirstOrDefault(i => i.Type == ImageType.Banner); - await _providerManager.SaveImage(item, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Banner, null, cancellationToken) + if (image != null) + { + await _providerManager.SaveImage(item, image.Url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Banner, null, cancellationToken) .ConfigureAwait(false); } } @@ -224,38 +193,18 @@ namespace MediaBrowser.Providers.TV { var bdNo = item.BackdropImagePaths.Count; - var eligibleBackdrops = data.Backdrops - .Where(i => - { - if (string.IsNullOrEmpty(i.Resolution)) - { - return true; - } - - var parts = i.Resolution.Split('x'); - - int width; - - if (int.TryParse(parts[0], NumberStyles.Any, UsCulture, out width)) - { - return width >= ConfigurationManager.Configuration.MinSeriesBackdropDownloadWidth; - } - - return true; - }) - .ToList(); - - foreach (var backdrop in eligibleBackdrops) + foreach (var backdrop in images.Where(i => i.Type == ImageType.Backdrop && + (!i.Width.HasValue || + i.Width.Value >= ConfigurationManager.Configuration.MinSeriesBackdropDownloadWidth))) { - var url = TVUtils.BannerUrl + backdrop.Url; + var url = backdrop.Url; if (item.ContainsImageWithSourceUrl(url)) { continue; } - await _providerManager.SaveImage(item, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, bdNo, cancellationToken) - .ConfigureAwait(false); + await _providerManager.SaveImage(item, url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, bdNo, cancellationToken).ConfigureAwait(false); bdNo++; @@ -263,158 +212,5 @@ namespace MediaBrowser.Providers.TV } } } - - private FanartXmlData FetchFanartXmlData(string bannersXmlPath, int backdropLimit, CancellationToken cancellationToken) - { - var settings = new XmlReaderSettings - { - CheckCharacters = false, - IgnoreProcessingInstructions = true, - IgnoreComments = true, - ValidationType = ValidationType.None - }; - - var data = new FanartXmlData(); - - using (var streamReader = new StreamReader(bannersXmlPath, Encoding.UTF8)) - { - // Use XmlReader for best performance - using (var reader = XmlReader.Create(streamReader, settings)) - { - reader.MoveToContent(); - - // Loop through each element - while (reader.Read()) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "Banner": - { - using (var subtree = reader.ReadSubtree()) - { - FetchInfoFromBannerNode(data, subtree, backdropLimit); - } - break; - } - default: - reader.Skip(); - break; - } - } - } - } - } - - return data; - } - - private void FetchInfoFromBannerNode(FanartXmlData data, XmlReader reader, int backdropLimit) - { - reader.MoveToContent(); - - string type = null; - string url = null; - string resolution = null; - - while (reader.Read()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "BannerType": - { - type = reader.ReadElementContentAsString() ?? string.Empty; - - if (string.Equals(type, "poster", StringComparison.OrdinalIgnoreCase)) - { - // Already got it - if (!string.IsNullOrEmpty(data.Poster)) - { - return; - } - } - else if (string.Equals(type, "series", StringComparison.OrdinalIgnoreCase)) - { - // Already got it - if (!string.IsNullOrEmpty(data.Banner)) - { - return; - } - } - else - { - return; - } - - break; - } - - case "BannerPath": - { - url = reader.ReadElementContentAsString() ?? string.Empty; - break; - } - - case "BannerType2": - { - resolution = reader.ReadElementContentAsString() ?? string.Empty; - break; - } - - default: - reader.Skip(); - break; - } - } - } - - if (!string.IsNullOrEmpty(url)) - { - if (string.Equals(type, "poster", StringComparison.OrdinalIgnoreCase)) - { - // Just grab the first - if (string.IsNullOrWhiteSpace(data.Poster)) - { - data.Poster = url; - } - } - else if (string.Equals(type, "series", StringComparison.OrdinalIgnoreCase)) - { - // Just grab the first - if (string.IsNullOrWhiteSpace(data.Banner)) - { - data.Banner = url; - } - } - else if (string.Equals(type, "fanart", StringComparison.OrdinalIgnoreCase)) - { - data.Backdrops.Add(new ImageInfo - { - Url = url, - Resolution = resolution - }); - } - } - } - } - - internal class FanartXmlData - { - public string LanguagePoster { get; set; } - public string LanguageBanner { get; set; } - public string Poster { get; set; } - public string Banner { get; set; } - public List Backdrops = new List(); - } - - internal class ImageInfo - { - public string Url { get; set; } - public string Resolution { get; set; } } } diff --git a/MediaBrowser.Providers/TV/RemoteSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs similarity index 99% rename from MediaBrowser.Providers/TV/RemoteSeriesProvider.cs rename to MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index 3e2736cbca..a22f4f1c32 100644 --- a/MediaBrowser.Providers/TV/RemoteSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.TV /// /// Class RemoteSeriesProvider /// - class RemoteSeriesProvider : BaseMetadataProvider, IDisposable + class TvdbSeriesProvider : BaseMetadataProvider, IDisposable { /// /// The tv db @@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.TV /// Gets the current. /// /// The current. - internal static RemoteSeriesProvider Current { get; private set; } + internal static TvdbSeriesProvider Current { get; private set; } /// /// The _zip client @@ -53,14 +53,14 @@ namespace MediaBrowser.Providers.TV private readonly IFileSystem _fileSystem; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The HTTP client. /// The log manager. /// The configuration manager. /// The zip client. /// httpClient - public RemoteSeriesProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IZipClient zipClient, IFileSystem fileSystem) + public TvdbSeriesProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IZipClient zipClient, IFileSystem fileSystem) : base(logManager, configurationManager) { if (httpClient == null)