using System; using System.Diagnostics.CodeAnalysis; namespace MediaBrowser.Common.Providers { /// /// Parsers for provider ids. /// public static class ProviderIdParsers { private const int ImdbMinNumbers = 7; private const int ImdbMaxNumbers = 8; private const string ImdbPrefix = "tt"; /// /// Parses an IMDb id from a string. /// /// The text to parse. /// The parsed IMDb id. /// True if parsing was successful, false otherwise. public static bool TryFindImdbId(ReadOnlySpan text, out ReadOnlySpan imdbId) { // IMDb id is at least 9 chars (tt + 7 numbers) while (text.Length >= 2 + ImdbMinNumbers) { var ttPos = text.IndexOf(ImdbPrefix); if (ttPos == -1) { imdbId = default; return false; } text = text.Slice(ttPos); var i = 2; var limit = Math.Min(text.Length, ImdbMaxNumbers + 2); for (; i < limit; i++) { var c = text[i]; if (!IsDigit(c)) { break; } } // Skip if more than 8 digits + 2 chars for tt if (i <= ImdbMaxNumbers + 2 && i >= ImdbMinNumbers + 2) { imdbId = text.Slice(0, i); return true; } text = text.Slice(i); } imdbId = default; return false; } /// /// Parses an TMDb id from a movie url. /// /// The text with the url to parse. /// The parsed TMDb id. /// True if parsing was successful, false otherwise. public static bool TryFindTmdbMovieId(ReadOnlySpan text, out ReadOnlySpan tmdbId) => TryFindProviderId(text, "themoviedb.org/movie/", out tmdbId); /// /// Parses an TMDb id from a series url. /// /// The text with the url to parse. /// The parsed TMDb id. /// True if parsing was successful, false otherwise. public static bool TryFindTmdbSeriesId(ReadOnlySpan text, out ReadOnlySpan tmdbId) => TryFindProviderId(text, "themoviedb.org/tv/", out tmdbId); /// /// Parses an TVDb id from a url. /// /// The text with the url to parse. /// The parsed TVDb id. /// True if parsing was successful, false otherwise. public static bool TryFindTvdbId(ReadOnlySpan text, out ReadOnlySpan tvdbId) => TryFindProviderId(text, "thetvdb.com/?tab=series&id=", out tvdbId); private static bool TryFindProviderId(ReadOnlySpan text, ReadOnlySpan searchString, [NotNullWhen(true)] out ReadOnlySpan providerId) { var searchPos = text.IndexOf(searchString); if (searchPos == -1) { providerId = default; return false; } text = text.Slice(searchPos + searchString.Length); int i = 0; for (; i < text.Length; i++) { var c = text[i]; if (!IsDigit(c)) { break; } } if (i >= 1) { providerId = text.Slice(0, i); return true; } providerId = default; return false; } private static bool IsDigit(char c) { return c >= '0' && c <= '9'; } } }