Refactor omdb providers
This commit is contained in:
parent
fa366f0099
commit
96ea865681
|
@ -402,8 +402,6 @@ namespace MediaBrowser.Model.Configuration
|
|||
/// </summary>
|
||||
public bool RequireHttps { get; set; } = false;
|
||||
|
||||
public bool EnableNewOmdbSupport { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the filter for remote IP connectivity. Used in conjuntion with <seealso cref="IsRemoteIPFilterBlacklist"/>.
|
||||
/// </summary>
|
||||
|
|
|
@ -4,7 +4,6 @@ using System.Collections.Generic;
|
|||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
|
@ -17,24 +16,17 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
{
|
||||
public class OmdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IHasOrder
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly OmdbItemProvider _itemProvider;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IServerConfigurationManager _configurationManager;
|
||||
private readonly IApplicationHost _appHost;
|
||||
private readonly OmdbProvider _omdbProvider;
|
||||
|
||||
public OmdbEpisodeProvider(
|
||||
IApplicationHost appHost,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
ILibraryManager libraryManager,
|
||||
IFileSystem fileSystem,
|
||||
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
|
||||
|
@ -44,12 +36,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
|
||||
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)
|
||||
{
|
||||
var result = new MetadataResult<Episode>()
|
||||
var result = new MetadataResult<Episode>
|
||||
{
|
||||
Item = new Episode(),
|
||||
QueriedById = true
|
||||
|
@ -61,13 +53,20 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
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;
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -22,14 +23,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
public class OmdbImageProvider : IRemoteImageProvider, IHasOrder
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IServerConfigurationManager _configurationManager;
|
||||
private readonly OmdbProvider _omdbProvider;
|
||||
|
||||
public OmdbImageProvider(IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IServerConfigurationManager configurationManager)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_fileSystem = fileSystem;
|
||||
_configurationManager = configurationManager;
|
||||
_omdbProvider = new OmdbProvider(_httpClientFactory, fileSystem, configurationManager);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
var imdbId = item.GetProviderId(MetadataProvider.Imdb);
|
||||
|
||||
var list = new List<RemoteImageInfo>();
|
||||
|
||||
var provider = new OmdbProvider(_httpClientFactory, _fileSystem, _configurationManager);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(imdbId))
|
||||
if (string.IsNullOrWhiteSpace(imdbId))
|
||||
{
|
||||
var rootObject = await provider.GetRootObject(imdbId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (!string.IsNullOrEmpty(rootObject.Poster))
|
||||
{
|
||||
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)
|
||||
});
|
||||
}
|
||||
}
|
||||
return Enumerable.Empty<RemoteImageInfo>();
|
||||
}
|
||||
|
||||
return list;
|
||||
var rootObject = await _omdbProvider.GetRootObject(imdbId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(rootObject.Poster) || string.Equals("N/A", rootObject.Poster, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Enumerable.Empty<RemoteImageInfo>();
|
||||
}
|
||||
|
||||
// the poster url is sometimes higher quality than the poster api
|
||||
return new[]
|
||||
{
|
||||
new RemoteImageInfo
|
||||
{
|
||||
ProviderName = Name,
|
||||
Url = rootObject.Poster
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||
|
|
|
@ -8,11 +8,11 @@ using System.Globalization;
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Extensions.Json;
|
||||
using MediaBrowser.Common;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
@ -31,13 +31,10 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IServerConfigurationManager _configurationManager;
|
||||
private readonly IApplicationHost _appHost;
|
||||
private readonly JsonSerializerOptions _jsonOptions;
|
||||
private readonly OmdbProvider _omdbProvider;
|
||||
|
||||
public OmdbItemProvider(
|
||||
IApplicationHost appHost,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
ILibraryManager libraryManager,
|
||||
IFileSystem fileSystem,
|
||||
|
@ -45,9 +42,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_libraryManager = libraryManager;
|
||||
_fileSystem = fileSystem;
|
||||
_configurationManager = configurationManager;
|
||||
_appHost = appHost;
|
||||
_omdbProvider = new OmdbProvider(_httpClientFactory, fileSystem, configurationManager);
|
||||
|
||||
_jsonOptions = new JsonSerializerOptions(JsonDefaults.Options);
|
||||
_jsonOptions.Converters.Add(new JsonOmdbNotAvailableStringConverter());
|
||||
|
@ -59,185 +54,167 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
// After primary option
|
||||
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)
|
||||
{
|
||||
return GetSearchResults(searchInfo, "series", cancellationToken);
|
||||
return GetSearchResultsInternal(searchInfo, true, 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 indexNumberEnd = episodeSearchInfo?.IndexNumberEnd;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
var name = searchInfo.Name;
|
||||
var year = searchInfo.Year;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
var parsedName = _libraryManager.ParseName(name);
|
||||
var yearInName = parsedName.Year;
|
||||
name = parsedName.Name;
|
||||
year ??= yearInName;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(imdbId))
|
||||
{
|
||||
if (year.HasValue)
|
||||
{
|
||||
urlQuery += "&y=" + year.Value.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// &s means search and returns a list of results as opposed to t
|
||||
if (isSearch)
|
||||
{
|
||||
urlQuery += "&s=" + WebUtility.UrlEncode(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
urlQuery += "&t=" + WebUtility.UrlEncode(name);
|
||||
}
|
||||
|
||||
urlQuery += "&type=" + type;
|
||||
}
|
||||
else
|
||||
{
|
||||
urlQuery += "&i=" + imdbId;
|
||||
isSearch = false;
|
||||
}
|
||||
|
||||
if (type == "episode")
|
||||
{
|
||||
if (searchInfo.IndexNumber.HasValue)
|
||||
{
|
||||
urlQuery += string.Format(CultureInfo.InvariantCulture, "&Episode={0}", searchInfo.IndexNumber);
|
||||
urlQuery.AppendFormat(CultureInfo.InvariantCulture, "&Episode={0}", searchInfo.IndexNumber);
|
||||
}
|
||||
|
||||
if (searchInfo.ParentIndexNumber.HasValue)
|
||||
{
|
||||
urlQuery += string.Format(CultureInfo.InvariantCulture, "&Season={0}", searchInfo.ParentIndexNumber);
|
||||
urlQuery.AppendFormat(CultureInfo.InvariantCulture, "&Season={0}", searchInfo.ParentIndexNumber);
|
||||
}
|
||||
}
|
||||
|
||||
var url = OmdbProvider.GetOmdbUrl(urlQuery);
|
||||
if (string.IsNullOrWhiteSpace(imdbId))
|
||||
{
|
||||
var name = searchInfo.Name;
|
||||
var year = searchInfo.Year;
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
var parsedName = _libraryManager.ParseName(name);
|
||||
var yearInName = parsedName.Year;
|
||||
name = parsedName.Name;
|
||||
year ??= yearInName;
|
||||
}
|
||||
|
||||
using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
|
||||
if (year.HasValue)
|
||||
{
|
||||
urlQuery.Append("&y=")
|
||||
.Append(year);
|
||||
}
|
||||
|
||||
// &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
|
||||
{
|
||||
urlQuery.Append("&i=")
|
||||
.Append(imdbId);
|
||||
isSearch = false;
|
||||
}
|
||||
|
||||
var url = OmdbProvider.GetOmdbUrl(urlQuery.ToString());
|
||||
|
||||
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
|
||||
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
|
||||
var resultList = new List<SearchResult>();
|
||||
|
||||
if (isSearch)
|
||||
{
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = new MetadataResult<Series>
|
||||
{
|
||||
Item = new Series(),
|
||||
QueriedById = true
|
||||
};
|
||||
|
||||
var imdbId = info.GetProviderId(MetadataProvider.Imdb);
|
||||
if (string.IsNullOrWhiteSpace(imdbId))
|
||||
{
|
||||
imdbId = await GetSeriesImdbId(info, cancellationToken).ConfigureAwait(false);
|
||||
result.QueriedById = false;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(imdbId))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
return result;
|
||||
return GetResult<Series>(info, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<MetadataResult<Movie>> GetMetadata(MovieInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
return GetMovieResult<Movie>(info, cancellationToken);
|
||||
return GetResult<Movie>(info, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<MetadataResult<T>> GetMovieResult<T>(ItemLookupInfo info, CancellationToken cancellationToken)
|
||||
private RemoteSearchResult ResultToMetadataResult(SearchResult result, ItemLookupInfo searchInfo, int? indexNumberEnd)
|
||||
{
|
||||
var item = new RemoteSearchResult
|
||||
{
|
||||
IndexNumber = searchInfo.IndexNumber,
|
||||
Name = result.Title,
|
||||
ParentIndexNumber = searchInfo.ParentIndexNumber,
|
||||
SearchProviderName = Name,
|
||||
IndexNumberEnd = indexNumberEnd
|
||||
};
|
||||
|
||||
item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
|
||||
|
||||
if (OmdbProvider.TryParseYear(result.Year, 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;
|
||||
}
|
||||
|
||||
private async Task<MetadataResult<T>> GetResult<T>(ItemLookupInfo info, CancellationToken cancellationToken)
|
||||
where T : BaseItem, new()
|
||||
{
|
||||
var result = new MetadataResult<T>
|
||||
|
@ -249,7 +226,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
var imdbId = info.GetProviderId(MetadataProvider.Imdb);
|
||||
if (string.IsNullOrWhiteSpace(imdbId))
|
||||
{
|
||||
imdbId = await GetMovieImdbId(info, cancellationToken).ConfigureAwait(false);
|
||||
imdbId = await GetImdbId(info, cancellationToken).ConfigureAwait(false);
|
||||
result.QueriedById = false;
|
||||
}
|
||||
|
||||
|
@ -258,22 +235,15 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
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);
|
||||
await _omdbProvider.Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<string> GetMovieImdbId(ItemLookupInfo info, CancellationToken cancellationToken)
|
||||
private async Task<string> GetImdbId(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)
|
||||
{
|
||||
var results = await GetSearchResultsInternal(info, "series", false, cancellationToken).ConfigureAwait(false);
|
||||
var results = await GetSearchResultsInternal(info, false, cancellationToken).ConfigureAwait(false);
|
||||
var first = results.FirstOrDefault();
|
||||
return first?.GetProviderId(MetadataProvider.Imdb);
|
||||
}
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -40,8 +42,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
_configurationManager = configurationManager;
|
||||
|
||||
_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>
|
||||
|
@ -64,8 +67,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
|
||||
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
|
||||
if (string.Equals(language, "en", StringComparison.OrdinalIgnoreCase) || _configurationManager.Configuration.EnableNewOmdbSupport)
|
||||
if (isEnglishRequested)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -113,7 +115,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
|
||||
}
|
||||
|
||||
ParseAdditionalMetadata(itemResult, result);
|
||||
ParseAdditionalMetadata(itemResult, result, isEnglishRequested);
|
||||
}
|
||||
|
||||
/// <summary>Gets data about an episode.</summary>
|
||||
|
@ -176,8 +178,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
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
|
||||
if (string.Equals(language, "en", StringComparison.OrdinalIgnoreCase) || _configurationManager.Configuration.EnableNewOmdbSupport)
|
||||
if (isEnglishRequested)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -225,7 +226,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
|
||||
}
|
||||
|
||||
ParseAdditionalMetadata(itemResult, result);
|
||||
ParseAdditionalMetadata(itemResult, result, isEnglishRequested);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -259,6 +260,30 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
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)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(imdbId))
|
||||
|
@ -291,7 +316,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
"i={0}&plot=short&tomatoes=true&r=json",
|
||||
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 JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
@ -331,37 +356,13 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
imdbParam,
|
||||
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 JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
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)
|
||||
{
|
||||
if (string.IsNullOrEmpty(imdbId))
|
||||
|
@ -390,31 +391,25 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
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
|
||||
{
|
||||
var item = itemResult.Item;
|
||||
|
||||
var isConfiguredForEnglish = IsConfiguredForEnglish(item) || _configurationManager.Configuration.EnableNewOmdbSupport;
|
||||
|
||||
// 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
|
||||
if (isConfiguredForEnglish && !string.IsNullOrWhiteSpace(result.Genre))
|
||||
if (isEnglishRequested && !string.IsNullOrWhiteSpace(result.Genre))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -427,7 +422,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
{
|
||||
var person = new PersonInfo
|
||||
{
|
||||
Name = result.Director.Trim(),
|
||||
Name = result.Director,
|
||||
Type = PersonType.Director
|
||||
};
|
||||
|
||||
|
@ -438,7 +433,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
{
|
||||
var person = new PersonInfo
|
||||
{
|
||||
Name = result.Writer.Trim(),
|
||||
Name = result.Writer,
|
||||
Type = PersonType.Writer
|
||||
};
|
||||
|
||||
|
@ -447,29 +442,34 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
|
||||
if (!string.IsNullOrWhiteSpace(result.Actors))
|
||||
{
|
||||
var actorList = result.Actors.Split(',');
|
||||
var actorList = result.Actors.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
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
|
||||
return string.Equals(lang, "en", StringComparison.OrdinalIgnoreCase);
|
||||
return string.Equals(language, "en", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
internal class SeasonRootObject
|
||||
|
@ -546,7 +546,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
if (Ratings != null)
|
||||
{
|
||||
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('%');
|
||||
if (float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var score))
|
||||
|
|
Loading…
Reference in New Issue
Block a user