< Summary - Jellyfin

Information
Class: MediaBrowser.Providers.Plugins.Tmdb.TmdbUtils
Assembly: MediaBrowser.Providers
File(s): /srv/git/jellyfin/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs
Line coverage
28%
Covered lines: 15
Uncovered lines: 38
Coverable lines: 53
Total lines: 206
Line coverage: 28.3%
Branch coverage
42%
Covered branches: 16
Total branches: 38
Branch coverage: 42.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%210%
CleanName(...)100%210%
MapCrewToPersonType(...)0%110100%
IsTrailerType(...)0%2040%
GetImageLanguagesParam(...)0%4260%
NormalizeLanguage(...)100%66100%
AdjustImageLanguage(...)100%1010100%
BuildParentalRating(...)0%620%

File(s)

/srv/git/jellyfin/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Diagnostics.CodeAnalysis;
 4using System.Text.RegularExpressions;
 5using Jellyfin.Data.Enums;
 6using MediaBrowser.Model.Entities;
 7using TMDbLib.Objects.General;
 8
 9namespace MediaBrowser.Providers.Plugins.Tmdb
 10{
 11    /// <summary>
 12    /// Utilities for the TMDb provider.
 13    /// </summary>
 14    public static partial class TmdbUtils
 15    {
 16        /// <summary>
 17        /// URL of the TMDb instance to use.
 18        /// </summary>
 19        public const string BaseTmdbUrl = "https://www.themoviedb.org/";
 20
 21        /// <summary>
 22        /// Name of the provider.
 23        /// </summary>
 24        public const string ProviderName = "TheMovieDb";
 25
 26        /// <summary>
 27        /// API key to use when performing an API call.
 28        /// </summary>
 29        public const string ApiKey = "4219e299c89411838049ab0dab19ebd5";
 30
 31        /// <summary>
 32        /// The crew types to keep.
 33        /// </summary>
 034        public static readonly string[] WantedCrewTypes =
 035        {
 036            PersonType.Director,
 037            PersonType.Writer,
 038            PersonType.Producer
 039        };
 40
 41        /// <summary>
 42        /// The crew kinds to keep.
 43        /// </summary>
 044        public static readonly PersonKind[] WantedCrewKinds =
 045        {
 046            PersonKind.Director,
 047            PersonKind.Writer,
 048            PersonKind.Producer
 049        };
 50
 51        [GeneratedRegex(@"[\W_]+")]
 52        private static partial Regex NonWordRegex();
 53
 54        /// <summary>
 55        /// Cleans the name according to TMDb requirements.
 56        /// </summary>
 57        /// <param name="name">The name of the entity.</param>
 58        /// <returns>The cleaned name.</returns>
 59        public static string CleanName(string name)
 60        {
 61            // TMDb expects a space separated list of words make sure that is the case
 062            return NonWordRegex().Replace(name, " ");
 63        }
 64
 65        /// <summary>
 66        /// Maps the TMDb provided roles for crew members to Jellyfin roles.
 67        /// </summary>
 68        /// <param name="crew">Crew member to map against the Jellyfin person types.</param>
 69        /// <returns>The Jellyfin person type.</returns>
 70        public static PersonKind MapCrewToPersonType(Crew crew)
 71        {
 072            if (crew.Department.Equals("production", StringComparison.OrdinalIgnoreCase)
 073                && crew.Job.Contains("director", StringComparison.OrdinalIgnoreCase))
 74            {
 075                return PersonKind.Director;
 76            }
 77
 078            if (crew.Department.Equals("production", StringComparison.OrdinalIgnoreCase)
 079                && crew.Job.Contains("producer", StringComparison.OrdinalIgnoreCase))
 80            {
 081                return PersonKind.Producer;
 82            }
 83
 084            if (crew.Department.Equals("writing", StringComparison.OrdinalIgnoreCase))
 85            {
 086                return PersonKind.Writer;
 87            }
 88
 089            return PersonKind.Unknown;
 90        }
 91
 92        /// <summary>
 93        /// Determines whether a video is a trailer.
 94        /// </summary>
 95        /// <param name="video">The TMDb video.</param>
 96        /// <returns>A boolean indicating whether the video is a trailer.</returns>
 97        public static bool IsTrailerType(Video video)
 98        {
 099            return video.Site.Equals("youtube", StringComparison.OrdinalIgnoreCase)
 0100                   && (video.Type.Equals("trailer", StringComparison.OrdinalIgnoreCase)
 0101                       || video.Type.Equals("teaser", StringComparison.OrdinalIgnoreCase));
 102        }
 103
 104        /// <summary>
 105        /// Normalizes a language string for use with TMDb's include image language parameter.
 106        /// </summary>
 107        /// <param name="preferredLanguage">The preferred language as either a 2 letter code with or without country cod
 108        /// <returns>The comma separated language string.</returns>
 109        public static string GetImageLanguagesParam(string preferredLanguage)
 110        {
 0111            var languages = new List<string>();
 112
 0113            if (!string.IsNullOrEmpty(preferredLanguage))
 114            {
 0115                preferredLanguage = NormalizeLanguage(preferredLanguage);
 116
 0117                languages.Add(preferredLanguage);
 118
 0119                if (preferredLanguage.Length == 5) // Like en-US
 120                {
 121                    // Currently, TMDb supports 2-letter language codes only.
 122                    // They are planning to change this in the future, thus we're
 123                    // supplying both codes if we're having a 5-letter code.
 0124                    languages.Add(preferredLanguage.Substring(0, 2));
 125                }
 126            }
 127
 0128            languages.Add("null");
 129
 130            // Always add English as fallback language
 0131            if (!string.Equals(preferredLanguage, "en", StringComparison.OrdinalIgnoreCase))
 132            {
 0133                languages.Add("en");
 134            }
 135
 0136            return string.Join(',', languages);
 137        }
 138
 139        /// <summary>
 140        /// Normalizes a language string for use with TMDb's language parameter.
 141        /// </summary>
 142        /// <param name="language">The language code.</param>
 143        /// <returns>The normalized language code.</returns>
 144        [return: NotNullIfNotNull(nameof(language))]
 145        public static string? NormalizeLanguage(string? language)
 146        {
 7147            if (string.IsNullOrEmpty(language))
 148            {
 2149                return language;
 150            }
 151
 152            // TMDb requires this to be uppercase
 153            // Everything after the hyphen must be written in uppercase due to a way TMDb wrote their API.
 154            // See here: https://www.themoviedb.org/talk/5119221d760ee36c642af4ad?page=3#56e372a0c3a3685a9e0019ab
 5155            var parts = language.Split('-');
 156
 5157            if (parts.Length == 2)
 158            {
 159                // TMDb doesn't support Switzerland (de-CH, it-CH or fr-CH) so use the language (de, it or fr) without c
 3160                if (string.Equals(parts[1], "CH", StringComparison.OrdinalIgnoreCase))
 161                {
 1162                    return parts[0];
 163                }
 164
 2165                language = parts[0] + "-" + parts[1].ToUpperInvariant();
 166            }
 167
 4168            return language;
 169        }
 170
 171        /// <summary>
 172        /// Adjusts the image's language code preferring the 5 letter language code eg. en-US.
 173        /// </summary>
 174        /// <param name="imageLanguage">The image's actual language code.</param>
 175        /// <param name="requestLanguage">The requested language code.</param>
 176        /// <returns>The language code.</returns>
 177        public static string AdjustImageLanguage(string imageLanguage, string requestLanguage)
 178        {
 4179            if (!string.IsNullOrEmpty(imageLanguage)
 4180                && !string.IsNullOrEmpty(requestLanguage)
 4181                && requestLanguage.Length > 2
 4182                && imageLanguage.Length == 2
 4183                && requestLanguage.StartsWith(imageLanguage, StringComparison.OrdinalIgnoreCase))
 184            {
 1185                return requestLanguage;
 186            }
 187
 3188            return imageLanguage;
 189        }
 190
 191        /// <summary>
 192        /// Combines the metadata country code and the parental rating from the API into the value we store in our datab
 193        /// </summary>
 194        /// <param name="countryCode">The ISO 3166-1 country code of the rating country.</param>
 195        /// <param name="ratingValue">The rating value returned by the TMDb API.</param>
 196        /// <returns>The combined parental rating of country code+rating value.</returns>
 197        public static string BuildParentalRating(string countryCode, string ratingValue)
 198        {
 199            // Exclude US because we store US values as TV-14 without the country code.
 0200            var ratingPrefix = string.Equals(countryCode, "US", StringComparison.OrdinalIgnoreCase) ? string.Empty : cou
 0201            var newRating = ratingPrefix + ratingValue;
 202
 0203            return newRating.Replace("DE-", "FSK-", StringComparison.OrdinalIgnoreCase);
 204        }
 205    }
 206}