aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers/Plugins
diff options
context:
space:
mode:
authorcvium <clausvium@gmail.com>2022-01-07 10:23:22 +0100
committercvium <clausvium@gmail.com>2022-01-07 10:23:22 +0100
commitc658a883a2bc84b46ed73d209d2983e8a324cdce (patch)
treedabdbb5ac224e202d5433e7062e0c1b6872d1af7 /MediaBrowser.Providers/Plugins
parent2899b77cd58456470b8dd4d01d3a8c525a9b5911 (diff)
parent6b4f5a86631e5bde93dae88553380c7ffd99b8e4 (diff)
Merge branch 'master' into keyframe_extraction_v1
# Conflicts: # Jellyfin.Api/Controllers/DynamicHlsController.cs # MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs # MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
Diffstat (limited to 'MediaBrowser.Providers/Plugins')
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs9
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs8
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherAlbumExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherArtistExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/Configuration/PluginConfiguration.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/Plugin.cs1
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/PluginConfiguration.cs19
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumArtistExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs40
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistProvider.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzOtherArtistExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzReleaseGroupExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzTrackId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs1
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/Configuration/PluginConfiguration.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs37
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs56
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs221
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs143
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/Plugin.cs1
-rw-r--r--MediaBrowser.Providers/Plugins/StudioImages/Configuration/PluginConfiguration.cs24
-rw-r--r--MediaBrowser.Providers/Plugins/StudioImages/Configuration/config.html58
-rw-r--r--MediaBrowser.Providers/Plugins/StudioImages/Plugin.cs44
-rw-r--r--MediaBrowser.Providers/Plugins/StudioImages/StudiosImageProvider.cs192
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Api/TmdbController.cs41
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs42
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Configuration/PluginConfiguration.cs35
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Configuration/config.html95
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieImageProvider.cs41
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs10
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs17
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Plugin.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs23
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs11
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs22
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs9
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesExternalId.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs38
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs9
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs175
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs9
54 files changed, 963 insertions, 516 deletions
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumExternalId.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumExternalId.cs
index 138cfef19a..3a400575bc 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumExternalId.cs
@@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
- public string UrlFormatString => "https://www.theaudiodb.com/album/{0}";
+ public string? UrlFormatString => "https://www.theaudiodb.com/album/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is MusicAlbum;
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs
index 81bbc26b82..ad0247fb2e 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591
using System.Collections.Generic;
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs
index 3e0b0014eb..43f30824b8 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CA1002, CS1591, SA1300
using System;
@@ -172,8 +174,11 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
- // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
- await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
+
+ var fileStreamOptions = AsyncFile.WriteOptions;
+ fileStreamOptions.Mode = FileMode.Create;
+ fileStreamOptions.PreallocationSize = stream.Length;
+ await using var xmlFileStream = new FileStream(path, fileStreamOptions);
await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistExternalId.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistExternalId.cs
index 8aceb48c0c..b9e57eb265 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistExternalId.cs
@@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
public ExternalIdMediaType? Type => ExternalIdMediaType.Artist;
/// <inheritdoc />
- public string UrlFormatString => "https://www.theaudiodb.com/artist/{0}";
+ public string? UrlFormatString => "https://www.theaudiodb.com/artist/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is MusicArtist;
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs
index 3ffdcdbeb2..9c24476608 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591
using System.Collections.Generic;
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs
index e0b2f9c588..538dc67c42 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CA1034, CS1591, CA1002, SA1028, SA1300
using System;
@@ -154,8 +156,10 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
Directory.CreateDirectory(Path.GetDirectoryName(path));
- // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
- await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
+ var fileStreamOptions = AsyncFile.WriteOptions;
+ fileStreamOptions.Mode = FileMode.Create;
+ fileStreamOptions.PreallocationSize = stream.Length;
+ await using var xmlFileStream = new FileStream(path, fileStreamOptions);
await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherAlbumExternalId.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherAlbumExternalId.cs
index 014481da24..f8f6253ffd 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherAlbumExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherAlbumExternalId.cs
@@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
/// <inheritdoc />
- public string UrlFormatString => "https://www.theaudiodb.com/album/{0}";
+ public string? UrlFormatString => "https://www.theaudiodb.com/album/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Audio;
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherArtistExternalId.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherArtistExternalId.cs
index 7875391043..fd598c9186 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherArtistExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherArtistExternalId.cs
@@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
public ExternalIdMediaType? Type => ExternalIdMediaType.OtherArtist;
/// <inheritdoc />
- public string UrlFormatString => "https://www.theaudiodb.com/artist/{0}";
+ public string? UrlFormatString => "https://www.theaudiodb.com/artist/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/Configuration/PluginConfiguration.cs b/MediaBrowser.Providers/Plugins/AudioDb/Configuration/PluginConfiguration.cs
index 664474dcdd..d61ec6cb17 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/Configuration/PluginConfiguration.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/Configuration/PluginConfiguration.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS1591
using MediaBrowser.Model.Plugins;
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/Plugin.cs b/MediaBrowser.Providers/Plugins/AudioDb/Plugin.cs
index ba0d7b5697..6c2ad0573e 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/Plugin.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/Plugin.cs
@@ -1,3 +1,4 @@
+#nullable disable
#pragma warning disable CS1591
using System;
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/PluginConfiguration.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/PluginConfiguration.cs
index 0cec9e359c..9c27bd7d3f 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/PluginConfiguration.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/Configuration/PluginConfiguration.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS1591
using MediaBrowser.Model.Plugins;
@@ -12,24 +12,13 @@ namespace MediaBrowser.Providers.Plugins.MusicBrainz
public string Server
{
- get
- {
- return _server;
- }
-
- set
- {
- _server = value.TrimEnd('/');
- }
+ get => _server;
+ set => _server = value.TrimEnd('/');
}
public long RateLimit
{
- get
- {
- return _rateLimit;
- }
-
+ get => _rateLimit;
set
{
if (value < Plugin.DefaultRateLimit && _server == Plugin.DefaultServer)
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumArtistExternalId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumArtistExternalId.cs
index 1b37e2a60d..c54cdda3d3 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumArtistExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumArtistExternalId.cs
@@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Music
public ExternalIdMediaType? Type => ExternalIdMediaType.AlbumArtist;
/// <inheritdoc />
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
+ public string? UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Audio;
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumExternalId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumExternalId.cs
index ef095111a8..8f7fadd060 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumExternalId.cs
@@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Music
public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
/// <inheritdoc />
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release/{0}";
+ public string? UrlFormatString => Plugin.Instance.Configuration.Server + "/release/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
index 93f8902def..5ae5ff3bec 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591, SA1401
using System;
@@ -301,7 +303,7 @@ namespace MediaBrowser.Providers.Music
return ReleaseResult.Parse(reader).FirstOrDefault();
}
- private static (string, string) ParseArtistCredit(XmlReader reader)
+ private static (string Name, string ArtistId) ParseArtistCredit(XmlReader reader)
{
reader.MoveToContent();
reader.Read();
@@ -317,6 +319,12 @@ namespace MediaBrowser.Providers.Music
{
case "name-credit":
{
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ break;
+ }
+
using var subReader = reader.ReadSubtree();
return ParseArtistNameCredit(subReader);
}
@@ -337,7 +345,7 @@ namespace MediaBrowser.Providers.Music
return default;
}
- private static (string, string) ParseArtistNameCredit(XmlReader reader)
+ private static (string Name, string ArtistId) ParseArtistNameCredit(XmlReader reader)
{
reader.MoveToContent();
reader.Read();
@@ -353,6 +361,12 @@ namespace MediaBrowser.Providers.Music
{
case "artist":
{
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ break;
+ }
+
var id = reader.GetAttribute("id");
using var subReader = reader.ReadSubtree();
return ParseArtistArtistCredit(subReader, id);
@@ -374,7 +388,7 @@ namespace MediaBrowser.Providers.Music
return (null, null);
}
- private static (string name, string id) ParseArtistArtistCredit(XmlReader reader, string artistId)
+ private static (string Name, string ArtistId) ParseArtistArtistCredit(XmlReader reader, string artistId)
{
reader.MoveToContent();
reader.Read();
@@ -455,8 +469,8 @@ namespace MediaBrowser.Providers.Music
};
using var reader = XmlReader.Create(oReader, settings);
- reader.MoveToContent();
- reader.Read();
+ await reader.MoveToContentAsync().ConfigureAwait(false);
+ await reader.ReadAsync().ConfigureAwait(false);
// Loop through each element
while (!reader.EOF && reader.ReadState == ReadState.Interactive)
@@ -469,7 +483,7 @@ namespace MediaBrowser.Providers.Music
{
if (reader.IsEmptyElement)
{
- reader.Read();
+ await reader.ReadAsync().ConfigureAwait(false);
continue;
}
@@ -479,14 +493,14 @@ namespace MediaBrowser.Providers.Music
default:
{
- reader.Skip();
+ await reader.SkipAsync().ConfigureAwait(false);
break;
}
}
}
else
{
- reader.Read();
+ await reader.ReadAsync().ConfigureAwait(false);
}
}
@@ -614,7 +628,7 @@ namespace MediaBrowser.Providers.Music
public string Overview;
public int? Year;
- public List<ValueTuple<string, string>> Artists = new List<ValueTuple<string, string>>();
+ public List<(string, string)> Artists = new();
public static IEnumerable<ReleaseResult> Parse(XmlReader reader)
{
@@ -753,10 +767,16 @@ namespace MediaBrowser.Providers.Music
case "artist-credit":
{
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ break;
+ }
+
using var subReader = reader.ReadSubtree();
var artist = ParseArtistCredit(subReader);
- if (!string.IsNullOrEmpty(artist.Item1))
+ if (!string.IsNullOrEmpty(artist.Name))
{
result.Artists.Add(artist);
}
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistExternalId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistExternalId.cs
index d654e1372f..941ffea721 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistExternalId.cs
@@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Music
public ExternalIdMediaType? Type => ExternalIdMediaType.Artist;
/// <inheritdoc />
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
+ public string? UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is MusicArtist;
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistProvider.cs
index 7cff5f5952..1feb7f4eab 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistProvider.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzArtistProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591
using System;
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzOtherArtistExternalId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzOtherArtistExternalId.cs
index f889a34b5c..05db2d98f7 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzOtherArtistExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzOtherArtistExternalId.cs
@@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Music
public ExternalIdMediaType? Type => ExternalIdMediaType.OtherArtist;
/// <inheritdoc />
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
+ public string? UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzReleaseGroupExternalId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzReleaseGroupExternalId.cs
index 53783d2c0c..acb652fe01 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzReleaseGroupExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzReleaseGroupExternalId.cs
@@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Music
public ExternalIdMediaType? Type => ExternalIdMediaType.ReleaseGroup;
/// <inheritdoc />
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release-group/{0}";
+ public string? UrlFormatString => Plugin.Instance.Configuration.Server + "/release-group/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzTrackId.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzTrackId.cs
index 627f8f098d..14805b9b79 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzTrackId.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzTrackId.cs
@@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Music
public ExternalIdMediaType? Type => ExternalIdMediaType.Track;
/// <inheritdoc />
- public string UrlFormatString => Plugin.Instance.Configuration.Server + "/track/{0}";
+ public string? UrlFormatString => Plugin.Instance.Configuration.Server + "/track/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Audio;
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs
index 69b69be428..cfa10dd648 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/Plugin.cs
@@ -1,3 +1,4 @@
+#nullable disable
#pragma warning disable CS1591
using System;
diff --git a/MediaBrowser.Providers/Plugins/Omdb/Configuration/PluginConfiguration.cs b/MediaBrowser.Providers/Plugins/Omdb/Configuration/PluginConfiguration.cs
index 196f14e7c8..0995470055 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/Configuration/PluginConfiguration.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/Configuration/PluginConfiguration.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS1591
using MediaBrowser.Model.Plugins;
diff --git a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs
index 19d90b9a1b..8bfdc461e6 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs
@@ -1,5 +1,3 @@
-#nullable enable
-
using System;
using System.ComponentModel;
using System.Text.Json;
diff --git a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs
index c19589d45b..f35880a046 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs
@@ -1,5 +1,3 @@
-#nullable enable
-
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs
index 24ef80a35d..d8b33a799f 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs
@@ -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, _appHost, _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;
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs
index df67aff31c..60b373483f 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs
@@ -1,11 +1,12 @@
+#nullable disable
+
#pragma warning disable CS1591
using System.Collections.Generic;
-using System.Globalization;
+using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Common;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -21,16 +22,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 IApplicationHost _appHost;
+ private readonly OmdbProvider _omdbProvider;
- public OmdbImageProvider(IApplicationHost appHost, IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IServerConfigurationManager configurationManager)
+ public OmdbImageProvider(IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IServerConfigurationManager configurationManager)
{
_httpClientFactory = httpClientFactory;
- _fileSystem = fileSystem;
- _configurationManager = configurationManager;
- _appHost = appHost;
+ _omdbProvider = new OmdbProvider(_httpClientFactory, fileSystem, configurationManager);
}
public string Name => "The Open Movie Database";
@@ -50,38 +47,27 @@ namespace MediaBrowser.Providers.Plugins.Omdb
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)
{
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, _appHost, _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)
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
index 02e696de51..e5753b2b59 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591, SA1300
using System;
@@ -6,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;
@@ -29,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,
@@ -43,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());
@@ -57,185 +54,166 @@ 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 (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 (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
{
- urlQuery += "&i=" + imdbId;
+ urlQuery.Append("&i=")
+ .Append(imdbId);
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);
- 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);
+ 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, _appHost, _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()
{
var result = new MetadataResult<T>
@@ -247,7 +225,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;
}
@@ -256,22 +234,15 @@ namespace MediaBrowser.Providers.Plugins.Omdb
result.Item.SetProviderId(MetadataProvider.Imdb, imdbId);
result.HasMetadata = true;
- await new OmdbProvider(_httpClientFactory, _fileSystem, _appHost, _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)
- {
- 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();
return first?.GetProviderId(MetadataProvider.Imdb);
}
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
index 479ae0f391..12ea2d55b9 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
@@ -1,16 +1,19 @@
+#nullable disable
+
#pragma warning disable CS159, SA1300
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;
using Jellyfin.Extensions.Json;
-using MediaBrowser.Common;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -26,25 +29,22 @@ namespace MediaBrowser.Providers.Plugins.Omdb
private readonly IFileSystem _fileSystem;
private readonly IServerConfigurationManager _configurationManager;
private readonly IHttpClientFactory _httpClientFactory;
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- private readonly IApplicationHost _appHost;
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)
+ public OmdbProvider(IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IServerConfigurationManager configurationManager)
{
_httpClientFactory = httpClientFactory;
_fileSystem = fileSystem;
_configurationManager = configurationManager;
- _appHost = appHost;
_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>
@@ -67,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;
@@ -78,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, _usCulture, out var year)
- && year >= 0)
+ if (TryParseYear(result.Year, out var year))
{
item.ProductionYear = year;
}
@@ -93,14 +92,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb
}
if (!string.IsNullOrEmpty(result.imdbVotes)
- && int.TryParse(result.imdbVotes, NumberStyles.Number, _usCulture, out var voteCount)
+ && int.TryParse(result.imdbVotes, NumberStyles.Number, CultureInfo.InvariantCulture, out var voteCount)
&& voteCount >= 0)
{
// item.VoteCount = voteCount;
}
if (!string.IsNullOrEmpty(result.imdbRating)
- && float.TryParse(result.imdbRating, NumberStyles.Any, _usCulture, out var imdbRating)
+ && float.TryParse(result.imdbRating, NumberStyles.Any, CultureInfo.InvariantCulture, out var imdbRating)
&& imdbRating >= 0)
{
item.CommunityRating = imdbRating;
@@ -116,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>
@@ -179,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;
@@ -190,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, _usCulture, out var year)
- && year >= 0)
+ if (TryParseYear(result.Year, out var year))
{
item.ProductionYear = year;
}
@@ -205,14 +203,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb
}
if (!string.IsNullOrEmpty(result.imdbVotes)
- && int.TryParse(result.imdbVotes, NumberStyles.Number, _usCulture, out var voteCount)
+ && int.TryParse(result.imdbVotes, NumberStyles.Number, CultureInfo.InvariantCulture, out var voteCount)
&& voteCount >= 0)
{
// item.VoteCount = voteCount;
}
if (!string.IsNullOrEmpty(result.imdbRating)
- && float.TryParse(result.imdbRating, NumberStyles.Any, _usCulture, out var imdbRating)
+ && float.TryParse(result.imdbRating, NumberStyles.Any, CultureInfo.InvariantCulture, out var imdbRating)
&& imdbRating >= 0)
{
item.CommunityRating = imdbRating;
@@ -228,7 +226,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
}
- ParseAdditionalMetadata(itemResult, result);
+ ParseAdditionalMetadata(itemResult, result, isEnglishRequested);
return true;
}
@@ -262,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))
@@ -294,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);
@@ -334,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))
@@ -393,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;
}
@@ -430,7 +422,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
{
var person = new PersonInfo
{
- Name = result.Director.Trim(),
+ Name = result.Director,
Type = PersonType.Director
};
@@ -441,7 +433,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
{
var person = new PersonInfo
{
- Name = result.Writer.Trim(),
+ Name = result.Writer,
Type = PersonType.Writer
};
@@ -450,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
@@ -549,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))
diff --git a/MediaBrowser.Providers/Plugins/Omdb/Plugin.cs b/MediaBrowser.Providers/Plugins/Omdb/Plugin.cs
index 047df4f33d..a0fba48f05 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/Plugin.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/Plugin.cs
@@ -1,3 +1,4 @@
+#nullable disable
#pragma warning disable CS1591
using System;
diff --git a/MediaBrowser.Providers/Plugins/StudioImages/Configuration/PluginConfiguration.cs b/MediaBrowser.Providers/Plugins/StudioImages/Configuration/PluginConfiguration.cs
new file mode 100644
index 0000000000..fad989ab43
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/StudioImages/Configuration/PluginConfiguration.cs
@@ -0,0 +1,24 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Model.Plugins;
+
+namespace MediaBrowser.Providers.Plugins.StudioImages
+{
+ public class PluginConfiguration : BasePluginConfiguration
+ {
+ private string _repository = Plugin.DefaultServer;
+
+ public string RepositoryUrl
+ {
+ get
+ {
+ return _repository;
+ }
+
+ set
+ {
+ _repository = value.TrimEnd('/');
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/StudioImages/Configuration/config.html b/MediaBrowser.Providers/Plugins/StudioImages/Configuration/config.html
new file mode 100644
index 0000000000..f9fe3dc2e9
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/StudioImages/Configuration/config.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Studio Images</title>
+</head>
+<body>
+ <div data-role="page" class="page type-interior pluginConfigurationPage configPage" data-require="emby-input,emby-button,emby-checkbox">
+ <div data-role="content">
+ <div class="content-primary">
+ <form class="configForm">
+ <div class="inputContainer">
+ <input is="emby-input" type="text" id="repository" required label="Repository" />
+ <div class="fieldDescription">This can be any Jellyfin-compatible artwork repository.</div>
+ </div>
+ <br />
+ <div>
+ <button is="emby-button" type="submit" class="raised button-submit block"><span>Save</span></button>
+ </div>
+ </form>
+ </div>
+ </div>
+ <script type="text/javascript">
+ var PluginConfig = {
+ pluginId: "872a7849-1171-458d-a6fb-3de3d442ad30"
+ };
+
+ document.querySelector('.configPage')
+ .addEventListener('pageshow', function () {
+ Dashboard.showLoadingMsg();
+ ApiClient.getPluginConfiguration(PluginConfig.pluginId).then(function (config) {
+ var repository = document.querySelector('#repository');
+ repository.value = config.RepositoryUrl;
+ repository.dispatchEvent(new Event('change', {
+ bubbles: true,
+ cancelable: false
+ }));
+
+ Dashboard.hideLoadingMsg();
+ });
+ });
+
+ document.querySelector('.configForm')
+ .addEventListener('submit', function (e) {
+ Dashboard.showLoadingMsg();
+
+ ApiClient.getPluginConfiguration(PluginConfig.pluginId).then(function (config) {
+ config.RepositoryUrl = document.querySelector('#server').value;
+
+ ApiClient.updatePluginConfiguration(PluginConfig.pluginId, config).then(Dashboard.processPluginConfigurationUpdateResult);
+ });
+
+ e.preventDefault();
+ return false;
+ });
+ </script>
+ </div>
+</body>
+</html>
diff --git a/MediaBrowser.Providers/Plugins/StudioImages/Plugin.cs b/MediaBrowser.Providers/Plugins/StudioImages/Plugin.cs
new file mode 100644
index 0000000000..e0ab31b56e
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/StudioImages/Plugin.cs
@@ -0,0 +1,44 @@
+#nullable disable
+#pragma warning disable CS1591
+
+using System;
+using System.Collections.Generic;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Plugins;
+using MediaBrowser.Model.Plugins;
+using MediaBrowser.Model.Serialization;
+
+namespace MediaBrowser.Providers.Plugins.StudioImages
+{
+ public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
+ {
+ // TODO change this for a Jellyfin-hosted repository.
+ public const string DefaultServer = "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname";
+
+ public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
+ : base(applicationPaths, xmlSerializer)
+ {
+ Instance = this;
+ }
+
+ public static Plugin Instance { get; private set; }
+
+ public override Guid Id => new Guid("872a7849-1171-458d-a6fb-3de3d442ad30");
+
+ public override string Name => "Studio Images";
+
+ public override string Description => "Get artwork for studios from any Jellyfin-compatible repository.";
+
+ // TODO remove when plugin removed from server.
+ public override string ConfigurationFileName => "Jellyfin.Plugin.StudioImages.xml";
+
+ public IEnumerable<PluginPageInfo> GetPages()
+ {
+ yield return new PluginPageInfo
+ {
+ Name = Name,
+ EmbeddedResourcePath = GetType().Namespace + ".Configuration.config.html"
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/StudioImages/StudiosImageProvider.cs b/MediaBrowser.Providers/Plugins/StudioImages/StudiosImageProvider.cs
new file mode 100644
index 0000000000..3a3048cec4
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/StudioImages/StudiosImageProvider.cs
@@ -0,0 +1,192 @@
+#nullable disable
+
+#pragma warning disable CS1591
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Extensions;
+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.Providers;
+using MediaBrowser.Providers.Plugins.StudioImages;
+
+namespace MediaBrowser.Providers.Studios
+{
+ public class StudiosImageProvider : IRemoteImageProvider
+ {
+ private readonly IServerConfigurationManager _config;
+ private readonly IHttpClientFactory _httpClientFactory;
+ private readonly IFileSystem _fileSystem;
+ private readonly string repositoryUrl;
+
+ public StudiosImageProvider(IServerConfigurationManager config, IHttpClientFactory httpClientFactory, IFileSystem fileSystem)
+ {
+ _config = config;
+ _httpClientFactory = httpClientFactory;
+ _fileSystem = fileSystem;
+ repositoryUrl = Plugin.Instance.Configuration.RepositoryUrl;
+ }
+
+ public string Name => "Artwork Repository";
+
+ public int Order => 0;
+
+ public bool Supports(BaseItem item)
+ {
+ return item is Studio;
+ }
+
+ public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
+ {
+ return new List<ImageType>
+ {
+ ImageType.Primary,
+ ImageType.Thumb
+ };
+ }
+
+ public Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)
+ {
+ return GetImages(item, true, true, cancellationToken);
+ }
+
+ private async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, bool posters, bool thumbs, CancellationToken cancellationToken)
+ {
+ var list = new List<RemoteImageInfo>();
+
+ if (posters)
+ {
+ var posterPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotestudioposters.txt");
+
+ posterPath = await EnsurePosterList(posterPath, cancellationToken).ConfigureAwait(false);
+
+ list.Add(GetImage(item, posterPath, ImageType.Primary, "folder"));
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (thumbs)
+ {
+ var thumbsPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotestudiothumbs.txt");
+
+ thumbsPath = await EnsureThumbsList(thumbsPath, cancellationToken).ConfigureAwait(false);
+
+ list.Add(GetImage(item, thumbsPath, ImageType.Thumb, "thumb"));
+ }
+
+ return list.Where(i => i != null);
+ }
+
+ private RemoteImageInfo GetImage(BaseItem item, string filename, ImageType type, string remoteFilename)
+ {
+ var list = GetAvailableImages(filename);
+
+ var match = FindMatch(item, list);
+
+ if (!string.IsNullOrEmpty(match))
+ {
+ var url = GetUrl(match, remoteFilename);
+
+ return new RemoteImageInfo
+ {
+ ProviderName = Name,
+ Type = type,
+ Url = url
+ };
+ }
+
+ return null;
+ }
+
+ private string GetUrl(string image, string filename)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}.jpg", repositoryUrl, image, filename);
+ }
+
+ private Task<string> EnsureThumbsList(string file, CancellationToken cancellationToken)
+ {
+ string url = string.Format(CultureInfo.InvariantCulture, "{0}/studiothumbs.txt", repositoryUrl);
+
+ return EnsureList(url, file, _fileSystem, cancellationToken);
+ }
+
+ private Task<string> EnsurePosterList(string file, CancellationToken cancellationToken)
+ {
+ string url = string.Format(CultureInfo.InvariantCulture, "{0}/studioposters.txt", repositoryUrl);
+
+ return EnsureList(url, file, _fileSystem, cancellationToken);
+ }
+
+ public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
+ return httpClient.GetAsync(url, cancellationToken);
+ }
+
+ /// <summary>
+ /// Ensures the list.
+ /// </summary>
+ /// <param name="url">The URL.</param>
+ /// <param name="file">The file.</param>
+ /// <param name="fileSystem">The file system.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ public async Task<string> EnsureList(string url, string file, IFileSystem fileSystem, CancellationToken cancellationToken)
+ {
+ var fileInfo = fileSystem.GetFileInfo(file);
+
+ if (!fileInfo.Exists || (DateTime.UtcNow - fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays > 1)
+ {
+ var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
+
+ Directory.CreateDirectory(Path.GetDirectoryName(file));
+ await using var response = await httpClient.GetStreamAsync(url, cancellationToken).ConfigureAwait(false);
+ await using var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
+ await response.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
+ }
+
+ return file;
+ }
+
+ public string FindMatch(BaseItem item, IEnumerable<string> images)
+ {
+ var name = GetComparableName(item.Name);
+
+ return images.FirstOrDefault(i => string.Equals(name, GetComparableName(i), StringComparison.OrdinalIgnoreCase));
+ }
+
+ private string GetComparableName(string name)
+ {
+ return name.Replace(" ", string.Empty, StringComparison.Ordinal)
+ .Replace(".", string.Empty, StringComparison.Ordinal)
+ .Replace("&", string.Empty, StringComparison.Ordinal)
+ .Replace("!", string.Empty, StringComparison.Ordinal)
+ .Replace(",", string.Empty, StringComparison.Ordinal)
+ .Replace("/", string.Empty, StringComparison.Ordinal);
+ }
+
+ public IEnumerable<string> GetAvailableImages(string file)
+ {
+ using var fileStream = File.OpenRead(file);
+ using var reader = new StreamReader(fileStream);
+
+ foreach (var line in reader.ReadAllLines())
+ {
+ if (!string.IsNullOrWhiteSpace(line))
+ {
+ yield return line;
+ }
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Api/TmdbController.cs b/MediaBrowser.Providers/Plugins/Tmdb/Api/TmdbController.cs
new file mode 100644
index 0000000000..0bab7c3cad
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Api/TmdbController.cs
@@ -0,0 +1,41 @@
+using System.Net.Mime;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using TMDbLib.Objects.General;
+
+namespace MediaBrowser.Providers.Plugins.Tmdb.Api
+{
+ /// <summary>
+ /// The TMDb api controller.
+ /// </summary>
+ [ApiController]
+ [Authorize(Policy = "DefaultAuthorization")]
+ [Route("[controller]")]
+ [Produces(MediaTypeNames.Application.Json)]
+ public class TmdbController : ControllerBase
+ {
+ private readonly TmdbClientManager _tmdbClientManager;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TmdbController"/> class.
+ /// </summary>
+ /// <param name="tmdbClientManager">The TMDb client manager.</param>
+ public TmdbController(TmdbClientManager tmdbClientManager)
+ {
+ _tmdbClientManager = tmdbClientManager;
+ }
+
+ /// <summary>
+ /// Gets the TMDb image configuration options.
+ /// </summary>
+ /// <returns>The image portion of the TMDb client configuration.</returns>
+ [HttpGet("ClientConfiguration")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ public async Task<ConfigImageTypes> TmdbClientConfiguration()
+ {
+ return (await _tmdbClientManager.GetClientConfiguration().ConfigureAwait(false)).Images;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetExternalId.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetExternalId.cs
index 1f7ec64338..3217ac2f13 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetExternalId.cs
@@ -21,7 +21,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
public ExternalIdMediaType? Type => ExternalIdMediaType.BoxSet;
/// <inheritdoc />
- public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "collection/{0}";
+ public string? UrlFormatString => TmdbUtils.BaseTmdbUrl + "collection/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item)
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs
index a5287e749f..29a557c315 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591
using System;
@@ -11,9 +13,7 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Providers;
namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
@@ -66,40 +66,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
return Enumerable.Empty<RemoteImageInfo>();
}
- var remoteImages = new List<RemoteImageInfo>();
-
- for (var i = 0; i < collection.Images.Posters.Count; i++)
- {
- var poster = collection.Images.Posters[i];
- remoteImages.Add(new RemoteImageInfo
- {
- Url = _tmdbClientManager.GetPosterUrl(poster.FilePath),
- CommunityRating = poster.VoteAverage,
- VoteCount = poster.VoteCount,
- Width = poster.Width,
- Height = poster.Height,
- Language = TmdbUtils.AdjustImageLanguage(poster.Iso_639_1, language),
- ProviderName = Name,
- Type = ImageType.Primary,
- RatingType = RatingType.Score
- });
- }
+ var posters = collection.Images.Posters;
+ var backdrops = collection.Images.Backdrops;
+ var remoteImages = new List<RemoteImageInfo>(posters.Count + backdrops.Count);
- for (var i = 0; i < collection.Images.Backdrops.Count; i++)
- {
- var backdrop = collection.Images.Backdrops[i];
- remoteImages.Add(new RemoteImageInfo
- {
- Url = _tmdbClientManager.GetBackdropUrl(backdrop.FilePath),
- CommunityRating = backdrop.VoteAverage,
- VoteCount = backdrop.VoteCount,
- Width = backdrop.Width,
- Height = backdrop.Height,
- ProviderName = Name,
- Type = ImageType.Backdrop,
- RatingType = RatingType.Score
- });
- }
+ _tmdbClientManager.ConvertPostersToRemoteImageInfo(posters, language, remoteImages);
+ _tmdbClientManager.ConvertBackdropsToRemoteImageInfo(backdrops, language, remoteImages);
return remoteImages;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs
index 5dd1f0b73a..62bc9c65f9 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591
using System;
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Configuration/PluginConfiguration.cs b/MediaBrowser.Providers/Plugins/Tmdb/Configuration/PluginConfiguration.cs
index 907f0160d6..dec7961484 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Configuration/PluginConfiguration.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Configuration/PluginConfiguration.cs
@@ -11,5 +11,40 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
/// Gets or sets a value indicating whether include adult content when searching with TMDb.
/// </summary>
public bool IncludeAdult { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether tags should be imported for series from TMDb.
+ /// </summary>
+ public bool ExcludeTagsSeries { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether tags should be imported for movies from TMDb.
+ /// </summary>
+ public bool ExcludeTagsMovies { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating the maximum number of cast members to fetch for an item.
+ /// </summary>
+ public int MaxCastMembers { get; set; } = 15;
+
+ /// <summary>
+ /// Gets or sets a value indicating the poster image size to fetch.
+ /// </summary>
+ public string? PosterSize { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating the backdrop image size to fetch.
+ /// </summary>
+ public string? BackdropSize { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating the profile image size to fetch.
+ /// </summary>
+ public string? ProfileSize { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating the still image size to fetch.
+ /// </summary>
+ public string? StillSize { get; set; }
}
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Configuration/config.html b/MediaBrowser.Providers/Plugins/Tmdb/Configuration/config.html
index 6f42549d7d..52693795b5 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Configuration/config.html
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Configuration/config.html
@@ -12,7 +12,33 @@
<input is="emby-checkbox" type="checkbox" id="includeAdult" />
<span>Include adult content in search results.</span>
</label>
- <br />
+ <label class="checkboxContainer">
+ <input is="emby-checkbox" type="checkbox" id="excludeTagsSeries" />
+ <span>Exclude tags/keywords from metadata fetched for series.</span>
+ </label>
+ <label class="checkboxContainer">
+ <input is="emby-checkbox" type="checkbox" id="excludeTagsMovies" />
+ <span>Exclude tags/keywords from metadata fetched for movies.</span>
+ </label>
+ <div class="inputContainer">
+ <input is="emby-input" type="number" id="maxCastMembers" pattern="[0-9]*" required min="0" max="1000" label="Max Cast Members" />
+ <div class="fieldDescription">The maximum number of cast members to fetch for an item.</div>
+ </div>
+ <div class="verticalSection verticalSection-extrabottompadding">
+ <h2>Image Scaling</h2>
+ <div class="selectContainer">
+ <select is="emby-select" id="selectPosterSize" label="Poster"></select>
+ </div>
+ <div class="selectContainer">
+ <select is="emby-select" id="selectBackdropSize" label="Backdrop"></select>
+ </div>
+ <div class="selectContainer">
+ <select is="emby-select" id="selectProfileSize" label="Profile"></select>
+ </div>
+ <div class="selectContainer">
+ <select is="emby-select" id="selectStillSize" label="Still"></select>
+ </div>
+ </div>
<div>
<button is="emby-button" type="submit" class="raised button-submit block"><span>Save</span></button>
</div>
@@ -27,22 +53,81 @@
document.querySelector('.configPage')
.addEventListener('pageshow', function () {
Dashboard.showLoadingMsg();
+
+ var clientConfig, pluginConfig;
+ var configureImageScaling = function() {
+ if (clientConfig === null || pluginConfig === null) {
+ return;
+ }
+
+ var sizeOptionsGenerator = function (size) {
+ return '<option value="' + size + '">' + size + '</option>';
+ }
+
+ var selPosterSize = document.querySelector('#selectPosterSize');
+ selPosterSize.innerHTML = clientConfig.PosterSizes.map(sizeOptionsGenerator);
+ selPosterSize.value = pluginConfig.PosterSize;
+
+ var selBackdropSize = document.querySelector('#selectBackdropSize');
+ selBackdropSize.innerHTML = clientConfig.BackdropSizes.map(sizeOptionsGenerator);
+ selBackdropSize.value = pluginConfig.BackdropSize;
+
+ var selProfileSize = document.querySelector('#selectProfileSize');
+ selProfileSize.innerHTML = clientConfig.ProfileSizes.map(sizeOptionsGenerator);
+ selProfileSize.value = pluginConfig.ProfileSize;
+
+ var selStillSize = document.querySelector('#selectStillSize');
+ selStillSize.innerHTML = clientConfig.StillSizes.map(sizeOptionsGenerator);
+ selStillSize.value = pluginConfig.StillSize;
+
+ Dashboard.hideLoadingMsg();
+ }
+
+ const request = {
+ url: ApiClient.getUrl('tmdb/ClientConfiguration'),
+ dataType: 'json',
+ type: 'GET',
+ headers: { accept: 'application/json' }
+ }
+ ApiClient.fetch(request).then(function (config) {
+ clientConfig = config;
+ configureImageScaling();
+ });
+
ApiClient.getPluginConfiguration(PluginConfig.pluginId).then(function (config) {
document.querySelector('#includeAdult').checked = config.IncludeAdult;
- Dashboard.hideLoadingMsg();
+ document.querySelector('#excludeTagsSeries').checked = config.ExcludeTagsSeries;
+ document.querySelector('#excludeTagsMovies').checked = config.ExcludeTagsMovies;
+
+ var maxCastMembers = document.querySelector('#maxCastMembers');
+ maxCastMembers.value = config.MaxCastMembers;
+ maxCastMembers.dispatchEvent(new Event('change', {
+ bubbles: true,
+ cancelable: false
+ }));
+
+ pluginConfig = config;
+ configureImageScaling();
});
});
-
+
document.querySelector('.configForm')
.addEventListener('submit', function (e) {
Dashboard.showLoadingMsg();
-
+
ApiClient.getPluginConfiguration(PluginConfig.pluginId).then(function (config) {
config.IncludeAdult = document.querySelector('#includeAdult').checked;
+ config.ExcludeTagsSeries = document.querySelector('#excludeTagsSeries').checked;
+ config.ExcludeTagsMovies = document.querySelector('#excludeTagsMovies').checked;
+ config.MaxCastMembers = document.querySelector('#maxCastMembers').value;
+ config.PosterSize = document.querySelector('#selectPosterSize').value;
+ config.BackdropSize = document.querySelector('#selectBackdropSize').value;
+ config.ProfileSize = document.querySelector('#selectProfileSize').value;
+ config.StillSize = document.querySelector('#selectStillSize').value;
ApiClient.updatePluginConfiguration(PluginConfig.pluginId, config).then(Dashboard.processPluginConfigurationUpdateResult);
});
-
+
e.preventDefault();
return false;
});
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieExternalId.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieExternalId.cs
index f1a1b65d82..31310a8d41 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieExternalId.cs
@@ -21,7 +21,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
public ExternalIdMediaType? Type => ExternalIdMediaType.Movie;
/// <inheritdoc />
- public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "movie/{0}";
+ public string? UrlFormatString => TmdbUtils.BaseTmdbUrl + "movie/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item)
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieImageProvider.cs
index d3cef49d8c..f71f7bd10d 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieImageProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591
using System;
@@ -11,7 +13,6 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using TMDbLib.Objects.Find;
@@ -82,40 +83,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
return Enumerable.Empty<RemoteImageInfo>();
}
- var remoteImages = new List<RemoteImageInfo>();
-
- for (var i = 0; i < movie.Images.Posters.Count; i++)
- {
- var poster = movie.Images.Posters[i];
- remoteImages.Add(new RemoteImageInfo
- {
- Url = _tmdbClientManager.GetPosterUrl(poster.FilePath),
- CommunityRating = poster.VoteAverage,
- VoteCount = poster.VoteCount,
- Width = poster.Width,
- Height = poster.Height,
- Language = TmdbUtils.AdjustImageLanguage(poster.Iso_639_1, language),
- ProviderName = Name,
- Type = ImageType.Primary,
- RatingType = RatingType.Score
- });
- }
+ var posters = movie.Images.Posters;
+ var backdrops = movie.Images.Backdrops;
+ var remoteImages = new List<RemoteImageInfo>(posters.Count + backdrops.Count);
- for (var i = 0; i < movie.Images.Backdrops.Count; i++)
- {
- var backdrop = movie.Images.Backdrops[i];
- remoteImages.Add(new RemoteImageInfo
- {
- Url = _tmdbClientManager.GetPosterUrl(backdrop.FilePath),
- CommunityRating = backdrop.VoteAverage,
- VoteCount = backdrop.VoteCount,
- Width = backdrop.Width,
- Height = backdrop.Height,
- ProviderName = Name,
- Type = ImageType.Backdrop,
- RatingType = RatingType.Score
- });
- }
+ _tmdbClientManager.ConvertPostersToRemoteImageInfo(posters, language, remoteImages);
+ _tmdbClientManager.ConvertBackdropsToRemoteImageInfo(backdrops, language, remoteImages);
return remoteImages;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs
index 54f8d450ac..e4a56fde94 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591
using System;
@@ -7,6 +9,7 @@ using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
@@ -239,8 +242,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
if (movieResult.Credits?.Cast != null)
{
- // TODO configurable
- foreach (var actor in movieResult.Credits.Cast.OrderBy(a => a.Order).Take(TmdbUtils.MaxCastMembers))
+ foreach (var actor in movieResult.Credits.Cast.OrderBy(a => a.Order).Take(Plugin.Instance.Configuration.MaxCastMembers))
{
var personInfo = new PersonInfo
{
@@ -278,8 +280,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
// Normalize this
var type = TmdbUtils.MapCrewToPersonType(person);
- if (!keepTypes.Contains(type, StringComparer.OrdinalIgnoreCase) &&
- !keepTypes.Contains(person.Job ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ if (!keepTypes.Contains(type, StringComparison.OrdinalIgnoreCase) &&
+ !keepTypes.Contains(person.Job ?? string.Empty, StringComparison.OrdinalIgnoreCase))
{
continue;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonExternalId.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonExternalId.cs
index de74a7a4c7..9804d60bdd 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonExternalId.cs
@@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
public ExternalIdMediaType? Type => ExternalIdMediaType.Person;
/// <inheritdoc />
- public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "person/{0}";
+ public string? UrlFormatString => TmdbUtils.BaseTmdbUrl + "person/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item)
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs
index 1fc5ccba59..7ce4cfe676 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs
@@ -60,21 +60,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
return Enumerable.Empty<RemoteImageInfo>();
}
- var remoteImages = new RemoteImageInfo[personResult.Images.Profiles.Count];
+ var profiles = personResult.Images.Profiles;
+ var remoteImages = new List<RemoteImageInfo>(profiles.Count);
- for (var i = 0; i < personResult.Images.Profiles.Count; i++)
- {
- var image = personResult.Images.Profiles[i];
- remoteImages[i] = new RemoteImageInfo
- {
- ProviderName = Name,
- Type = ImageType.Primary,
- Width = image.Width,
- Height = image.Height,
- Language = TmdbUtils.AdjustImageLanguage(image.Iso_639_1, language),
- Url = _tmdbClientManager.GetProfileUrl(image.FilePath)
- };
- }
+ _tmdbClientManager.ConvertProfilesToRemoteImageInfo(profiles, language, remoteImages);
return remoteImages;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
index dac1183889..8790e37592 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591
using System;
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Plugin.cs b/MediaBrowser.Providers/Plugins/Tmdb/Plugin.cs
index ea81eb96e0..4adde8366a 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Plugin.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Plugin.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
using System;
using System.Collections.Generic;
using MediaBrowser.Common.Configuration;
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs
index 45e18c0ac0..5eec776b5b 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591
using System;
@@ -10,7 +12,6 @@ using System.Threading.Tasks;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
@@ -73,23 +74,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
return Enumerable.Empty<RemoteImageInfo>();
}
- var remoteImages = new RemoteImageInfo[stills.Count];
- for (var i = 0; i < stills.Count; i++)
- {
- var image = stills[i];
- remoteImages[i] = new RemoteImageInfo
- {
- Url = _tmdbClientManager.GetStillUrl(image.FilePath),
- CommunityRating = image.VoteAverage,
- VoteCount = image.VoteCount,
- Width = image.Width,
- Height = image.Height,
- Language = TmdbUtils.AdjustImageLanguage(image.Iso_639_1, language),
- ProviderName = Name,
- Type = ImageType.Primary,
- RatingType = RatingType.Score
- };
- }
+ var remoteImages = new List<RemoteImageInfo>(stills.Count);
+
+ _tmdbClientManager.ConvertStillsToRemoteImageInfo(stills, language, remoteImages);
return remoteImages;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs
index 8ec8f64641..f50f158772 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591
using System;
@@ -7,6 +9,7 @@ using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
@@ -152,7 +155,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
if (credits?.Cast != null)
{
- foreach (var actor in credits.Cast.OrderBy(a => a.Order).Take(TmdbUtils.MaxCastMembers))
+ foreach (var actor in credits.Cast.OrderBy(a => a.Order).Take(Plugin.Instance.Configuration.MaxCastMembers))
{
metadataResult.AddPerson(new PersonInfo
{
@@ -166,7 +169,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
if (credits?.GuestStars != null)
{
- foreach (var guest in credits.GuestStars.OrderBy(a => a.Order).Take(TmdbUtils.MaxCastMembers))
+ foreach (var guest in credits.GuestStars.OrderBy(a => a.Order).Take(Plugin.Instance.Configuration.MaxCastMembers))
{
metadataResult.AddPerson(new PersonInfo
{
@@ -186,8 +189,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
// Normalize this
var type = TmdbUtils.MapCrewToPersonType(person);
- if (!TmdbUtils.WantedCrewTypes.Contains(type, StringComparer.OrdinalIgnoreCase)
- && !TmdbUtils.WantedCrewTypes.Contains(person.Job ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ if (!TmdbUtils.WantedCrewTypes.Contains(type, StringComparison.OrdinalIgnoreCase)
+ && !TmdbUtils.WantedCrewTypes.Contains(person.Job ?? string.Empty, StringComparison.OrdinalIgnoreCase))
{
continue;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs
index 1bda1a09be..4446fa9665 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs
@@ -11,9 +11,7 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Providers;
namespace MediaBrowser.Providers.Plugins.Tmdb.TV
@@ -63,23 +61,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
return Enumerable.Empty<RemoteImageInfo>();
}
- var remoteImages = new RemoteImageInfo[posters.Count];
- for (var i = 0; i < posters.Count; i++)
- {
- var image = posters[i];
- remoteImages[i] = new RemoteImageInfo
- {
- Url = _tmdbClientManager.GetPosterUrl(image.FilePath),
- CommunityRating = image.VoteAverage,
- VoteCount = image.VoteCount,
- Width = image.Width,
- Height = image.Height,
- Language = TmdbUtils.AdjustImageLanguage(image.Iso_639_1, language),
- ProviderName = Name,
- Type = ImageType.Primary,
- RatingType = RatingType.Score
- };
- }
+ var remoteImages = new List<RemoteImageInfo>(posters.Count);
+
+ _tmdbClientManager.ConvertPostersToRemoteImageInfo(posters, language, remoteImages);
return remoteImages;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs
index 66e30115dc..27c52a5a22 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs
@@ -7,6 +7,7 @@ using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
@@ -33,7 +34,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
{
var result = new MetadataResult<Season>();
- info.SeriesProviderIds.TryGetValue(MetadataProvider.Tmdb.ToString(), out string seriesTmdbId);
+ info.SeriesProviderIds.TryGetValue(MetadataProvider.Tmdb.ToString(), out string? seriesTmdbId);
var seasonNumber = info.IndexNumber;
@@ -67,7 +68,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
var credits = seasonResult.Credits;
if (credits?.Cast != null)
{
- var cast = credits.Cast.OrderBy(c => c.Order).Take(TmdbUtils.MaxCastMembers).ToList();
+ var cast = credits.Cast.OrderBy(c => c.Order).Take(Plugin.Instance.Configuration.MaxCastMembers).ToList();
for (var i = 0; i < cast.Count; i++)
{
result.AddPerson(new PersonInfo
@@ -87,8 +88,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
// Normalize this
var type = TmdbUtils.MapCrewToPersonType(person);
- if (!TmdbUtils.WantedCrewTypes.Contains(type, StringComparer.OrdinalIgnoreCase)
- && !TmdbUtils.WantedCrewTypes.Contains(person.Job ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ if (!TmdbUtils.WantedCrewTypes.Contains(type, StringComparison.OrdinalIgnoreCase)
+ && !TmdbUtils.WantedCrewTypes.Contains(person.Job ?? string.Empty, StringComparison.OrdinalIgnoreCase))
{
continue;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesExternalId.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesExternalId.cs
index 6ecc055d71..8a2be80cde 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesExternalId.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesExternalId.cs
@@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
public ExternalIdMediaType? Type => ExternalIdMediaType.Series;
/// <inheritdoc />
- public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "tv/{0}";
+ public string? UrlFormatString => TmdbUtils.BaseTmdbUrl + "tv/{0}";
/// <inheritdoc />
public bool Supports(IHasProviderIds item)
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs
index f3f3403789..5ef3736c4f 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs
@@ -11,7 +11,6 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
@@ -70,41 +69,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
var posters = series.Images.Posters;
var backdrops = series.Images.Backdrops;
+ var remoteImages = new List<RemoteImageInfo>(posters.Count + backdrops.Count);
- var remoteImages = new RemoteImageInfo[posters.Count + backdrops.Count];
-
- for (var i = 0; i < posters.Count; i++)
- {
- var poster = posters[i];
- remoteImages[i] = new RemoteImageInfo
- {
- Url = _tmdbClientManager.GetPosterUrl(poster.FilePath),
- CommunityRating = poster.VoteAverage,
- VoteCount = poster.VoteCount,
- Width = poster.Width,
- Height = poster.Height,
- Language = TmdbUtils.AdjustImageLanguage(poster.Iso_639_1, language),
- ProviderName = Name,
- Type = ImageType.Primary,
- RatingType = RatingType.Score
- };
- }
-
- for (var i = 0; i < backdrops.Count; i++)
- {
- var backdrop = series.Images.Backdrops[i];
- remoteImages[posters.Count + i] = new RemoteImageInfo
- {
- Url = _tmdbClientManager.GetBackdropUrl(backdrop.FilePath),
- CommunityRating = backdrop.VoteAverage,
- VoteCount = backdrop.VoteCount,
- Width = backdrop.Width,
- Height = backdrop.Height,
- ProviderName = Name,
- Type = ImageType.Backdrop,
- RatingType = RatingType.Score
- };
- }
+ _tmdbClientManager.ConvertPostersToRemoteImageInfo(posters, language, remoteImages);
+ _tmdbClientManager.ConvertBackdropsToRemoteImageInfo(backdrops, language, remoteImages);
return remoteImages;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs
index da76345b5b..f565b65698 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs
@@ -1,3 +1,5 @@
+#nullable disable
+
#pragma warning disable CS1591
using System;
@@ -7,6 +9,7 @@ using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
@@ -329,7 +332,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
{
if (seriesResult.Credits?.Cast != null)
{
- foreach (var actor in seriesResult.Credits.Cast.OrderBy(a => a.Order).Take(TmdbUtils.MaxCastMembers))
+ foreach (var actor in seriesResult.Credits.Cast.OrderBy(a => a.Order).Take(Plugin.Instance.Configuration.MaxCastMembers))
{
var personInfo = new PersonInfo
{
@@ -363,8 +366,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
// Normalize this
var type = TmdbUtils.MapCrewToPersonType(person);
- if (!keepTypes.Contains(type, StringComparer.OrdinalIgnoreCase)
- && !keepTypes.Contains(person.Job ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ if (!keepTypes.Contains(type, StringComparison.OrdinalIgnoreCase)
+ && !keepTypes.Contains(person.Job ?? string.Empty, StringComparison.OrdinalIgnoreCase))
{
continue;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs
index 5bd5dd2e80..28d6f4d0c1 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs
@@ -1,8 +1,13 @@
-using System;
+#nullable disable
+
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
using Microsoft.Extensions.Caching.Memory;
using TMDbLib.Client;
using TMDbLib.Objects.Collections;
@@ -55,11 +60,17 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
await EnsureClientConfigAsync().ConfigureAwait(false);
+ var extraMethods = MovieMethods.Credits | MovieMethods.Releases | MovieMethods.Images | MovieMethods.Videos;
+ if (!(Plugin.Instance?.Configuration.ExcludeTagsMovies).GetValueOrDefault())
+ {
+ extraMethods |= MovieMethods.Keywords;
+ }
+
movie = await _tmDbClient.GetMovieAsync(
tmdbId,
TmdbUtils.NormalizeLanguage(language),
imageLanguages,
- MovieMethods.Credits | MovieMethods.Releases | MovieMethods.Images | MovieMethods.Keywords | MovieMethods.Videos,
+ extraMethods,
cancellationToken).ConfigureAwait(false);
if (movie != null)
@@ -121,11 +132,17 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
await EnsureClientConfigAsync().ConfigureAwait(false);
+ var extraMethods = TvShowMethods.Credits | TvShowMethods.Images | TvShowMethods.ExternalIds | TvShowMethods.Videos | TvShowMethods.ContentRatings | TvShowMethods.EpisodeGroups;
+ if (!(Plugin.Instance?.Configuration.ExcludeTagsSeries).GetValueOrDefault())
+ {
+ extraMethods |= TvShowMethods.Keywords;
+ }
+
series = await _tmDbClient.GetTvShowAsync(
tmdbId,
language: TmdbUtils.NormalizeLanguage(language),
includeImageLanguage: imageLanguages,
- extraMethods: TvShowMethods.Credits | TvShowMethods.Images | TvShowMethods.Keywords | TvShowMethods.ExternalIds | TvShowMethods.Videos | TvShowMethods.ContentRatings | TvShowMethods.EpisodeGroups,
+ extraMethods: extraMethods,
cancellationToken: cancellationToken).ConfigureAwait(false);
if (series != null)
@@ -469,33 +486,29 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
}
/// <summary>
- /// Gets the absolute URL of the poster.
+ /// Handles bad path checking and builds the absolute url.
/// </summary>
- /// <param name="posterPath">The relative URL of the poster.</param>
+ /// <param name="size">The image size to fetch.</param>
+ /// <param name="path">The relative URL of the image.</param>
/// <returns>The absolute URL.</returns>
- public string GetPosterUrl(string posterPath)
+ private string GetUrl(string size, string path)
{
- if (string.IsNullOrEmpty(posterPath))
+ if (string.IsNullOrEmpty(path))
{
return null;
}
- return _tmDbClient.GetImageUrl(_tmDbClient.Config.Images.PosterSizes[^1], posterPath).ToString();
+ return _tmDbClient.GetImageUrl(size, path, true).ToString();
}
/// <summary>
- /// Gets the absolute URL of the backdrop image.
+ /// Gets the absolute URL of the poster.
/// </summary>
- /// <param name="posterPath">The relative URL of the backdrop image.</param>
+ /// <param name="posterPath">The relative URL of the poster.</param>
/// <returns>The absolute URL.</returns>
- public string GetBackdropUrl(string posterPath)
+ public string GetPosterUrl(string posterPath)
{
- if (string.IsNullOrEmpty(posterPath))
- {
- return null;
- }
-
- return _tmDbClient.GetImageUrl(_tmDbClient.Config.Images.BackdropSizes[^1], posterPath).ToString();
+ return GetUrl(Plugin.Instance.Configuration.PosterSize, posterPath);
}
/// <summary>
@@ -505,32 +518,130 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
/// <returns>The absolute URL.</returns>
public string GetProfileUrl(string actorProfilePath)
{
- if (string.IsNullOrEmpty(actorProfilePath))
- {
- return null;
- }
+ return GetUrl(Plugin.Instance.Configuration.ProfileSize, actorProfilePath);
+ }
- return _tmDbClient.GetImageUrl(_tmDbClient.Config.Images.ProfileSizes[^1], actorProfilePath).ToString();
+ /// <summary>
+ /// Converts poster <see cref="ImageData"/>s into <see cref="RemoteImageInfo"/>s.
+ /// </summary>
+ /// <param name="images">The input images.</param>
+ /// <param name="requestLanguage">The requested language.</param>
+ /// <param name="results">The collection to add the remote images into.</param>
+ public void ConvertPostersToRemoteImageInfo(List<ImageData> images, string requestLanguage, List<RemoteImageInfo> results)
+ {
+ ConvertToRemoteImageInfo(images, Plugin.Instance.Configuration.PosterSize, ImageType.Primary, requestLanguage, results);
}
/// <summary>
- /// Gets the absolute URL of the still image.
+ /// Converts backdrop <see cref="ImageData"/>s into <see cref="RemoteImageInfo"/>s.
/// </summary>
- /// <param name="filePath">The relative URL of the still image.</param>
- /// <returns>The absolute URL.</returns>
- public string GetStillUrl(string filePath)
+ /// <param name="images">The input images.</param>
+ /// <param name="requestLanguage">The requested language.</param>
+ /// <param name="results">The collection to add the remote images into.</param>
+ public void ConvertBackdropsToRemoteImageInfo(List<ImageData> images, string requestLanguage, List<RemoteImageInfo> results)
+ {
+ ConvertToRemoteImageInfo(images, Plugin.Instance.Configuration.BackdropSize, ImageType.Backdrop, requestLanguage, results);
+ }
+
+ /// <summary>
+ /// Converts profile <see cref="ImageData"/>s into <see cref="RemoteImageInfo"/>s.
+ /// </summary>
+ /// <param name="images">The input images.</param>
+ /// <param name="requestLanguage">The requested language.</param>
+ /// <param name="results">The collection to add the remote images into.</param>
+ public void ConvertProfilesToRemoteImageInfo(List<ImageData> images, string requestLanguage, List<RemoteImageInfo> results)
+ {
+ ConvertToRemoteImageInfo(images, Plugin.Instance.Configuration.ProfileSize, ImageType.Primary, requestLanguage, results);
+ }
+
+ /// <summary>
+ /// Converts still <see cref="ImageData"/>s into <see cref="RemoteImageInfo"/>s.
+ /// </summary>
+ /// <param name="images">The input images.</param>
+ /// <param name="requestLanguage">The requested language.</param>
+ /// <param name="results">The collection to add the remote images into.</param>
+ public void ConvertStillsToRemoteImageInfo(List<ImageData> images, string requestLanguage, List<RemoteImageInfo> results)
{
- if (string.IsNullOrEmpty(filePath))
+ ConvertToRemoteImageInfo(images, Plugin.Instance.Configuration.StillSize, ImageType.Primary, requestLanguage, results);
+ }
+
+ /// <summary>
+ /// Converts <see cref="ImageData"/>s into <see cref="RemoteImageInfo"/>s.
+ /// </summary>
+ /// <param name="images">The input images.</param>
+ /// <param name="size">The size of the image to fetch.</param>
+ /// <param name="type">The type of the image.</param>
+ /// <param name="requestLanguage">The requested language.</param>
+ /// <param name="results">The collection to add the remote images into.</param>
+ private void ConvertToRemoteImageInfo(List<ImageData> images, string size, ImageType type, string requestLanguage, List<RemoteImageInfo> results)
+ {
+ // sizes provided are for original resolution, don't store them when downloading scaled images
+ var scaleImage = !string.Equals(size, "original", StringComparison.OrdinalIgnoreCase);
+
+ for (var i = 0; i < images.Count; i++)
{
- return null;
+ var image = images[i];
+
+ results.Add(new RemoteImageInfo
+ {
+ Url = GetUrl(size, image.FilePath),
+ CommunityRating = image.VoteAverage,
+ VoteCount = image.VoteCount,
+ Width = scaleImage ? null : image.Width,
+ Height = scaleImage ? null : image.Height,
+ Language = TmdbUtils.AdjustImageLanguage(image.Iso_639_1, requestLanguage),
+ ProviderName = TmdbUtils.ProviderName,
+ Type = type,
+ RatingType = RatingType.Score
+ });
+ }
+ }
+
+ private async Task EnsureClientConfigAsync()
+ {
+ if (!_tmDbClient.HasConfig)
+ {
+ var config = await _tmDbClient.GetConfigAsync().ConfigureAwait(false);
+ ValidatePreferences(config);
+ }
+ }
+
+ private static void ValidatePreferences(TMDbConfig config)
+ {
+ var imageConfig = config.Images;
+
+ var pluginConfig = Plugin.Instance.Configuration;
+
+ if (!imageConfig.PosterSizes.Contains(pluginConfig.PosterSize))
+ {
+ pluginConfig.PosterSize = imageConfig.PosterSizes[^1];
}
- return _tmDbClient.GetImageUrl(_tmDbClient.Config.Images.StillSizes[^1], filePath).ToString();
+ if (!imageConfig.BackdropSizes.Contains(pluginConfig.BackdropSize))
+ {
+ pluginConfig.BackdropSize = imageConfig.BackdropSizes[^1];
+ }
+
+ if (!imageConfig.ProfileSizes.Contains(pluginConfig.ProfileSize))
+ {
+ pluginConfig.ProfileSize = imageConfig.ProfileSizes[^1];
+ }
+
+ if (!imageConfig.StillSizes.Contains(pluginConfig.StillSize))
+ {
+ pluginConfig.StillSize = imageConfig.StillSizes[^1];
+ }
}
- private Task EnsureClientConfigAsync()
+ /// <summary>
+ /// Gets the <see cref="TMDbClient"/> configuration.
+ /// </summary>
+ /// <returns>The configuration.</returns>
+ public async Task<TMDbConfig> GetClientConfiguration()
{
- return !_tmDbClient.HasConfig ? _tmDbClient.GetConfigAsync() : Task.CompletedTask;
+ await EnsureClientConfigAsync().ConfigureAwait(false);
+
+ return _tmDbClient.Config;
}
/// <inheritdoc />
@@ -540,7 +651,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
GC.SuppressFinalize(this);
}
-/// <summary>
+ /// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs b/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs
index b713736a0f..234d717bfb 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs
@@ -1,5 +1,3 @@
-#nullable enable
-
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
@@ -13,7 +11,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
/// </summary>
public static class TmdbUtils
{
- private static readonly Regex _nonWords = new (@"[\W_]+", RegexOptions.Compiled);
+ private static readonly Regex _nonWords = new(@"[\W_]+", RegexOptions.Compiled);
/// <summary>
/// URL of the TMDB instance to use.
@@ -31,11 +29,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
public const string ApiKey = "4219e299c89411838049ab0dab19ebd5";
/// <summary>
- /// Maximum number of cast members to pull.
- /// </summary>
- public const int MaxCastMembers = 15;
-
- /// <summary>
/// The crew types to keep.
/// </summary>
public static readonly string[] WantedCrewTypes =