aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs')
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs147
1 files changed, 91 insertions, 56 deletions
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
index c45149c3a..1ae712e9e 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS159, SA1300
using System;
using System.Collections.Generic;
@@ -6,37 +6,55 @@ using System.Globalization;
using System.IO;
using System.Linq;
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;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Serialization;
namespace MediaBrowser.Providers.Plugins.Omdb
{
+ /// <summary>Provider for OMDB service.</summary>
public class OmdbProvider
{
- private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
private readonly IServerConfigurationManager _configurationManager;
private readonly IHttpClientFactory _httpClientFactory;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IApplicationHost _appHost;
-
- public OmdbProvider(IJsonSerializer jsonSerializer, IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IApplicationHost appHost, IServerConfigurationManager configurationManager)
+ private readonly JsonSerializerOptions _jsonOptions;
+
+ /// <summary>Initializes a new instance of the <see cref="OmdbProvider"/> class.</summary>
+ /// <param name="httpClientFactory">HttpClientFactory to use for calls to OMDB service.</param>
+ /// <param name="fileSystem">IFileSystem to use for store OMDB data.</param>
+ /// <param name="appHost">IApplicationHost to use.</param>
+ /// <param name="configurationManager">IServerConfigurationManager to use.</param>
+ public OmdbProvider(IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IApplicationHost appHost, IServerConfigurationManager configurationManager)
{
- _jsonSerializer = jsonSerializer;
_httpClientFactory = httpClientFactory;
_fileSystem = fileSystem;
_configurationManager = configurationManager;
_appHost = appHost;
+
+ _jsonOptions = new JsonSerializerOptions(JsonDefaults.Options);
+ _jsonOptions.Converters.Add(new JsonOmdbNotAvailableStringConverter());
+ _jsonOptions.Converters.Add(new JsonOmdbNotAvailableInt32Converter());
}
+ /// <summary>Fetches data from OMDB service.</summary>
+ /// <param name="itemResult">Metadata about media item.</param>
+ /// <param name="imdbId">IMDB ID for media.</param>
+ /// <param name="language">Media language.</param>
+ /// <param name="country">Country of origin.</param>
+ /// <param name="cancellationToken">CancellationToken to use for operation.</param>
+ /// <typeparam name="T">The first generic type parameter.</typeparam>
+ /// <returns>Returns a Task object that can be awaited.</returns>
public async Task Fetch<T>(MetadataResult<T> itemResult, string imdbId, string language, string country, CancellationToken cancellationToken)
where T : BaseItem
{
@@ -49,7 +67,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
var result = await GetRootObject(imdbId, cancellationToken).ConfigureAwait(false);
- // 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)
{
item.Name = result.Title;
@@ -101,6 +119,17 @@ namespace MediaBrowser.Providers.Plugins.Omdb
ParseAdditionalMetadata(itemResult, result);
}
+ /// <summary>Gets data about an episode.</summary>
+ /// <param name="itemResult">Metadata about episode.</param>
+ /// <param name="episodeNumber">Episode number.</param>
+ /// <param name="seasonNumber">Season number.</param>
+ /// <param name="episodeImdbId">Episode ID.</param>
+ /// <param name="seriesImdbId">Season ID.</param>
+ /// <param name="language">Episode language.</param>
+ /// <param name="country">Country of origin.</param>
+ /// <param name="cancellationToken">CancellationToken to use for operation.</param>
+ /// <typeparam name="T">The first generic type parameter.</typeparam>
+ /// <returns>Whether operation was successful.</returns>
public async Task<bool> FetchEpisodeData<T>(MetadataResult<T> itemResult, int episodeNumber, int seasonNumber, string episodeImdbId, string seriesImdbId, string language, string country, CancellationToken cancellationToken)
where T : BaseItem
{
@@ -113,7 +142,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
var seasonResult = await GetSeasonRootObject(seriesImdbId, seasonNumber, cancellationToken).ConfigureAwait(false);
- if (seasonResult == null)
+ if (seasonResult?.Episodes == null)
{
return false;
}
@@ -150,7 +179,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
return false;
}
- // 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)
{
item.Name = result.Title;
@@ -207,44 +236,20 @@ namespace MediaBrowser.Providers.Plugins.Omdb
internal async Task<RootObject> GetRootObject(string imdbId, CancellationToken cancellationToken)
{
var path = await EnsureItemInfo(imdbId, cancellationToken).ConfigureAwait(false);
-
- string resultString;
-
- using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
- {
- using (var reader = new StreamReader(stream, new UTF8Encoding(false)))
- {
- resultString = reader.ReadToEnd();
- resultString = resultString.Replace("\"N/A\"", "\"\"");
- }
- }
-
- var result = _jsonSerializer.DeserializeFromString<RootObject>(resultString);
- return result;
+ await using var stream = File.OpenRead(path);
+ return await JsonSerializer.DeserializeAsync<RootObject>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false);
}
internal async Task<SeasonRootObject> GetSeasonRootObject(string imdbId, int seasonId, CancellationToken cancellationToken)
{
var path = await EnsureSeasonInfo(imdbId, seasonId, cancellationToken).ConfigureAwait(false);
-
- string resultString;
-
- using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
- {
- using (var reader = new StreamReader(stream, new UTF8Encoding(false)))
- {
- resultString = reader.ReadToEnd();
- resultString = resultString.Replace("\"N/A\"", "\"\"");
- }
- }
-
- var result = _jsonSerializer.DeserializeFromString<SeasonRootObject>(resultString);
- return result;
+ await using var stream = File.OpenRead(path);
+ return await JsonSerializer.DeserializeAsync<SeasonRootObject>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false);
}
internal static bool IsValidSeries(Dictionary<string, string> seriesProviderIds)
{
- if (seriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out string id) && !string.IsNullOrEmpty(id))
+ if (seriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out string id))
{
// This check should ideally never be necessary but we're seeing some cases of this and haven't tracked them down yet.
if (!string.IsNullOrWhiteSpace(id))
@@ -256,6 +261,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
return false;
}
+ /// <summary>Gets OMDB URL.</summary>
+ /// <param name="query">Appends query string to URL.</param>
+ /// <returns>OMDB URL with optional query string.</returns>
public static string GetOmdbUrl(string query)
{
const string Url = "https://www.omdbapi.com?apikey=2c9d9507";
@@ -289,6 +297,10 @@ namespace MediaBrowser.Providers.Plugins.Omdb
return path;
}
}
+ else
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+ }
var url = GetOmdbUrl(
string.Format(
@@ -296,11 +308,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
"i={0}&plot=short&tomatoes=true&r=json",
imdbParam));
- using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false);
- await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
- var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(stream).ConfigureAwait(false);
- Directory.CreateDirectory(Path.GetDirectoryName(path));
- _jsonSerializer.SerializeToFile(rootObject, path);
+ var rootObject = await GetDeserializedOmdbResponse<RootObject>(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
+ await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
+ await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false);
return path;
}
@@ -326,6 +336,10 @@ namespace MediaBrowser.Providers.Plugins.Omdb
return path;
}
}
+ else
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+ }
var url = GetOmdbUrl(
string.Format(
@@ -334,15 +348,32 @@ namespace MediaBrowser.Providers.Plugins.Omdb
imdbParam,
seasonId));
- using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false);
- await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
- var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<SeasonRootObject>(stream).ConfigureAwait(false);
- Directory.CreateDirectory(Path.GetDirectoryName(path));
- _jsonSerializer.SerializeToFile(rootObject, path);
+ var rootObject = await GetDeserializedOmdbResponse<SeasonRootObject>(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
+ await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
+ 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);
@@ -384,13 +415,13 @@ namespace MediaBrowser.Providers.Plugins.Omdb
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
+ // But only do it if English is the preferred language because this data will not be localized
if (isConfiguredForEnglish && !string.IsNullOrWhiteSpace(result.Genre))
{
item.Genres = Array.Empty<string>();
foreach (var genre in result.Genre
- .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
+ .Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(i => i.Trim())
.Where(i => !string.IsNullOrWhiteSpace(i)))
{
@@ -400,7 +431,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
if (isConfiguredForEnglish)
{
- // Omdb is currently english only, so for other languages skip this and let secondary providers fill it in
+ // Omdb is currently English only, so for other languages skip this and let secondary providers fill it in
item.Overview = result.Plot;
}
@@ -424,7 +455,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
{
var person = new PersonInfo
{
- Name = result.Director.Trim(),
+ Name = result.Writer.Trim(),
Type = PersonType.Writer
};
@@ -454,7 +485,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
{
var lang = 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);
}
@@ -464,7 +495,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
public string seriesID { get; set; }
- public int Season { get; set; }
+ public int? Season { get; set; }
public int? totalSeasons { get; set; }
@@ -525,7 +556,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
public string Response { get; set; }
- public int Episode { get; set; }
+ public int? Episode { get; set; }
public float? GetRottenTomatoScore()
{
@@ -546,10 +577,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb
}
}
+#pragma warning disable CA1034
+ /// <summary>Describes OMDB rating.</summary>
public class OmdbRating
{
+ /// <summary>Gets or sets rating source.</summary>
public string Source { get; set; }
+ /// <summary>Gets or sets rating value.</summary>
public string Value { get; set; }
}
}