diff options
Diffstat (limited to 'MediaBrowser.Providers/Plugins/Tmdb')
9 files changed, 147 insertions, 63 deletions
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index 833d1ae38..4a0884c07 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -7,8 +7,6 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using TMDbLib.Objects.Find; -using TMDbLib.Objects.Search; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -16,6 +14,8 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; +using TMDbLib.Objects.Find; +using TMDbLib.Objects.Search; namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { @@ -206,12 +206,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies if (ourRelease != null) { - var ratingPrefix = string.Equals(info.MetadataCountryCode, "us", StringComparison.OrdinalIgnoreCase) ? string.Empty : info.MetadataCountryCode + "-"; - var newRating = ratingPrefix + ourRelease.Certification; - - newRating = newRating.Replace("de-", "FSK-", StringComparison.OrdinalIgnoreCase); - - movie.OfficialRating = newRating; + movie.OfficialRating = TmdbUtils.BuildParentalRating(ourRelease.Iso_3166_1, ourRelease.Certification); } else if (usRelease != null) { diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs index 3f57c4bc4..e4c908a62 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs @@ -1,6 +1,5 @@ #pragma warning disable CS1591 -using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -49,37 +48,36 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken) { var person = (Person)item; - var personTmdbId = Convert.ToInt32(person.GetProviderId(MetadataProvider.Tmdb), CultureInfo.InvariantCulture); - if (personTmdbId > 0) + if (!person.TryGetProviderId(MetadataProvider.Tmdb, out var personTmdbId)) { - var personResult = await _tmdbClientManager.GetPersonAsync(personTmdbId, cancellationToken).ConfigureAwait(false); - if (personResult?.Images?.Profiles == null) - { - return Enumerable.Empty<RemoteImageInfo>(); - } + return Enumerable.Empty<RemoteImageInfo>(); + } - var remoteImages = new List<RemoteImageInfo>(); - var language = item.GetPreferredMetadataLanguage(); + var language = item.GetPreferredMetadataLanguage(); + var personResult = await _tmdbClientManager.GetPersonAsync(int.Parse(personTmdbId, CultureInfo.InvariantCulture), language, cancellationToken).ConfigureAwait(false); + if (personResult?.Images?.Profiles == null) + { + return Enumerable.Empty<RemoteImageInfo>(); + } - for (var i = 0; i < personResult.Images.Profiles.Count; i++) - { - var image = personResult.Images.Profiles[i]; - remoteImages.Add(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) - }); - } + var remoteImages = new RemoteImageInfo[personResult.Images.Profiles.Count]; - return remoteImages.OrderByLanguageDescending(language); + 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) + }; } - return Enumerable.Empty<RemoteImageInfo>(); + return remoteImages.OrderByLanguageDescending(language); } public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs index 4384c203e..6db550b1d 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; @@ -30,11 +29,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken) { - var personTmdbId = Convert.ToInt32(searchInfo.GetProviderId(MetadataProvider.Tmdb), CultureInfo.InvariantCulture); - - if (personTmdbId <= 0) + if (searchInfo.TryGetProviderId(MetadataProvider.Tmdb, out var personTmdbId)) { - var personResult = await _tmdbClientManager.GetPersonAsync(personTmdbId, cancellationToken).ConfigureAwait(false); + var personResult = await _tmdbClientManager.GetPersonAsync(int.Parse(personTmdbId, CultureInfo.InvariantCulture), searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false); if (personResult != null) { @@ -51,19 +48,15 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People } result.SetProviderId(MetadataProvider.Tmdb, personResult.Id.ToString(CultureInfo.InvariantCulture)); - result.SetProviderId(MetadataProvider.Imdb, personResult.ExternalIds.ImdbId); + if (!string.IsNullOrEmpty(personResult.ExternalIds.ImdbId)) + { + result.SetProviderId(MetadataProvider.Imdb, personResult.ExternalIds.ImdbId); + } return new[] { result }; } } - // TODO why? Because of the old rate limit? - if (searchInfo.IsAutomated) - { - // Don't hammer moviedb searching by name - return Enumerable.Empty<RemoteSearchResult>(); - } - var personSearchResult = await _tmdbClientManager.SearchPersonAsync(searchInfo.Name, cancellationToken).ConfigureAwait(false); var remoteSearchResults = new List<RemoteSearchResult>(); @@ -102,7 +95,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People if (personTmdbId > 0) { - var person = await _tmdbClientManager.GetPersonAsync(personTmdbId, cancellationToken).ConfigureAwait(false); + var person = await _tmdbClientManager.GetPersonAsync(personTmdbId, id.MetadataLanguage, cancellationToken).ConfigureAwait(false); result.HasMetadata = true; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs index d92336624..ba18c542f 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs @@ -65,7 +65,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV // TODO use image languages if All Languages isn't toggled, but there's currently no way to get that value in here var episodeResult = await _tmdbClientManager - .GetEpisodeAsync(seriesTmdbId, seasonNumber.Value, episodeNumber.Value, null, null, cancellationToken) + .GetEpisodeAsync(seriesTmdbId, seasonNumber.Value, episodeNumber.Value, series.DisplayOrder, null, null, cancellationToken) .ConfigureAwait(false); var stills = episodeResult?.Images?.Stills; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs index b455e5634..8ec8f6464 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs @@ -92,7 +92,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV } var episodeResult = await _tmdbClientManager - .GetEpisodeAsync(seriesTmdbId, seasonNumber.Value, episodeNumber.Value, info.MetadataLanguage, TmdbUtils.GetImageLanguagesParam(info.MetadataLanguage), cancellationToken) + .GetEpisodeAsync(seriesTmdbId, seasonNumber.Value, episodeNumber.Value, info.SeriesDisplayOrder, info.MetadataLanguage, TmdbUtils.GetImageLanguagesParam(info.MetadataLanguage), cancellationToken) .ConfigureAwait(false); if (episodeResult == null) @@ -121,9 +121,20 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV CommunityRating = Convert.ToSingle(episodeResult.VoteAverage) }; - if (!string.IsNullOrEmpty(episodeResult.ExternalIds?.TvdbId)) + var externalIds = episodeResult.ExternalIds; + if (!string.IsNullOrEmpty(externalIds?.TvdbId)) { - item.SetProviderId(MetadataProvider.Tvdb, episodeResult.ExternalIds.TvdbId); + item.SetProviderId(MetadataProvider.Tvdb, externalIds.TvdbId); + } + + if (!string.IsNullOrEmpty(externalIds?.ImdbId)) + { + item.SetProviderId(MetadataProvider.Imdb, externalIds.ImdbId); + } + + if (!string.IsNullOrEmpty(externalIds?.TvrageId)) + { + item.SetProviderId(MetadataProvider.TvRage, externalIds.TvrageId); } if (episodeResult.Videos?.Results != null) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs index a96fc8ed6..326c116b3 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs @@ -54,7 +54,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (string.IsNullOrEmpty(tmdbId)) { - return null; + return Enumerable.Empty<RemoteImageInfo>(); } var language = item.GetPreferredMetadataLanguage(); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs index 496e1ae25..da76345b5 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs @@ -300,7 +300,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (ourRelease != null) { - series.OfficialRating = ourRelease.Rating; + series.OfficialRating = TmdbUtils.BuildParentalRating(ourRelease.Iso_3166_1, ourRelease.Rating); } else if (usRelease != null) { diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs index bf0f027fc..79ec6139d 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb tmdbId, language: TmdbUtils.NormalizeLanguage(language), includeImageLanguage: imageLanguages, - extraMethods: TvShowMethods.Credits | TvShowMethods.Images | TvShowMethods.Keywords | TvShowMethods.ExternalIds | TvShowMethods.Videos | TvShowMethods.ContentRatings, + extraMethods: TvShowMethods.Credits | TvShowMethods.Images | TvShowMethods.Keywords | TvShowMethods.ExternalIds | TvShowMethods.Videos | TvShowMethods.ContentRatings | TvShowMethods.EpisodeGroups, cancellationToken: cancellationToken).ConfigureAwait(false); if (series != null) @@ -137,6 +137,56 @@ namespace MediaBrowser.Providers.Plugins.Tmdb } /// <summary> + /// Gets a tv show episode group from the TMDb API based on the show id and the display order. + /// </summary> + /// <param name="tvShowId">The tv show's TMDb id.</param> + /// <param name="displayOrder">The display order.</param> + /// <param name="language">The tv show's language.</param> + /// <param name="imageLanguages">A comma-separated list of image languages.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>The TMDb tv show episode group information or null if not found.</returns> + private async Task<TvGroupCollection> GetSeriesGroupAsync(int tvShowId, string displayOrder, string language, string imageLanguages, CancellationToken cancellationToken) + { + TvGroupType? groupType = + string.Equals(displayOrder, "absolute", StringComparison.Ordinal) ? TvGroupType.Absolute : + string.Equals(displayOrder, "dvd", StringComparison.Ordinal) ? TvGroupType.DVD : + null; + + if (groupType == null) + { + return null; + } + + var key = $"group-{tvShowId.ToString(CultureInfo.InvariantCulture)}-{displayOrder}-{language}"; + if (_memoryCache.TryGetValue(key, out TvGroupCollection group)) + { + return group; + } + + await EnsureClientConfigAsync().ConfigureAwait(false); + + var series = await GetSeriesAsync(tvShowId, language, imageLanguages, cancellationToken).ConfigureAwait(false); + var episodeGroupId = series?.EpisodeGroups.Results.Find(g => g.Type == groupType)?.Id; + + if (episodeGroupId == null) + { + return null; + } + + group = await _tmDbClient.GetTvEpisodeGroupsAsync( + episodeGroupId, + language: TmdbUtils.NormalizeLanguage(language), + cancellationToken: cancellationToken).ConfigureAwait(false); + + if (group != null) + { + _memoryCache.Set(key, group, TimeSpan.FromHours(CacheDurationInHours)); + } + + return group; + } + + /// <summary> /// Gets a tv season from the TMDb API based on the tv show's TMDb id. /// </summary> /// <param name="tvShowId">The tv season's TMDb id.</param> @@ -177,13 +227,14 @@ namespace MediaBrowser.Providers.Plugins.Tmdb /// <param name="tvShowId">The tv show's TMDb id.</param> /// <param name="seasonNumber">The season number.</param> /// <param name="episodeNumber">The episode number.</param> + /// <param name="displayOrder">The display order.</param> /// <param name="language">The episode's language.</param> /// <param name="imageLanguages">A comma-separated list of image languages.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The TMDb tv episode information or null if not found.</returns> - public async Task<TvEpisode> GetEpisodeAsync(int tvShowId, int seasonNumber, int episodeNumber, string language, string imageLanguages, CancellationToken cancellationToken) + public async Task<TvEpisode> GetEpisodeAsync(int tvShowId, int seasonNumber, int episodeNumber, string displayOrder, string language, string imageLanguages, CancellationToken cancellationToken) { - var key = $"episode-{tvShowId.ToString(CultureInfo.InvariantCulture)}-s{seasonNumber.ToString(CultureInfo.InvariantCulture)}e{episodeNumber.ToString(CultureInfo.InvariantCulture)}-{language}"; + var key = $"episode-{tvShowId.ToString(CultureInfo.InvariantCulture)}-s{seasonNumber.ToString(CultureInfo.InvariantCulture)}e{episodeNumber.ToString(CultureInfo.InvariantCulture)}-{displayOrder}-{language}"; if (_memoryCache.TryGetValue(key, out TvEpisode episode)) { return episode; @@ -191,6 +242,19 @@ namespace MediaBrowser.Providers.Plugins.Tmdb await EnsureClientConfigAsync().ConfigureAwait(false); + var group = await GetSeriesGroupAsync(tvShowId, displayOrder, language, imageLanguages, cancellationToken); + if (group != null) + { + var season = group.Groups.Find(s => s.Order == seasonNumber); + // Episode order starts at 0 + var ep = season?.Episodes.Find(e => e.Order == episodeNumber - 1); + if (ep != null) + { + seasonNumber = ep.SeasonNumber; + episodeNumber = ep.EpisodeNumber; + } + } + episode = await _tmDbClient.GetTvEpisodeAsync( tvShowId, seasonNumber, @@ -212,11 +276,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb /// Gets a person eg. cast or crew member from the TMDb API based on its TMDb id. /// </summary> /// <param name="personTmdbId">The person's TMDb id.</param> + /// <param name="language">The episode's language.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The TMDb person information or null if not found.</returns> - public async Task<Person> GetPersonAsync(int personTmdbId, CancellationToken cancellationToken) + public async Task<Person> GetPersonAsync(int personTmdbId, string language, CancellationToken cancellationToken) { - var key = $"person-{personTmdbId.ToString(CultureInfo.InvariantCulture)}"; + var key = $"person-{personTmdbId.ToString(CultureInfo.InvariantCulture)}-{language}"; if (_memoryCache.TryGetValue(key, out Person person)) { return person; @@ -226,6 +291,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb person = await _tmDbClient.GetPersonAsync( personTmdbId, + TmdbUtils.NormalizeLanguage(language), PersonMethods.TvCredits | PersonMethods.MovieCredits | PersonMethods.Images | PersonMethods.ExternalIds, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs b/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs index 15a44c7ed..b713736a0 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs @@ -63,19 +63,19 @@ namespace MediaBrowser.Providers.Plugins.Tmdb /// <returns>The Jellyfin person type.</returns> public static string MapCrewToPersonType(Crew crew) { - if (crew.Department.Equals("production", StringComparison.InvariantCultureIgnoreCase) - && crew.Job.Contains("director", StringComparison.InvariantCultureIgnoreCase)) + if (crew.Department.Equals("production", StringComparison.OrdinalIgnoreCase) + && crew.Job.Contains("director", StringComparison.OrdinalIgnoreCase)) { return PersonType.Director; } - if (crew.Department.Equals("production", StringComparison.InvariantCultureIgnoreCase) - && crew.Job.Contains("producer", StringComparison.InvariantCultureIgnoreCase)) + if (crew.Department.Equals("production", StringComparison.OrdinalIgnoreCase) + && crew.Job.Contains("producer", StringComparison.OrdinalIgnoreCase)) { return PersonType.Producer; } - if (crew.Department.Equals("writing", StringComparison.InvariantCultureIgnoreCase)) + if (crew.Department.Equals("writing", StringComparison.OrdinalIgnoreCase)) { return PersonType.Writer; } @@ -148,6 +148,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb if (parts.Length == 2) { + // TMDB doesn't support Switzerland (de-CH, it-CH or fr-CH) so use the language (de, it or fr) without country code + if (string.Equals(parts[1], "CH", StringComparison.OrdinalIgnoreCase)) + { + return parts[0]; + } + language = parts[0] + "-" + parts[1].ToUpperInvariant(); } @@ -173,5 +179,20 @@ namespace MediaBrowser.Providers.Plugins.Tmdb return imageLanguage; } + + /// <summary> + /// Combines the metadata country code and the parental rating from the Api into the value we store in our database. + /// </summary> + /// <param name="countryCode">The Iso 3166-1 country code of the rating country.</param> + /// <param name="ratingValue">The rating value returned by the Tmdb Api.</param> + /// <returns>The combined parental rating of country code+rating value.</returns> + public static string BuildParentalRating(string countryCode, string ratingValue) + { + // exclude US because we store us values as TV-14 without the country code. + var ratingPrefix = string.Equals(countryCode, "US", StringComparison.OrdinalIgnoreCase) ? string.Empty : countryCode + "-"; + var newRating = ratingPrefix + ratingValue; + + return newRating.Replace("DE-", "FSK-", StringComparison.OrdinalIgnoreCase); + } } } |
