diff --git a/Jellyfin.Plugin.Tvdb/ProviderIdsExtensions.cs b/Jellyfin.Plugin.Tvdb/ProviderIdsExtensions.cs
new file mode 100644
index 0000000..bed1a30
--- /dev/null
+++ b/Jellyfin.Plugin.Tvdb/ProviderIdsExtensions.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Globalization;
+
+using MediaBrowser.Model.Entities;
+
+namespace Jellyfin.Plugin.Tvdb;
+
+internal static class ProviderIdsExtensions
+{
+ ///
+ /// Check whether an item includes an entry for any supported provider IDs.
+ ///
+ /// The .
+ /// True, if contains any supported provider IDs.
+ internal static bool IsSupported(this IHasProviderIds? item)
+ {
+ return HasProviderId(item, MetadataProvider.Tvdb)
+ || HasProviderId(item, MetadataProvider.Imdb)
+ || HasProviderId(item, MetadataProvider.Zap2It);
+ }
+
+ ///
+ /// Get the TvDB id stored within the item.
+ ///
+ /// The item to get the TvDB id from.
+ /// The Id, or 0.
+ public static int GetTvdbId(this IHasProviderIds item)
+ => Convert.ToInt32(item.GetProviderId(TvdbPlugin.ProviderId), CultureInfo.InvariantCulture);
+
+ ///
+ public static void SetTvdbId(this IHasProviderIds item, long? value)
+ => SetTvdbId(item, value.HasValue && value > 0 ? value.Value.ToString(CultureInfo.InvariantCulture) : null);
+
+ ///
+ /// Set the TvDB id in the item, if provided is not or white space.
+ ///
+ /// >The to set the TvDB id.
+ /// TvDB id to set.
+ /// if value was set.
+ public static bool SetTvdbId(this IHasProviderIds item, string? value)
+ => SetProviderIdIfHasValue(item, TvdbPlugin.ProviderId, value);
+
+ ///
+ public static bool SetProviderIdIfHasValue(this IHasProviderIds item, MetadataProvider provider, string? value)
+ => SetProviderIdIfHasValue(item, provider.ToString(), value);
+
+ ///
+ /// Set the provider id in the item, if provided is not or white space.
+ ///
+ /// >The to set the TvDB id.
+ /// Provider name.
+ /// Provider id to set.
+ /// if value was set.
+ public static bool SetProviderIdIfHasValue(this IHasProviderIds item, string name, string? value)
+ {
+ if (!HasValue(value))
+ {
+ return false;
+ }
+
+ item.SetProviderId(name, value);
+ return true;
+ }
+
+ ///
+ /// Checks whether the item has TvDB Id stored.
+ ///
+ /// The item.
+ /// True, if item has TvDB Id stored.
+ public static bool HasTvdbId(this IHasProviderIds? item)
+ => HasTvdbId(item, out var value);
+
+ ///
+ public static bool HasTvdbId(this IHasProviderIds? item, out string? value)
+ => HasProviderId(item, TvdbPlugin.ProviderId, out value);
+
+ ///
+ public static bool HasProviderId(this IHasProviderIds? item, MetadataProvider provider)
+ => HasProviderId(item, provider, out var value);
+
+ ///
+ public static bool HasProviderId(this IHasProviderIds? item, MetadataProvider provider, out string? value)
+ => HasProviderId(item, provider.ToString(), out value);
+
+ ///
+ /// Checks whether the item has provider id stored.
+ ///
+ /// The item.
+ /// Provider.
+ /// True, if item has provider id stored.
+ public static bool HasProviderId(this IHasProviderIds? item, string name)
+ => HasProviderId(item, name, out var value);
+
+ ///
+ /// Checks whether the item has provider id stored.
+ ///
+ /// The item.
+ /// Provider.
+ /// The current provider id value.
+ /// True, if item has provider id stored.
+ public static bool HasProviderId(this IHasProviderIds? item, string name, out string? value)
+ {
+ value = null;
+ var result = item is { }
+ && item.TryGetProviderId(name, out value)
+ && HasValue(value);
+
+ value = result ? value : null;
+ return result;
+ }
+
+ private static bool HasValue(string? value)
+ => !string.IsNullOrWhiteSpace(value);
+}
diff --git a/Jellyfin.Plugin.Tvdb/Providers/TvdbEpisodeImageProvider.cs b/Jellyfin.Plugin.Tvdb/Providers/TvdbEpisodeImageProvider.cs
index 878738d..edaccb6 100644
--- a/Jellyfin.Plugin.Tvdb/Providers/TvdbEpisodeImageProvider.cs
+++ b/Jellyfin.Plugin.Tvdb/Providers/TvdbEpisodeImageProvider.cs
@@ -58,7 +58,7 @@ public async Task> GetImages(BaseItem item, Cancell
var series = episode.Series;
var imageResult = new List();
var language = item.GetPreferredMetadataLanguage();
- if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
+ if (series.IsSupported())
{
// Process images
try
@@ -85,7 +85,7 @@ public async Task> GetImages(BaseItem item, Cancell
"Episode {SeasonNumber}x{EpisodeNumber} not found for series {SeriesTvdbId}:{Name}",
episode.ParentIndexNumber,
episode.IndexNumber,
- series.GetProviderId(TvdbPlugin.ProviderId),
+ series.GetTvdbId(),
series.Name);
return imageResult;
}
@@ -99,7 +99,7 @@ await _tvdbClientManager
}
catch (Exception e)
{
- _logger.LogError(e, "Failed to retrieve episode images for series {TvDbId}:{Name}", series.GetProviderId(TvdbPlugin.ProviderId), series.Name);
+ _logger.LogError(e, "Failed to retrieve episode images for series {TvDbId}:{Name}", series.GetTvdbId(), series.Name);
}
}
diff --git a/Jellyfin.Plugin.Tvdb/Providers/TvdbEpisodeProvider.cs b/Jellyfin.Plugin.Tvdb/Providers/TvdbEpisodeProvider.cs
index 73621b2..c09f2ce 100644
--- a/Jellyfin.Plugin.Tvdb/Providers/TvdbEpisodeProvider.cs
+++ b/Jellyfin.Plugin.Tvdb/Providers/TvdbEpisodeProvider.cs
@@ -50,7 +50,7 @@ public async Task> GetSearchResults(EpisodeInfo
// Either an episode number or date must be provided; and the dictionary of provider ids must be valid
if ((searchInfo.IndexNumber == null && searchInfo.PremiereDate == null)
- || !TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds))
+ || !searchInfo.IsSupported())
{
return list;
}
@@ -82,32 +82,26 @@ public async Task> GetSearchResults(EpisodeInfo
///
public async Task> GetMetadata(EpisodeInfo info, CancellationToken cancellationToken)
{
- var result = new MetadataResult
- {
- QueriedById = true
- };
-
- if (TvdbSeriesProvider.IsValidSeries(info.SeriesProviderIds) &&
- (info.IndexNumber.HasValue || info.PremiereDate.HasValue))
+ if ((info.IndexNumber == null && info.PremiereDate == null)
+ || !info.IsSupported())
{
- // Check for multiple episodes per file, if not run one query.
- if (info.IndexNumberEnd.HasValue)
+ _logger.LogDebug("No series identity found for {EpisodeName}", info.Name);
+ return new MetadataResult
{
- _logger.LogDebug("Multiple episodes found in {Path}", info.Path);
+ QueriedById = true
+ };
+ }
- result = await GetCombinedEpisode(info, cancellationToken).ConfigureAwait(false);
- }
- else
- {
- result = await GetEpisode(info, cancellationToken).ConfigureAwait(false);
- }
+ // Check for multiple episodes per file, if not run one query.
+ if (info.IndexNumberEnd.HasValue)
+ {
+ _logger.LogDebug("Multiple episodes found in {Path}", info.Path);
+ return await GetCombinedEpisode(info, cancellationToken).ConfigureAwait(false);
}
else
{
- _logger.LogDebug("No series identity found for {EpisodeName}", info.Name);
+ return await GetEpisode(info, cancellationToken).ConfigureAwait(false);
}
-
- return result;
}
private async Task> GetCombinedEpisode(EpisodeInfo info, CancellationToken cancellationToken)
@@ -159,7 +153,6 @@ private async Task> GetEpisode(EpisodeInfo searchInfo, C
QueriedById = true
};
- var seriesTvdbId = searchInfo.SeriesProviderIds.FirstOrDefault(x => x.Key == TvdbPlugin.ProviderId).Value;
string? episodeTvdbId = null;
try
{
@@ -172,7 +165,7 @@ private async Task> GetEpisode(EpisodeInfo searchInfo, C
"Episode S{Season:00}E{Episode:00} not found for series {SeriesTvdbId}:{Name}",
searchInfo.ParentIndexNumber,
searchInfo.IndexNumber,
- seriesTvdbId,
+ searchInfo.GetTvdbId(),
searchInfo.Name);
return result;
}
@@ -190,7 +183,7 @@ private async Task> GetEpisode(EpisodeInfo searchInfo, C
e,
"Failed to retrieve episode with id {EpisodeTvDbId}, series id {SeriesTvdbId}:{Name}",
episodeTvdbId,
- seriesTvdbId,
+ searchInfo.GetTvdbId(),
searchInfo.Name);
}
@@ -220,12 +213,9 @@ private static MetadataResult MapEpisodeToResult(EpisodeInfo id, Episod
result.ResetPeople();
var item = result.Item;
- item.SetProviderId(TvdbPlugin.ProviderId, episode.Id.GetValueOrDefault().ToString(CultureInfo.InvariantCulture));
+ item.SetTvdbId(episode.Id);
var imdbID = episode.RemoteIds.FirstOrDefault(x => string.Equals(x.SourceName, "IMDB", StringComparison.OrdinalIgnoreCase))?.Id;
- if (!string.IsNullOrEmpty(imdbID))
- {
- item.SetProviderId(MetadataProvider.Imdb, imdbID);
- }
+ item.SetProviderIdIfHasValue(MetadataProvider.Imdb, imdbID);
if (string.Equals(id.SeriesDisplayOrder, "dvd", StringComparison.OrdinalIgnoreCase))
{
diff --git a/Jellyfin.Plugin.Tvdb/Providers/TvdbMissingEpisodeProvider.cs b/Jellyfin.Plugin.Tvdb/Providers/TvdbMissingEpisodeProvider.cs
index 9b468cf..d3886cd 100644
--- a/Jellyfin.Plugin.Tvdb/Providers/TvdbMissingEpisodeProvider.cs
+++ b/Jellyfin.Plugin.Tvdb/Providers/TvdbMissingEpisodeProvider.cs
@@ -102,7 +102,8 @@ private static bool EpisodeExists(EpisodeBaseRecord episodeRecord, IReadOnlyList
private static bool EpisodeEquals(Episode episode, EpisodeBaseRecord otherEpisodeRecord)
{
- return episode.ContainsEpisodeNumber(otherEpisodeRecord.Number.GetValueOrDefault())
+ return otherEpisodeRecord.Number.HasValue
+ && episode.ContainsEpisodeNumber(otherEpisodeRecord.Number.Value)
&& episode.ParentIndexNumber == otherEpisodeRecord.SeasonNumber;
}
@@ -155,13 +156,13 @@ private void OnProviderManagerRefreshComplete(object? sender, GenericEventArgs();
@@ -191,7 +192,8 @@ private async Task HandleSeries(Series series)
var allEpisodes = await GetAllEpisodes(tvdbId, series.GetPreferredMetadataLanguage()).ConfigureAwait(false);
var allSeasons = allEpisodes
- .Select(ep => ep.SeasonNumber.GetValueOrDefault())
+ .Where(ep => ep.SeasonNumber.HasValue)
+ .Select(ep => ep.SeasonNumber!.Value)
.Distinct()
.ToList();
@@ -202,14 +204,14 @@ private async Task HandleSeries(Series series)
private async Task HandleSeason(Season season)
{
- if (season.Series == null
- || !season.Series.TryGetProviderId(MetadataProvider.Tvdb.ToString(), out var tvdbIdTxt))
+ var series = season.Series;
+ if (series.HasTvdbId())
{
_logger.LogDebug("No TVDB Id available.");
return;
}
- var tvdbId = Convert.ToInt32(tvdbIdTxt, CultureInfo.InvariantCulture);
+ var tvdbId = series.GetTvdbId();
var allEpisodes = await GetAllEpisodes(tvdbId, season.GetPreferredMetadataLanguage())
.ConfigureAwait(false);
@@ -321,14 +323,13 @@ private void OnLibraryManagerItemRemoved(object? sender, ItemChangeEventArgs ite
}
else if (itemChangeEventArgs.Item is Episode episode)
{
- if (episode.Series == null
- || !episode.Series.TryGetProviderId(MetadataProvider.Tvdb.ToString(), out var tvdbIdTxt))
+ if (!episode.Series.HasTvdbId())
{
_logger.LogDebug("No TVDB Id available.");
return;
}
- var tvdbId = Convert.ToInt32(tvdbIdTxt, CultureInfo.InvariantCulture);
+ var tvdbId = episode.Series.GetTvdbId();
var episodeRecords = GetAllEpisodes(tvdbId, episode.GetPreferredMetadataLanguage()).GetAwaiter().GetResult();
@@ -385,7 +386,8 @@ private void AddMissingEpisodes(
var episodeRecord = allEpisodeRecords[i];
// skip if it exists already
- if (existingEpisodes.TryGetValue(episodeRecord.SeasonNumber.GetValueOrDefault(), out var episodes)
+ if (episodeRecord.SeasonNumber.HasValue
+ && existingEpisodes.TryGetValue(episodeRecord.SeasonNumber.Value, out var episodes)
&& EpisodeExists(episodeRecord, episodes))
{
_logger.LogDebug("{MethodName}: Skip, already existing S{Season:00}E{Episode:00}", nameof(AddMissingEpisodes), episodeRecord.SeasonNumber, episodeRecord.Number);
@@ -435,7 +437,7 @@ private Season AddVirtualSeason(int season, Series series)
private void AddVirtualEpisode(EpisodeBaseRecord? episode, Season? season)
{
- if (episode == null || season == null)
+ if (episode?.SeasonNumber == null || season == null)
{
return;
}
@@ -447,7 +449,7 @@ private void AddVirtualEpisode(EpisodeBaseRecord? episode, Season? season)
IndexNumber = episode.Number,
ParentIndexNumber = episode.SeasonNumber,
Id = _libraryManager.GetNewItemId(
- season.Series.Id + episode.SeasonNumber.GetValueOrDefault().ToString(CultureInfo.InvariantCulture) + "Episode " + episode.Number,
+ $"{season.Series.Id}{episode.SeasonNumber}Episode {episode.Number}",
typeof(Episode)),
IsVirtualItem = true,
SeasonId = season.Id,
@@ -467,7 +469,7 @@ private void AddVirtualEpisode(EpisodeBaseRecord? episode, Season? season)
}
newEpisode.PresentationUniqueKey = newEpisode.GetPresentationUniqueKey();
- newEpisode.SetProviderId(MetadataProvider.Tvdb, episode.Id.GetValueOrDefault().ToString(CultureInfo.InvariantCulture));
+ newEpisode.SetTvdbId(episode.Id);
_logger.LogDebug(
"Creating virtual episode {SeriesName} S{Season:00}E{Episode:00}",
diff --git a/Jellyfin.Plugin.Tvdb/Providers/TvdbPersonImageProvider.cs b/Jellyfin.Plugin.Tvdb/Providers/TvdbPersonImageProvider.cs
index 480e640..6becb20 100644
--- a/Jellyfin.Plugin.Tvdb/Providers/TvdbPersonImageProvider.cs
+++ b/Jellyfin.Plugin.Tvdb/Providers/TvdbPersonImageProvider.cs
@@ -72,7 +72,7 @@ public async Task> GetImages(BaseItem item, Cancell
EnableImages = false
}
}).Cast()
- .Where(i => TvdbSeriesProvider.IsValidSeries(i.ProviderIds))
+ .Where(i => i.IsSupported())
.ToList();
var infos = (await Task.WhenAll(seriesWithPerson.Select(async i =>
@@ -93,7 +93,7 @@ public Task GetImageResponse(string url, CancellationToken
private async Task GetImageFromSeriesData(Series series, string personName, CancellationToken cancellationToken)
{
- var tvdbId = Convert.ToInt32(series.GetProviderId(TvdbPlugin.ProviderId), CultureInfo.InvariantCulture);
+ var tvdbId = series.GetTvdbId();
try
{
diff --git a/Jellyfin.Plugin.Tvdb/Providers/TvdbSeasonImageProvider.cs b/Jellyfin.Plugin.Tvdb/Providers/TvdbSeasonImageProvider.cs
index 7a04702..4d37006 100644
--- a/Jellyfin.Plugin.Tvdb/Providers/TvdbSeasonImageProvider.cs
+++ b/Jellyfin.Plugin.Tvdb/Providers/TvdbSeasonImageProvider.cs
@@ -69,7 +69,7 @@ public async Task> GetImages(BaseItem item, Cancell
var season = (Season)item;
var series = season.Series;
- if (series == null || !season.IndexNumber.HasValue || !TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
+ if (!series.IsSupported() || season.IndexNumber is null)
{
return Enumerable.Empty();
}
@@ -83,9 +83,10 @@ public async Task> GetImages(BaseItem item, Cancell
.ConfigureAwait(false);
var seasonArtworkTypeLookup = artworkTypes
.Where(t => string.Equals(t.RecordType, "season", StringComparison.OrdinalIgnoreCase))
- .ToDictionary(t => t.Id);
+ .Where(t => t.Id.HasValue)
+ .ToDictionary(t => t.Id!.Value);
- var seriesTvdbId = Convert.ToInt32(series.GetProviderId(TvdbPlugin.ProviderId), CultureInfo.InvariantCulture);
+ var seriesTvdbId = series.GetTvdbId();
var seasonNumber = season.IndexNumber.Value;
var seasonArtworks = await GetSeasonArtworks(seriesTvdbId, seasonNumber, cancellationToken)
@@ -94,7 +95,7 @@ public async Task> GetImages(BaseItem item, Cancell
var remoteImages = new List();
foreach (var artwork in seasonArtworks)
{
- var artworkType = seasonArtworkTypeLookup.GetValueOrDefault(artwork.Type);
+ var artworkType = artwork.Type is null ? null : seasonArtworkTypeLookup.GetValueOrDefault(artwork.Type!.Value);
var imageType = artworkType.GetImageType();
var artworkLanguage = artwork.Language is null ? null : languageLookup.GetValueOrDefault(artwork.Language);
diff --git a/Jellyfin.Plugin.Tvdb/Providers/TvdbSeriesImageProvider.cs b/Jellyfin.Plugin.Tvdb/Providers/TvdbSeriesImageProvider.cs
index 1ffa445..1e39591 100644
--- a/Jellyfin.Plugin.Tvdb/Providers/TvdbSeriesImageProvider.cs
+++ b/Jellyfin.Plugin.Tvdb/Providers/TvdbSeriesImageProvider.cs
@@ -66,7 +66,7 @@ public IEnumerable GetSupportedImages(BaseItem item)
///
public async Task> GetImages(BaseItem item, CancellationToken cancellationToken)
{
- if (!TvdbSeriesProvider.IsValidSeries(item.ProviderIds))
+ if (!item.IsSupported())
{
return Enumerable.Empty();
}
@@ -80,16 +80,17 @@ public async Task> GetImages(BaseItem item, Cancell
.ConfigureAwait(false);
var seriesArtworkTypeLookup = artworkTypes
.Where(t => string.Equals(t.RecordType, "series", StringComparison.OrdinalIgnoreCase))
- .ToDictionary(t => t.Id);
+ .Where(t => t.Id.HasValue)
+ .ToDictionary(t => t.Id!.Value);
- var seriesTvdbId = Convert.ToInt32(item.GetProviderId(TvdbPlugin.ProviderId), CultureInfo.InvariantCulture);
+ var seriesTvdbId = item.GetTvdbId();
var seriesArtworks = await GetSeriesArtworks(seriesTvdbId, cancellationToken)
.ConfigureAwait(false);
var remoteImages = new List();
foreach (var artwork in seriesArtworks)
{
- var artworkType = seriesArtworkTypeLookup.GetValueOrDefault(artwork.Type);
+ var artworkType = artwork.Type is null ? null : seriesArtworkTypeLookup.GetValueOrDefault(artwork.Type!.Value);
var imageType = artworkType.GetImageType();
var artworkLanguage = artwork.Language is null ? null : languageLookup.GetValueOrDefault(artwork.Language);
diff --git a/Jellyfin.Plugin.Tvdb/Providers/TvdbSeriesProvider.cs b/Jellyfin.Plugin.Tvdb/Providers/TvdbSeriesProvider.cs
index 4bab013..821f837 100644
--- a/Jellyfin.Plugin.Tvdb/Providers/TvdbSeriesProvider.cs
+++ b/Jellyfin.Plugin.Tvdb/Providers/TvdbSeriesProvider.cs
@@ -52,7 +52,7 @@ public TvdbSeriesProvider(IHttpClientFactory httpClientFactory, ILogger
public async Task> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
{
- if (IsValidSeries(searchInfo.ProviderIds))
+ if (searchInfo.IsSupported())
{
return await FetchSeriesSearchResult(searchInfo, cancellationToken).ConfigureAwait(false);
}
@@ -68,7 +68,7 @@ public async Task> GetMetadata(SeriesInfo info, Cancellat
QueriedById = true,
};
- if (!IsValidSeries(info.ProviderIds))
+ if (!info.IsSupported())
{
result.QueriedById = false;
await Identify(info).ConfigureAwait(false);
@@ -76,7 +76,7 @@ public async Task> GetMetadata(SeriesInfo info, Cancellat
cancellationToken.ThrowIfCancellationRequested();
- if (IsValidSeries(info.ProviderIds))
+ if (info.IsSupported())
{
result.Item = new Series();
result.HasMetadata = true;
@@ -94,65 +94,48 @@ public Task GetImageResponse(string url, CancellationToken
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(new Uri(url), cancellationToken);
}
- ///
- /// Check whether a dictionary of provider IDs includes an entry for a valid TV metadata provider.
- ///
- /// The provider IDs to check.
- /// True, if the series contains a valid TV provider ID, otherwise false.
- internal static bool IsValidSeries(Dictionary ids)
- {
- return (ids.TryGetValue(MetadataProvider.Tvdb.ToString(), out var tvdbId) && !string.IsNullOrEmpty(tvdbId))
- || (ids.TryGetValue(MetadataProvider.Imdb.ToString(), out var imdbId) && !string.IsNullOrEmpty(imdbId))
- || (ids.TryGetValue(MetadataProvider.Zap2It.ToString(), out var zap2ItId) && !string.IsNullOrEmpty(zap2ItId));
- }
-
private async Task> FetchSeriesSearchResult(SeriesInfo seriesInfo, CancellationToken cancellationToken)
{
- var tvdbId = seriesInfo.GetProviderId(MetadataProvider.Tvdb);
- if (string.IsNullOrEmpty(tvdbId))
+ async Task TryGetTvdbIdWithRemoteId(MetadataProvider metadataProvider)
{
- var imdbId = seriesInfo.GetProviderId(MetadataProvider.Imdb);
- if (!string.IsNullOrEmpty(imdbId))
+ var id = seriesInfo.GetProviderId(metadataProvider);
+ if (string.IsNullOrEmpty(id))
{
- tvdbId = await GetSeriesByRemoteId(
- imdbId,
- seriesInfo.MetadataLanguage,
- seriesInfo.Name,
- cancellationToken).ConfigureAwait(false);
+ return null;
}
+
+ return await GetSeriesByRemoteId(
+ id,
+ seriesInfo.MetadataLanguage,
+ seriesInfo.Name,
+ cancellationToken).ConfigureAwait(false);
}
- if (string.IsNullOrEmpty(tvdbId))
+ int? tvdbId;
+ if (seriesInfo.HasTvdbId())
{
- var zap2ItId = seriesInfo.GetProviderId(MetadataProvider.Zap2It);
- if (!string.IsNullOrEmpty(zap2ItId))
- {
- tvdbId = await GetSeriesByRemoteId(
- zap2ItId,
- seriesInfo.MetadataLanguage,
- seriesInfo.Name,
- cancellationToken).ConfigureAwait(false);
- }
+ tvdbId = seriesInfo.GetTvdbId();
+ }
+ else
+ {
+ var tvdbIdTxt = await TryGetTvdbIdWithRemoteId(MetadataProvider.Imdb).ConfigureAwait(false)
+ ?? await TryGetTvdbIdWithRemoteId(MetadataProvider.Zap2It).ConfigureAwait(false)
+ ?? await TryGetTvdbIdWithRemoteId(MetadataProvider.Tmdb).ConfigureAwait(false);
+
+ tvdbId = tvdbIdTxt is null ? null : Convert.ToInt32(tvdbIdTxt, CultureInfo.InvariantCulture);
}
- if (string.IsNullOrEmpty(tvdbId))
+ if (!tvdbId.HasValue)
{
- var tmdbId = seriesInfo.GetProviderId(MetadataProvider.Tmdb);
- if (!string.IsNullOrEmpty(tmdbId))
- {
- tvdbId = await GetSeriesByRemoteId(
- tmdbId,
- seriesInfo.MetadataLanguage,
- seriesInfo.Name,
- cancellationToken).ConfigureAwait(false);
- }
+ _logger.LogWarning("No valid tvdb id found for series {TvdbId}:{SeriesName}", tvdbId, seriesInfo.Name);
+ return Array.Empty();
}
try
{
var seriesResult =
await _tvdbClientManager
- .GetSeriesExtendedByIdAsync(Convert.ToInt32(tvdbId, CultureInfo.InvariantCulture), seriesInfo.MetadataLanguage, cancellationToken, small: true)
+ .GetSeriesExtendedByIdAsync(tvdbId.Value, seriesInfo.MetadataLanguage, cancellationToken, small: true)
.ConfigureAwait(false);
return new[] { MapSeriesToRemoteSearchResult(seriesResult) };
}
@@ -181,67 +164,64 @@ private RemoteSearchResult MapSeriesToRemoteSearchResult(SeriesExtendedRecord se
}
var imdbID = series.RemoteIds.FirstOrDefault(x => x.SourceName == "IMDB")?.Id;
- if (!string.IsNullOrEmpty(imdbID))
- {
- remoteResult.SetProviderId(MetadataProvider.Imdb, imdbID);
- }
-
- remoteResult.SetProviderId(MetadataProvider.Tvdb, series.Id.GetValueOrDefault().ToString(CultureInfo.InvariantCulture));
+ remoteResult.SetProviderIdIfHasValue(MetadataProvider.Imdb, imdbID);
+ remoteResult.SetTvdbId(series.Id);
return remoteResult;
}
private async Task FetchSeriesMetadata(
MetadataResult result,
- SeriesInfo info,
+ SeriesInfo seriesInfo,
CancellationToken cancellationToken)
{
- string metadataLanguage = info.MetadataLanguage;
- Dictionary seriesProviderIds = info.ProviderIds;
- var series = result.Item;
+ var seriesMetadata = result.Item;
+ async Task TryGetTvdbIdWithRemoteId(string id)
+ {
+ return await GetSeriesByRemoteId(
+ id,
+ seriesInfo.MetadataLanguage,
+ seriesInfo.Name,
+ cancellationToken).ConfigureAwait(false);
+ }
- if (seriesProviderIds.TryGetValue(TvdbPlugin.ProviderId, out var tvdbId) && !string.IsNullOrEmpty(tvdbId))
+ if (seriesInfo.HasTvdbId(out var tvdbIdTxt))
{
- series.SetProviderId(TvdbPlugin.ProviderId, tvdbId);
+ seriesMetadata.SetTvdbId(tvdbIdTxt);
}
- if (seriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out var imdbId) && !string.IsNullOrEmpty(imdbId))
+ if (seriesInfo.HasProviderId(MetadataProvider.Imdb, out var imdbId))
{
- series.SetProviderId(MetadataProvider.Imdb, imdbId);
- tvdbId = await GetSeriesByRemoteId(
- imdbId,
- metadataLanguage,
- info.Name,
- cancellationToken).ConfigureAwait(false);
+ seriesMetadata.SetProviderId(MetadataProvider.Imdb, imdbId!);
+ tvdbIdTxt ??= await TryGetTvdbIdWithRemoteId(imdbId!).ConfigureAwait(false);
}
- if (seriesProviderIds.TryGetValue(MetadataProvider.Zap2It.ToString(), out var zap2It) && !string.IsNullOrEmpty(zap2It))
+ if (seriesInfo.HasProviderId(MetadataProvider.Zap2It, out var zap2It))
{
- series.SetProviderId(MetadataProvider.Zap2It, zap2It);
- tvdbId = await GetSeriesByRemoteId(
- zap2It,
- metadataLanguage,
- info.Name,
- cancellationToken).ConfigureAwait(false);
+ seriesMetadata.SetProviderId(MetadataProvider.Zap2It, zap2It!);
+ tvdbIdTxt ??= await TryGetTvdbIdWithRemoteId(zap2It!).ConfigureAwait(false);
}
- if (seriesProviderIds.TryGetValue(MetadataProvider.Tmdb.ToString(), out var tmdbId) && !string.IsNullOrEmpty(tmdbId))
+ if (seriesInfo.HasProviderId(MetadataProvider.Tmdb, out var tmdbId))
{
- series.SetProviderId(MetadataProvider.Tmdb, tmdbId);
- tvdbId = await GetSeriesByRemoteId(
- tmdbId,
- metadataLanguage,
- info.Name,
- cancellationToken).ConfigureAwait(false);
+ seriesMetadata.SetProviderId(MetadataProvider.Tmdb, tmdbId!);
+ tvdbIdTxt ??= await TryGetTvdbIdWithRemoteId(tmdbId!).ConfigureAwait(false);
+ }
+
+ if (string.IsNullOrWhiteSpace(tvdbIdTxt))
+ {
+ _logger.LogWarning("No valid tvdb id found for series {TvdbId}:{SeriesName}", tvdbIdTxt, seriesInfo.Name);
+ return;
}
+ var tvdbId = Convert.ToInt32(tvdbIdTxt, CultureInfo.InvariantCulture);
try
{
var seriesResult =
await _tvdbClientManager
- .GetSeriesExtendedByIdAsync(Convert.ToInt32(tvdbId, CultureInfo.InvariantCulture), metadataLanguage, cancellationToken, Meta4.Translations, false)
+ .GetSeriesExtendedByIdAsync(tvdbId, seriesInfo.MetadataLanguage, cancellationToken, Meta4.Translations, false)
.ConfigureAwait(false);
- MapSeriesToResult(result, seriesResult, info);
+ MapSeriesToResult(result, seriesResult, seriesInfo);
result.ResetPeople();
@@ -257,12 +237,12 @@ await _tvdbClientManager
}
else
{
- _logger.LogError("Failed to retrieve actors for series {TvdbId}:{SeriesName}", tvdbId, info.Name);
+ _logger.LogError("Failed to retrieve actors for series {TvdbId}:{SeriesName}", tvdbId, seriesInfo.Name);
}
}
catch (Exception e)
{
- _logger.LogError(e, "Failed to retrieve series with id {TvdbId}:{SeriesName}", tvdbId, info.Name);
+ _logger.LogError(e, "Failed to retrieve series with id {TvdbId}:{SeriesName}", tvdbId, seriesInfo.Name);
return;
}
}
@@ -281,13 +261,13 @@ await _tvdbClientManager
return null;
}
- if (resultData is null || resultData.Count == 0 || resultData[0] is null || resultData[0].Series is null || resultData[0].Series.Id.HasValue == false)
+ if (resultData is null || resultData.Count == 0 || resultData[0]?.Series?.Id is null)
{
_logger.LogWarning("TvdbSearch: No series found for remote id: {RemoteId}", remoteId);
return null;
}
- return resultData[0].Series.Id.GetValueOrDefault().ToString(CultureInfo.InvariantCulture);
+ return resultData[0].Series.Id?.ToString(CultureInfo.InvariantCulture);
}
///
@@ -367,32 +347,22 @@ private async Task> FindSeriesInternal(string name, str
var seriesResult =
await _tvdbClientManager.GetSeriesExtendedByIdAsync(Convert.ToInt32(seriesSearchResult.Tvdb_id, CultureInfo.InvariantCulture), language, cancellationToken, small: true)
.ConfigureAwait(false);
+
var imdbId = seriesResult.RemoteIds.FirstOrDefault(x => string.Equals(x.SourceName, "IMDB", StringComparison.OrdinalIgnoreCase))?.Id.ToString();
- if (!string.IsNullOrEmpty(imdbId))
- {
- remoteSearchResult.SetProviderId(MetadataProvider.Imdb, imdbId);
- }
+ remoteSearchResult.SetProviderIdIfHasValue(MetadataProvider.Imdb, imdbId);
var zap2ItId = seriesResult.RemoteIds.FirstOrDefault(x => string.Equals(x.SourceName, "Zap2It", StringComparison.OrdinalIgnoreCase))?.Id.ToString();
-
- if (!string.IsNullOrEmpty(zap2ItId))
- {
- remoteSearchResult.SetProviderId(MetadataProvider.Zap2It, zap2ItId);
- }
+ remoteSearchResult.SetProviderIdIfHasValue(MetadataProvider.Zap2It, zap2ItId);
var tmdbId = seriesResult.RemoteIds.FirstOrDefault(x => string.Equals(x.SourceName, "TheMovieDB.com", StringComparison.OrdinalIgnoreCase))?.Id.ToString();
-
- if (!string.IsNullOrEmpty(tmdbId))
- {
- remoteSearchResult.SetProviderId(MetadataProvider.Tmdb, tmdbId);
- }
+ remoteSearchResult.SetProviderIdIfHasValue(MetadataProvider.Tmdb, tmdbId);
}
catch (Exception e)
{
_logger.LogError(e, "Unable to retrieve series with id {TvdbId}:{SeriesName}", seriesSearchResult.Tvdb_id, seriesSearchResult.Name);
}
- remoteSearchResult.SetProviderId(TvdbPlugin.ProviderId, seriesSearchResult.Tvdb_id);
+ remoteSearchResult.SetTvdbId(seriesSearchResult.Tvdb_id);
list.Add(new Tuple, RemoteSearchResult>(tvdbTitles, remoteSearchResult));
}
@@ -450,7 +420,7 @@ private static void MapActorsToResult(MetadataResult result, IEnumerable
private async Task Identify(SeriesInfo info)
{
- if (!string.IsNullOrWhiteSpace(info.GetProviderId(TvdbPlugin.ProviderId)))
+ if (info.HasTvdbId())
{
return;
}
@@ -459,21 +429,16 @@ private async Task Identify(SeriesInfo info)
.ConfigureAwait(false);
var entry = remoteSearchResults.FirstOrDefault();
-
- if (entry != null)
+ if (entry.HasTvdbId(out var tvdbId))
{
- var id = entry.GetProviderId(TvdbPlugin.ProviderId);
- if (!string.IsNullOrEmpty(id))
- {
- info.SetProviderId(TvdbPlugin.ProviderId, id);
- }
+ info.SetTvdbId(tvdbId);
}
}
private static void MapSeriesToResult(MetadataResult result, SeriesExtendedRecord tvdbSeries, SeriesInfo info)
{
Series series = result.Item;
- series.SetProviderId(TvdbPlugin.ProviderId, tvdbSeries.Id.GetValueOrDefault().ToString(CultureInfo.InvariantCulture));
+ series.SetTvdbId(tvdbSeries.Id);
// Tvdb uses 3 letter code for language (prob ISO 639-2)
// Reverts to OriginalName if no translation is found
series.Name = tvdbSeries.Translations.GetTranslatedNamedOrDefault(info.MetadataLanguage) ?? tvdbSeries.Name;
@@ -485,23 +450,15 @@ private static void MapSeriesToResult(MetadataResult result, SeriesExten
// series.CommunityRating = (float?)tvdbSeries.SiteRating;
// Attempts to default to USA if not found
series.OfficialRating = tvdbSeries.ContentRatings.FirstOrDefault(x => string.Equals(x.Country, TvdbCultureInfo.GetCountryInfo(info.MetadataCountryCode)?.ThreeLetterISORegionName, StringComparison.OrdinalIgnoreCase))?.Name ?? tvdbSeries.ContentRatings.FirstOrDefault(x => string.Equals(x.Country, "usa", StringComparison.OrdinalIgnoreCase))?.Name;
+
var imdbId = tvdbSeries.RemoteIds.FirstOrDefault(x => string.Equals(x.SourceName, "IMDB", StringComparison.OrdinalIgnoreCase))?.Id.ToString();
- var zap2ItId = tvdbSeries.RemoteIds.FirstOrDefault(x => string.Equals(x.SourceName, "Zap2It", StringComparison.OrdinalIgnoreCase))?.Id.ToString();
- var tmdbId = tvdbSeries.RemoteIds.FirstOrDefault(x => string.Equals(x.SourceName, "TheMovieDB.com", StringComparison.OrdinalIgnoreCase))?.Id.ToString();
- if (!string.IsNullOrEmpty(imdbId))
- {
- series.SetProviderId(MetadataProvider.Imdb, imdbId);
- }
+ series.SetProviderIdIfHasValue(MetadataProvider.Imdb, imdbId);
- if (!string.IsNullOrEmpty(zap2ItId))
- {
- series.SetProviderId(MetadataProvider.Zap2It, zap2ItId);
- }
+ var zap2ItId = tvdbSeries.RemoteIds.FirstOrDefault(x => string.Equals(x.SourceName, "Zap2It", StringComparison.OrdinalIgnoreCase))?.Id.ToString();
+ series.SetProviderIdIfHasValue(MetadataProvider.Zap2It, zap2ItId);
- if (!string.IsNullOrEmpty(tmdbId))
- {
- series.SetProviderId(MetadataProvider.Tmdb, tmdbId);
- }
+ var tmdbId = tvdbSeries.RemoteIds.FirstOrDefault(x => string.Equals(x.SourceName, "TheMovieDB.com", StringComparison.OrdinalIgnoreCase))?.Id.ToString();
+ series.SetProviderIdIfHasValue(MetadataProvider.Tmdb, tmdbId);
if (Enum.TryParse(tvdbSeries.Status.Name, true, out SeriesStatus seriesStatus))
{
diff --git a/Jellyfin.Plugin.Tvdb/TvdbClientManager.cs b/Jellyfin.Plugin.Tvdb/TvdbClientManager.cs
index afe2b1f..93266dc 100644
--- a/Jellyfin.Plugin.Tvdb/TvdbClientManager.cs
+++ b/Jellyfin.Plugin.Tvdb/TvdbClientManager.cs
@@ -321,7 +321,6 @@ public async Task> GetArtworkTypeAsync(CancellationTo
{
var seriesClient = _serviceProvider.GetRequiredService();
await LoginAsync().ConfigureAwait(false);
- searchInfo.SeriesProviderIds.TryGetValue(TvdbPlugin.ProviderId, out var seriesTvdbId);
int? episodeNumber = null;
int? seasonNumber = null;
string? airDate = null;
@@ -368,27 +367,27 @@ public async Task> GetArtworkTypeAsync(CancellationTo
{
case "dvd":
case "absolute":
- seriesResponse = await seriesClient.GetSeriesEpisodesAsync(page: 0, id: Convert.ToInt32(seriesTvdbId, CultureInfo.InvariantCulture), season_type: searchInfo.SeriesDisplayOrder, season: seasonNumber, episodeNumber: episodeNumber, airDate: airDate, cancellationToken: cancellationToken).ConfigureAwait(false);
+ seriesResponse = await seriesClient.GetSeriesEpisodesAsync(page: 0, id: searchInfo.GetTvdbId(), season_type: searchInfo.SeriesDisplayOrder, season: seasonNumber, episodeNumber: episodeNumber, airDate: airDate, cancellationToken: cancellationToken).ConfigureAwait(false);
break;
default:
- seriesResponse = await seriesClient.GetSeriesEpisodesAsync(page: 0, id: Convert.ToInt32(seriesTvdbId, CultureInfo.InvariantCulture), season_type: "default", season: seasonNumber, episodeNumber: episodeNumber, airDate: airDate, cancellationToken: cancellationToken).ConfigureAwait(false);
+ seriesResponse = await seriesClient.GetSeriesEpisodesAsync(page: 0, id: searchInfo.GetTvdbId(), season_type: "default", season: seasonNumber, episodeNumber: episodeNumber, airDate: airDate, cancellationToken: cancellationToken).ConfigureAwait(false);
break;
}
}
else // when special use default order
{
- seriesResponse = await seriesClient.GetSeriesEpisodesAsync(page: 0, id: Convert.ToInt32(seriesTvdbId, CultureInfo.InvariantCulture), season_type: "default", season: seasonNumber, episodeNumber: episodeNumber, airDate: airDate, cancellationToken: cancellationToken).ConfigureAwait(false);
+ seriesResponse = await seriesClient.GetSeriesEpisodesAsync(page: 0, id: searchInfo.GetTvdbId(), season_type: "default", season: seasonNumber, episodeNumber: episodeNumber, airDate: airDate, cancellationToken: cancellationToken).ConfigureAwait(false);
}
Data2 seriesData = seriesResponse.Data;
- if (seriesData == null || seriesData.Episodes == null || seriesData.Episodes.Count == 0 || seriesData.Episodes[0].Id.HasValue == false)
+ if (seriesData?.Episodes == null || seriesData.Episodes.Count == 0)
{
return null;
}
else
{
- return seriesData.Episodes[0].Id.GetValueOrDefault().ToString(CultureInfo.InvariantCulture);
+ return seriesData.Episodes[0].Id?.ToString(CultureInfo.InvariantCulture);
}
}
diff --git a/Jellyfin.Plugin.Tvdb/TvdbSdkExtensions.cs b/Jellyfin.Plugin.Tvdb/TvdbSdkExtensions.cs
index 75f5fa9..5d32e00 100644
--- a/Jellyfin.Plugin.Tvdb/TvdbSdkExtensions.cs
+++ b/Jellyfin.Plugin.Tvdb/TvdbSdkExtensions.cs
@@ -159,7 +159,7 @@ private static bool IsMatch(this Translation translation, string? language)
language);
}
- private static RemoteImageInfo? CreateRemoteImageInfo(string imageUrl, string thumbnailUrl, (long Width, long Height) imageDimension, string providerName, ImageType? type, Language? language)
+ private static RemoteImageInfo? CreateRemoteImageInfo(string imageUrl, string thumbnailUrl, (long? Width, long? Height) imageDimension, string providerName, ImageType? type, Language? language)
{
if (type is null)
{