diff --git a/src/Jackett.Common/Extensions/StringExtensions.cs b/src/Jackett.Common/Extensions/StringExtensions.cs new file mode 100644 index 000000000..f02e376e6 --- /dev/null +++ b/src/Jackett.Common/Extensions/StringExtensions.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +namespace Jackett.Common.Extensions +{ + public static class StringExtensions + { + public static bool ContainsIgnoreCase(this string source, string contains) => source != null && contains != null && CultureInfo.InvariantCulture.CompareInfo.IndexOf(source, contains, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) >= 0; + + public static bool ContainsIgnoreCase(this IEnumerable source, string value) => source.Contains(value, StringComparer.InvariantCultureIgnoreCase); + } +} diff --git a/src/Jackett.Common/Models/TorznabQuery.cs b/src/Jackett.Common/Models/TorznabQuery.cs index 81d04b3bb..7649feb21 100644 --- a/src/Jackett.Common/Models/TorznabQuery.cs +++ b/src/Jackett.Common/Models/TorznabQuery.cs @@ -2,6 +2,7 @@ using System; using System.Globalization; using System.Linq; using System.Text.RegularExpressions; +using Jackett.Common.Extensions; using Jackett.Common.Utils; namespace Jackett.Common.Models @@ -187,6 +188,8 @@ namespace Jackett.Common.Models // With limit we can limit the amount of characters which should be compared (use it if a tracker doesn't return the full title). public bool MatchQueryStringAND(string title, int? limit = null, string queryStringOverride = null) { + var commonWords = new[] { "and", "the", "an" }; + // We cache the regex split results so we have to do it only once for each query. if (QueryStringParts == null) { @@ -196,22 +199,17 @@ namespace Jackett.Common.Models { if (limit > queryString.Length) limit = queryString.Length; + queryString = queryString.Substring(0, (int)limit); } - var splitRegex = new Regex("[^a-zA-Z0-9]+"); - QueryStringParts = splitRegex.Split(queryString); + + var splitRegex = new Regex("[^\\w]+"); + + QueryStringParts = splitRegex.Split(queryString).Where(p => !string.IsNullOrWhiteSpace(p) && p.Length > 1 && !commonWords.ContainsIgnoreCase(p)).ToArray(); } // Check if each part of the query string is in the given title. - foreach (var queryStringPart in QueryStringParts) - { - if (title.IndexOf(queryStringPart, StringComparison.OrdinalIgnoreCase) < 0) - { - return false; - } - } - - return true; + return QueryStringParts.All(title.ContainsIgnoreCase); } public string GetEpisodeSearchString()