From 812af82fae81244b82e656e6f282e47c4eb5f4d0 Mon Sep 17 00:00:00 2001 From: Qstick Date: Tue, 4 Sep 2018 22:55:08 -0400 Subject: [PATCH] Fixed: Search fails for many artist and albums with specials (#466) * Fixed: Search fails for many artist/albums with specials * fixup! Replace & with space * fixup! Add two more test cases * fixup! Add last test case * fixup: Newznab test case --- .../SearchDefinitionFixture.cs | 36 +++++++++++++------ .../NewznabRequestGeneratorFixture.cs | 4 +-- .../Definitions/AlbumSearchCriteria.cs | 4 ++- .../Definitions/SearchCriteriaBase.cs | 11 +++--- .../Gazelle/GazelleRequestGenerator.cs | 4 +-- .../Headphones/HeadphonesRequestGenerator.cs | 6 ++-- .../Newznab/NewznabRequestGenerator.cs | 8 ++--- .../Omgwtfnzbs/OmgwtfnzbsRequestGenerator.cs | 6 ++-- .../Indexers/Rarbg/RarbgRequestGenerator.cs | 4 +-- .../Waffles/WafflesRequestGenerator.cs | 4 +-- 10 files changed, 51 insertions(+), 36 deletions(-) diff --git a/src/NzbDrone.Core.Test/IndexerSearchTests/SearchDefinitionFixture.cs b/src/NzbDrone.Core.Test/IndexerSearchTests/SearchDefinitionFixture.cs index a85ffc5bb..5451cf758 100644 --- a/src/NzbDrone.Core.Test/IndexerSearchTests/SearchDefinitionFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerSearchTests/SearchDefinitionFixture.cs @@ -3,22 +3,36 @@ using System.Linq; using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.IndexerSearch.Definitions; +using NzbDrone.Core.Music; using NzbDrone.Core.Test.Framework; namespace NzbDrone.Core.Test.IndexerSearchTests -{ - public class SearchDefinitionFixture : CoreTest +{ + public class AlbumSearchDefinitionFixture : CoreTest { - [TestCase("Betty White's Off Their Rockers", "Betty+Whites+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")] - public void should_replace_some_special_characters(string input, string expected) + [TestCase("Mötley Crüe", "Motley+Crue")] + [TestCase("방탄소년단", "방탄소년단")] + public void should_replace_some_special_characters_artist(string artist, string expected) { - Subject.SceneTitles = new List { input }; - Subject.QueryTitles.First().Should().Be(expected); + Subject.Artist = new Artist { Name = artist }; + Subject.ArtistQuery.Should().Be(expected); + } + + [TestCase("…and Justice for All", "and+Justice+for+All")] + [TestCase("American III: Solitary Man", "American+III+Solitary+Man")] + [TestCase("Sad Clowns & Hillbillies", "Sad+Clowns+Hillbillies")] + [TestCase("¿Quién sabe?", "Quien+sabe")] + public void should_replace_some_special_characters(string album, string expected) + { + Subject.AlbumTitle = album; + Subject.AlbumQuery.Should().Be(expected); + } + + [TestCase("+", "+")] + public void should_not_replace_some_special_characters_if_result_empty_string(string album, string expected) + { + Subject.AlbumTitle = album; + Subject.AlbumQuery.Should().Be(expected); } } } diff --git a/src/NzbDrone.Core.Test/IndexerTests/NewznabTests/NewznabRequestGeneratorFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/NewznabTests/NewznabRequestGeneratorFixture.cs index f36ad951b..ddbd94bd2 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/NewznabTests/NewznabRequestGeneratorFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/NewznabTests/NewznabRequestGeneratorFixture.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using FluentAssertions; using Moq; @@ -60,7 +60,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests var page = results.GetAllTiers().First().First(); - page.Url.Query.Should().Contain("artist=Alien Ant Farm"); + page.Url.Query.Should().Contain("artist=Alien%20Ant%20Farm"); page.Url.Query.Should().Contain("album=TruANT"); } } diff --git a/src/NzbDrone.Core/IndexerSearch/Definitions/AlbumSearchCriteria.cs b/src/NzbDrone.Core/IndexerSearch/Definitions/AlbumSearchCriteria.cs index a5e21ebab..b79ea3e2c 100644 --- a/src/NzbDrone.Core/IndexerSearch/Definitions/AlbumSearchCriteria.cs +++ b/src/NzbDrone.Core/IndexerSearch/Definitions/AlbumSearchCriteria.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace NzbDrone.Core.IndexerSearch.Definitions { @@ -8,6 +8,8 @@ namespace NzbDrone.Core.IndexerSearch.Definitions public string AlbumTitle { get; set; } public int AlbumYear { get; set; } + public string AlbumQuery => GetQueryTitle(AlbumTitle); + public override string ToString() { return string.Format("[{0} - {1} ({2})]", Artist.Name, AlbumTitle, AlbumYear); diff --git a/src/NzbDrone.Core/IndexerSearch/Definitions/SearchCriteriaBase.cs b/src/NzbDrone.Core/IndexerSearch/Definitions/SearchCriteriaBase.cs index b24aad1b5..8dddfd2ad 100644 --- a/src/NzbDrone.Core/IndexerSearch/Definitions/SearchCriteriaBase.cs +++ b/src/NzbDrone.Core/IndexerSearch/Definitions/SearchCriteriaBase.cs @@ -13,9 +13,6 @@ namespace NzbDrone.Core.IndexerSearch.Definitions 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); - [System.Obsolete("Sonarr TV Stuff -- Shouldn't be needed for Lidarr")] - public List SceneTitles { get; set; } - public virtual bool MonitoredEpisodesOnly { get; set; } public virtual bool UserInvokedSearch { get; set; } public virtual bool InteractiveSearch { get; set; } @@ -24,7 +21,7 @@ namespace NzbDrone.Core.IndexerSearch.Definitions public List Albums { get; set; } public List Tracks { get; set; } - public List QueryTitles => SceneTitles.Select(GetQueryTitle).ToList(); + public string ArtistQuery => GetQueryTitle(Artist.Name); public static string GetQueryTitle(string title) { @@ -32,14 +29,16 @@ namespace NzbDrone.Core.IndexerSearch.Definitions var cleanTitle = BeginningThe.Replace(title, string.Empty); - cleanTitle = cleanTitle.Replace("&", "and"); + cleanTitle = cleanTitle.Replace(" & ", " "); cleanTitle = SpecialCharacter.Replace(cleanTitle, ""); cleanTitle = NonWord.Replace(cleanTitle, "+"); //remove any repeating +s cleanTitle = Regex.Replace(cleanTitle, @"\+{2,}", "+"); cleanTitle = cleanTitle.RemoveAccent(); - return cleanTitle.Trim('+', ' '); + cleanTitle = cleanTitle.Trim('+', ' '); + + return cleanTitle.Length == 0 ? title : cleanTitle; } } } diff --git a/src/NzbDrone.Core/Indexers/Gazelle/GazelleRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Gazelle/GazelleRequestGenerator.cs index bf74d30a2..3e226dc54 100644 --- a/src/NzbDrone.Core/Indexers/Gazelle/GazelleRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Gazelle/GazelleRequestGenerator.cs @@ -30,14 +30,14 @@ namespace NzbDrone.Core.Indexers.Gazelle public IndexerPageableRequestChain GetSearchRequests(AlbumSearchCriteria searchCriteria) { var pageableRequests = new IndexerPageableRequestChain(); - pageableRequests.Add(GetRequest(string.Format("&artistname={0}&groupname={1}", searchCriteria.Artist.Name, searchCriteria.AlbumTitle))); + pageableRequests.Add(GetRequest(string.Format("&artistname={0}&groupname={1}", searchCriteria.ArtistQuery, searchCriteria.AlbumQuery))); return pageableRequests; } public IndexerPageableRequestChain GetSearchRequests(ArtistSearchCriteria searchCriteria) { var pageableRequests = new IndexerPageableRequestChain(); - pageableRequests.Add(GetRequest(string.Format("&artistname={0}",searchCriteria.Artist.Name))); + pageableRequests.Add(GetRequest(string.Format("&artistname={0}",searchCriteria.ArtistQuery))); return pageableRequests; } diff --git a/src/NzbDrone.Core/Indexers/Headphones/HeadphonesRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Headphones/HeadphonesRequestGenerator.cs index 44a649bf2..49fdc0d83 100644 --- a/src/NzbDrone.Core/Indexers/Headphones/HeadphonesRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Headphones/HeadphonesRequestGenerator.cs @@ -40,8 +40,8 @@ namespace NzbDrone.Core.Indexers.Headphones pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "search", string.Format("&q={0}", NewsnabifyTitle(string.Format("{0} {1}", - searchCriteria.Artist.Name, - searchCriteria.AlbumTitle))))); + searchCriteria.ArtistQuery, + searchCriteria.AlbumQuery))))); return pageableRequests; } @@ -54,7 +54,7 @@ namespace NzbDrone.Core.Indexers.Headphones pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "search", string.Format("&q={0}", - NewsnabifyTitle(searchCriteria.Artist.Name)))); + NewsnabifyTitle(searchCriteria.ArtistQuery)))); return pageableRequests; } diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs index 389aeed82..72fcb96ba 100644 --- a/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs @@ -71,8 +71,8 @@ namespace NzbDrone.Core.Indexers.Newznab { AddAudioPageableRequests(pageableRequests, searchCriteria, string.Format("&artist={0}&album={1}", - NewsnabifyTitle(searchCriteria.Artist.Name), - NewsnabifyTitle(searchCriteria.AlbumTitle))); + NewsnabifyTitle(searchCriteria.ArtistQuery), + NewsnabifyTitle(searchCriteria.AlbumQuery))); } if (SupportsSearch) @@ -82,8 +82,8 @@ namespace NzbDrone.Core.Indexers.Newznab pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "search", string.Format("&q={0}", NewsnabifyTitle(string.Format("{0} {1}", - searchCriteria.Artist.Name, - searchCriteria.AlbumTitle))))); + searchCriteria.ArtistQuery, + searchCriteria.AlbumQuery))))); } diff --git a/src/NzbDrone.Core/Indexers/Omgwtfnzbs/OmgwtfnzbsRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Omgwtfnzbs/OmgwtfnzbsRequestGenerator.cs index 272be331c..45a2a7414 100644 --- a/src/NzbDrone.Core/Indexers/Omgwtfnzbs/OmgwtfnzbsRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Omgwtfnzbs/OmgwtfnzbsRequestGenerator.cs @@ -31,8 +31,8 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs pageableRequests.Add(GetPagedRequests(string.Format("{0}+{1}", - searchCriteria.Artist.Name, - searchCriteria.AlbumTitle))); + searchCriteria.ArtistQuery, + searchCriteria.AlbumQuery))); return pageableRequests; @@ -44,7 +44,7 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs pageableRequests.Add(GetPagedRequests(string.Format("{0}", - searchCriteria.Artist.Name))); + searchCriteria.ArtistQuery))); return pageableRequests; diff --git a/src/NzbDrone.Core/Indexers/Rarbg/RarbgRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Rarbg/RarbgRequestGenerator.cs index 662249477..b5b14ea59 100644 --- a/src/NzbDrone.Core/Indexers/Rarbg/RarbgRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Rarbg/RarbgRequestGenerator.cs @@ -29,7 +29,7 @@ namespace NzbDrone.Core.Indexers.Rarbg { var pageableRequests = new IndexerPageableRequestChain(); - pageableRequests.Add(GetPagedRequests("search", null, "{0}+{1}", searchCriteria.Artist.Name, searchCriteria.AlbumTitle)); + pageableRequests.Add(GetPagedRequests("search", null, "{0}+{1}", searchCriteria.ArtistQuery, searchCriteria.AlbumQuery)); return pageableRequests; } @@ -38,7 +38,7 @@ namespace NzbDrone.Core.Indexers.Rarbg { var pageableRequests = new IndexerPageableRequestChain(); - pageableRequests.Add(GetPagedRequests("search", null, "{0}", searchCriteria.Artist.Name)); + pageableRequests.Add(GetPagedRequests("search", null, "{0}", searchCriteria.ArtistQuery)); return pageableRequests; } diff --git a/src/NzbDrone.Core/Indexers/Waffles/WafflesRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Waffles/WafflesRequestGenerator.cs index 44039cece..50d4589b5 100644 --- a/src/NzbDrone.Core/Indexers/Waffles/WafflesRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Waffles/WafflesRequestGenerator.cs @@ -30,7 +30,7 @@ namespace NzbDrone.Core.Indexers.Waffles { var pageableRequests = new IndexerPageableRequestChain(); - pageableRequests.Add(GetPagedRequests(MaxPages, string.Format("&q=artist:{0} album:{1}",searchCriteria.Artist.Name,searchCriteria.AlbumTitle))); + pageableRequests.Add(GetPagedRequests(MaxPages, string.Format("&q=artist:{0} album:{1}",searchCriteria.ArtistQuery,searchCriteria.AlbumQuery))); return pageableRequests; } @@ -39,7 +39,7 @@ namespace NzbDrone.Core.Indexers.Waffles { var pageableRequests = new IndexerPageableRequestChain(); - pageableRequests.Add(GetPagedRequests(MaxPages, string.Format("&q=artist:{0}", searchCriteria.Artist.Name))); + pageableRequests.Add(GetPagedRequests(MaxPages, string.Format("&q=artist:{0}", searchCriteria.ArtistQuery))); return pageableRequests; }