diff --git a/src/NzbDrone.Core/IndexerSearch/Definitions/AudiobookSearchCriteria.cs b/src/NzbDrone.Core/IndexerSearch/Definitions/AudiobookSearchCriteria.cs new file mode 100644 index 0000000000..44560117c1 --- /dev/null +++ b/src/NzbDrone.Core/IndexerSearch/Definitions/AudiobookSearchCriteria.cs @@ -0,0 +1,34 @@ +namespace NzbDrone.Core.IndexerSearch.Definitions +{ + public class AudiobookSearchCriteria : SearchCriteriaBase + { + public string Author { get; set; } + public string Title { get; set; } + public string Narrator { get; set; } + public string ASIN { get; set; } + public string ISBN { get; set; } + public int? Year { get; set; } + public bool? Abridged { get; set; } + + public override string ToString() + { + if (!string.IsNullOrWhiteSpace(Author) && !string.IsNullOrWhiteSpace(Title)) + { + var result = $"[{Author} - {Title}"; + if (!string.IsNullOrWhiteSpace(Narrator)) + { + result += $" (narrated by {Narrator})"; + } + + return result + "]"; + } + + if (!string.IsNullOrWhiteSpace(ASIN)) + { + return $"[ASIN: {ASIN}]"; + } + + return $"[{Title ?? Author ?? "Unknown"}]"; + } + } +} diff --git a/src/NzbDrone.Core/IndexerSearch/Definitions/BookSearchCriteria.cs b/src/NzbDrone.Core/IndexerSearch/Definitions/BookSearchCriteria.cs new file mode 100644 index 0000000000..1370e79b2d --- /dev/null +++ b/src/NzbDrone.Core/IndexerSearch/Definitions/BookSearchCriteria.cs @@ -0,0 +1,26 @@ +namespace NzbDrone.Core.IndexerSearch.Definitions +{ + public class BookSearchCriteria : SearchCriteriaBase + { + public string Author { get; set; } + public string Title { get; set; } + public string ISBN { get; set; } + public string Publisher { get; set; } + public int? Year { get; set; } + + public override string ToString() + { + if (!string.IsNullOrWhiteSpace(Author) && !string.IsNullOrWhiteSpace(Title)) + { + return $"[{Author} - {Title}]"; + } + + if (!string.IsNullOrWhiteSpace(ISBN)) + { + return $"[ISBN: {ISBN}]"; + } + + return $"[{Title ?? Author ?? "Unknown"}]"; + } + } +} diff --git a/src/NzbDrone.Core/Indexers/FileList/FileListRequestGenerator.cs b/src/NzbDrone.Core/Indexers/FileList/FileListRequestGenerator.cs index 6f081a4de8..d1c25c9127 100644 --- a/src/NzbDrone.Core/Indexers/FileList/FileListRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/FileList/FileListRequestGenerator.cs @@ -40,6 +40,16 @@ public virtual IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria return pageableRequests; } + public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + + public IndexerPageableRequestChain GetSearchRequests(AudiobookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + private IEnumerable GetRequest(string searchType, string parameters) { if (Settings.Categories.Empty()) diff --git a/src/NzbDrone.Core/Indexers/HDBits/HDBitsRequestGenerator.cs b/src/NzbDrone.Core/Indexers/HDBits/HDBitsRequestGenerator.cs index ed8612b2f1..7d21db9f3f 100644 --- a/src/NzbDrone.Core/Indexers/HDBits/HDBitsRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/HDBits/HDBitsRequestGenerator.cs @@ -34,6 +34,16 @@ public virtual IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria return pageableRequests; } + public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + + public IndexerPageableRequestChain GetSearchRequests(AudiobookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + private bool TryAddSearchParameters(TorrentQuery query, SearchCriteriaBase searchCriteria) { if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNullOrWhiteSpace()) diff --git a/src/NzbDrone.Core/Indexers/IIndexerRequestGenerator.cs b/src/NzbDrone.Core/Indexers/IIndexerRequestGenerator.cs index ef32b2ab09..2100a2089e 100644 --- a/src/NzbDrone.Core/Indexers/IIndexerRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/IIndexerRequestGenerator.cs @@ -8,6 +8,8 @@ public interface IIndexerRequestGenerator { IndexerPageableRequestChain GetRecentRequests(); IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria); + IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria); + IndexerPageableRequestChain GetSearchRequests(AudiobookSearchCriteria searchCriteria); Func> GetCookies { get; set; } Action, DateTime?> CookiesUpdater { get; set; } } diff --git a/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsRequestGenerator.cs b/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsRequestGenerator.cs index fbc810067a..c7995ebb44 100644 --- a/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsRequestGenerator.cs @@ -23,6 +23,16 @@ public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchC return new IndexerPageableRequestChain(); } + public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + + public IndexerPageableRequestChain GetSearchRequests(AudiobookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + private IEnumerable GetRssRequests() { yield return new IndexerRequest(Settings.BaseUrl, HttpAccept.Rss); diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs index 97a4651379..cf9550de25 100644 --- a/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs @@ -113,6 +113,66 @@ public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchC return pageableRequests; } + public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria) + { + var pageableRequests = new IndexerPageableRequestChain(); + + var categories = Settings.Categories.Any() + ? Settings.Categories + : new[] { NewznabStandardCategory.Books, NewznabStandardCategory.BooksEBook }; + + if (!string.IsNullOrWhiteSpace(searchCriteria.ISBN)) + { + pageableRequests.Add(GetPagedRequests(MaxPages, categories, "book", $"&q={Uri.EscapeDataString(searchCriteria.ISBN)}")); + } + else if (!string.IsNullOrWhiteSpace(searchCriteria.Author) && !string.IsNullOrWhiteSpace(searchCriteria.Title)) + { + var query = $"{searchCriteria.Author} {searchCriteria.Title}"; + if (searchCriteria.Year.HasValue) + { + query += $" {searchCriteria.Year}"; + } + + pageableRequests.Add(GetPagedRequests(MaxPages, categories, "book", $"&q={Uri.EscapeDataString(query)}")); + } + else if (!string.IsNullOrWhiteSpace(searchCriteria.Title)) + { + pageableRequests.Add(GetPagedRequests(MaxPages, categories, "book", $"&q={Uri.EscapeDataString(searchCriteria.Title)}")); + } + + return pageableRequests; + } + + public IndexerPageableRequestChain GetSearchRequests(AudiobookSearchCriteria searchCriteria) + { + var pageableRequests = new IndexerPageableRequestChain(); + + var categories = Settings.Categories.Any() + ? Settings.Categories + : new[] { NewznabStandardCategory.AudioAudiobook, NewznabStandardCategory.Audio }; + + if (!string.IsNullOrWhiteSpace(searchCriteria.ASIN)) + { + pageableRequests.Add(GetPagedRequests(MaxPages, categories, "search", $"&q={Uri.EscapeDataString(searchCriteria.ASIN)}")); + } + else if (!string.IsNullOrWhiteSpace(searchCriteria.Author) && !string.IsNullOrWhiteSpace(searchCriteria.Title)) + { + var query = $"{searchCriteria.Author} {searchCriteria.Title}"; + if (!string.IsNullOrWhiteSpace(searchCriteria.Narrator)) + { + query += $" {searchCriteria.Narrator}"; + } + + pageableRequests.Add(GetPagedRequests(MaxPages, categories, "search", $"&q={Uri.EscapeDataString(query)}")); + } + else if (!string.IsNullOrWhiteSpace(searchCriteria.Title)) + { + pageableRequests.Add(GetPagedRequests(MaxPages, categories, "search", $"&q={Uri.EscapeDataString(searchCriteria.Title)}")); + } + + return pageableRequests; + } + private void AddMovieIdPageableRequests(IndexerPageableRequestChain chain, int maxPages, IEnumerable categories, SearchCriteriaBase searchCriteria) { var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.Movie.MovieMetadata.Value.TmdbId > 0; diff --git a/src/NzbDrone.Core/Indexers/Nyaa/NyaaRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Nyaa/NyaaRequestGenerator.cs index 97a08a420e..fdf76bac7b 100644 --- a/src/NzbDrone.Core/Indexers/Nyaa/NyaaRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Nyaa/NyaaRequestGenerator.cs @@ -30,6 +30,16 @@ public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchC return pageableRequests; } + public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + + public IndexerPageableRequestChain GetSearchRequests(AudiobookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + private IEnumerable GetPagedRequests(string term) { var baseUrl = $"{Settings.BaseUrl.TrimEnd('/')}/?page=rss{Settings.AdditionalParameters}"; diff --git a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornRequestGenerator.cs b/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornRequestGenerator.cs index cd5ee553b0..8c22d0159d 100644 --- a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornRequestGenerator.cs @@ -43,6 +43,16 @@ public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchC return pageableRequests; } + public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + + public IndexerPageableRequestChain GetSearchRequests(AudiobookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + private IEnumerable GetRequest(string searchParameters) { var request = diff --git a/src/NzbDrone.Core/Indexers/RssIndexerRequestGenerator.cs b/src/NzbDrone.Core/Indexers/RssIndexerRequestGenerator.cs index 7897af38fb..a54b6217ab 100644 --- a/src/NzbDrone.Core/Indexers/RssIndexerRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/RssIndexerRequestGenerator.cs @@ -28,6 +28,16 @@ public virtual IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria return new IndexerPageableRequestChain(); } + public virtual IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + + public virtual IndexerPageableRequestChain GetSearchRequests(AudiobookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + public Func> GetCookies { get; set; } public Action, DateTime?> CookiesUpdater { get; set; } } diff --git a/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoRequestGenerator.cs b/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoRequestGenerator.cs index a8d8eeb1d4..557d862910 100644 --- a/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotatoRequestGenerator.cs @@ -74,6 +74,16 @@ public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchC return pageableRequests; } + public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + + public IndexerPageableRequestChain GetSearchRequests(AudiobookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + public Func> GetCookies { get; set; } public Action, DateTime?> CookiesUpdater { get; set; } } diff --git a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerRequestGenerator.cs b/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerRequestGenerator.cs index fbdad06350..d1596d7471 100644 --- a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerRequestGenerator.cs @@ -24,6 +24,16 @@ public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchC return new IndexerPageableRequestChain(); } + public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + + public IndexerPageableRequestChain GetSearchRequests(AudiobookSearchCriteria searchCriteria) + { + return new IndexerPageableRequestChain(); + } + private IEnumerable GetRssRequests(string searchParameters) { var request = new IndexerRequest(Settings.BaseUrl.Trim().TrimEnd('/'), HttpAccept.Rss);