mirror of
https://github.com/Radarr/Radarr
synced 2026-01-20 14:33:34 +01:00
New: Improve Newznab Searching (Book-Search Caps, ISBN Search)
This commit is contained in:
parent
ee43ccf620
commit
3ae3c9dfc1
13 changed files with 52 additions and 43 deletions
|
|
@ -13,7 +13,7 @@ public class AlbumSearchDefinitionFixture : CoreTest<BookSearchCriteria>
|
|||
public void should_replace_some_special_characters_artist(string artist, string expected)
|
||||
{
|
||||
Subject.Author = new Author { Name = artist };
|
||||
Subject.ArtistQuery.Should().Be(expected);
|
||||
Subject.AuthorQuery.Should().Be(expected);
|
||||
}
|
||||
|
||||
[TestCase("…and Justice for All", "and+Justice+for+All")]
|
||||
|
|
@ -25,14 +25,14 @@ public void should_replace_some_special_characters_artist(string artist, string
|
|||
public void should_replace_some_special_characters(string album, string expected)
|
||||
{
|
||||
Subject.BookTitle = album;
|
||||
Subject.AlbumQuery.Should().Be(expected);
|
||||
Subject.BookQuery.Should().Be(expected);
|
||||
}
|
||||
|
||||
[TestCase("+", "+")]
|
||||
public void should_not_replace_some_special_characters_if_result_empty_string(string album, string expected)
|
||||
{
|
||||
Subject.BookTitle = album;
|
||||
Subject.AlbumQuery.Should().Be(expected);
|
||||
Subject.BookQuery.Should().Be(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public void should_use_all_categories_for_feed()
|
|||
[Test]
|
||||
public void should_search_by_artist_and_album_if_supported()
|
||||
{
|
||||
_capabilities.SupportedAudioSearchParameters = new[] { "q", "author", "book" };
|
||||
_capabilities.SupportedBookSearchParameters = new[] { "q", "author", "title" };
|
||||
|
||||
var results = Subject.GetSearchRequests(_singleAlbumSearchCriteria);
|
||||
results.GetTier(0).Should().HaveCount(1);
|
||||
|
|
@ -59,7 +59,7 @@ public void should_search_by_artist_and_album_if_supported()
|
|||
var page = results.GetAllTiers().First().First();
|
||||
|
||||
page.Url.Query.Should().Contain("author=Alien%20Ant%20Farm");
|
||||
page.Url.Query.Should().Contain("book=TruANT");
|
||||
page.Url.Query.Should().Contain("title=TruANT");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ public class BookSearchCriteria : SearchCriteriaBase
|
|||
{
|
||||
public string BookTitle { get; set; }
|
||||
public int BookYear { get; set; }
|
||||
public string BookIsbn { get; set; }
|
||||
public string Disambiguation { get; set; }
|
||||
|
||||
public string AlbumQuery => GetQueryTitle($"{BookTitle}{(Disambiguation.IsNullOrWhiteSpace() ? string.Empty : $"+{Disambiguation}")}");
|
||||
public string BookQuery => GetQueryTitle($"{BookTitle}{(Disambiguation.IsNullOrWhiteSpace() ? string.Empty : $"+{Disambiguation}")}");
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public abstract class SearchCriteriaBase
|
|||
public Author Author { get; set; }
|
||||
public List<Book> Books { get; set; }
|
||||
|
||||
public string ArtistQuery => GetQueryTitle(Author.Name);
|
||||
public string AuthorQuery => GetQueryTitle(Author.Name);
|
||||
|
||||
public static string GetQueryTitle(string title)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public NzbSearchService(IIndexerFactory indexerFactory,
|
|||
public List<DownloadDecision> BookSearch(int bookId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch)
|
||||
{
|
||||
var book = _bookService.GetBook(bookId);
|
||||
return AlbumSearch(book, missingOnly, userInvokedSearch, interactiveSearch);
|
||||
return BookSearch(book, missingOnly, userInvokedSearch, interactiveSearch);
|
||||
}
|
||||
|
||||
public List<DownloadDecision> AuthorSearch(int authorId, bool missingOnly, bool userInvokedSearch, bool interactiveSearch)
|
||||
|
|
@ -56,22 +56,23 @@ public List<DownloadDecision> AuthorSearch(int authorId, bool missingOnly, bool
|
|||
public List<DownloadDecision> ArtistSearch(Author author, bool missingOnly, bool userInvokedSearch, bool interactiveSearch)
|
||||
{
|
||||
var searchSpec = Get<AuthorSearchCriteria>(author, userInvokedSearch, interactiveSearch);
|
||||
var albums = _bookService.GetBooksByAuthor(author.Id);
|
||||
var books = _bookService.GetBooksByAuthor(author.Id);
|
||||
|
||||
albums = albums.Where(a => a.Monitored).ToList();
|
||||
books = books.Where(a => a.Monitored).ToList();
|
||||
|
||||
searchSpec.Books = albums;
|
||||
searchSpec.Books = books;
|
||||
|
||||
return Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec);
|
||||
}
|
||||
|
||||
public List<DownloadDecision> AlbumSearch(Book book, bool missingOnly, bool userInvokedSearch, bool interactiveSearch)
|
||||
public List<DownloadDecision> BookSearch(Book book, bool missingOnly, bool userInvokedSearch, bool interactiveSearch)
|
||||
{
|
||||
var author = _authorService.GetAuthor(book.AuthorId);
|
||||
|
||||
var searchSpec = Get<BookSearchCriteria>(author, new List<Book> { book }, userInvokedSearch, interactiveSearch);
|
||||
|
||||
searchSpec.BookTitle = book.Title;
|
||||
searchSpec.BookIsbn = book.Isbn13;
|
||||
if (book.ReleaseDate.HasValue)
|
||||
{
|
||||
searchSpec.BookYear = book.ReleaseDate.Value.Year;
|
||||
|
|
|
|||
|
|
@ -29,14 +29,14 @@ public virtual IndexerPageableRequestChain GetRecentRequests()
|
|||
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
|
||||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
pageableRequests.Add(GetRequest(string.Format("&artistname={0}&groupname={1}", searchCriteria.ArtistQuery, searchCriteria.AlbumQuery)));
|
||||
pageableRequests.Add(GetRequest(string.Format("&artistname={0}&groupname={1}", searchCriteria.AuthorQuery, searchCriteria.BookQuery)));
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
public IndexerPageableRequestChain GetSearchRequests(AuthorSearchCriteria searchCriteria)
|
||||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
pageableRequests.Add(GetRequest(string.Format("&artistname={0}", searchCriteria.ArtistQuery)));
|
||||
pageableRequests.Add(GetRequest(string.Format("&artistname={0}", searchCriteria.AuthorQuery)));
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,8 +111,8 @@ protected virtual ValidationFailure TestCapabilities()
|
|||
return null;
|
||||
}
|
||||
|
||||
if (capabilities.SupportedAudioSearchParameters != null &&
|
||||
new[] { "author", "book" }.All(v => capabilities.SupportedAudioSearchParameters.Contains(v)))
|
||||
if (capabilities.SupportedBookSearchParameters != null &&
|
||||
new[] { "author", "book" }.All(v => capabilities.SupportedBookSearchParameters.Contains(v)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.Newznab
|
||||
{
|
||||
|
|
@ -8,7 +8,7 @@ public class NewznabCapabilities
|
|||
public int MaxPageSize { get; set; }
|
||||
public string[] SupportedSearchParameters { get; set; }
|
||||
public string[] SupportedTvSearchParameters { get; set; }
|
||||
public string[] SupportedAudioSearchParameters { get; set; }
|
||||
public string[] SupportedBookSearchParameters { get; set; }
|
||||
public bool SupportsAggregateIdSearch { get; set; }
|
||||
public List<NewznabCategory> Categories { get; set; }
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ public NewznabCapabilities()
|
|||
MaxPageSize = 100;
|
||||
SupportedSearchParameters = new[] { "q" };
|
||||
SupportedTvSearchParameters = new[] { "q", "rid", "season", "ep" }; // This should remain 'rid' for older newznab installs.
|
||||
SupportedAudioSearchParameters = new[] { "q", "author", "book" };
|
||||
SupportedBookSearchParameters = new[] { "q", "author", "title" };
|
||||
SupportsAggregateIdSearch = false;
|
||||
Categories = new List<NewznabCategory>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,14 +128,14 @@ private NewznabCapabilities ParseCapabilities(HttpResponse response)
|
|||
capabilities.SupportsAggregateIdSearch = true;
|
||||
}
|
||||
|
||||
var xmlAudioSearch = xmlSearching.Element("audio-search");
|
||||
var xmlAudioSearch = xmlSearching.Element("book-search");
|
||||
if (xmlAudioSearch == null || xmlAudioSearch.Attribute("available").Value != "yes")
|
||||
{
|
||||
capabilities.SupportedAudioSearchParameters = null;
|
||||
capabilities.SupportedBookSearchParameters = null;
|
||||
}
|
||||
else if (xmlAudioSearch.Attribute("supportedParams") != null)
|
||||
{
|
||||
capabilities.SupportedAudioSearchParameters = xmlAudioSearch.Attribute("supportedParams").Value.Split(',');
|
||||
capabilities.SupportedBookSearchParameters = xmlAudioSearch.Attribute("supportedParams").Value.Split(',');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@ private bool SupportsAudioSearch
|
|||
{
|
||||
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
|
||||
|
||||
return capabilities.SupportedAudioSearchParameters != null &&
|
||||
capabilities.SupportedAudioSearchParameters.Contains("q") &&
|
||||
capabilities.SupportedAudioSearchParameters.Contains("author") &&
|
||||
capabilities.SupportedAudioSearchParameters.Contains("book");
|
||||
return capabilities.SupportedBookSearchParameters != null &&
|
||||
capabilities.SupportedBookSearchParameters.Contains("q") &&
|
||||
capabilities.SupportedBookSearchParameters.Contains("author") &&
|
||||
capabilities.SupportedBookSearchParameters.Contains("title");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -51,9 +51,9 @@ public virtual IndexerPageableRequestChain GetRecentRequests()
|
|||
|
||||
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
|
||||
|
||||
if (capabilities.SupportedAudioSearchParameters != null)
|
||||
if (capabilities.SupportedBookSearchParameters != null)
|
||||
{
|
||||
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "music", ""));
|
||||
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "book", ""));
|
||||
}
|
||||
else if (capabilities.SupportedSearchParameters != null)
|
||||
{
|
||||
|
|
@ -69,9 +69,9 @@ public virtual IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria
|
|||
|
||||
if (SupportsAudioSearch)
|
||||
{
|
||||
AddAudioPageableRequests(pageableRequests,
|
||||
AddBookPageableRequests(pageableRequests,
|
||||
searchCriteria,
|
||||
NewsnabifyTitle($"&author={searchCriteria.ArtistQuery}&book={searchCriteria.AlbumQuery}"));
|
||||
NewsnabifyTitle($"&author={searchCriteria.AuthorQuery}&title={searchCriteria.BookQuery}"));
|
||||
}
|
||||
|
||||
if (SupportsSearch)
|
||||
|
|
@ -81,7 +81,14 @@ public virtual IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria
|
|||
pageableRequests.Add(GetPagedRequests(MaxPages,
|
||||
Settings.Categories,
|
||||
"search",
|
||||
NewsnabifyTitle($"&q={searchCriteria.ArtistQuery}+{searchCriteria.AlbumQuery}")));
|
||||
NewsnabifyTitle($"&q={searchCriteria.BookIsbn}")));
|
||||
|
||||
pageableRequests.AddTier();
|
||||
|
||||
pageableRequests.Add(GetPagedRequests(MaxPages,
|
||||
Settings.Categories,
|
||||
"search",
|
||||
NewsnabifyTitle($"&q={searchCriteria.AuthorQuery}+{searchCriteria.BookQuery}")));
|
||||
}
|
||||
|
||||
return pageableRequests;
|
||||
|
|
@ -93,9 +100,9 @@ public virtual IndexerPageableRequestChain GetSearchRequests(AuthorSearchCriteri
|
|||
|
||||
if (SupportsAudioSearch)
|
||||
{
|
||||
AddAudioPageableRequests(pageableRequests,
|
||||
AddBookPageableRequests(pageableRequests,
|
||||
searchCriteria,
|
||||
NewsnabifyTitle($"&author={searchCriteria.ArtistQuery}"));
|
||||
NewsnabifyTitle($"&author={searchCriteria.AuthorQuery}"));
|
||||
}
|
||||
|
||||
if (SupportsSearch)
|
||||
|
|
@ -105,17 +112,17 @@ public virtual IndexerPageableRequestChain GetSearchRequests(AuthorSearchCriteri
|
|||
pageableRequests.Add(GetPagedRequests(MaxPages,
|
||||
Settings.Categories,
|
||||
"search",
|
||||
NewsnabifyTitle($"&q={searchCriteria.ArtistQuery}")));
|
||||
NewsnabifyTitle($"&q={searchCriteria.AuthorQuery}")));
|
||||
}
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private void AddAudioPageableRequests(IndexerPageableRequestChain chain, SearchCriteriaBase searchCriteria, string parameters)
|
||||
private void AddBookPageableRequests(IndexerPageableRequestChain chain, SearchCriteriaBase searchCriteria, string parameters)
|
||||
{
|
||||
chain.AddTier();
|
||||
|
||||
chain.Add(GetPagedRequests(MaxPages, Settings.Categories, "music", $"&q={parameters}"));
|
||||
chain.Add(GetPagedRequests(MaxPages, Settings.Categories, "book", $"&q={parameters}"));
|
||||
}
|
||||
|
||||
private IEnumerable<IndexerRequest> GetPagedRequests(int maxPages, IEnumerable<int> categories, string searchType, string parameters)
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ public virtual IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria
|
|||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
|
||||
pageableRequests.Add(GetPagedRequests(string.Format("{0}+{1}",
|
||||
searchCriteria.ArtistQuery,
|
||||
searchCriteria.AlbumQuery)));
|
||||
searchCriteria.AuthorQuery,
|
||||
searchCriteria.BookQuery)));
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ public virtual IndexerPageableRequestChain GetSearchRequests(AuthorSearchCriteri
|
|||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
|
||||
pageableRequests.Add(GetPagedRequests(string.Format("{0}",
|
||||
searchCriteria.ArtistQuery)));
|
||||
searchCriteria.AuthorQuery)));
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public virtual IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria
|
|||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
|
||||
pageableRequests.Add(GetPagedRequests("search", null, "{0}+{1}", searchCriteria.ArtistQuery, searchCriteria.AlbumQuery));
|
||||
pageableRequests.Add(GetPagedRequests("search", null, "{0}+{1}", searchCriteria.AuthorQuery, searchCriteria.BookQuery));
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
|
@ -39,7 +39,7 @@ public virtual IndexerPageableRequestChain GetSearchRequests(AuthorSearchCriteri
|
|||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
|
||||
pageableRequests.Add(GetPagedRequests("search", null, "{0}", searchCriteria.ArtistQuery));
|
||||
pageableRequests.Add(GetPagedRequests("search", null, "{0}", searchCriteria.AuthorQuery));
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,8 +91,8 @@ protected virtual ValidationFailure TestCapabilities()
|
|||
return null;
|
||||
}
|
||||
|
||||
if (capabilities.SupportedAudioSearchParameters != null &&
|
||||
new[] { "author", "book" }.All(v => capabilities.SupportedAudioSearchParameters.Contains(v)))
|
||||
if (capabilities.SupportedBookSearchParameters != null &&
|
||||
new[] { "author", "title" }.All(v => capabilities.SupportedBookSearchParameters.Contains(v)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue