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