mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-04 03:27:21 -05:00 
			
		
		
		
	fixes #605 - Add manual image selection for Series
This commit is contained in:
		
							parent
							
								
									14dbfc0962
								
							
						
					
					
						commit
						403534f80e
					
				@ -20,7 +20,7 @@ namespace MediaBrowser.Api
 | 
				
			|||||||
        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
 | 
					        [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
 | 
				
			||||||
        public string Id { get; set; }
 | 
					        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; }
 | 
					        public ImageType? Type { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
 | 
				
			|||||||
@ -114,9 +114,10 @@
 | 
				
			|||||||
    <Compile Include="TV\ManualFanartSeriesProvider.cs" />
 | 
					    <Compile Include="TV\ManualFanartSeriesProvider.cs" />
 | 
				
			||||||
    <Compile Include="TV\ManualTvdbEpisodeImageProvider.cs" />
 | 
					    <Compile Include="TV\ManualTvdbEpisodeImageProvider.cs" />
 | 
				
			||||||
    <Compile Include="TV\ManualTvdbSeasonImageProvider.cs" />
 | 
					    <Compile Include="TV\ManualTvdbSeasonImageProvider.cs" />
 | 
				
			||||||
    <Compile Include="TV\RemoteEpisodeProvider.cs" />
 | 
					    <Compile Include="TV\ManualTvdbSeriesImageProvider.cs" />
 | 
				
			||||||
    <Compile Include="TV\RemoteSeasonProvider.cs" />
 | 
					    <Compile Include="TV\TvdbEpisodeProvider.cs" />
 | 
				
			||||||
    <Compile Include="TV\RemoteSeriesProvider.cs" />
 | 
					    <Compile Include="TV\TvdbSeasonProvider.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="TV\TvdbSeriesProvider.cs" />
 | 
				
			||||||
    <Compile Include="TV\SeasonProviderFromXml.cs" />
 | 
					    <Compile Include="TV\SeasonProviderFromXml.cs" />
 | 
				
			||||||
    <Compile Include="TV\SeriesDynamicInfoProvider.cs" />
 | 
					    <Compile Include="TV\SeriesDynamicInfoProvider.cs" />
 | 
				
			||||||
    <Compile Include="TV\SeriesPostScanTask.cs" />
 | 
					    <Compile Include="TV\SeriesPostScanTask.cs" />
 | 
				
			||||||
 | 
				
			|||||||
@ -245,7 +245,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public int Priority
 | 
					        public int Priority
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get { return 1; }
 | 
					            get { return 0; }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -303,7 +303,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public int Priority
 | 
					        public int Priority
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get { return 1; }
 | 
					            get { return 0; }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -52,9 +52,9 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
            if (!string.IsNullOrEmpty(seriesId))
 | 
					            if (!string.IsNullOrEmpty(seriesId))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Process images
 | 
					                // 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);
 | 
					                var result = files.Select(i => GetImageInfo(i, cancellationToken)).Where(i => i != null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -59,7 +59,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
            if (!string.IsNullOrEmpty(seriesId) && season.IndexNumber.HasValue)
 | 
					            if (!string.IsNullOrEmpty(seriesId) && season.IndexNumber.HasValue)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Process images
 | 
					                // Process images
 | 
				
			||||||
                var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId);
 | 
					                var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var path = Path.Combine(seriesDataPath, "banners.xml");
 | 
					                var path = Path.Combine(seriesDataPath, "banners.xml");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -279,10 +279,14 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
                    ProviderName = Name,
 | 
					                    ProviderName = Name,
 | 
				
			||||||
                    Language = language,
 | 
					                    Language = language,
 | 
				
			||||||
                    Width = width,
 | 
					                    Width = width,
 | 
				
			||||||
                    Height = height,
 | 
					                    Height = height
 | 
				
			||||||
                    ThumbnailUrl = thumbnailUrl
 | 
					 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (!string.IsNullOrEmpty(thumbnailUrl))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    imageInfo.ThumbnailUrl = TVUtils.BannerUrl + thumbnailUrl;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (string.Equals(bannerType, "season", StringComparison.OrdinalIgnoreCase))
 | 
					                if (string.Equals(bannerType, "season", StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    if (string.Equals(bannerType2, "season", StringComparison.OrdinalIgnoreCase))
 | 
					                    if (string.Equals(bannerType2, "season", StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
@ -307,7 +311,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public int Priority
 | 
					        public int Priority
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get { return 0; }
 | 
					            get { return 1; }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										312
									
								
								MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								MediaBrowser.Providers/TV/ManualTvdbSeriesImageProvider.cs
									
									
									
									
									
										Normal file
									
								
							@ -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<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return images.Where(i => i.Type == imageType);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Task<IEnumerable<RemoteImageInfo>> 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<IEnumerable<RemoteImageInfo>>(new RemoteImageInfo[] { });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private IEnumerable<RemoteImageInfo> GetImages(string xmlPath, CancellationToken cancellationToken)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var settings = new XmlReaderSettings
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                CheckCharacters = false,
 | 
				
			||||||
 | 
					                IgnoreProcessingInstructions = true,
 | 
				
			||||||
 | 
					                IgnoreComments = true,
 | 
				
			||||||
 | 
					                ValidationType = ValidationType.None
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var list = new List<RemoteImageInfo>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            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<RemoteImageInfo> 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; }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -111,7 +111,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId);
 | 
					            var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var episodeFiles = Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.TopDirectoryOnly)
 | 
					            var episodeFiles = Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.TopDirectoryOnly)
 | 
				
			||||||
                .Select(Path.GetFileNameWithoutExtension)
 | 
					                .Select(Path.GetFileNameWithoutExtension)
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Class RemoteEpisodeProvider
 | 
					    /// Class RemoteEpisodeProvider
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    class RemoteEpisodeProvider : BaseMetadataProvider
 | 
					    class TvdbEpisodeProvider : BaseMetadataProvider
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// The _provider manager
 | 
					        /// The _provider manager
 | 
				
			||||||
@ -39,16 +39,16 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
        protected IHttpClient HttpClient { get; private set; }
 | 
					        protected IHttpClient HttpClient { get; private set; }
 | 
				
			||||||
        private readonly IFileSystem _fileSystem;
 | 
					        private readonly IFileSystem _fileSystem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        internal static RemoteEpisodeProvider Current;
 | 
					        internal static TvdbEpisodeProvider Current;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Initializes a new instance of the <see cref="RemoteEpisodeProvider" /> class.
 | 
					        /// Initializes a new instance of the <see cref="TvdbEpisodeProvider" /> class.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="httpClient">The HTTP client.</param>
 | 
					        /// <param name="httpClient">The HTTP client.</param>
 | 
				
			||||||
        /// <param name="logManager">The log manager.</param>
 | 
					        /// <param name="logManager">The log manager.</param>
 | 
				
			||||||
        /// <param name="configurationManager">The configuration manager.</param>
 | 
					        /// <param name="configurationManager">The configuration manager.</param>
 | 
				
			||||||
        /// <param name="providerManager">The provider manager.</param>
 | 
					        /// <param name="providerManager">The provider manager.</param>
 | 
				
			||||||
        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)
 | 
					            : base(logManager, configurationManager)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            HttpClient = httpClient;
 | 
					            HttpClient = httpClient;
 | 
				
			||||||
@ -149,7 +149,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
            if (!string.IsNullOrEmpty(seriesId))
 | 
					            if (!string.IsNullOrEmpty(seriesId))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Process images
 | 
					                // Process images
 | 
				
			||||||
                var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId);
 | 
					                var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var files = GetEpisodeXmlFiles(episode, seriesDataPath);
 | 
					                var files = GetEpisodeXmlFiles(episode, seriesDataPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -254,7 +254,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (!string.IsNullOrEmpty(seriesId))
 | 
					            if (!string.IsNullOrEmpty(seriesId))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId);
 | 
					                var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                try
 | 
					                try
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@ -438,7 +438,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
                                                {
 | 
					                                                {
 | 
				
			||||||
                                                    var url = TVUtils.BannerUrl + val;
 | 
					                                                    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)
 | 
					                                                catch (HttpException)
 | 
				
			||||||
                                                {
 | 
					                                                {
 | 
				
			||||||
@ -107,7 +107,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
        /// <returns>Task.</returns>
 | 
					        /// <returns>Task.</returns>
 | 
				
			||||||
        private async Task DownloadImageFromSeries(BaseItem item, Series series, CancellationToken cancellationToken)
 | 
					        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");
 | 
					            var actorXmlPath = Path.Combine(tvdbPath, "actors.xml");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -117,7 +117,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                url = TVUtils.BannerUrl + url;
 | 
					                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);
 | 
					                                               ImageType.Primary, null, cancellationToken).ConfigureAwait(false);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -77,7 +77,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var path = RemoteSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths);
 | 
					            var path = TvdbSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Directory.CreateDirectory(path);
 | 
					            Directory.CreateDirectory(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -107,7 +107,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
                    Url = ServerTimeUrl,
 | 
					                    Url = ServerTimeUrl,
 | 
				
			||||||
                    CancellationToken = cancellationToken,
 | 
					                    CancellationToken = cancellationToken,
 | 
				
			||||||
                    EnableHttpCompression = true,
 | 
					                    EnableHttpCompression = true,
 | 
				
			||||||
                    ResourcePool = RemoteSeriesProvider.Current.TvDbResourcePool
 | 
					                    ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                }).ConfigureAwait(false))
 | 
					                }).ConfigureAwait(false))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@ -195,7 +195,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
                Url = string.Format(UpdatesUrl, lastUpdateTime),
 | 
					                Url = string.Format(UpdatesUrl, lastUpdateTime),
 | 
				
			||||||
                CancellationToken = cancellationToken,
 | 
					                CancellationToken = cancellationToken,
 | 
				
			||||||
                EnableHttpCompression = true,
 | 
					                EnableHttpCompression = true,
 | 
				
			||||||
                ResourcePool = RemoteSeriesProvider.Current.TvDbResourcePool
 | 
					                ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }).ConfigureAwait(false))
 | 
					            }).ConfigureAwait(false))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -315,7 +315,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            Directory.CreateDirectory(seriesDataPath);
 | 
					            Directory.CreateDirectory(seriesDataPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return RemoteSeriesProvider.Current.DownloadSeriesZip(id, seriesDataPath, lastTvDbUpdateTime, cancellationToken);
 | 
					            return TvdbSeriesProvider.Current.DownloadSeriesZip(id, seriesDataPath, lastTvDbUpdateTime, cancellationToken);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Class RemoteSeasonProvider
 | 
					    /// Class RemoteSeasonProvider
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    class RemoteSeasonProvider : BaseMetadataProvider
 | 
					    class TvdbSeasonProvider : BaseMetadataProvider
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// The _provider manager
 | 
					        /// The _provider manager
 | 
				
			||||||
@ -28,13 +28,13 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
        private readonly IFileSystem _fileSystem;
 | 
					        private readonly IFileSystem _fileSystem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Initializes a new instance of the <see cref="RemoteSeasonProvider"/> class.
 | 
					        /// Initializes a new instance of the <see cref="TvdbSeasonProvider"/> class.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="logManager">The log manager.</param>
 | 
					        /// <param name="logManager">The log manager.</param>
 | 
				
			||||||
        /// <param name="configurationManager">The configuration manager.</param>
 | 
					        /// <param name="configurationManager">The configuration manager.</param>
 | 
				
			||||||
        /// <param name="providerManager">The provider manager.</param>
 | 
					        /// <param name="providerManager">The provider manager.</param>
 | 
				
			||||||
        /// <exception cref="System.ArgumentNullException">httpClient</exception>
 | 
					        /// <exception cref="System.ArgumentNullException">httpClient</exception>
 | 
				
			||||||
        public RemoteSeasonProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
 | 
					        public TvdbSeasonProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
 | 
				
			||||||
            : base(logManager, configurationManager)
 | 
					            : base(logManager, configurationManager)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _providerManager = providerManager;
 | 
					            _providerManager = providerManager;
 | 
				
			||||||
@ -113,7 +113,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
            if (!string.IsNullOrEmpty(seriesId))
 | 
					            if (!string.IsNullOrEmpty(seriesId))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Process images
 | 
					                // 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);
 | 
					                var imagesFileInfo = new FileInfo(imagesXmlPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -145,7 +145,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            cancellationToken.ThrowIfCancellationRequested();
 | 
					            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;
 | 
					            const int backdropLimit = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (image != null)
 | 
					                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);
 | 
					                      .ConfigureAwait(false);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -174,7 +174,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (image != null)
 | 
					                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);
 | 
					                      .ConfigureAwait(false);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -192,7 +192,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
                        continue;
 | 
					                        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++;
 | 
					                    bdNo++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3,20 +3,17 @@ using MediaBrowser.Common.Net;
 | 
				
			|||||||
using MediaBrowser.Controller.Configuration;
 | 
					using MediaBrowser.Controller.Configuration;
 | 
				
			||||||
using MediaBrowser.Controller.Entities;
 | 
					using MediaBrowser.Controller.Entities;
 | 
				
			||||||
using MediaBrowser.Controller.Entities.TV;
 | 
					using MediaBrowser.Controller.Entities.TV;
 | 
				
			||||||
using MediaBrowser.Controller.IO;
 | 
					 | 
				
			||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Controller.Providers;
 | 
					using MediaBrowser.Controller.Providers;
 | 
				
			||||||
using MediaBrowser.Model.Entities;
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Logging;
 | 
					using MediaBrowser.Model.Logging;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Providers;
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Globalization;
 | 
					 | 
				
			||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Text;
 | 
					 | 
				
			||||||
using System.Threading;
 | 
					using System.Threading;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using System.Xml;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace MediaBrowser.Providers.TV
 | 
					namespace MediaBrowser.Providers.TV
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -125,7 +122,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
            if (!string.IsNullOrEmpty(seriesId))
 | 
					            if (!string.IsNullOrEmpty(seriesId))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Process images
 | 
					                // 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);
 | 
					                var imagesFileInfo = new FileInfo(imagesXmlPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -158,64 +155,36 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            cancellationToken.ThrowIfCancellationRequested();
 | 
					            cancellationToken.ThrowIfCancellationRequested();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var series = (Series)item;
 | 
					            var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualTvdbSeriesImageProvider.ProviderName).ConfigureAwait(false);
 | 
				
			||||||
            var seriesId = series.GetProviderId(MetadataProviders.Tvdb);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!string.IsNullOrEmpty(seriesId))
 | 
					            const int backdropLimit = 1;
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // Process images
 | 
					 | 
				
			||||||
                var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var imagesXmlPath = Path.Combine(seriesDataPath, "banners.xml");
 | 
					            await DownloadImages(item, images.ToList(), backdropLimit, cancellationToken).ConfigureAwait(false);
 | 
				
			||||||
 | 
					 | 
				
			||||||
                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
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            SetLastRefreshed(item, DateTime.UtcNow);
 | 
					            SetLastRefreshed(item, DateTime.UtcNow);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return false;
 | 
					        private async Task DownloadImages(BaseItem item, List<RemoteImageInfo> images, int backdropLimit, CancellationToken cancellationToken)
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private async Task DownloadImages(BaseItem item, FanartXmlData data, int backdropLimit, CancellationToken cancellationToken)
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!item.HasImage(ImageType.Primary))
 | 
					            if (!item.HasImage(ImageType.Primary))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var url = data.LanguagePoster ?? data.Poster;
 | 
					                var image = images.FirstOrDefault(i => i.Type == ImageType.Primary);
 | 
				
			||||||
                if (!string.IsNullOrEmpty(url))
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    url = TVUtils.BannerUrl + url;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    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);
 | 
					                      .ConfigureAwait(false);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (ConfigurationManager.Configuration.DownloadSeriesImages.Banner && !item.HasImage(ImageType.Banner))
 | 
					            if (ConfigurationManager.Configuration.DownloadSeriesImages.Banner && !item.HasImage(ImageType.Banner))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var url = data.LanguageBanner ?? data.Banner;
 | 
					                var image = images.FirstOrDefault(i => i.Type == ImageType.Banner);
 | 
				
			||||||
                if (!string.IsNullOrEmpty(url))
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    url = TVUtils.BannerUrl + url;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    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);
 | 
					                      .ConfigureAwait(false);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -224,38 +193,18 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                var bdNo = item.BackdropImagePaths.Count;
 | 
					                var bdNo = item.BackdropImagePaths.Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var eligibleBackdrops = data.Backdrops
 | 
					                foreach (var backdrop in images.Where(i => i.Type == ImageType.Backdrop && 
 | 
				
			||||||
                    .Where(i =>
 | 
					                    (!i.Width.HasValue || 
 | 
				
			||||||
 | 
					                    i.Width.Value >= ConfigurationManager.Configuration.MinSeriesBackdropDownloadWidth)))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                        if (string.IsNullOrEmpty(i.Resolution))
 | 
					                    var url = backdrop.Url;
 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            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)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    var url = TVUtils.BannerUrl + backdrop.Url;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (item.ContainsImageWithSourceUrl(url))
 | 
					                    if (item.ContainsImageWithSourceUrl(url))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        continue;
 | 
					                        continue;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    await _providerManager.SaveImage(item, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, bdNo, cancellationToken)
 | 
					                    await _providerManager.SaveImage(item, url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, bdNo, cancellationToken).ConfigureAwait(false);
 | 
				
			||||||
                      .ConfigureAwait(false);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    bdNo++;
 | 
					                    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<ImageInfo> Backdrops = new List<ImageInfo>();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    internal class ImageInfo
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        public string Url { get; set; }
 | 
					 | 
				
			||||||
        public string Resolution { get; set; }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Class RemoteSeriesProvider
 | 
					    /// Class RemoteSeriesProvider
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    class RemoteSeriesProvider : BaseMetadataProvider, IDisposable
 | 
					    class TvdbSeriesProvider : BaseMetadataProvider, IDisposable
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// The tv db
 | 
					        /// The tv db
 | 
				
			||||||
@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
        /// Gets the current.
 | 
					        /// Gets the current.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <value>The current.</value>
 | 
					        /// <value>The current.</value>
 | 
				
			||||||
        internal static RemoteSeriesProvider Current { get; private set; }
 | 
					        internal static TvdbSeriesProvider Current { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// The _zip client
 | 
					        /// The _zip client
 | 
				
			||||||
@ -53,14 +53,14 @@ namespace MediaBrowser.Providers.TV
 | 
				
			|||||||
        private readonly IFileSystem _fileSystem;
 | 
					        private readonly IFileSystem _fileSystem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Initializes a new instance of the <see cref="RemoteSeriesProvider" /> class.
 | 
					        /// Initializes a new instance of the <see cref="TvdbSeriesProvider" /> class.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="httpClient">The HTTP client.</param>
 | 
					        /// <param name="httpClient">The HTTP client.</param>
 | 
				
			||||||
        /// <param name="logManager">The log manager.</param>
 | 
					        /// <param name="logManager">The log manager.</param>
 | 
				
			||||||
        /// <param name="configurationManager">The configuration manager.</param>
 | 
					        /// <param name="configurationManager">The configuration manager.</param>
 | 
				
			||||||
        /// <param name="zipClient">The zip client.</param>
 | 
					        /// <param name="zipClient">The zip client.</param>
 | 
				
			||||||
        /// <exception cref="System.ArgumentNullException">httpClient</exception>
 | 
					        /// <exception cref="System.ArgumentNullException">httpClient</exception>
 | 
				
			||||||
        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)
 | 
					            : base(logManager, configurationManager)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (httpClient == null)
 | 
					            if (httpClient == null)
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user