diff options
| author | dkanada <dkanada@users.noreply.github.com> | 2019-05-31 01:48:20 -0700 |
|---|---|---|
| committer | dkanada <dkanada@users.noreply.github.com> | 2019-05-31 01:48:20 -0700 |
| commit | 09dfa071dc27820f1820bd56126dfa5cd5e01027 (patch) | |
| tree | 4e471c00c99b000f10b18834569497bcad262ecc | |
| parent | b1f764984f7098ee1164efee77f1bcb3de9fd08a (diff) | |
move fanart image provider to plugin
| -rw-r--r-- | MediaBrowser.Api/Library/LibraryService.cs | 12 | ||||
| -rw-r--r-- | MediaBrowser.Model/Configuration/FanartOptions.cs | 11 | ||||
| -rw-r--r-- | MediaBrowser.Model/Configuration/ServerConfiguration.cs | 7 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs | 334 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Music/FanArtAlbumProvider.cs | 201 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Music/FanArtArtistProvider.cs | 335 | ||||
| -rw-r--r-- | MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs | 205 | ||||
| -rw-r--r-- | MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs | 378 |
8 files changed, 3 insertions, 1480 deletions
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 9f8da9c16..ddf45f9f3 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -490,18 +490,6 @@ namespace MediaBrowser.Api.Library { return false; } - else if (string.Equals(name, "FanArt", StringComparison.OrdinalIgnoreCase)) - { - if (string.Equals(type, "Season", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - if (string.Equals(type, "MusicVideo", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - return true; - } else if (string.Equals(name, "TheAudioDB", StringComparison.OrdinalIgnoreCase)) { return true; diff --git a/MediaBrowser.Model/Configuration/FanartOptions.cs b/MediaBrowser.Model/Configuration/FanartOptions.cs deleted file mode 100644 index 9c8be39be..000000000 --- a/MediaBrowser.Model/Configuration/FanartOptions.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace MediaBrowser.Model.Configuration -{ - public class FanartOptions - { - /// <summary> - /// Gets or sets the user API key. - /// </summary> - /// <value>The user API key.</value> - public string UserApiKey { get; set; } - } -} diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 0ba36b4b9..2673597ca 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -49,9 +49,9 @@ namespace MediaBrowser.Model.Configuration public bool EnableNormalizedItemByNameIds { get; set; } /// <summary> - /// Gets or sets the value pointing to the file system where the ssl certiifcate is located.. + /// Gets or sets the value pointing to the file system where the ssl certificate is located.. /// </summary> - /// <value>The value pointing to the file system where the ssl certiifcate is located..</value> + /// <value>The value pointing to the file system where the ssl certificate is located..</value> public string CertificatePath { get; set; } public string CertificatePassword { get; set; } @@ -259,7 +259,7 @@ namespace MediaBrowser.Model.Configuration { ItemType = "MusicVideo", DisabledMetadataFetchers = new [] { "The Open Movie Database" }, - DisabledImageFetchers = new [] { "The Open Movie Database", "FanArt" } + DisabledImageFetchers = new [] { "The Open Movie Database" } }, new MetadataOptions { @@ -285,7 +285,6 @@ namespace MediaBrowser.Model.Configuration { ItemType = "Season", DisabledMetadataFetchers = new [] { "TheMovieDb" }, - DisabledImageFetchers = new [] { "FanArt" } }, new MetadataOptions { diff --git a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs deleted file mode 100644 index 70d187bf5..000000000 --- a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs +++ /dev/null @@ -1,334 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Music; -using MediaBrowser.Providers.TV; -using MediaBrowser.Providers.TV.FanArt; - -namespace MediaBrowser.Providers.Movies -{ - public class FanartMovieImageProvider : IRemoteImageProvider, IHasOrder - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IServerConfigurationManager _config; - private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; - private readonly IJsonSerializer _json; - - private const string FanArtBaseUrl = "https://webservice.fanart.tv/v3/movies/{1}?api_key={0}"; - - internal static FanartMovieImageProvider Current; - - public FanartMovieImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IJsonSerializer json) - { - _config = config; - _httpClient = httpClient; - _fileSystem = fileSystem; - _json = json; - - Current = this; - } - - public string Name => ProviderName; - - public static string ProviderName => "FanArt"; - - public bool Supports(BaseItem item) - { - return item is Movie || item is BoxSet || item is MusicVideo; - } - - public IEnumerable<ImageType> GetSupportedImages(BaseItem item) - { - return new List<ImageType> - { - ImageType.Primary, - ImageType.Thumb, - ImageType.Art, - ImageType.Logo, - ImageType.Disc, - ImageType.Banner, - ImageType.Backdrop - }; - } - - public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken) - { - var baseItem = item; - var list = new List<RemoteImageInfo>(); - - var movieId = baseItem.GetProviderId(MetadataProviders.Tmdb); - - if (!string.IsNullOrEmpty(movieId)) - { - // Bad id entered - try - { - await EnsureMovieJson(movieId, cancellationToken).ConfigureAwait(false); - } - catch (HttpException ex) - { - if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound) - { - throw; - } - } - - var path = GetFanartJsonPath(movieId); - - try - { - AddImages(list, path, cancellationToken); - } - catch (FileNotFoundException) - { - // No biggie. Don't blow up - } - catch (IOException) - { - // No biggie. Don't blow up - } - } - - var language = item.GetPreferredMetadataLanguage(); - - var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); - - // Sort first by width to prioritize HD versions - return list.OrderByDescending(i => i.Width ?? 0) - .ThenByDescending(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); - } - - private void AddImages(List<RemoteImageInfo> list, string path, CancellationToken cancellationToken) - { - var root = _json.DeserializeFromFile<RootObject>(path); - - AddImages(list, root, cancellationToken); - } - - private void AddImages(List<RemoteImageInfo> list, RootObject obj, CancellationToken cancellationToken) - { - PopulateImages(list, obj.hdmovieclearart, ImageType.Art, 1000, 562); - PopulateImages(list, obj.hdmovielogo, ImageType.Logo, 800, 310); - PopulateImages(list, obj.moviedisc, ImageType.Disc, 1000, 1000); - PopulateImages(list, obj.movieposter, ImageType.Primary, 1000, 1426); - PopulateImages(list, obj.movielogo, ImageType.Logo, 400, 155); - PopulateImages(list, obj.movieart, ImageType.Art, 500, 281); - PopulateImages(list, obj.moviethumb, ImageType.Thumb, 1000, 562); - PopulateImages(list, obj.moviebanner, ImageType.Banner, 1000, 185); - PopulateImages(list, obj.moviebackground, ImageType.Backdrop, 1920, 1080); - } - - private void PopulateImages(List<RemoteImageInfo> list, List<Image> images, ImageType type, int width, int height) - { - if (images == null) - { - return; - } - - list.AddRange(images.Select(i => - { - var url = i.url; - - if (!string.IsNullOrEmpty(url)) - { - var likesString = i.likes; - - var info = new RemoteImageInfo - { - RatingType = RatingType.Likes, - Type = type, - Width = width, - Height = height, - ProviderName = Name, - Url = url, - Language = i.lang - }; - - if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Integer, _usCulture, out var likes)) - { - info.CommunityRating = likes; - } - - return info; - } - - return null; - }).Where(i => i != null)); - } - - public int Order => 1; - - public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) - { - return _httpClient.GetResponse(new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = url - }); - } - - /// <summary> - /// Gets the movie data path. - /// </summary> - /// <param name="appPaths">The application paths.</param> - /// <param name="id">The identifier.</param> - /// <returns>System.String.</returns> - internal static string GetMovieDataPath(IApplicationPaths appPaths, string id) - { - var dataPath = Path.Combine(GetMoviesDataPath(appPaths), id); - - return dataPath; - } - - /// <summary> - /// Gets the movie data path. - /// </summary> - /// <param name="appPaths">The app paths.</param> - /// <returns>System.String.</returns> - internal static string GetMoviesDataPath(IApplicationPaths appPaths) - { - var dataPath = Path.Combine(appPaths.CachePath, "fanart-movies"); - - return dataPath; - } - - public string GetFanartJsonPath(string id) - { - var movieDataPath = GetMovieDataPath(_config.ApplicationPaths, id); - return Path.Combine(movieDataPath, "fanart.json"); - } - - /// <summary> - /// Downloads the movie json. - /// </summary> - /// <param name="id">The identifier.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - internal async Task DownloadMovieJson(string id, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var url = string.Format(FanArtBaseUrl, FanartArtistProvider.ApiKey, id); - - var clientKey = FanartSeriesProvider.Current.GetFanartOptions().UserApiKey; - if (!string.IsNullOrWhiteSpace(clientKey)) - { - url += "&client_key=" + clientKey; - } - - var path = GetFanartJsonPath(id); - - Directory.CreateDirectory(Path.GetDirectoryName(path)); - - try - { - using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - BufferContent = true - - }, "GET").ConfigureAwait(false)) - { - using (var response = httpResponse.Content) - { - using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) - { - await response.CopyToAsync(fileStream).ConfigureAwait(false); - } - } - } - } - catch (HttpException exception) - { - if (exception.StatusCode.HasValue && exception.StatusCode.Value == HttpStatusCode.NotFound) - { - // If the user has automatic updates enabled, save a dummy object to prevent repeated download attempts - _json.SerializeToFile(new RootObject(), path); - - return; - } - - throw; - } - } - - internal Task EnsureMovieJson(string id, CancellationToken cancellationToken) - { - var path = GetFanartJsonPath(id); - - var fileInfo = _fileSystem.GetFileSystemInfo(path); - - if (fileInfo.Exists) - { - if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 2) - { - return Task.CompletedTask; - } - } - - return DownloadMovieJson(id, cancellationToken); - } - - public class Image - { - public string id { get; set; } - public string url { get; set; } - public string lang { get; set; } - public string likes { get; set; } - } - - public class RootObject - { - public string name { get; set; } - public string tmdb_id { get; set; } - public string imdb_id { get; set; } - public List<Image> hdmovielogo { get; set; } - public List<Image> moviedisc { get; set; } - public List<Image> movielogo { get; set; } - public List<Image> movieposter { get; set; } - public List<Image> hdmovieclearart { get; set; } - public List<Image> movieart { get; set; } - public List<Image> moviebackground { get; set; } - public List<Image> moviebanner { get; set; } - public List<Image> moviethumb { get; set; } - } - } -} diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs deleted file mode 100644 index ebb740ffe..000000000 --- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs +++ /dev/null @@ -1,201 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Providers.Music -{ - public class FanartAlbumProvider : IRemoteImageProvider, IHasOrder - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IServerConfigurationManager _config; - private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; - private readonly IJsonSerializer _jsonSerializer; - - public FanartAlbumProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IJsonSerializer jsonSerializer) - { - _config = config; - _httpClient = httpClient; - _fileSystem = fileSystem; - _jsonSerializer = jsonSerializer; - } - - public string Name => ProviderName; - - public static string ProviderName => "FanArt"; - - public bool Supports(BaseItem item) - { - return item is MusicAlbum; - } - - public IEnumerable<ImageType> GetSupportedImages(BaseItem item) - { - return new List<ImageType> - { - ImageType.Primary, - ImageType.Disc - }; - } - - public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken) - { - var album = (MusicAlbum)item; - - var list = new List<RemoteImageInfo>(); - - var musicArtist = album.MusicArtist; - - if (musicArtist == null) - { - return list; - } - - var artistMusicBrainzId = musicArtist.GetProviderId(MetadataProviders.MusicBrainzArtist); - - if (!string.IsNullOrEmpty(artistMusicBrainzId)) - { - await FanartArtistProvider.Current.EnsureArtistJson(artistMusicBrainzId, cancellationToken).ConfigureAwait(false); - - var artistJsonPath = FanartArtistProvider.GetArtistJsonPath(_config.CommonApplicationPaths, artistMusicBrainzId); - - var musicBrainzReleaseGroupId = album.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); - - var musicBrainzId = album.GetProviderId(MetadataProviders.MusicBrainzAlbum); - - try - { - AddImages(list, artistJsonPath, musicBrainzId, musicBrainzReleaseGroupId, cancellationToken); - } - catch (FileNotFoundException) - { - - } - catch (IOException) - { - - } - } - - var language = item.GetPreferredMetadataLanguage(); - - var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); - - // Sort first by width to prioritize HD versions - return list.OrderByDescending(i => i.Width ?? 0) - .ThenByDescending(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) - .ThenByDescending(i => i.VoteCount ?? 0); - } - - /// <summary> - /// Adds the images. - /// </summary> - /// <param name="list">The list.</param> - /// <param name="path">The path.</param> - /// <param name="releaseId">The release identifier.</param> - /// <param name="releaseGroupId">The release group identifier.</param> - /// <param name="cancellationToken">The cancellation token.</param> - private void AddImages(List<RemoteImageInfo> list, string path, string releaseId, string releaseGroupId, CancellationToken cancellationToken) - { - var obj = _jsonSerializer.DeserializeFromFile<FanartArtistProvider.FanartArtistResponse>(path); - - if (obj.albums != null) - { - var album = obj.albums.FirstOrDefault(i => string.Equals(i.release_group_id, releaseGroupId, StringComparison.OrdinalIgnoreCase)); - - if (album != null) - { - PopulateImages(list, album.albumcover, ImageType.Primary, 1000, 1000); - PopulateImages(list, album.cdart, ImageType.Disc, 1000, 1000); - } - } - } - - private void PopulateImages(List<RemoteImageInfo> list, - List<FanartArtistProvider.FanartArtistImage> images, - ImageType type, - int width, - int height) - { - if (images == null) - { - return; - } - - list.AddRange(images.Select(i => - { - var url = i.url; - - if (!string.IsNullOrEmpty(url)) - { - var likesString = i.likes; - - var info = new RemoteImageInfo - { - RatingType = RatingType.Likes, - Type = type, - Width = width, - Height = height, - ProviderName = Name, - Url = url.Replace("http://", "https://", StringComparison.OrdinalIgnoreCase), - Language = i.lang - }; - - if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Integer, _usCulture, out var likes)) - { - info.CommunityRating = likes; - } - - return info; - } - - return null; - }).Where(i => i != null)); - } - // After embedded provider - public int Order => 1; - - public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) - { - return _httpClient.GetResponse(new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = url - }); - } - } -} diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs deleted file mode 100644 index 75b4213c5..000000000 --- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs +++ /dev/null @@ -1,335 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.TV; -using MediaBrowser.Providers.TV.FanArt; - -namespace MediaBrowser.Providers.Music -{ - public class FanartArtistProvider : IRemoteImageProvider, IHasOrder - { - internal const string ApiKey = "184e1a2b1fe3b94935365411f919f638"; - private const string FanArtBaseUrl = "https://webservice.fanart.tv/v3.1/music/{1}?api_key={0}"; - - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IServerConfigurationManager _config; - private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; - private readonly IJsonSerializer _jsonSerializer; - - internal static FanartArtistProvider Current; - - public FanartArtistProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IJsonSerializer jsonSerializer) - { - _config = config; - _httpClient = httpClient; - _fileSystem = fileSystem; - _jsonSerializer = jsonSerializer; - - Current = this; - } - - public string Name => ProviderName; - - public static string ProviderName => "FanArt"; - - public bool Supports(BaseItem item) - { - return item is MusicArtist; - } - - public IEnumerable<ImageType> GetSupportedImages(BaseItem item) - { - return new List<ImageType> - { - ImageType.Primary, - ImageType.Logo, - ImageType.Art, - ImageType.Banner, - ImageType.Backdrop - }; - } - - public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken) - { - var artist = (MusicArtist)item; - - var list = new List<RemoteImageInfo>(); - - var artistMusicBrainzId = artist.GetProviderId(MetadataProviders.MusicBrainzArtist); - - if (!string.IsNullOrEmpty(artistMusicBrainzId)) - { - await EnsureArtistJson(artistMusicBrainzId, cancellationToken).ConfigureAwait(false); - - var artistJsonPath = GetArtistJsonPath(_config.CommonApplicationPaths, artistMusicBrainzId); - - try - { - AddImages(list, artistJsonPath, cancellationToken); - } - catch (FileNotFoundException) - { - - } - catch (IOException) - { - - } - } - - var language = item.GetPreferredMetadataLanguage(); - - var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); - - // Sort first by width to prioritize HD versions - return list.OrderByDescending(i => i.Width ?? 0) - .ThenByDescending(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) - .ThenByDescending(i => i.VoteCount ?? 0); - } - - /// <summary> - /// Adds the images. - /// </summary> - /// <param name="list">The list.</param> - /// <param name="path">The path.</param> - /// <param name="cancellationToken">The cancellation token.</param> - private void AddImages(List<RemoteImageInfo> list, string path, CancellationToken cancellationToken) - { - var obj = _jsonSerializer.DeserializeFromFile<FanartArtistResponse>(path); - - PopulateImages(list, obj.artistbackground, ImageType.Backdrop, 1920, 1080); - PopulateImages(list, obj.artistthumb, ImageType.Primary, 500, 281); - PopulateImages(list, obj.hdmusiclogo, ImageType.Logo, 800, 310); - PopulateImages(list, obj.musicbanner, ImageType.Banner, 1000, 185); - PopulateImages(list, obj.musiclogo, ImageType.Logo, 400, 155); - PopulateImages(list, obj.hdmusicarts, ImageType.Art, 1000, 562); - PopulateImages(list, obj.musicarts, ImageType.Art, 500, 281); - } - - private void PopulateImages(List<RemoteImageInfo> list, - List<FanartArtistImage> images, - ImageType type, - int width, - int height) - { - if (images == null) - { - return; - } - - list.AddRange(images.Select(i => - { - var url = i.url; - - if (!string.IsNullOrEmpty(url)) - { - var likesString = i.likes; - - var info = new RemoteImageInfo - { - RatingType = RatingType.Likes, - Type = type, - Width = width, - Height = height, - ProviderName = Name, - Url = url.Replace("http://", "https://", StringComparison.OrdinalIgnoreCase), - Language = i.lang - }; - - if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Integer, _usCulture, out var likes)) - { - info.CommunityRating = likes; - } - - return info; - } - - return null; - }).Where(i => i != null)); - } - - public int Order => 0; - - public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) - { - return _httpClient.GetResponse(new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = url - }); - } - - internal Task EnsureArtistJson(string musicBrainzId, CancellationToken cancellationToken) - { - var jsonPath = GetArtistJsonPath(_config.ApplicationPaths, musicBrainzId); - - var fileInfo = _fileSystem.GetFileSystemInfo(jsonPath); - - if (fileInfo.Exists) - { - if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 2) - { - return Task.CompletedTask; - } - } - - return DownloadArtistJson(musicBrainzId, cancellationToken); - } - - /// <summary> - /// Downloads the artist data. - /// </summary> - /// <param name="musicBrainzId">The music brainz id.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task{System.Boolean}.</returns> - internal async Task DownloadArtistJson(string musicBrainzId, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var url = string.Format(FanArtBaseUrl, ApiKey, musicBrainzId); - - var clientKey = FanartSeriesProvider.Current.GetFanartOptions().UserApiKey; - if (!string.IsNullOrWhiteSpace(clientKey)) - { - url += "&client_key=" + clientKey; - } - - var jsonPath = GetArtistJsonPath(_config.ApplicationPaths, musicBrainzId); - - Directory.CreateDirectory(Path.GetDirectoryName(jsonPath)); - - try - { - using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - BufferContent = true - - }, "GET").ConfigureAwait(false)) - { - using (var response = httpResponse.Content) - { - using (var saveFileStream = _fileSystem.GetFileStream(jsonPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) - { - await response.CopyToAsync(saveFileStream).ConfigureAwait(false); - } - } - } - } - catch (HttpException ex) - { - if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound) - { - _jsonSerializer.SerializeToFile(new FanartArtistResponse(), jsonPath); - } - else - { - throw; - } - } - } - - /// <summary> - /// Gets the artist data path. - /// </summary> - /// <param name="appPaths">The application paths.</param> - /// <param name="musicBrainzArtistId">The music brainz artist identifier.</param> - /// <returns>System.String.</returns> - private static string GetArtistDataPath(IApplicationPaths appPaths, string musicBrainzArtistId) - { - var dataPath = Path.Combine(GetArtistDataPath(appPaths), musicBrainzArtistId); - - return dataPath; - } - - /// <summary> - /// Gets the artist data path. - /// </summary> - /// <param name="appPaths">The application paths.</param> - /// <returns>System.String.</returns> - internal static string GetArtistDataPath(IApplicationPaths appPaths) - { - var dataPath = Path.Combine(appPaths.CachePath, "fanart-music"); - - return dataPath; - } - - internal static string GetArtistJsonPath(IApplicationPaths appPaths, string musicBrainzArtistId) - { - var dataPath = GetArtistDataPath(appPaths, musicBrainzArtistId); - - return Path.Combine(dataPath, "fanart.json"); - } - - - public class FanartArtistImage - { - public string id { get; set; } - public string url { get; set; } - public string likes { get; set; } - public string disc { get; set; } - public string size { get; set; } - public string lang { get; set; } - } - - public class Album - { - public string release_group_id { get; set; } - public List<FanartArtistImage> cdart { get; set; } - public List<FanartArtistImage> albumcover { get; set; } - } - - public class FanartArtistResponse - { - public string name { get; set; } - public string mbid_id { get; set; } - public List<FanartArtistImage> artistthumb { get; set; } - public List<FanartArtistImage> artistbackground { get; set; } - public List<FanartArtistImage> hdmusiclogo { get; set; } - public List<FanartArtistImage> musicbanner { get; set; } - public List<FanartArtistImage> musiclogo { get; set; } - public List<FanartArtistImage> musicarts { get; set; } - public List<FanartArtistImage> hdmusicarts { get; set; } - public List<Album> albums { get; set; } - } - } -} diff --git a/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs b/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs deleted file mode 100644 index 58356910f..000000000 --- a/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs +++ /dev/null @@ -1,205 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Providers.TV.FanArt -{ - public class FanArtSeasonProvider : IRemoteImageProvider, IHasOrder - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IServerConfigurationManager _config; - private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; - private readonly IJsonSerializer _json; - - public FanArtSeasonProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IJsonSerializer json) - { - _config = config; - _httpClient = httpClient; - _fileSystem = fileSystem; - _json = json; - } - - public string Name => ProviderName; - - public static string ProviderName => "FanArt"; - - public bool Supports(BaseItem item) - { - return item is Season; - } - - public IEnumerable<ImageType> GetSupportedImages(BaseItem item) - { - return new List<ImageType> - { - ImageType.Backdrop, - ImageType.Thumb, - ImageType.Banner, - ImageType.Primary - }; - } - - public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken) - { - var list = new List<RemoteImageInfo>(); - - var season = (Season)item; - var series = season.Series; - - if (series != null) - { - var id = series.GetProviderId(MetadataProviders.Tvdb); - - if (!string.IsNullOrEmpty(id) && season.IndexNumber.HasValue) - { - // Bad id entered - try - { - await FanartSeriesProvider.Current.EnsureSeriesJson(id, cancellationToken).ConfigureAwait(false); - } - catch (HttpException ex) - { - if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound) - { - throw; - } - } - - var path = FanartSeriesProvider.Current.GetFanartJsonPath(id); - - try - { - AddImages(list, season.IndexNumber.Value, path, cancellationToken); - } - catch (FileNotFoundException) - { - // No biggie. Don't blow up - } - catch (IOException) - { - // No biggie. Don't blow up - } - } - } - - var language = item.GetPreferredMetadataLanguage(); - - var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); - - // Sort first by width to prioritize HD versions - return list.OrderByDescending(i => i.Width ?? 0) - .ThenByDescending(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) - .ThenByDescending(i => i.VoteCount ?? 0); - } - - private void AddImages(List<RemoteImageInfo> list, int seasonNumber, string path, CancellationToken cancellationToken) - { - var root = _json.DeserializeFromFile<FanartSeriesProvider.RootObject>(path); - - AddImages(list, root, seasonNumber, cancellationToken); - } - - private void AddImages(List<RemoteImageInfo> list, FanartSeriesProvider.RootObject obj, int seasonNumber, CancellationToken cancellationToken) - { - PopulateImages(list, obj.seasonposter, ImageType.Primary, 1000, 1426, seasonNumber); - PopulateImages(list, obj.seasonbanner, ImageType.Banner, 1000, 185, seasonNumber); - PopulateImages(list, obj.seasonthumb, ImageType.Thumb, 500, 281, seasonNumber); - PopulateImages(list, obj.showbackground, ImageType.Backdrop, 1920, 1080, seasonNumber); - } - - private void PopulateImages(List<RemoteImageInfo> list, - List<FanartSeriesProvider.Image> images, - ImageType type, - int width, - int height, - int seasonNumber) - { - if (images == null) - { - return; - } - - list.AddRange(images.Select(i => - { - var url = i.url; - var season = i.season; - - if (!string.IsNullOrEmpty(url) && - !string.IsNullOrEmpty(season) && - int.TryParse(season, NumberStyles.Integer, _usCulture, out var imageSeasonNumber) && - seasonNumber == imageSeasonNumber) - { - var likesString = i.likes; - - var info = new RemoteImageInfo - { - RatingType = RatingType.Likes, - Type = type, - Width = width, - Height = height, - ProviderName = Name, - Url = url.Replace("http://", "https://", StringComparison.OrdinalIgnoreCase), - Language = i.lang - }; - - if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Integer, _usCulture, out var likes)) - { - info.CommunityRating = likes; - } - - return info; - } - - return null; - }).Where(i => i != null)); - } - - public int Order => 1; - - public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) - { - return _httpClient.GetResponse(new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = url - }); - } - } -} diff --git a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs deleted file mode 100644 index 49cd9596e..000000000 --- a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs +++ /dev/null @@ -1,378 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Music; - -namespace MediaBrowser.Providers.TV.FanArt -{ - public class FanartSeriesProvider : IRemoteImageProvider, IHasOrder - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IServerConfigurationManager _config; - private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; - private readonly IJsonSerializer _json; - - private const string FanArtBaseUrl = "https://webservice.fanart.tv/v3/tv/{1}?api_key={0}"; - - internal static FanartSeriesProvider Current { get; private set; } - - public FanartSeriesProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IJsonSerializer json) - { - _config = config; - _httpClient = httpClient; - _fileSystem = fileSystem; - _json = json; - - Current = this; - } - - public string Name => ProviderName; - - public static string ProviderName => "FanArt"; - - public bool Supports(BaseItem item) - { - return item is Series; - } - - public IEnumerable<ImageType> GetSupportedImages(BaseItem item) - { - return new List<ImageType> - { - ImageType.Primary, - ImageType.Thumb, - ImageType.Art, - ImageType.Logo, - ImageType.Backdrop, - ImageType.Banner - }; - } - - public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken) - { - var list = new List<RemoteImageInfo>(); - - var series = (Series)item; - - var id = series.GetProviderId(MetadataProviders.Tvdb); - - if (!string.IsNullOrEmpty(id)) - { - // Bad id entered - try - { - await EnsureSeriesJson(id, cancellationToken).ConfigureAwait(false); - } - catch (HttpException ex) - { - if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound) - { - throw; - } - } - - var path = GetFanartJsonPath(id); - - try - { - AddImages(list, path, cancellationToken); - } - catch (FileNotFoundException) - { - // No biggie. Don't blow up - } - catch (IOException) - { - // No biggie. Don't blow up - } - } - - var language = item.GetPreferredMetadataLanguage(); - - var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); - - // Sort first by width to prioritize HD versions - return list.OrderByDescending(i => i.Width ?? 0) - .ThenByDescending(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) - .ThenByDescending(i => i.VoteCount ?? 0); - } - - private void AddImages(List<RemoteImageInfo> list, string path, CancellationToken cancellationToken) - { - var root = _json.DeserializeFromFile<RootObject>(path); - - AddImages(list, root, cancellationToken); - } - - private void AddImages(List<RemoteImageInfo> list, RootObject obj, CancellationToken cancellationToken) - { - PopulateImages(list, obj.hdtvlogo, ImageType.Logo, 800, 310); - PopulateImages(list, obj.hdclearart, ImageType.Art, 1000, 562); - PopulateImages(list, obj.clearlogo, ImageType.Logo, 400, 155); - PopulateImages(list, obj.clearart, ImageType.Art, 500, 281); - PopulateImages(list, obj.showbackground, ImageType.Backdrop, 1920, 1080, true); - PopulateImages(list, obj.seasonthumb, ImageType.Thumb, 500, 281); - PopulateImages(list, obj.tvthumb, ImageType.Thumb, 500, 281); - PopulateImages(list, obj.tvbanner, ImageType.Banner, 1000, 185); - PopulateImages(list, obj.tvposter, ImageType.Primary, 1000, 1426); - } - - private void PopulateImages(List<RemoteImageInfo> list, - List<Image> images, - ImageType type, - int width, - int height, - bool allowSeasonAll = false) - { - if (images == null) - { - return; - } - - list.AddRange(images.Select(i => - { - var url = i.url; - var season = i.season; - - var isSeasonValid = string.IsNullOrEmpty(season) || - (allowSeasonAll && string.Equals(season, "all", StringComparison.OrdinalIgnoreCase)); - - if (!string.IsNullOrEmpty(url) && isSeasonValid) - { - var likesString = i.likes; - - var info = new RemoteImageInfo - { - RatingType = RatingType.Likes, - Type = type, - Width = width, - Height = height, - ProviderName = Name, - Url = url.Replace("http://", "https://", StringComparison.OrdinalIgnoreCase), - Language = i.lang - }; - - if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Integer, _usCulture, out var likes)) - { - info.CommunityRating = likes; - } - - return info; - } - - return null; - }).Where(i => i != null)); - } - - public int Order => 1; - - public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) - { - return _httpClient.GetResponse(new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = url - }); - } - - /// <summary> - /// Gets the series data path. - /// </summary> - /// <param name="appPaths">The app paths.</param> - /// <param name="seriesId">The series id.</param> - /// <returns>System.String.</returns> - internal static string GetSeriesDataPath(IApplicationPaths appPaths, string seriesId) - { - var seriesDataPath = Path.Combine(GetSeriesDataPath(appPaths), seriesId); - - return seriesDataPath; - } - - /// <summary> - /// Gets the series data path. - /// </summary> - /// <param name="appPaths">The app paths.</param> - /// <returns>System.String.</returns> - internal static string GetSeriesDataPath(IApplicationPaths appPaths) - { - var dataPath = Path.Combine(appPaths.CachePath, "fanart-tv"); - - return dataPath; - } - - public string GetFanartJsonPath(string tvdbId) - { - var dataPath = GetSeriesDataPath(_config.ApplicationPaths, tvdbId); - return Path.Combine(dataPath, "fanart.json"); - } - - private readonly SemaphoreSlim _ensureSemaphore = new SemaphoreSlim(1, 1); - internal async Task EnsureSeriesJson(string tvdbId, CancellationToken cancellationToken) - { - var path = GetFanartJsonPath(tvdbId); - - // Only allow one thread in here at a time since every season will be calling this method, possibly concurrently - await _ensureSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - var fileInfo = _fileSystem.GetFileSystemInfo(path); - - if (fileInfo.Exists) - { - if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 2) - { - return; - } - } - - await DownloadSeriesJson(tvdbId, cancellationToken).ConfigureAwait(false); - } - finally - { - _ensureSemaphore.Release(); - } - } - - public FanartOptions GetFanartOptions() - { - return _config.GetConfiguration<FanartOptions>("fanart"); - } - - /// <summary> - /// Downloads the series json. - /// </summary> - /// <param name="tvdbId">The TVDB identifier.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - internal async Task DownloadSeriesJson(string tvdbId, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var url = string.Format(FanArtBaseUrl, FanartArtistProvider.ApiKey, tvdbId); - - var clientKey = GetFanartOptions().UserApiKey; - if (!string.IsNullOrWhiteSpace(clientKey)) - { - url += "&client_key=" + clientKey; - } - - var path = GetFanartJsonPath(tvdbId); - - Directory.CreateDirectory(Path.GetDirectoryName(path)); - - try - { - using (var httpResponse = await _httpClient.SendAsync(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - BufferContent = true - - }, "GET").ConfigureAwait(false)) - { - using (var response = httpResponse.Content) - { - using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) - { - await response.CopyToAsync(fileStream).ConfigureAwait(false); - } - } - } - } - catch (HttpException exception) - { - if (exception.StatusCode.HasValue && exception.StatusCode.Value == HttpStatusCode.NotFound) - { - // If the user has automatic updates enabled, save a dummy object to prevent repeated download attempts - _json.SerializeToFile(new RootObject(), path); - - return; - } - - throw; - } - } - - public class Image - { - public string id { get; set; } - public string url { get; set; } - public string lang { get; set; } - public string likes { get; set; } - public string season { get; set; } - } - - public class RootObject - { - public string name { get; set; } - public string thetvdb_id { get; set; } - public List<Image> clearlogo { get; set; } - public List<Image> hdtvlogo { get; set; } - public List<Image> clearart { get; set; } - public List<Image> showbackground { get; set; } - public List<Image> tvthumb { get; set; } - public List<Image> seasonposter { get; set; } - public List<Image> seasonthumb { get; set; } - public List<Image> hdclearart { get; set; } - public List<Image> tvbanner { get; set; } - public List<Image> characterart { get; set; } - public List<Image> tvposter { get; set; } - public List<Image> seasonbanner { get; set; } - } - } - - public class FanartConfigStore : IConfigurationFactory - { - public IEnumerable<ConfigurationStore> GetConfigurations() - { - return new ConfigurationStore[] - { - new ConfigurationStore - { - Key = "fanart", - ConfigurationType = typeof(FanartOptions) - } - }; - } - } -} |
