From a5706194cb020a77a1dad28b249a06c4a37a1f28 Mon Sep 17 00:00:00 2001 From: robinw0410 Date: Sat, 28 Feb 2026 01:31:53 +0100 Subject: [PATCH] Replace apostrophes with spaces instead of removing them in search titles Stripping apostrophes entirely merges adjacent tokens (e.g. "t'aimais" becomes "taimais"), causing indexer searches to return zero results for titles containing apostrophes. Replacing with a space lets the existing NonWord pass convert them to "+" separators, keeping tokens distinct. Fixes #11370 --- .../IndexerSearchTests/SearchDefinitionFixture.cs | 11 ++++++----- .../IndexerSearch/Definitions/SearchCriteriaBase.cs | 6 ++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/NzbDrone.Core.Test/IndexerSearchTests/SearchDefinitionFixture.cs b/src/NzbDrone.Core.Test/IndexerSearchTests/SearchDefinitionFixture.cs index 132cffaa07..d83366b407 100644 --- a/src/NzbDrone.Core.Test/IndexerSearchTests/SearchDefinitionFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerSearchTests/SearchDefinitionFixture.cs @@ -9,16 +9,17 @@ namespace NzbDrone.Core.Test.IndexerSearchTests { public class SearchDefinitionFixture : CoreTest { - [TestCase("Betty White's Off Their Rockers", "Betty+Whites+Off+Their+Rockers")] + [TestCase("Betty White’s Off Their Rockers", "Betty+White+s+Off+Their+Rockers")] [TestCase("Star Wars: The Clone Wars", "Star+Wars+The+Clone+Wars")] [TestCase("Hawaii Five-0", "Hawaii+Five+0")] [TestCase("Franklin & Bash", "Franklin+and+Bash")] [TestCase("Chicago P.D.", "Chicago+PD")] [TestCase("Kourtney And Khlo\u00E9 Take The Hamptons", "Kourtney+And+Khloe+Take+The+Hamptons")] - [TestCase("Betty White`s Off Their Rockers", "Betty+Whites+Off+Their+Rockers")] - [TestCase("Betty White\u00b4s Off Their Rockers", "Betty+Whites+Off+Their+Rockers")] - [TestCase("Betty White‘s Off Their Rockers", "Betty+Whites+Off+Their+Rockers")] - [TestCase("Betty White’s Off Their Rockers", "Betty+Whites+Off+Their+Rockers")] + [TestCase("Betty White`s Off Their Rockers", "Betty+White+s+Off+Their+Rockers")] + [TestCase("Betty White\u00b4s Off Their Rockers", "Betty+White+s+Off+Their+Rockers")] + [TestCase("Betty White’s Off Their Rockers", "Betty+White+s+Off+Their+Rockers")] + [TestCase("Betty White’s Off Their Rockers", "Betty+White+s+Off+Their+Rockers")] + [TestCase("Moi qui t’aimais", "Moi+qui+t+aimais")] public void should_replace_some_special_characters(string input, string expected) { Subject.SceneTitles = new List { input }; diff --git a/src/NzbDrone.Core/IndexerSearch/Definitions/SearchCriteriaBase.cs b/src/NzbDrone.Core/IndexerSearch/Definitions/SearchCriteriaBase.cs index aeb4d78038..f1f036ce3a 100644 --- a/src/NzbDrone.Core/IndexerSearch/Definitions/SearchCriteriaBase.cs +++ b/src/NzbDrone.Core/IndexerSearch/Definitions/SearchCriteriaBase.cs @@ -9,7 +9,8 @@ namespace NzbDrone.Core.IndexerSearch.Definitions { public abstract class SearchCriteriaBase { - private static readonly Regex SpecialCharacter = new Regex(@"['.\u0060\u00B4\u2018\u2019]", RegexOptions.IgnoreCase | RegexOptions.Compiled); + private static readonly Regex ApostropheCharacter = new Regex(@"['\u0060\u00B4\u2018\u2019]", RegexOptions.IgnoreCase | RegexOptions.Compiled); + private static readonly Regex PeriodCharacter = new Regex(@"[.]", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex NonWord = new Regex(@"[\W]", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex BeginningThe = new Regex(@"^the\s", RegexOptions.IgnoreCase | RegexOptions.Compiled); @@ -28,7 +29,8 @@ public static string GetCleanSceneTitle(string title) var cleanTitle = BeginningThe.Replace(title, string.Empty); cleanTitle = cleanTitle.Replace("&", "and"); - cleanTitle = SpecialCharacter.Replace(cleanTitle, ""); + cleanTitle = ApostropheCharacter.Replace(cleanTitle, " "); + cleanTitle = PeriodCharacter.Replace(cleanTitle, ""); cleanTitle = NonWord.Replace(cleanTitle, "+"); // remove any repeating +s