Newznab Work

This commit is contained in:
Qstick
2020-11-20 02:42:36 -05:00
parent 8e72c7153d
commit b586b6ac1c
26 changed files with 325 additions and 160 deletions
@@ -20,7 +20,7 @@ namespace NzbDrone.Core.Indexers.Newznab
public override DownloadProtocol Protocol => DownloadProtocol.Usenet;
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
public override IndexerCapabilities Capabilities { get => new IndexerCapabilities(); protected set => base.Capabilities = value; }
public override IndexerCapabilities Capabilities { get => GetCapabilitiesFromSettings(); protected set => base.Capabilities = value; }
public override int PageSize => _capabilitiesProvider.GetCapabilities(Settings).LimitsDefault.Value;
@@ -38,6 +38,29 @@ namespace NzbDrone.Core.Indexers.Newznab
return new NewznabRssParser(Settings);
}
public IndexerCapabilities GetCapabilitiesFromSettings()
{
var caps = new IndexerCapabilities();
if (Definition == null || Settings == null || Settings.Categories == null)
{
return caps;
}
foreach (var category in Settings.Categories)
{
caps.Categories.AddCategoryMapping(category.Name, category);
}
return caps;
}
public override IndexerCapabilities GetCapabilities()
{
// Newznab uses different Caps per site, so we need to cache them to db on first indexer add to prevent issues with loading UI and pulling caps every time.
return _capabilitiesProvider.GetCapabilities(Settings);
}
public override IEnumerable<ProviderDefinition> DefaultDefinitions
{
get
@@ -206,12 +206,15 @@ namespace NzbDrone.Core.Indexers.Newznab
foreach (var xmlSubcat in xmlCategory.Elements("subcat"))
{
cat.SubCategories.Add(new IndexerCategory
var subCat = new IndexerCategory
{
Id = int.Parse(xmlSubcat.Attribute("id").Value),
Name = xmlSubcat.Attribute("name").Value,
Description = xmlSubcat.Attribute("description") != null ? xmlSubcat.Attribute("description").Value : string.Empty
});
};
cat.SubCategories.Add(subCat);
capabilities.Categories.AddCategoryMapping(subCat.Name, subCat);
}
capabilities.Categories.AddCategoryMapping(cat.Name, cat);
@@ -22,55 +22,35 @@ namespace NzbDrone.Core.Indexers.Newznab
PageSize = 100;
}
private bool SupportsSearch
{
get
{
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
return capabilities.SearchParams != null &&
capabilities.SearchParams.Contains(SearchParam.Q);
}
}
private bool SupportsImdbSearch
{
get
{
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
return capabilities.MovieSearchParams != null &&
capabilities.MovieSearchParams.Contains(MovieSearchParam.ImdbId);
}
}
private bool SupportsTmdbSearch
{
get
{
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
return capabilities.MovieSearchParams != null &&
capabilities.MovieSearchParams.Contains(MovieSearchParam.TmdbId);
}
}
private bool SupportsAggregatedIdSearch
{
get
{
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
// TODO: Fix this, return capabilities.SupportsAggregateIdSearch;
return true;
}
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
AddMovieIdPageableRequests(pageableRequests, MaxPages, searchCriteria.Categories, searchCriteria);
var pageableRequests = new IndexerPageableRequestChain();
var parameters = string.Empty;
if (searchCriteria.TmdbId.HasValue && capabilities.MovieSearchTmdbAvailable)
{
parameters += string.Format("&tmdbid={0}", searchCriteria.TmdbId.Value);
}
if (searchCriteria.ImdbId.IsNotNullOrWhiteSpace() && capabilities.MovieSearchImdbAvailable)
{
parameters += string.Format("&imdbid={0}", searchCriteria.ImdbId);
}
if (searchCriteria.TraktId.HasValue && capabilities.MovieSearchTraktAvailable)
{
parameters += string.Format("&traktid={0}", searchCriteria.ImdbId);
}
if (searchCriteria.SearchTerm.IsNotNullOrWhiteSpace())
{
parameters += string.Format("&q={0}", searchCriteria.SearchTerm);
}
pageableRequests.Add(GetPagedRequests(searchCriteria,
parameters));
return pageableRequests;
}
@@ -82,7 +62,50 @@ namespace NzbDrone.Core.Indexers.Newznab
public IndexerPageableRequestChain GetSearchRequests(TvSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
var pageableRequests = new IndexerPageableRequestChain();
var parameters = string.Empty;
if (searchCriteria.TvdbId.HasValue && capabilities.TvSearchTvdbAvailable)
{
parameters += string.Format("&tvdbid={0}", searchCriteria.TvdbId.Value);
}
if (searchCriteria.ImdbId.IsNotNullOrWhiteSpace() && capabilities.TvSearchImdbAvailable)
{
parameters += string.Format("&imdbid={0}", searchCriteria.ImdbId);
}
if (searchCriteria.TvMazeId.HasValue && capabilities.TvSearchTvMazeAvailable)
{
parameters += string.Format("&tvmazeid={0}", searchCriteria.TvMazeId);
}
if (searchCriteria.RId.HasValue && capabilities.TvSearchTvRageAvailable)
{
parameters += string.Format("&rid={0}", searchCriteria.RId);
}
if (searchCriteria.Season.HasValue && capabilities.TvSearchSeasonAvailable)
{
parameters += string.Format("&season={0}", searchCriteria.Season);
}
if (searchCriteria.Ep.HasValue && capabilities.TvSearchEpAvailable)
{
parameters += string.Format("&ep={0}", searchCriteria.Ep);
}
if (searchCriteria.SearchTerm.IsNotNullOrWhiteSpace())
{
parameters += string.Format("&q={0}", searchCriteria.SearchTerm);
}
pageableRequests.Add(GetPagedRequests(searchCriteria,
parameters));
return pageableRequests;
}
public IndexerPageableRequestChain GetSearchRequests(BookSearchCriteria searchCriteria)
@@ -94,74 +117,18 @@ namespace NzbDrone.Core.Indexers.Newznab
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(MaxPages,
searchCriteria.Categories,
"search",
string.Format("&q={0}", NewsnabifyTitle(searchCriteria.SearchTerm))));
var searchQuery = searchCriteria.SearchTerm;
pageableRequests.Add(GetPagedRequests(searchCriteria,
searchQuery.IsNotNullOrWhiteSpace() ? string.Format("&q={0}", NewsnabifyTitle(searchCriteria.SearchTerm)) : string.Empty));
return pageableRequests;
}
private void AddMovieIdPageableRequests(IndexerPageableRequestChain chain, int maxPages, IEnumerable<int> categories, MovieSearchCriteria searchCriteria)
private IEnumerable<IndexerRequest> GetPagedRequests(SearchCriteriaBase searchCriteria, string parameters)
{
var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.TmdbId > 0;
var includeImdbSearch = SupportsImdbSearch && searchCriteria.ImdbId.IsNotNullOrWhiteSpace();
if (SupportsAggregatedIdSearch && (includeTmdbSearch || includeImdbSearch))
{
var ids = "";
if (includeTmdbSearch)
{
ids += "&tmdbid=" + searchCriteria.TmdbId;
}
if (includeImdbSearch)
{
ids += "&imdbid=" + searchCriteria.ImdbId.Substring(2);
}
chain.Add(GetPagedRequests(maxPages, categories, "movie", ids));
}
else
{
if (includeTmdbSearch)
{
chain.Add(GetPagedRequests(maxPages,
categories,
"movie",
string.Format("&tmdbid={0}", searchCriteria.TmdbId)));
}
else if (includeImdbSearch)
{
chain.Add(GetPagedRequests(maxPages,
categories,
"movie",
string.Format("&imdbid={0}", searchCriteria.ImdbId.Substring(2))));
}
}
if (SupportsSearch)
{
chain.AddTier();
var searchQuery = searchCriteria.SearchTerm;
if (!Settings.RemoveYear)
{
searchQuery = string.Format("{0}", searchQuery);
}
chain.Add(GetPagedRequests(MaxPages,
categories,
"movie",
string.Format("&q={0}", NewsnabifyTitle(searchQuery))));
}
}
private IEnumerable<IndexerRequest> GetPagedRequests(int maxPages, IEnumerable<int> categories, string searchType, string parameters)
{
var baseUrl = string.Format("{0}{1}?t={2}&extended=1", Settings.BaseUrl.TrimEnd('/'), Settings.ApiPath.TrimEnd('/'), searchType);
var baseUrl = string.Format("{0}{1}?t={2}&extended=1", Settings.BaseUrl.TrimEnd('/'), Settings.ApiPath.TrimEnd('/'), searchCriteria.SearchType);
var categories = searchCriteria.Categories;
if (categories != null && categories.Any())
{
@@ -174,16 +141,23 @@ namespace NzbDrone.Core.Indexers.Newznab
baseUrl += "&apikey=" + Settings.ApiKey;
}
if (searchCriteria.Limit.HasValue)
{
parameters += string.Format("&limit={0}", searchCriteria.Limit);
}
if (searchCriteria.Offset.HasValue)
{
parameters += string.Format("&offset={0}", searchCriteria.Offset);
}
if (PageSize == 0)
{
yield return new IndexerRequest(string.Format("{0}{1}", baseUrl, parameters), HttpAccept.Rss);
}
else
{
for (var page = 0; page < maxPages; page++)
{
yield return new IndexerRequest(string.Format("{0}&offset={1}&limit={2}{3}", baseUrl, page * PageSize, PageSize, parameters), HttpAccept.Rss);
}
yield return new IndexerRequest(string.Format("{0}&offset={1}&limit={2}{3}", baseUrl, searchCriteria.Offset, searchCriteria.Limit, parameters), HttpAccept.Rss);
}
}
@@ -96,6 +96,27 @@ namespace NzbDrone.Core.Indexers.Newznab
return ParseUrl(item.TryGetValue("comments"));
}
protected override ICollection<IndexerCategory> GetCategory(XElement item)
{
var cats = TryGetMultipleNewznabAttributes(item, "category");
var results = new List<IndexerCategory>();
foreach (var cat in cats)
{
if (int.TryParse(cat, out var intCategory))
{
var indexerCat = _settings.Categories.FirstOrDefault(c => c.Id == intCategory);
if (indexerCat != null)
{
results.Add(indexerCat);
}
}
}
return results;
}
protected override long GetSize(XElement item)
{
long size;
@@ -174,5 +195,22 @@ namespace NzbDrone.Core.Indexers.Newznab
return defaultValue;
}
protected List<string> TryGetMultipleNewznabAttributes(XElement item, string key)
{
var attrElements = item.Elements(ns + "attr").Where(e => e.Attribute("name").Value.Equals(key, StringComparison.OrdinalIgnoreCase));
var results = new List<string>();
foreach (var element in attrElements)
{
var attrValue = element.Attribute("value");
if (attrValue != null)
{
results.Add(attrValue.Value);
}
}
return results;
}
}
}
@@ -76,6 +76,8 @@ namespace NzbDrone.Core.Indexers.Newznab
Type = FieldType.Checkbox)]
public bool RemoveYear { get; set; }
public List<IndexerCategory> Categories { get; set; }
// Field 8 is used by TorznabSettings MinimumSeeders
// If you need to add another field here, update TorznabSettings as well and this comment
public virtual NzbDroneValidationResult Validate()