#nullable enable 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; /// /// 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 TryParseImdbId(ReadOnlySpan text, [NotNullWhen(true)] out string? imdbId) { var tt = "tt".AsSpan(); // imdb id is at least 9 chars (tt + 7 numbers) while (text.Length >= 2 + ImdbMinNumbers) { var ttPos = text.IndexOf(tt); if (ttPos == -1) { imdbId = default; return false; } text = text.Slice(ttPos + tt.Length); var i = 0; for (; i < Math.Min(text.Length, ImdbMaxNumbers); i++) { var c = text[i]; if (!IsDigit(c)) { break; } } // skip if more than 8 digits if (i <= ImdbMaxNumbers && i >= ImdbMinNumbers) { imdbId = string.Concat(tt, 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 TryParseTmdbMovieId(ReadOnlySpan text, [NotNullWhen(true)] out string? tmdbId) => TryParseProviderId(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 TryParseTmdbSeriesId(ReadOnlySpan text, [NotNullWhen(true)] out string? tmdbId) => TryParseProviderId(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 TryParseTvdbId(ReadOnlySpan text, [NotNullWhen(true)] out string? tvdbId) => TryParseProviderId(text, "thetvdb.com/?tab=series&id=", out tvdbId); private static bool TryParseProviderId(ReadOnlySpan text, ReadOnlySpan searchString, [NotNullWhen(true)] out string? 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).ToString(); return true; } providerId = default; return false; } private static bool IsDigit(char c) { return c >= '0' && c <= '9'; } } }