Lots of workings to search processing, UI Categories

pull/6/head
Qstick 4 years ago
parent 710b4f5ec6
commit 8e72c7153d

@ -4,48 +4,25 @@ import Label from 'Components/Label';
function CapabilitiesLabel(props) {
const {
movieSearchAvailable,
tvSearchAvailable,
musicSearchAvailable,
bookSearchAvailable
categories
} = props.capabilities;
const filteredList = categories.filter((item) => item.id < 100000).map((item) => item.name).sort();
return (
<span>
{
bookSearchAvailable ?
<Label>
{'Books'}
</Label> :
null
}
{
movieSearchAvailable ?
<Label>
{'Movies'}
</Label> :
null
}
{
musicSearchAvailable ?
<Label>
{'Music'}
</Label> :
null
}
{
tvSearchAvailable ?
<Label>
{'TV'}
</Label> :
null
filteredList.map((category) => {
return (
<Label key={category}>
{category}
</Label>
);
})
}
{
!tvSearchAvailable && !musicSearchAvailable && !movieSearchAvailable && !bookSearchAvailable ?
filteredList.length === 0 ?
<Label>
{'None'}
</Label> :
@ -61,10 +38,7 @@ CapabilitiesLabel.propTypes = {
CapabilitiesLabel.defaultProps = {
capabilities: {
movieSearchAvailable: false,
tvSearchAvailable: false,
musicSearchAvailable: false,
bookSearchAvailable: false
categories: []
}
};

@ -21,7 +21,7 @@
.capabilities {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
flex: 0 0 180px;
flex: 0 0 350px;
}
.added {

@ -28,7 +28,7 @@
.capabilities {
composes: cell;
flex: 0 0 180px;
flex: 0 0 350px;
}
.added {

@ -0,0 +1,23 @@
import PropTypes from 'prop-types';
import React from 'react';
import Label from 'Components/Label';
function CategoryLabel({ categories }) {
let catName = '';
if (categories && categories.length > 0) {
catName = categories[0].name;
}
return (
<Label>
{catName}
</Label>
);
}
CategoryLabel.propTypes = {
categories: PropTypes.arrayOf(PropTypes.object).isRequired
};
export default CategoryLabel;

@ -10,6 +10,7 @@
flex: 4 0 110px;
}
.category,
.indexer {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';

@ -17,6 +17,7 @@
flex: 4 0 110px;
}
.category,
.indexer {
composes: cell;

@ -10,6 +10,7 @@ import formatDateTime from 'Utilities/Date/formatDateTime';
import formatAge from 'Utilities/Number/formatAge';
import formatBytes from 'Utilities/Number/formatBytes';
import translate from 'Utilities/String/translate';
import CategoryLabel from './CategoryLabel';
import Peers from './Peers';
import ProtocolLabel from './ProtocolLabel';
import styles from './SearchIndexRow.css';
@ -22,6 +23,7 @@ class SearchIndexRow extends Component {
render() {
const {
protocol,
categories,
age,
ageHours,
ageMinutes,
@ -132,6 +134,19 @@ class SearchIndexRow extends Component {
);
}
if (column.name === 'category') {
return (
<VirtualTableRowCell
key={column.name}
className={styles[column.name]}
>
<CategoryLabel
categories={categories}
/>
</VirtualTableRowCell>
);
}
if (column.name === 'indexerFlags') {
return (
<VirtualTableRowCell
@ -192,6 +207,7 @@ class SearchIndexRow extends Component {
SearchIndexRow.propTypes = {
guid: PropTypes.string.isRequired,
categories: PropTypes.arrayOf(PropTypes.object).isRequired,
protocol: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
ageHours: PropTypes.number.isRequired,

@ -66,6 +66,12 @@ export const defaultState = {
isSortable: true,
isVisible: true
},
{
name: 'category',
label: translate('Category'),
isSortable: true,
isVisible: true
},
{
name: 'indexerFlags',
label: React.createElement(Icon, { name: icons.FLAG }),

@ -34,25 +34,6 @@ namespace NzbDrone.Core.Test.IndexerTests.HDBitsTests
_movieSearchCriteria.ImdbId = null;
}
[Test]
public void should_use_all_categories_for_feed()
{
var results = Subject.GetRecentRequests();
results.GetAllTiers().Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
var encoding = HttpHeader.GetEncodingFromContentType(page.HttpRequest.Headers.ContentType);
var body = encoding.GetString(page.HttpRequest.ContentData);
var query = JsonConvert.DeserializeObject<TorrentQuery>(body);
query.Category.Should().HaveCount(2);
query.Username.Should().Be(Subject.Settings.Username);
query.Passkey.Should().Be(Subject.Settings.ApiKey);
}
[Test]
public void should_search_by_imdbid_if_supported()
{

@ -36,30 +36,6 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
.Returns(_capabilities);
}
[Test]
public void should_use_all_categories_for_feed()
{
var results = Subject.GetRecentRequests();
results.GetAllTiers().Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
page.Url.Query.Should().Contain("&cat=1,2&");
}
[Test]
public void should_not_have_duplicate_categories()
{
var results = Subject.GetRecentRequests();
results.GetAllTiers().Should().HaveCount(1);
var page = results.GetAllTiers().First().First();
page.Url.FullUri.Should().Contain("&cat=1,2,3&");
}
[Test]
public void should_return_subsequent_pages()
{

@ -108,7 +108,7 @@ namespace NzbDrone.Core.Applications.Lidarr
Fields = schema.Fields,
};
lidarrIndexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value = $"{Settings.ProwlarrUrl}/api/v1/indexer/1/";
lidarrIndexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value = $"{Settings.ProwlarrUrl}/api/v1/indexer/{indexer.Id}/";
lidarrIndexer.Fields.FirstOrDefault(x => x.Name == "apiPath").Value = "/newznab";
lidarrIndexer.Fields.FirstOrDefault(x => x.Name == "apiKey").Value = _configFileProvider.ApiKey;

@ -108,7 +108,7 @@ namespace NzbDrone.Core.Applications.Radarr
Fields = schema.Fields,
};
radarrIndexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value = $"{Settings.ProwlarrUrl}/api/v1/indexer/1/";
radarrIndexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value = $"{Settings.ProwlarrUrl}/api/v1/indexer/{indexer.Id}/";
radarrIndexer.Fields.FirstOrDefault(x => x.Name == "apiPath").Value = "/newznab";
radarrIndexer.Fields.FirstOrDefault(x => x.Name == "apiKey").Value = _configFileProvider.ApiKey;

@ -108,7 +108,7 @@ namespace NzbDrone.Core.Applications.Readarr
Fields = schema.Fields,
};
readarrIndexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value = $"{Settings.ProwlarrUrl}/api/v1/indexer/1/";
readarrIndexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value = $"{Settings.ProwlarrUrl}/api/v1/indexer/{indexer.Id}/";
readarrIndexer.Fields.FirstOrDefault(x => x.Name == "apiPath").Value = "/newznab";
readarrIndexer.Fields.FirstOrDefault(x => x.Name == "apiKey").Value = _configFileProvider.ApiKey;

@ -108,7 +108,7 @@ namespace NzbDrone.Core.Applications.Sonarr
Fields = schema.Fields,
};
sonarrIndexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value = $"{Settings.ProwlarrUrl}/api/v1/indexer/1/";
sonarrIndexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value = $"{Settings.ProwlarrUrl}/api/v1/indexer/{indexer.Id}/";
sonarrIndexer.Fields.FirstOrDefault(x => x.Name == "apiPath").Value = "/newznab";
sonarrIndexer.Fields.FirstOrDefault(x => x.Name == "apiKey").Value = _configFileProvider.ApiKey;

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NzbDrone.Core.IndexerSearch.Definitions
{
public class BasicSearchCriteria : SearchCriteriaBase
{
}
}

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NzbDrone.Core.IndexerSearch.Definitions
{
public class BookSearchCriteria : SearchCriteriaBase
{
}
}

@ -3,10 +3,8 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
public class MovieSearchCriteria : SearchCriteriaBase
{
public string ImdbId { get; set; }
public int TmdbId { get; set; }
public override string ToString()
{
return string.Format("[{0}]", ImdbId);
}
public int? TmdbId { get; set; }
public int? Year { get; set; }
public int? TraktId { get; set; }
}
}

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NzbDrone.Core.IndexerSearch.Definitions
{
public class MusicSearchCriteria : SearchCriteriaBase
{
public string Album { get; set; }
public string Artist { get; set; }
public string Label { get; set; }
}
}

@ -16,5 +16,8 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
public List<int> IndexerIds { get; set; }
public string SearchTerm { get; set; }
public int[] Categories { get; set; }
public string SearchType { get; set; }
public int? Limit { get; set; }
public int? Offset { get; set; }
}
}

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NzbDrone.Core.IndexerSearch.Definitions
{
public class TvSearchCriteria : SearchCriteriaBase
{
public int? Season { get; set; }
public int? Ep { get; set; }
public string ImdbId { get; set; }
public int? TvdbId { get; set; }
public int? RId { get; set; }
public int? TvMazeId { get; set; }
public int? TraktId { get; set; }
}
}

@ -7,19 +7,21 @@ namespace NzbDrone.Core.IndexerSearch
public string q { get; set; }
public string cat { get; set; }
public string imdbid { get; set; }
public string tmdbid { get; set; }
public int? tmdbid { get; set; }
public string extended { get; set; }
public string limit { get; set; }
public string offset { get; set; }
public string rid { get; set; }
public string tvdbid { get; set; }
public string season { get; set; }
public string ep { get; set; }
public int? limit { get; set; }
public int? offset { get; set; }
public int? rid { get; set; }
public int? tvmazeid { get; set; }
public int? traktid { get; set; }
public int? tvdbid { get; set; }
public int? season { get; set; }
public int? ep { get; set; }
public string album { get; set; }
public string artist { get; set; }
public string label { get; set; }
public string track { get; set; }
public string year { get; set; }
public int? year { get; set; }
public string genre { get; set; }
public string author { get; set; }
public string title { get; set; }

@ -72,12 +72,14 @@ namespace NzbDrone.Core.IndexerSearch
new XElement("guid", r.Guid), // GUID and (Link or Magnet) are mandatory
new XElement("prowlarrindexer", new XAttribute("id", r.IndexerId), r.Indexer),
r.PublishDate == DateTime.MinValue ? new XElement("pubDate", XmlDateFormat(DateTime.Now)) : new XElement("pubDate", XmlDateFormat(r.PublishDate)),
r.Category == null ? null : from c in r.Category select new XElement("category", c),
new XElement("size", r.Size),
r.Category == null ? null : from c in r.Category select new XElement("category", c.Id),
new XElement(
"enclosure",
new XAttribute("length", r.Size),
new XAttribute("url", r.DownloadUrl ?? t.MagnetUrl ?? string.Empty),
r.Size == null ? null : new XAttribute("length", r.Size),
new XAttribute("type", "application/x-bittorrent")),
r.Category == null ? null : from c in r.Category select GetTorznabElement("category", c.Id),
GetTorznabElement("rageid", r.TvRageId),
GetTorznabElement("thetvdb", r.TvdbId),
GetTorznabElement("imdb", r.ImdbId.ToString("D7")),

@ -16,7 +16,6 @@ namespace NzbDrone.Core.IndexerSearch
{
public interface ISearchForNzb
{
List<ReleaseInfo> Search(string query, List<int> indexerIds, bool interactiveSearch);
NewznabResults Search(NewznabRequest request, List<int> indexerIds, bool interactiveSearch);
}
@ -35,17 +34,70 @@ namespace NzbDrone.Core.IndexerSearch
_logger = logger;
}
public List<ReleaseInfo> Search(string query, List<int> indexerIds, bool interactiveSearch)
public NewznabResults Search(NewznabRequest request, List<int> indexerIds, bool interactiveSearch)
{
var searchSpec = Get<MovieSearchCriteria>(new NewznabRequest { q = query }, indexerIds, interactiveSearch);
var results = new NewznabResults();
return Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec);
switch (request.t)
{
case "movie":
return MovieSearch(request, indexerIds, interactiveSearch);
case "music":
return MusicSearch(request, indexerIds, interactiveSearch);
case "tvsearch":
return TvSearch(request, indexerIds, interactiveSearch);
case "book":
return BookSearch(request, indexerIds, interactiveSearch);
default:
return BasicSearch(request, indexerIds, interactiveSearch);
}
}
public NewznabResults Search(NewznabRequest request, List<int> indexerIds, bool interactiveSearch)
private NewznabResults MovieSearch(NewznabRequest request, List<int> indexerIds, bool interactiveSearch)
{
var searchSpec = Get<MovieSearchCriteria>(request, indexerIds, interactiveSearch);
searchSpec.ImdbId = request.imdbid;
searchSpec.TmdbId = request.tmdbid;
searchSpec.TraktId = request.traktid;
searchSpec.Year = request.year;
return new NewznabResults { Releases = Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec) };
}
private NewznabResults MusicSearch(NewznabRequest request, List<int> indexerIds, bool interactiveSearch)
{
var searchSpec = Get<MusicSearchCriteria>(request, indexerIds, interactiveSearch);
return new NewznabResults { Releases = Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec) };
}
private NewznabResults TvSearch(NewznabRequest request, List<int> indexerIds, bool interactiveSearch)
{
var searchSpec = Get<TvSearchCriteria>(request, indexerIds, interactiveSearch);
searchSpec.Season = request.season;
searchSpec.Ep = request.ep;
searchSpec.TvdbId = request.tvdbid;
searchSpec.ImdbId = request.imdbid;
searchSpec.TraktId = request.traktid;
searchSpec.RId = request.rid;
searchSpec.TvMazeId = request.tvmazeid;
return new NewznabResults { Releases = Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec) };
}
private NewznabResults BookSearch(NewznabRequest request, List<int> indexerIds, bool interactiveSearch)
{
var searchSpec = Get<TvSearchCriteria>(request, indexerIds, interactiveSearch);
return new NewznabResults { Releases = Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec) };
}
private NewznabResults BasicSearch(NewznabRequest request, List<int> indexerIds, bool interactiveSearch)
{
var searchSpec = Get<BasicSearchCriteria>(request, indexerIds, interactiveSearch);
return new NewznabResults { Releases = Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec) };
}
@ -67,6 +119,9 @@ namespace NzbDrone.Core.IndexerSearch
}
spec.SearchTerm = query.q;
spec.SearchType = query.t;
spec.Limit = query.limit;
spec.Offset = query.offset;
spec.IndexerIds = indexerIds;

@ -37,5 +37,25 @@ namespace NzbDrone.Core.Indexers.AwesomeHD
yield return new IndexerRequest($"{Settings.BaseUrl.Trim().TrimEnd('/')}/searchapi.php?action=latestmovies&passkey={Settings.Passkey.Trim()}", HttpAccept.Rss);
}
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
}
}

@ -2,6 +2,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using AngleSharp.Dom;
@ -9,7 +10,6 @@ using Newtonsoft.Json.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.IndexerSearch.Definitions;
namespace NzbDrone.Core.Indexers.Cardigann
{
@ -22,7 +22,8 @@ namespace NzbDrone.Core.Indexers.Cardigann
protected string SiteLink { get; private set; }
/* protected readonly List<CategoryMapping> categoryMapping = new List<CategoryMapping>(); */
protected readonly List<CategoryMapping> _categoryMapping = new List<CategoryMapping>();
protected readonly List<string> _defaultCategories = new List<string>();
protected readonly string[] OptionalFields = new string[] { "imdb", "rageid", "tvdbid", "banner" };
@ -54,6 +55,70 @@ namespace NzbDrone.Core.Indexers.Cardigann
_logger = logger;
SiteLink = definition.Links.First();
if (_definition.Caps.Categories != null)
{
foreach (var category in _definition.Caps.Categories)
{
var cat = TorznabCatType.GetCatByName(category.Value);
if (cat == null)
{
_logger.Error(string.Format("CardigannIndexer ({0}): invalid Torznab category for id {1}: {2}", _definition.Id, category.Key, category.Value));
continue;
}
AddCategoryMapping(category.Key, cat);
}
}
if (_definition.Caps.Categorymappings != null)
{
foreach (var categorymapping in _definition.Caps.Categorymappings)
{
IndexerCategory torznabCat = null;
if (categorymapping.cat != null)
{
torznabCat = TorznabCatType.GetCatByName(categorymapping.cat);
if (torznabCat == null)
{
_logger.Error(string.Format("CardigannIndexer ({0}): invalid Torznab category for id {1}: {2}", _definition.Id, categorymapping.id, categorymapping.cat));
continue;
}
}
AddCategoryMapping(categorymapping.id, torznabCat, categorymapping.desc);
if (categorymapping.Default)
{
_defaultCategories.Add(categorymapping.id);
}
}
}
}
public void AddCategoryMapping(string trackerCategory, IndexerCategory torznabCategory, string trackerCategoryDesc = null)
{
_categoryMapping.Add(new CategoryMapping(trackerCategory, trackerCategoryDesc, torznabCategory.Id));
if (trackerCategoryDesc == null)
{
return;
}
// create custom cats (1:1 categories) if trackerCategoryDesc is defined
// - if trackerCategory is "integer" we use that number to generate custom category id
// - if trackerCategory is "string" we compute a hash to generate fixed integer id for the custom category
// the hash is not perfect but it should work in most cases. we can't use sequential numbers because
// categories are updated frequently and the id must be fixed to work in 3rd party apps
if (!int.TryParse(trackerCategory, out var trackerCategoryInt))
{
var hashed = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(trackerCategory));
trackerCategoryInt = BitConverter.ToUInt16(hashed, 0); // id between 0 and 65535 < 100000
}
var customCat = new IndexerCategory(trackerCategoryInt + 100000, trackerCategoryDesc);
_categoryMapping.Add(new CategoryMapping(trackerCategory, trackerCategoryDesc, customCat.Id));
}
protected IElement QuerySelector(IElement element, string selector)
@ -186,53 +251,36 @@ namespace NzbDrone.Core.Indexers.Cardigann
return variables;
}
protected ICollection<int> MapTrackerCatToNewznab(string input)
protected ICollection<IndexerCategory> MapTrackerCatToNewznab(string input)
{
if (input == null)
{
return new List<int>();
}
var cats = _definition.Caps.Categorymappings.Where(m => m.id != null && m.id.ToLowerInvariant() == input.ToLowerInvariant()).Select(c => TorznabCatType.GetCatByName(c.cat).Id).ToList();
// 1:1 category mapping
try
if (string.IsNullOrWhiteSpace(input))
{
var trackerCategoryInt = int.Parse(input);
cats.Add(trackerCategoryInt + 100000);
}
catch (FormatException)
{
// input is not an integer, continue
return new List<IndexerCategory>();
}
var cats = _categoryMapping
.Where(m =>
!string.IsNullOrWhiteSpace(m.TrackerCategory) &&
string.Equals(m.TrackerCategory, input, StringComparison.InvariantCultureIgnoreCase))
.Select(c => TorznabCatType.AllCats.FirstOrDefault(n => n.Id == c.NewzNabCategory) ?? new IndexerCategory { Id = c.NewzNabCategory })
.ToList();
return cats;
}
public List<string> MapTorznabCapsToTrackers(int[] searchCategories, bool mapChildrenCatsToParent = false)
{
var queryCats = new List<string>();
if (searchCategories == null)
{
return queryCats;
return new List<string>();
}
foreach (var searchCat in searchCategories)
{
var match = TorznabCatType.AllCats.FirstOrDefault(c => c.Id == searchCat);
if (match != null)
{
queryCats.Add(match.Name);
}
}
var results = new List<string>();
var result = _definition.Caps.Categorymappings
.Where(c => queryCats.Contains(c.cat))
.Select(mapping => mapping.id).Distinct().ToList();
results.AddRange(_categoryMapping
.Where(c => searchCategories.Contains(c.NewzNabCategory))
.Select(mapping => mapping.TrackerCategory).Distinct().ToList());
return result;
return results;
}
protected delegate string TemplateTextModifier(string str);

@ -472,13 +472,14 @@ namespace NzbDrone.Core.Indexers.Cardigann
result.AddRange(releases.Select(x => new TorrentInfo
{
PublishDate = x.PublishDate,
Guid = x.Guid.ToString(),
Title = x.Title,
Size = x.Size.Value,
DownloadUrl = x.Link?.ToString(),
DownloadUrl = x.Link.AbsoluteUri,
CommentUrl = x.Comments?.ToString(),
InfoUrl = x.Link?.ToString(),
MagnetUrl = x.MagnetUri?.ToString(),
MagnetUrl = x.MagnetUri?.AbsoluteUri,
InfoHash = x.InfoHash,
Seeders = (int?)x.Seeders,
Peers = (int?)x.Peers,

@ -11,7 +11,7 @@ namespace NzbDrone.Core.Indexers.Cardigann
public Uri Link { get; set; }
public Uri Comments { get; set; }
public DateTime PublishDate { get; set; }
public ICollection<int> Category { get; set; }
public ICollection<IndexerCategory> Category { get; set; }
public long? Size { get; set; }
public long? Files { get; set; }
public long? Grabs { get; set; }

@ -10,8 +10,6 @@ namespace NzbDrone.Core.Indexers.Cardigann
{
public class CardigannRequestGenerator : CardigannBase, IIndexerRequestGenerator
{
private List<string> _defaultCategories = new List<string>();
public CardigannRequestGenerator(CardigannDefinition definition,
CardigannSettings settings,
Logger logger)
@ -22,71 +20,134 @@ namespace NzbDrone.Core.Indexers.Cardigann
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
public virtual IndexerPageableRequestChain GetRecentRequests()
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
_logger.Trace("Getting recent");
_logger.Trace("Getting search");
var pageableRequests = new IndexerPageableRequestChain();
var variables = GetBaseTemplateVariables();
var variables = GetQueryVariableDefaults(searchCriteria);
variables[".Query.Type"] = null;
variables[".Query.Q"] = null;
variables[".Query.Categories"] = null;
variables[".Query.IMDBID"] = null;
variables[".Query.IMDBIDShort"] = null;
variables[".Query.TMDBID"] = null;
variables[".Query.Movie"] = null;
variables[".Query.Year"] = searchCriteria.Year;
variables[".Query.IMDBID"] = searchCriteria.ImdbId;
variables[".Query.IMDBIDShort"] = searchCriteria.ImdbId.Replace("tt", "");
variables[".Query.TMDBID"] = searchCriteria.TmdbId;
variables[".Query.TraktID"] = searchCriteria.TraktId;
pageableRequests.Add(GetRequest(variables));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
_logger.Trace("Getting search");
var pageableRequests = new IndexerPageableRequestChain();
var variables = GetQueryVariableDefaults(searchCriteria);
variables[".Query.Album"] = searchCriteria.Album;
variables[".Query.Artist"] = searchCriteria.Artist;
variables[".Query.Label"] = searchCriteria.Label;
variables[".Query.Track"] = null;
pageableRequests.Add(GetRequest(variables));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var variables = GetBaseTemplateVariables();
var variables = GetQueryVariableDefaults(searchCriteria);
variables[".Query.Type"] = "movie";
variables[".Query.Q"] = searchCriteria.SearchTerm;
variables[".Query.Categories"] = searchCriteria.Categories;
variables[".Query.Series"] = null;
variables[".Query.Ep"] = searchCriteria.Ep;
variables[".Query.Season"] = searchCriteria.Season;
variables[".Query.IMDBID"] = searchCriteria.ImdbId;
variables[".Query.IMDBIDShort"] = null;
variables[".Query.TMDBID"] = searchCriteria.TmdbId;
variables[".Query.IMDBIDShort"] = searchCriteria.ImdbId.Replace("tt", "");
variables[".Query.TVDBID"] = searchCriteria.TvdbId;
variables[".Query.TVRageID"] = searchCriteria.RId;
variables[".Query.TVMazeID"] = searchCriteria.TvMazeId;
variables[".Query.TraktID"] = searchCriteria.TraktId;
pageableRequests.Add(GetRequest(variables));
return pageableRequests;
}
private IEnumerable<IndexerRequest> GetRequest(Dictionary<string, object> variables)
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
var search = _definition.Search;
var pageableRequests = new IndexerPageableRequestChain();
var variables = GetQueryVariableDefaults(searchCriteria);
variables[".Query.Author"] = null;
variables[".Query.Title"] = null;
pageableRequests.Add(GetRequest(variables));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var variables = GetQueryVariableDefaults(searchCriteria);
pageableRequests.Add(GetRequest(variables));
return pageableRequests;
}
private Dictionary<string, object> GetQueryVariableDefaults(SearchCriteriaBase searchCriteria)
{
var variables = GetBaseTemplateVariables();
variables[".Query.Type"] = searchCriteria.SearchType;
variables[".Query.Q"] = searchCriteria.SearchTerm;
variables[".Query.Categories"] = searchCriteria.Categories;
variables[".Query.Limit"] = searchCriteria.Limit;
variables[".Query.Offset"] = searchCriteria.Offset;
variables[".Query.Extended"] = null;
variables[".Query.APIKey"] = null;
//Movie
variables[".Query.Movie"] = null;
variables[".Query.Year"] = null;
variables[".Query.IMDBID"] = null;
variables[".Query.IMDBIDShort"] = null;
variables[".Query.TMDBID"] = null;
//Tv
variables[".Query.Series"] = null;
variables[".Query.Ep"] = null;
variables[".Query.Season"] = null;
variables[".Query.Movie"] = null;
variables[".Query.Year"] = null;
variables[".Query.Limit"] = null;
variables[".Query.Offset"] = null;
variables[".Query.Extended"] = null;
variables[".Query.APIKey"] = null;
variables[".Query.TVDBID"] = null;
variables[".Query.TVRageID"] = null;
variables[".Query.TVMazeID"] = null;
variables[".Query.TraktID"] = null;
//Music
variables[".Query.Album"] = null;
variables[".Query.Artist"] = null;
variables[".Query.Label"] = null;
variables[".Query.Track"] = null;
variables[".Query.Episode"] = null;
//Book
variables[".Query.Author"] = null;
variables[".Query.Title"] = null;
return variables;
}
private IEnumerable<IndexerRequest> GetRequest(Dictionary<string, object> variables)
{
var search = _definition.Search;
var mappedCategories = MapTorznabCapsToTrackers((int[])variables[".Query.Categories"]);
if (mappedCategories.Count == 0)
{

@ -34,6 +34,26 @@ namespace NzbDrone.Core.Indexers.FileList
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
private IEnumerable<IndexerRequest> GetRequest(string searchType, string parameters)
{
var categoriesQuery = string.Join(",", Settings.Categories.Distinct());

@ -12,13 +12,6 @@ namespace NzbDrone.Core.Indexers.HDBits
{
public HDBitsSettings Settings { get; set; }
public virtual IndexerPageableRequestChain GetRecentRequests()
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(new TorrentQuery()));
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
@ -76,5 +69,25 @@ namespace NzbDrone.Core.Indexers.HDBits
yield return new IndexerRequest(request);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
}
}

@ -28,6 +28,26 @@ namespace NzbDrone.Core.Indexers.IPTorrents
yield return new IndexerRequest(Settings.BaseUrl, HttpAccept.Rss);
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}

@ -66,30 +66,38 @@ namespace NzbDrone.Core.Indexers.Newznab
}
}
public virtual IndexerPageableRequestChain GetRecentRequests()
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
// Some indexers might forget to enable movie search, but normal search still works fine. Thus we force a normal search.
if (capabilities.MovieSearchParams != null)
{
pageableRequests.Add(GetPagedRequests(MaxPages, new int[] { 2000 }, "movie", ""));
}
else if (capabilities.SearchParams != null)
{
pageableRequests.Add(GetPagedRequests(MaxPages, new int[] { 2000 }, "search", ""));
}
AddMovieIdPageableRequests(pageableRequests, MaxPages, searchCriteria.Categories, searchCriteria);
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
AddMovieIdPageableRequests(pageableRequests, MaxPages, searchCriteria.Categories, searchCriteria);
pageableRequests.Add(GetPagedRequests(MaxPages,
searchCriteria.Categories,
"search",
string.Format("&q={0}", NewsnabifyTitle(searchCriteria.SearchTerm))));
return pageableRequests;
}
@ -153,15 +161,14 @@ namespace NzbDrone.Core.Indexers.Newznab
private IEnumerable<IndexerRequest> GetPagedRequests(int maxPages, IEnumerable<int> categories, string searchType, string parameters)
{
if (categories.Empty())
var baseUrl = string.Format("{0}{1}?t={2}&extended=1", Settings.BaseUrl.TrimEnd('/'), Settings.ApiPath.TrimEnd('/'), searchType);
if (categories != null && categories.Any())
{
yield break;
var categoriesQuery = string.Join(",", categories.Distinct());
baseUrl += string.Format("&cats={0}", categoriesQuery);
}
var categoriesQuery = string.Join(",", categories.Distinct());
var baseUrl = string.Format("{0}{1}?t={2}&cat={3}&extended=1{4}", Settings.BaseUrl.TrimEnd('/'), Settings.ApiPath.TrimEnd('/'), searchType, categoriesQuery, Settings.AdditionalParameters);
if (Settings.ApiKey.IsNotNullOrWhiteSpace())
{
baseUrl += "&apikey=" + Settings.ApiKey;

@ -18,15 +18,6 @@ namespace NzbDrone.Core.Indexers.Nyaa
PageSize = 100;
}
public virtual IndexerPageableRequestChain GetRecentRequests()
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(MaxPages, null));
return pageableRequests;
}
private IEnumerable<IndexerRequest> GetPagedRequests(int maxPages, string term)
{
var baseUrl = string.Format("{0}/?page=rss{1}", Settings.BaseUrl.TrimEnd('/'), Settings.AdditionalParameters);
@ -65,6 +56,26 @@ namespace NzbDrone.Core.Indexers.Nyaa
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}

@ -16,15 +16,6 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
public IHttpClient HttpClient { get; set; }
public Logger Logger { get; set; }
public virtual IndexerPageableRequestChain GetRecentRequests()
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(null));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
@ -66,5 +57,25 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
}
}

@ -116,6 +116,26 @@ namespace NzbDrone.Core.Indexers.Rarbg
yield return new IndexerRequest(requestBuilder.Build());
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}

@ -80,6 +80,26 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}

@ -39,6 +39,26 @@ namespace NzbDrone.Core.Indexers.TorrentRss
yield return request;
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}

@ -49,6 +49,46 @@ namespace NzbDrone.Core.Indexers
return FetchReleases(g => g.GetSearchRequests(searchCriteria));
}
public override IList<ReleaseInfo> Fetch(MusicSearchCriteria searchCriteria)
{
if (!SupportsSearch)
{
return new List<ReleaseInfo>();
}
return FetchReleases(g => g.GetSearchRequests(searchCriteria));
}
public override IList<ReleaseInfo> Fetch(TvSearchCriteria searchCriteria)
{
if (!SupportsSearch)
{
return new List<ReleaseInfo>();
}
return FetchReleases(g => g.GetSearchRequests(searchCriteria));
}
public override IList<ReleaseInfo> Fetch(BookSearchCriteria searchCriteria)
{
if (!SupportsSearch)
{
return new List<ReleaseInfo>();
}
return FetchReleases(g => g.GetSearchRequests(searchCriteria));
}
public override IList<ReleaseInfo> Fetch(BasicSearchCriteria searchCriteria)
{
if (!SupportsSearch)
{
return new List<ReleaseInfo>();
}
return FetchReleases(g => g.GetSearchRequests(searchCriteria));
}
protected IndexerPageableRequestChain GetRequestChain(SearchCriteriaBase searchCriteria = null)
{
var generator = GetRequestGenerator();
@ -254,7 +294,7 @@ namespace NzbDrone.Core.Indexers
protected virtual bool IsValidRelease(ReleaseInfo release)
{
if (release.DownloadUrl.IsNullOrWhiteSpace())
if (release.DownloadUrl == null)
{
return false;
}

@ -15,5 +15,9 @@ namespace NzbDrone.Core.Indexers
IndexerPrivacy Privacy { get; }
IList<ReleaseInfo> Fetch(MovieSearchCriteria searchCriteria);
IList<ReleaseInfo> Fetch(MusicSearchCriteria searchCriteria);
IList<ReleaseInfo> Fetch(TvSearchCriteria searchCriteria);
IList<ReleaseInfo> Fetch(BookSearchCriteria searchCriteria);
IList<ReleaseInfo> Fetch(BasicSearchCriteria searchCriteria);
}
}

@ -7,6 +7,10 @@ namespace NzbDrone.Core.Indexers
public interface IIndexerRequestGenerator
{
IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria);
IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria);
IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria);
IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria);
IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria);
Func<IDictionary<string, string>> GetCookies { get; set; }
Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}

@ -66,6 +66,10 @@ namespace NzbDrone.Core.Indexers
protected TSettings Settings => (TSettings)Definition.Settings;
public abstract IList<ReleaseInfo> Fetch(MovieSearchCriteria searchCriteria);
public abstract IList<ReleaseInfo> Fetch(MusicSearchCriteria searchCriteria);
public abstract IList<ReleaseInfo> Fetch(TvSearchCriteria searchCriteria);
public abstract IList<ReleaseInfo> Fetch(BookSearchCriteria searchCriteria);
public abstract IList<ReleaseInfo> Fetch(BasicSearchCriteria searchCriteria);
protected virtual IList<ReleaseInfo> CleanupReleases(IEnumerable<ReleaseInfo> releases)
{

@ -114,6 +114,7 @@ namespace NzbDrone.Core.Indexers
throw new Exception("In search mode 'search' only 'q' parameter is supported and it's mandatory");
}
SearchParams.Add(SearchParam.Q);
break;
case "tv-search":
ParseTvSearchParams(entry.Value);
@ -277,6 +278,13 @@ namespace NzbDrone.Core.Indexers
return string.Join(",", parameters);
}
private string SupportedSearchParams()
{
var parameters = new List<string> { "q" }; // q is always enabled
return string.Join(",", parameters);
}
private string SupportedMovieSearchParams()
{
var parameters = new List<string> { "q" }; // q is always enabled
@ -350,7 +358,7 @@ namespace NzbDrone.Core.Indexers
new XElement("searching",
new XElement("search",
new XAttribute("available", SearchAvailable ? "yes" : "no"),
new XAttribute("supportedParams", "q")),
new XAttribute("supportedParams", SupportedSearchParams())),
new XElement("tv-search",
new XAttribute("available", TvSearchAvailable ? "yes" : "no"),
new XAttribute("supportedParams", SupportedTvSearchParams())),

@ -28,6 +28,26 @@ namespace NzbDrone.Core.Indexers
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(MusicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(BasicSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public Func<IDictionary<string, string>> GetCookies { get; set; }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
}

@ -9,7 +9,7 @@ namespace NzbDrone.Core.Parser.Model
{
public string Guid { get; set; }
public string Title { get; set; }
public long Size { get; set; }
public long? Size { get; set; }
public string DownloadUrl { get; set; }
public string InfoUrl { get; set; }
public string CommentUrl { get; set; }
@ -28,7 +28,7 @@ namespace NzbDrone.Core.Parser.Model
public string Container { get; set; }
public string Codec { get; set; }
public string Resolution { get; set; }
public ICollection<int> Category { get; set; }
public ICollection<IndexerCategory> Category { get; set; }
public IndexerFlags IndexerFlags { get; set; }

@ -1,3 +1,4 @@
using System;
using System.Text;
namespace NzbDrone.Core.Parser.Model

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NzbDrone.Core.Indexers;
using Prowlarr.Http.REST;
namespace Prowlarr.Api.V1.Indexers
{
public class IndexerCapabilityResource : RestResource
{
public int? LimitsMax { get; set; }
public int? LimitsDefault { get; set; }
public List<IndexerCategory> Categories;
}
public static class IndexerCapabilitiesResourceMapper
{
public static IndexerCapabilityResource ToResource(this IndexerCapabilities model)
{
if (model == null)
{
return null;
}
return new IndexerCapabilityResource
{
LimitsMax = model.LimitsMax,
LimitsDefault = model.LimitsDefault,
Categories = model.Categories.GetTorznabCategoryTree()
};
}
public static List<IndexerCapabilityResource> ToResource(this IEnumerable<IndexerCapabilities> models)
{
return models.Select(ToResource).ToList();
}
}
}

@ -64,6 +64,7 @@ namespace Prowlarr.Api.V1.Indexers
return response;
case "tvsearch":
case "music":
case "book":
case "movie":
Response movieResponse = _nzbSearchService.Search(request, new List<int> { indexer.Id }, false).ToXml();
movieResponse.ContentType = "application/rss+xml";

@ -17,7 +17,7 @@ namespace Prowlarr.Api.V1.Indexers
public bool SupportsSearch { get; set; }
public DownloadProtocol Protocol { get; set; }
public IndexerPrivacy Privacy { get; set; }
public IndexerCapabilities Capabilities { get; set; }
public IndexerCapabilityResource Capabilities { get; set; }
public int Priority { get; set; }
public DateTime Added { get; set; }
}
@ -59,7 +59,7 @@ namespace Prowlarr.Api.V1.Indexers
resource.EnableInteractiveSearch = definition.EnableInteractiveSearch;
resource.SupportsRss = definition.SupportsRss;
resource.SupportsSearch = definition.SupportsSearch;
resource.Capabilities = definition.Capabilities;
resource.Capabilities = definition.Capabilities.ToResource();
resource.Protocol = definition.Protocol;
resource.Privacy = definition.Privacy;
resource.Priority = definition.Priority;

@ -6,6 +6,7 @@ using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.IndexerSearch;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using Prowlarr.Http;
@ -49,7 +50,7 @@ namespace Prowlarr.Api.V1.Search
{
try
{
var decisions = _nzbSearhService.Search(query, indexerIds, true);
var decisions = _nzbSearhService.Search(new NewznabRequest { q = query, t = "search" }, indexerIds, true).Releases;
return MapDecisions(decisions);
}

@ -6,5 +6,6 @@ namespace Prowlarr.Api.V1.Search
{
public List<int> IndexerIds { get; set; }
public string Query { get; set; }
public int[] Categories { get; set; }
}
}

@ -26,6 +26,7 @@ namespace Prowlarr.Api.V1.Search
public string DownloadUrl { get; set; }
public string InfoUrl { get; set; }
public IEnumerable<string> IndexerFlags { get; set; }
public ICollection<IndexerCategory> Categories { get; set; }
public string MagnetUrl { get; set; }
public string InfoHash { get; set; }
@ -51,7 +52,7 @@ namespace Prowlarr.Api.V1.Search
Age = releaseInfo.Age,
AgeHours = releaseInfo.AgeHours,
AgeMinutes = releaseInfo.AgeMinutes,
Size = releaseInfo.Size,
Size = releaseInfo.Size ?? 0,
IndexerId = releaseInfo.IndexerId,
Indexer = releaseInfo.Indexer,
Title = releaseInfo.Title,
@ -60,6 +61,7 @@ namespace Prowlarr.Api.V1.Search
CommentUrl = releaseInfo.CommentUrl,
DownloadUrl = releaseInfo.DownloadUrl,
InfoUrl = releaseInfo.InfoUrl,
Categories = releaseInfo.Category,
//ReleaseWeight
MagnetUrl = torrentInfo.MagnetUrl,

Loading…
Cancel
Save