diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 72fe5a854..73236bad8 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -44,8 +44,8 @@ namespace Emby.Server.Implementations.Library // for imdbid we also accept pattern matching if (string.Equals(attribute, "imdbid", StringComparison.OrdinalIgnoreCase)) { - var match = ProviderIdParsers.TryParseImdbId(str, out var imdbId); - return match ? imdbId : null; + var match = ProviderIdParsers.TryFindImdbId(str, out var imdbId); + return match ? imdbId.ToString() : null; } return null; diff --git a/MediaBrowser.Common/Providers/ProviderIdParsers.cs b/MediaBrowser.Common/Providers/ProviderIdParsers.cs index 7744124ea..26eaccac5 100644 --- a/MediaBrowser.Common/Providers/ProviderIdParsers.cs +++ b/MediaBrowser.Common/Providers/ProviderIdParsers.cs @@ -12,6 +12,7 @@ namespace MediaBrowser.Common.Providers { private const int ImdbMinNumbers = 7; private const int ImdbMaxNumbers = 8; + private const string ImdbPrefix = "tt"; /// /// Parses an IMDb id from a string. @@ -19,9 +20,9 @@ namespace MediaBrowser.Common.Providers /// 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) + public static bool TryFindImdbId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan imdbId) { - var tt = "tt".AsSpan(); + var tt = ImdbPrefix.AsSpan(); // imdb id is at least 9 chars (tt + 7 numbers) while (text.Length >= 2 + ImdbMinNumbers) @@ -33,9 +34,10 @@ namespace MediaBrowser.Common.Providers return false; } - text = text.Slice(ttPos + tt.Length); - var i = 0; - for (; i < Math.Min(text.Length, ImdbMaxNumbers); i++) + 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)) @@ -44,10 +46,10 @@ namespace MediaBrowser.Common.Providers } } - // skip if more than 8 digits - if (i <= ImdbMaxNumbers && i >= ImdbMinNumbers) + // skip if more than 8 digits + 2 chars for tt + if (i <= ImdbMaxNumbers + 2 && i >= ImdbMinNumbers + 2) { - imdbId = string.Concat(tt, text.Slice(0, i)); + imdbId = text.Slice(0, i); return true; } @@ -64,8 +66,8 @@ namespace MediaBrowser.Common.Providers /// 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); + public static bool TryFindTmdbMovieId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tmdbId) + => TryFindProviderId(text, "themoviedb.org/movie/", out tmdbId); /// /// Parses an TMDb id from a series url. @@ -73,8 +75,8 @@ namespace MediaBrowser.Common.Providers /// 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); + public static bool TryFindTmdbSeriesId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tmdbId) + => TryFindProviderId(text, "themoviedb.org/tv/", out tmdbId); /// /// Parses an TVDb id from a url. @@ -82,10 +84,10 @@ namespace MediaBrowser.Common.Providers /// 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); + public static bool TryFindTvdbId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tvdbId) + => TryFindProviderId(text, "thetvdb.com/?tab=series&id=", out tvdbId); - private static bool TryParseProviderId(ReadOnlySpan text, ReadOnlySpan searchString, [NotNullWhen(true)] out string? providerId) + private static bool TryFindProviderId(ReadOnlySpan text, ReadOnlySpan searchString, [NotNullWhen(true)] out ReadOnlySpan providerId) { var searchPos = text.IndexOf(searchString); if (searchPos == -1) @@ -109,7 +111,7 @@ namespace MediaBrowser.Common.Providers if (i >= 1) { - providerId = text.Slice(0, i).ToString(); + providerId = text.Slice(0, i); return true; } diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index d2fa120e8..c5627f880 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -219,29 +219,29 @@ namespace MediaBrowser.XbmcMetadata.Parsers protected void ParseProviderLinks(T item, string xml) { - if (ProviderIdParsers.TryParseImdbId(xml, out var imdbId)) + if (ProviderIdParsers.TryFindImdbId(xml, out var imdbId)) { - item.SetProviderId(MetadataProvider.Imdb, imdbId); + item.SetProviderId(MetadataProvider.Imdb, imdbId.ToString()); } if (item is Movie) { - if (ProviderIdParsers.TryParseTmdbMovieId(xml, out var tmdbId)) + if (ProviderIdParsers.TryFindTmdbMovieId(xml, out var tmdbId)) { - item.SetProviderId(MetadataProvider.Tmdb, tmdbId); + item.SetProviderId(MetadataProvider.Tmdb, tmdbId.ToString()); } } if (item is Series) { - if (ProviderIdParsers.TryParseTmdbSeriesId(xml, out var tmdbId)) + if (ProviderIdParsers.TryFindTmdbSeriesId(xml, out var tmdbId)) { - item.SetProviderId(MetadataProvider.Tmdb, tmdbId); + item.SetProviderId(MetadataProvider.Tmdb, tmdbId.ToString()); } - if (ProviderIdParsers.TryParseTvdbId(xml, out var tvdbId)) + if (ProviderIdParsers.TryFindTvdbId(xml, out var tvdbId)) { - item.SetProviderId(MetadataProvider.Tvdb, tvdbId); + item.SetProviderId(MetadataProvider.Tvdb, tvdbId.ToString()); } } } diff --git a/tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs b/tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs index cfe1ea86b..1ce54c59b 100644 --- a/tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs +++ b/tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Providers; +using System; +using MediaBrowser.Common.Providers; using Xunit; namespace Jellyfin.Common.Tests.Providers @@ -20,9 +21,9 @@ namespace Jellyfin.Common.Tests.Providers [InlineData("tt123456789", true, "tt12345678")] public void Parse_Imdb(string text, bool shouldSucceed, string? imdbId) { - var succeeded = ProviderIdParsers.TryParseImdbId(text, out string? parsedId); + var succeeded = ProviderIdParsers.TryFindImdbId(text, out ReadOnlySpan parsedId); Assert.Equal(shouldSucceed, succeeded); - Assert.Equal(imdbId, parsedId); + Assert.Equal(imdbId ?? Span.Empty.ToString(), parsedId.ToString()); } [Theory] @@ -32,9 +33,9 @@ namespace Jellyfin.Common.Tests.Providers [InlineData("https://www.themoviedb.org/tv/1668-friends", false, null)] public void Parse_TmdbMovie(string text, bool shouldSucceed, string? tmdbId) { - var succeeded = ProviderIdParsers.TryParseTmdbMovieId(text, out string? parsedId); + var succeeded = ProviderIdParsers.TryFindTmdbMovieId(text, out ReadOnlySpan parsedId); Assert.Equal(shouldSucceed, succeeded); - Assert.Equal(tmdbId, parsedId); + Assert.Equal(tmdbId ?? Span.Empty.ToString(), parsedId.ToString()); } [Theory] @@ -44,9 +45,9 @@ namespace Jellyfin.Common.Tests.Providers [InlineData("https://www.themoviedb.org/movie/30287-fallo", false, null)] public void Parse_TmdbSeries(string text, bool shouldSucceed, string? tmdbId) { - var succeeded = ProviderIdParsers.TryParseTmdbSeriesId(text, out string? parsedId); + var succeeded = ProviderIdParsers.TryFindTmdbSeriesId(text, out ReadOnlySpan parsedId); Assert.Equal(shouldSucceed, succeeded); - Assert.Equal(tmdbId, parsedId); + Assert.Equal(tmdbId ?? Span.Empty.ToString(), parsedId.ToString()); } [Theory] @@ -56,9 +57,9 @@ namespace Jellyfin.Common.Tests.Providers [InlineData("https://www.themoviedb.org/tv/1668-friends", false, null)] public void Parse_Tvdb(string text, bool shouldSucceed, string? tvdbId) { - var succeeded = ProviderIdParsers.TryParseTvdbId(text, out string? parsedId); + var succeeded = ProviderIdParsers.TryFindTvdbId(text, out ReadOnlySpan parsedId); Assert.Equal(shouldSucceed, succeeded); - Assert.Equal(tvdbId, parsedId); + Assert.Equal(tvdbId ?? Span.Empty.ToString(), parsedId.ToString()); } } }