Sfoglia il codice sorgente

Merge pull request #6870 from cvium/fix_omdb_image_provider

Cody Robibero 3 anni fa
parent
commit
03c7bcf9c6

+ 0 - 2
MediaBrowser.Model/Configuration/ServerConfiguration.cs

@@ -402,8 +402,6 @@ namespace MediaBrowser.Model.Configuration
         /// </summary>
         /// </summary>
         public bool RequireHttps { get; set; } = false;
         public bool RequireHttps { get; set; } = false;
 
 
-        public bool EnableNewOmdbSupport { get; set; } = true;
-
         /// <summary>
         /// <summary>
         /// Gets or sets the filter for remote IP connectivity. Used in conjuntion with <seealso cref="IsRemoteIPFilterBlacklist"/>.
         /// Gets or sets the filter for remote IP connectivity. Used in conjuntion with <seealso cref="IsRemoteIPFilterBlacklist"/>.
         /// </summary>
         /// </summary>

+ 18 - 19
MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs

@@ -4,7 +4,6 @@ using System.Collections.Generic;
 using System.Net.Http;
 using System.Net.Http;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using MediaBrowser.Common;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
@@ -17,24 +16,17 @@ namespace MediaBrowser.Providers.Plugins.Omdb
 {
 {
     public class OmdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IHasOrder
     public class OmdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IHasOrder
     {
     {
-        private readonly IHttpClientFactory _httpClientFactory;
         private readonly OmdbItemProvider _itemProvider;
         private readonly OmdbItemProvider _itemProvider;
-        private readonly IFileSystem _fileSystem;
-        private readonly IServerConfigurationManager _configurationManager;
-        private readonly IApplicationHost _appHost;
+        private readonly OmdbProvider _omdbProvider;
 
 
         public OmdbEpisodeProvider(
         public OmdbEpisodeProvider(
-            IApplicationHost appHost,
             IHttpClientFactory httpClientFactory,
             IHttpClientFactory httpClientFactory,
             ILibraryManager libraryManager,
             ILibraryManager libraryManager,
             IFileSystem fileSystem,
             IFileSystem fileSystem,
             IServerConfigurationManager configurationManager)
             IServerConfigurationManager configurationManager)
         {
         {
-            _httpClientFactory = httpClientFactory;
-            _fileSystem = fileSystem;
-            _configurationManager = configurationManager;
-            _appHost = appHost;
-            _itemProvider = new OmdbItemProvider(_appHost, httpClientFactory, libraryManager, fileSystem, configurationManager);
+            _itemProvider = new OmdbItemProvider(httpClientFactory, libraryManager, fileSystem, configurationManager);
+            _omdbProvider = new OmdbProvider(httpClientFactory, fileSystem, configurationManager);
         }
         }
 
 
         // After TheTvDb
         // After TheTvDb
@@ -44,12 +36,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb
 
 
         public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken)
         public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken)
         {
         {
-            return _itemProvider.GetSearchResults(searchInfo, "episode", cancellationToken);
+            return _itemProvider.GetSearchResults(searchInfo, cancellationToken);
         }
         }
 
 
         public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo info, CancellationToken cancellationToken)
         public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo info, CancellationToken cancellationToken)
         {
         {
-            var result = new MetadataResult<Episode>()
+            var result = new MetadataResult<Episode>
             {
             {
                 Item = new Episode(),
                 Item = new Episode(),
                 QueriedById = true
                 QueriedById = true
@@ -61,13 +53,20 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                 return result;
                 return result;
             }
             }
 
 
-            if (info.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out string? seriesImdbId) && !string.IsNullOrEmpty(seriesImdbId))
+            if (info.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out string? seriesImdbId)
+                && !string.IsNullOrEmpty(seriesImdbId)
+                && info.IndexNumber.HasValue
+                && info.ParentIndexNumber.HasValue)
             {
             {
-                if (info.IndexNumber.HasValue && info.ParentIndexNumber.HasValue)
-                {
-                    result.HasMetadata = await new OmdbProvider(_httpClientFactory, _fileSystem, _configurationManager)
-                        .FetchEpisodeData(result, info.IndexNumber.Value, info.ParentIndexNumber.Value, info.GetProviderId(MetadataProvider.Imdb), seriesImdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
-                }
+                result.HasMetadata = await _omdbProvider.FetchEpisodeData(
+                    result,
+                    info.IndexNumber.Value,
+                    info.ParentIndexNumber.Value,
+                    info.GetProviderId(MetadataProvider.Imdb),
+                    seriesImdbId,
+                    info.MetadataLanguage,
+                    info.MetadataCountryCode,
+                    cancellationToken).ConfigureAwait(false);
             }
             }
 
 
             return result;
             return result;

+ 19 - 31
MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs

@@ -2,8 +2,9 @@
 
 
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
+using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Globalization;
+using System.Linq;
 using System.Net.Http;
 using System.Net.Http;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
@@ -22,14 +23,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb
     public class OmdbImageProvider : IRemoteImageProvider, IHasOrder
     public class OmdbImageProvider : IRemoteImageProvider, IHasOrder
     {
     {
         private readonly IHttpClientFactory _httpClientFactory;
         private readonly IHttpClientFactory _httpClientFactory;
-        private readonly IFileSystem _fileSystem;
-        private readonly IServerConfigurationManager _configurationManager;
+        private readonly OmdbProvider _omdbProvider;
 
 
         public OmdbImageProvider(IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IServerConfigurationManager configurationManager)
         public OmdbImageProvider(IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IServerConfigurationManager configurationManager)
         {
         {
             _httpClientFactory = httpClientFactory;
             _httpClientFactory = httpClientFactory;
-            _fileSystem = fileSystem;
-            _configurationManager = configurationManager;
+            _omdbProvider = new OmdbProvider(_httpClientFactory, fileSystem, configurationManager);
         }
         }
 
 
         public string Name => "The Open Movie Database";
         public string Name => "The Open Movie Database";
@@ -49,38 +48,27 @@ namespace MediaBrowser.Providers.Plugins.Omdb
         public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)
         public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)
         {
         {
             var imdbId = item.GetProviderId(MetadataProvider.Imdb);
             var imdbId = item.GetProviderId(MetadataProvider.Imdb);
+            if (string.IsNullOrWhiteSpace(imdbId))
+            {
+                return Enumerable.Empty<RemoteImageInfo>();
+            }
 
 
-            var list = new List<RemoteImageInfo>();
-
-            var provider = new OmdbProvider(_httpClientFactory, _fileSystem, _configurationManager);
+            var rootObject = await _omdbProvider.GetRootObject(imdbId, cancellationToken).ConfigureAwait(false);
 
 
-            if (!string.IsNullOrWhiteSpace(imdbId))
+            if (string.IsNullOrEmpty(rootObject.Poster))
             {
             {
-                var rootObject = await provider.GetRootObject(imdbId, cancellationToken).ConfigureAwait(false);
+                return Enumerable.Empty<RemoteImageInfo>();
+            }
 
 
-                if (!string.IsNullOrEmpty(rootObject.Poster))
+            // the poster url is sometimes higher quality than the poster api
+            return new[]
+            {
+                new RemoteImageInfo
                 {
                 {
-                    if (item is Episode)
-                    {
-                        // img.omdbapi.com is returning 404's
-                        list.Add(new RemoteImageInfo
-                        {
-                            ProviderName = Name,
-                            Url = rootObject.Poster
-                        });
-                    }
-                    else
-                    {
-                        list.Add(new RemoteImageInfo
-                        {
-                            ProviderName = Name,
-                            Url = string.Format(CultureInfo.InvariantCulture, "https://img.omdbapi.com/?i={0}&apikey=2c9d9507", imdbId)
-                        });
-                    }
+                    ProviderName = Name,
+                    Url = rootObject.Poster
                 }
                 }
-            }
-
-            return list;
+            };
         }
         }
 
 
         public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)

+ 94 - 125
MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs

@@ -8,11 +8,11 @@ using System.Globalization;
 using System.Linq;
 using System.Linq;
 using System.Net;
 using System.Net;
 using System.Net.Http;
 using System.Net.Http;
+using System.Text;
 using System.Text.Json;
 using System.Text.Json;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using Jellyfin.Extensions.Json;
 using Jellyfin.Extensions.Json;
-using MediaBrowser.Common;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
@@ -31,13 +31,10 @@ namespace MediaBrowser.Providers.Plugins.Omdb
     {
     {
         private readonly IHttpClientFactory _httpClientFactory;
         private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILibraryManager _libraryManager;
         private readonly ILibraryManager _libraryManager;
-        private readonly IFileSystem _fileSystem;
-        private readonly IServerConfigurationManager _configurationManager;
-        private readonly IApplicationHost _appHost;
         private readonly JsonSerializerOptions _jsonOptions;
         private readonly JsonSerializerOptions _jsonOptions;
+        private readonly OmdbProvider _omdbProvider;
 
 
         public OmdbItemProvider(
         public OmdbItemProvider(
-            IApplicationHost appHost,
             IHttpClientFactory httpClientFactory,
             IHttpClientFactory httpClientFactory,
             ILibraryManager libraryManager,
             ILibraryManager libraryManager,
             IFileSystem fileSystem,
             IFileSystem fileSystem,
@@ -45,9 +42,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
         {
         {
             _httpClientFactory = httpClientFactory;
             _httpClientFactory = httpClientFactory;
             _libraryManager = libraryManager;
             _libraryManager = libraryManager;
-            _fileSystem = fileSystem;
-            _configurationManager = configurationManager;
-            _appHost = appHost;
+            _omdbProvider = new OmdbProvider(_httpClientFactory, fileSystem, configurationManager);
 
 
             _jsonOptions = new JsonSerializerOptions(JsonDefaults.Options);
             _jsonOptions = new JsonSerializerOptions(JsonDefaults.Options);
             _jsonOptions.Converters.Add(new JsonOmdbNotAvailableStringConverter());
             _jsonOptions.Converters.Add(new JsonOmdbNotAvailableStringConverter());
@@ -59,185 +54,166 @@ namespace MediaBrowser.Providers.Plugins.Omdb
         // After primary option
         // After primary option
         public int Order => 2;
         public int Order => 2;
 
 
+        public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken)
+        {
+            return GetSearchResultsInternal(searchInfo, true, cancellationToken);
+        }
+
         public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
         public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
         {
         {
-            return GetSearchResults(searchInfo, "series", cancellationToken);
+            return GetSearchResultsInternal(searchInfo, true, cancellationToken);
         }
         }
 
 
         public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken)
         public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken)
         {
         {
-            return GetSearchResults(searchInfo, "movie", cancellationToken);
+            return GetSearchResultsInternal(searchInfo, true, cancellationToken);
         }
         }
 
 
-        public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ItemLookupInfo searchInfo, string type, CancellationToken cancellationToken)
+        public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken)
         {
         {
-            return GetSearchResultsInternal(searchInfo, type, true, cancellationToken);
+            return GetSearchResultsInternal(searchInfo, true, cancellationToken);
         }
         }
 
 
-        private async Task<IEnumerable<RemoteSearchResult>> GetSearchResultsInternal(ItemLookupInfo searchInfo, string type, bool isSearch, CancellationToken cancellationToken)
+        private async Task<IEnumerable<RemoteSearchResult>> GetSearchResultsInternal(ItemLookupInfo searchInfo, bool isSearch, CancellationToken cancellationToken)
         {
         {
+            var type = searchInfo switch
+            {
+                EpisodeInfo => "episode",
+                SeriesInfo => "series",
+                _ => "movie"
+            };
+
+            // This is a bit hacky?
             var episodeSearchInfo = searchInfo as EpisodeInfo;
             var episodeSearchInfo = searchInfo as EpisodeInfo;
+            var indexNumberEnd = episodeSearchInfo?.IndexNumberEnd;
 
 
             var imdbId = searchInfo.GetProviderId(MetadataProvider.Imdb);
             var imdbId = searchInfo.GetProviderId(MetadataProvider.Imdb);
 
 
-            var urlQuery = "plot=full&r=json";
-            if (type == "episode" && episodeSearchInfo != null)
+            var urlQuery = new StringBuilder("plot=full&r=json");
+            if (episodeSearchInfo != null)
             {
             {
                 episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out imdbId);
                 episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out imdbId);
-            }
-
-            var name = searchInfo.Name;
-            var year = searchInfo.Year;
+                if (searchInfo.IndexNumber.HasValue)
+                {
+                    urlQuery.Append("&Episode=").Append(searchInfo.IndexNumber.Value);
+                }
 
 
-            if (!string.IsNullOrWhiteSpace(name))
-            {
-                var parsedName = _libraryManager.ParseName(name);
-                var yearInName = parsedName.Year;
-                name = parsedName.Name;
-                year ??= yearInName;
+                if (searchInfo.ParentIndexNumber.HasValue)
+                {
+                    urlQuery.Append("&Season=").Append(searchInfo.ParentIndexNumber.Value);
+                }
             }
             }
 
 
             if (string.IsNullOrWhiteSpace(imdbId))
             if (string.IsNullOrWhiteSpace(imdbId))
             {
             {
-                if (year.HasValue)
+                var name = searchInfo.Name;
+                var year = searchInfo.Year;
+                if (!string.IsNullOrWhiteSpace(name))
                 {
                 {
-                    urlQuery += "&y=" + year.Value.ToString(CultureInfo.InvariantCulture);
+                    var parsedName = _libraryManager.ParseName(name);
+                    var yearInName = parsedName.Year;
+                    name = parsedName.Name;
+                    year ??= yearInName;
                 }
                 }
 
 
-                // &s means search and returns a list of results as opposed to t
-                if (isSearch)
-                {
-                    urlQuery += "&s=" + WebUtility.UrlEncode(name);
-                }
-                else
+                if (year.HasValue)
                 {
                 {
-                    urlQuery += "&t=" + WebUtility.UrlEncode(name);
+                    urlQuery.Append("&y=").Append(year);
                 }
                 }
 
 
-                urlQuery += "&type=" + type;
+                // &s means search and returns a list of results as opposed to t
+                urlQuery.Append(isSearch ? "&s=" : "&t=");
+                urlQuery.Append(WebUtility.UrlEncode(name));
+                urlQuery.Append("&type=")
+                    .Append(type);
             }
             }
             else
             else
             {
             {
-                urlQuery += "&i=" + imdbId;
+                urlQuery.Append("&i=")
+                    .Append(imdbId);
                 isSearch = false;
                 isSearch = false;
             }
             }
 
 
-            if (type == "episode")
-            {
-                if (searchInfo.IndexNumber.HasValue)
-                {
-                    urlQuery += string.Format(CultureInfo.InvariantCulture, "&Episode={0}", searchInfo.IndexNumber);
-                }
-
-                if (searchInfo.ParentIndexNumber.HasValue)
-                {
-                    urlQuery += string.Format(CultureInfo.InvariantCulture, "&Season={0}", searchInfo.ParentIndexNumber);
-                }
-            }
-
-            var url = OmdbProvider.GetOmdbUrl(urlQuery);
+            var url = OmdbProvider.GetOmdbUrl(urlQuery.ToString());
 
 
-            using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
+            using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
             await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
-            var resultList = new List<SearchResult>();
 
 
             if (isSearch)
             if (isSearch)
             {
             {
                 var searchResultList = await JsonSerializer.DeserializeAsync<SearchResultList>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false);
                 var searchResultList = await JsonSerializer.DeserializeAsync<SearchResultList>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false);
-                if (searchResultList != null && searchResultList.Search != null)
+                if (searchResultList?.Search != null)
                 {
                 {
-                    resultList.AddRange(searchResultList.Search);
+                    var resultCount = searchResultList.Search.Count;
+                    var result = new RemoteSearchResult[resultCount];
+                    for (var i = 0; i < resultCount; i++)
+                    {
+                        result[i] = ResultToMetadataResult(searchResultList.Search[i], searchInfo, indexNumberEnd);
+                    }
+
+                    return result;
                 }
                 }
             }
             }
             else
             else
             {
             {
                 var result = await JsonSerializer.DeserializeAsync<SearchResult>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false);
                 var result = await JsonSerializer.DeserializeAsync<SearchResult>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false);
-                if (string.Equals(result.Response, "true", StringComparison.OrdinalIgnoreCase))
+                if (string.Equals(result?.Response, "true", StringComparison.OrdinalIgnoreCase))
                 {
                 {
-                    resultList.Add(result);
+                    return new[] { ResultToMetadataResult(result, searchInfo, indexNumberEnd) };
                 }
                 }
             }
             }
 
 
-            return resultList.Select(result =>
-            {
-                var item = new RemoteSearchResult
-                {
-                    IndexNumber = searchInfo.IndexNumber,
-                    Name = result.Title,
-                    ParentIndexNumber = searchInfo.ParentIndexNumber,
-                    SearchProviderName = Name
-                };
-
-                if (episodeSearchInfo != null && episodeSearchInfo.IndexNumberEnd.HasValue)
-                {
-                    item.IndexNumberEnd = episodeSearchInfo.IndexNumberEnd.Value;
-                }
-
-                item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
-
-                if (result.Year.Length > 0
-                    && int.TryParse(result.Year.AsSpan().Slice(0, Math.Min(result.Year.Length, 4)), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedYear))
-                {
-                    item.ProductionYear = parsedYear;
-                }
-
-                if (!string.IsNullOrEmpty(result.Released)
-                    && DateTime.TryParse(result.Released, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var released))
-                {
-                    item.PremiereDate = released;
-                }
-
-                if (!string.IsNullOrWhiteSpace(result.Poster) && !string.Equals(result.Poster, "N/A", StringComparison.OrdinalIgnoreCase))
-                {
-                    item.ImageUrl = result.Poster;
-                }
-
-                return item;
-            });
+            return Enumerable.Empty<RemoteSearchResult>();
         }
         }
 
 
         public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
         public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
         {
         {
-            return GetMovieResult<Trailer>(info, cancellationToken);
+            return GetResult<Trailer>(info, cancellationToken);
         }
         }
 
 
-        public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken)
+        public Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
         {
         {
-            return GetSearchResults(searchInfo, "movie", cancellationToken);
+            return GetResult<Series>(info, cancellationToken);
         }
         }
 
 
-        public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
+        public Task<MetadataResult<Movie>> GetMetadata(MovieInfo info, CancellationToken cancellationToken)
         {
         {
-            var result = new MetadataResult<Series>
+            return GetResult<Movie>(info, cancellationToken);
+        }
+
+        private RemoteSearchResult ResultToMetadataResult(SearchResult result, ItemLookupInfo searchInfo, int? indexNumberEnd)
+        {
+            var item = new RemoteSearchResult
             {
             {
-                Item = new Series(),
-                QueriedById = true
+                IndexNumber = searchInfo.IndexNumber,
+                Name = result.Title,
+                ParentIndexNumber = searchInfo.ParentIndexNumber,
+                SearchProviderName = Name,
+                IndexNumberEnd = indexNumberEnd
             };
             };
 
 
-            var imdbId = info.GetProviderId(MetadataProvider.Imdb);
-            if (string.IsNullOrWhiteSpace(imdbId))
+            item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
+
+            if (OmdbProvider.TryParseYear(result.Year, out var parsedYear))
             {
             {
-                imdbId = await GetSeriesImdbId(info, cancellationToken).ConfigureAwait(false);
-                result.QueriedById = false;
+                item.ProductionYear = parsedYear;
             }
             }
 
 
-            if (!string.IsNullOrEmpty(imdbId))
+            if (!string.IsNullOrEmpty(result.Released)
+                && DateTime.TryParse(result.Released, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var released))
             {
             {
-                result.Item.SetProviderId(MetadataProvider.Imdb, imdbId);
-                result.HasMetadata = true;
-
-                await new OmdbProvider(_httpClientFactory, _fileSystem, _configurationManager).Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
+                item.PremiereDate = released;
             }
             }
 
 
-            return result;
-        }
+            if (!string.IsNullOrWhiteSpace(result.Poster))
+            {
+                item.ImageUrl = result.Poster;
+            }
 
 
-        public Task<MetadataResult<Movie>> GetMetadata(MovieInfo info, CancellationToken cancellationToken)
-        {
-            return GetMovieResult<Movie>(info, cancellationToken);
+            return item;
         }
         }
 
 
-        private async Task<MetadataResult<T>> GetMovieResult<T>(ItemLookupInfo info, CancellationToken cancellationToken)
+        private async Task<MetadataResult<T>> GetResult<T>(ItemLookupInfo info, CancellationToken cancellationToken)
             where T : BaseItem, new()
             where T : BaseItem, new()
         {
         {
             var result = new MetadataResult<T>
             var result = new MetadataResult<T>
@@ -249,7 +225,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             var imdbId = info.GetProviderId(MetadataProvider.Imdb);
             var imdbId = info.GetProviderId(MetadataProvider.Imdb);
             if (string.IsNullOrWhiteSpace(imdbId))
             if (string.IsNullOrWhiteSpace(imdbId))
             {
             {
-                imdbId = await GetMovieImdbId(info, cancellationToken).ConfigureAwait(false);
+                imdbId = await GetImdbId(info, cancellationToken).ConfigureAwait(false);
                 result.QueriedById = false;
                 result.QueriedById = false;
             }
             }
 
 
@@ -258,22 +234,15 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                 result.Item.SetProviderId(MetadataProvider.Imdb, imdbId);
                 result.Item.SetProviderId(MetadataProvider.Imdb, imdbId);
                 result.HasMetadata = true;
                 result.HasMetadata = true;
 
 
-                await new OmdbProvider(_httpClientFactory, _fileSystem, _configurationManager).Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
+                await _omdbProvider.Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
             }
             }
 
 
             return result;
             return result;
         }
         }
 
 
-        private async Task<string> GetMovieImdbId(ItemLookupInfo info, CancellationToken cancellationToken)
-        {
-            var results = await GetSearchResultsInternal(info, "movie", false, cancellationToken).ConfigureAwait(false);
-            var first = results.FirstOrDefault();
-            return first?.GetProviderId(MetadataProvider.Imdb);
-        }
-
-        private async Task<string> GetSeriesImdbId(SeriesInfo info, CancellationToken cancellationToken)
+        private async Task<string> GetImdbId(ItemLookupInfo info, CancellationToken cancellationToken)
         {
         {
-            var results = await GetSearchResultsInternal(info, "series", false, cancellationToken).ConfigureAwait(false);
+            var results = await GetSearchResultsInternal(info, false, cancellationToken).ConfigureAwait(false);
             var first = results.FirstOrDefault();
             var first = results.FirstOrDefault();
             return first?.GetProviderId(MetadataProvider.Imdb);
             return first?.GetProviderId(MetadataProvider.Imdb);
         }
         }

+ 63 - 63
MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs

@@ -4,10 +4,12 @@
 
 
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Globalization;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
 using System.Net.Http;
 using System.Net.Http;
+using System.Net.Http.Json;
 using System.Text.Json;
 using System.Text.Json;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
@@ -40,8 +42,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             _configurationManager = configurationManager;
             _configurationManager = configurationManager;
 
 
             _jsonOptions = new JsonSerializerOptions(JsonDefaults.Options);
             _jsonOptions = new JsonSerializerOptions(JsonDefaults.Options);
-            _jsonOptions.Converters.Add(new JsonOmdbNotAvailableStringConverter());
-            _jsonOptions.Converters.Add(new JsonOmdbNotAvailableInt32Converter());
+            // These converters need to take priority
+            _jsonOptions.Converters.Insert(0, new JsonOmdbNotAvailableStringConverter());
+            _jsonOptions.Converters.Insert(0, new JsonOmdbNotAvailableInt32Converter());
         }
         }
 
 
         /// <summary>Fetches data from OMDB service.</summary>
         /// <summary>Fetches data from OMDB service.</summary>
@@ -64,8 +67,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
 
 
             var result = await GetRootObject(imdbId, cancellationToken).ConfigureAwait(false);
             var result = await GetRootObject(imdbId, cancellationToken).ConfigureAwait(false);
 
 
+            var isEnglishRequested = IsConfiguredForEnglish(item, language);
             // Only take the name and rating if the user's language is set to English, since Omdb has no localization
             // Only take the name and rating if the user's language is set to English, since Omdb has no localization
-            if (string.Equals(language, "en", StringComparison.OrdinalIgnoreCase) || _configurationManager.Configuration.EnableNewOmdbSupport)
+            if (isEnglishRequested)
             {
             {
                 item.Name = result.Title;
                 item.Name = result.Title;
 
 
@@ -75,9 +79,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                 }
                 }
             }
             }
 
 
-            if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4
-                && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, CultureInfo.InvariantCulture, out var year)
-                && year >= 0)
+            if (TryParseYear(result.Year, out var year))
             {
             {
                 item.ProductionYear = year;
                 item.ProductionYear = year;
             }
             }
@@ -113,7 +115,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                 item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
                 item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
             }
             }
 
 
-            ParseAdditionalMetadata(itemResult, result);
+            ParseAdditionalMetadata(itemResult, result, isEnglishRequested);
         }
         }
 
 
         /// <summary>Gets data about an episode.</summary>
         /// <summary>Gets data about an episode.</summary>
@@ -176,8 +178,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                 return false;
                 return false;
             }
             }
 
 
+            var isEnglishRequested = IsConfiguredForEnglish(item, language);
             // Only take the name and rating if the user's language is set to English, since Omdb has no localization
             // Only take the name and rating if the user's language is set to English, since Omdb has no localization
-            if (string.Equals(language, "en", StringComparison.OrdinalIgnoreCase) || _configurationManager.Configuration.EnableNewOmdbSupport)
+            if (isEnglishRequested)
             {
             {
                 item.Name = result.Title;
                 item.Name = result.Title;
 
 
@@ -187,9 +190,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                 }
                 }
             }
             }
 
 
-            if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4
-                && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, CultureInfo.InvariantCulture, out var year)
-                && year >= 0)
+            if (TryParseYear(result.Year, out var year))
             {
             {
                 item.ProductionYear = year;
                 item.ProductionYear = year;
             }
             }
@@ -225,7 +226,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                 item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
                 item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
             }
             }
 
 
-            ParseAdditionalMetadata(itemResult, result);
+            ParseAdditionalMetadata(itemResult, result, isEnglishRequested);
 
 
             return true;
             return true;
         }
         }
@@ -259,6 +260,30 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             return Url + "&" + query;
             return Url + "&" + query;
         }
         }
 
 
+        /// <summary>
+        /// Extract the year from a string.
+        /// </summary>
+        /// <param name="input">The input string.</param>
+        /// <param name="year">The year.</param>
+        /// <returns>A value indicating whether the input could successfully be parsed as a year.</returns>
+        public static bool TryParseYear(string input, [NotNullWhen(true)] out int? year)
+        {
+            if (string.IsNullOrEmpty(input))
+            {
+                year = 0;
+                return false;
+            }
+
+            if (int.TryParse(input.AsSpan(0, 4), NumberStyles.Number, CultureInfo.InvariantCulture, out var result))
+            {
+                year = result;
+                return true;
+            }
+
+            year = 0;
+            return false;
+        }
+
         private async Task<string> EnsureItemInfo(string imdbId, CancellationToken cancellationToken)
         private async Task<string> EnsureItemInfo(string imdbId, CancellationToken cancellationToken)
         {
         {
             if (string.IsNullOrWhiteSpace(imdbId))
             if (string.IsNullOrWhiteSpace(imdbId))
@@ -291,7 +316,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                     "i={0}&plot=short&tomatoes=true&r=json",
                     "i={0}&plot=short&tomatoes=true&r=json",
                     imdbParam));
                     imdbParam));
 
 
-            var rootObject = await GetDeserializedOmdbResponse<RootObject>(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
+            var rootObject = await _httpClientFactory.CreateClient(NamedClient.Default).GetFromJsonAsync<RootObject>(url, _jsonOptions, cancellationToken).ConfigureAwait(false);
             await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
             await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
             await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false);
             await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false);
 
 
@@ -331,37 +356,13 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                     imdbParam,
                     imdbParam,
                     seasonId));
                     seasonId));
 
 
-            var rootObject = await GetDeserializedOmdbResponse<SeasonRootObject>(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
+            var rootObject = await _httpClientFactory.CreateClient(NamedClient.Default).GetFromJsonAsync<SeasonRootObject>(url, _jsonOptions, cancellationToken).ConfigureAwait(false);
             await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
             await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
             await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false);
             await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false);
 
 
             return path;
             return path;
         }
         }
 
 
-        /// <summary>Gets response from OMDB service as type T.</summary>
-        /// <param name="httpClient">HttpClient instance to use for service call.</param>
-        /// <param name="url">Http URL to use for service call.</param>
-        /// <param name="cancellationToken">CancellationToken to use for service call.</param>
-        /// <typeparam name="T">The first generic type parameter.</typeparam>
-        /// <returns>OMDB service response as type T.</returns>
-        public async Task<T> GetDeserializedOmdbResponse<T>(HttpClient httpClient, string url, CancellationToken cancellationToken)
-        {
-            using var response = await GetOmdbResponse(httpClient, url, cancellationToken).ConfigureAwait(false);
-            await using Stream content = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
-
-            return await JsonSerializer.DeserializeAsync<T>(content, _jsonOptions, cancellationToken).ConfigureAwait(false);
-        }
-
-        /// <summary>Gets response from OMDB service.</summary>
-        /// <param name="httpClient">HttpClient instance to use for service call.</param>
-        /// <param name="url">Http URL to use for service call.</param>
-        /// <param name="cancellationToken">CancellationToken to use for service call.</param>
-        /// <returns>OMDB service response as HttpResponseMessage.</returns>
-        public static Task<HttpResponseMessage> GetOmdbResponse(HttpClient httpClient, string url, CancellationToken cancellationToken)
-        {
-            return httpClient.GetAsync(url, cancellationToken);
-        }
-
         internal string GetDataFilePath(string imdbId)
         internal string GetDataFilePath(string imdbId)
         {
         {
             if (string.IsNullOrEmpty(imdbId))
             if (string.IsNullOrEmpty(imdbId))
@@ -390,31 +391,25 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             return Path.Combine(dataPath, filename);
             return Path.Combine(dataPath, filename);
         }
         }
 
 
-        private void ParseAdditionalMetadata<T>(MetadataResult<T> itemResult, RootObject result)
+        private static void ParseAdditionalMetadata<T>(MetadataResult<T> itemResult, RootObject result, bool isEnglishRequested)
             where T : BaseItem
             where T : BaseItem
         {
         {
             var item = itemResult.Item;
             var item = itemResult.Item;
 
 
-            var isConfiguredForEnglish = IsConfiguredForEnglish(item) || _configurationManager.Configuration.EnableNewOmdbSupport;
-
             // Grab series genres because IMDb data is better than TVDB. Leave movies alone
             // Grab series genres because IMDb data is better than TVDB. Leave movies alone
             // But only do it if English is the preferred language because this data will not be localized
             // But only do it if English is the preferred language because this data will not be localized
-            if (isConfiguredForEnglish && !string.IsNullOrWhiteSpace(result.Genre))
+            if (isEnglishRequested && !string.IsNullOrWhiteSpace(result.Genre))
             {
             {
                 item.Genres = Array.Empty<string>();
                 item.Genres = Array.Empty<string>();
 
 
-                foreach (var genre in result.Genre
-                    .Split(',', StringSplitOptions.RemoveEmptyEntries)
-                    .Select(i => i.Trim())
-                    .Where(i => !string.IsNullOrWhiteSpace(i)))
+                foreach (var genre in result.Genre.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
                 {
                 {
                     item.AddGenre(genre);
                     item.AddGenre(genre);
                 }
                 }
             }
             }
 
 
-            if (isConfiguredForEnglish)
+            if (isEnglishRequested)
             {
             {
-                // Omdb is currently English only, so for other languages skip this and let secondary providers fill it in
                 item.Overview = result.Plot;
                 item.Overview = result.Plot;
             }
             }
 
 
@@ -427,7 +422,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             {
             {
                 var person = new PersonInfo
                 var person = new PersonInfo
                 {
                 {
-                    Name = result.Director.Trim(),
+                    Name = result.Director,
                     Type = PersonType.Director
                     Type = PersonType.Director
                 };
                 };
 
 
@@ -438,7 +433,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             {
             {
                 var person = new PersonInfo
                 var person = new PersonInfo
                 {
                 {
-                    Name = result.Writer.Trim(),
+                    Name = result.Writer,
                     Type = PersonType.Writer
                     Type = PersonType.Writer
                 };
                 };
 
 
@@ -447,29 +442,34 @@ namespace MediaBrowser.Providers.Plugins.Omdb
 
 
             if (!string.IsNullOrWhiteSpace(result.Actors))
             if (!string.IsNullOrWhiteSpace(result.Actors))
             {
             {
-                var actorList = result.Actors.Split(',');
+                var actorList = result.Actors.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
                 foreach (var actor in actorList)
                 foreach (var actor in actorList)
                 {
                 {
-                    if (!string.IsNullOrWhiteSpace(actor))
+                    if (string.IsNullOrWhiteSpace(actor))
                     {
                     {
-                        var person = new PersonInfo
-                        {
-                            Name = actor.Trim(),
-                            Type = PersonType.Actor
-                        };
-
-                        itemResult.AddPerson(person);
+                        continue;
                     }
                     }
+
+                    var person = new PersonInfo
+                    {
+                        Name = actor,
+                        Type = PersonType.Actor
+                    };
+
+                    itemResult.AddPerson(person);
                 }
                 }
             }
             }
         }
         }
 
 
-        private bool IsConfiguredForEnglish(BaseItem item)
+        private static bool IsConfiguredForEnglish(BaseItem item, string language)
         {
         {
-            var lang = item.GetPreferredMetadataLanguage();
+            if (string.IsNullOrEmpty(language))
+            {
+                language = item.GetPreferredMetadataLanguage();
+            }
 
 
             // The data isn't localized and so can only be used for English users
             // The data isn't localized and so can only be used for English users
-            return string.Equals(lang, "en", StringComparison.OrdinalIgnoreCase);
+            return string.Equals(language, "en", StringComparison.OrdinalIgnoreCase);
         }
         }
 
 
         internal class SeasonRootObject
         internal class SeasonRootObject
@@ -546,7 +546,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                 if (Ratings != null)
                 if (Ratings != null)
                 {
                 {
                     var rating = Ratings.FirstOrDefault(i => string.Equals(i.Source, "Rotten Tomatoes", StringComparison.OrdinalIgnoreCase));
                     var rating = Ratings.FirstOrDefault(i => string.Equals(i.Source, "Rotten Tomatoes", StringComparison.OrdinalIgnoreCase));
-                    if (rating != null && rating.Value != null)
+                    if (rating?.Value != null)
                     {
                     {
                         var value = rating.Value.TrimEnd('%');
                         var value = rating.Value.TrimEnd('%');
                         if (float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var score))
                         if (float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var score))