diff --git a/src/NzbDrone.Core/Indexers/Definitions/Torznab/Torznab.cs b/src/NzbDrone.Core/Indexers/Definitions/Torznab/Torznab.cs index bfb51ba8d..a90b1cb9a 100644 --- a/src/NzbDrone.Core/Indexers/Definitions/Torznab/Torznab.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/Torznab/Torznab.cs @@ -19,12 +19,15 @@ namespace NzbDrone.Core.Indexers.Torznab private readonly INewznabCapabilitiesProvider _capabilitiesProvider; public override string Name => "Torznab"; - public override string BaseUrl => ""; + public override string BaseUrl => GetBaseUrlFromSettings(); + public override bool FollowRedirect => true; + public override bool SupportsRedirect => true; public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override IndexerPrivacy Privacy => IndexerPrivacy.Private; public override int PageSize => _capabilitiesProvider.GetCapabilities(Settings).LimitsDefault.Value; + public override IndexerCapabilities Capabilities { get => GetCapabilitiesFromSettings(); protected set => base.Capabilities = value; } public override IIndexerRequestGenerator GetRequestGenerator() { @@ -37,7 +40,42 @@ namespace NzbDrone.Core.Indexers.Torznab public override IParseIndexerResponse GetParser() { - return new TorznabRssParser(); + return new TorznabRssParser(Settings); + } + + public string GetBaseUrlFromSettings() + { + var baseUrl = ""; + + if (Definition == null || Settings == null || Settings.Categories == null) + { + return baseUrl; + } + + return Settings.BaseUrl; + } + + 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 DefaultDefinitions @@ -68,7 +106,7 @@ namespace NzbDrone.Core.Indexers.Torznab SupportsRss = SupportsRss, SupportsSearch = SupportsSearch, SupportsRedirect = SupportsRedirect, - Capabilities = new IndexerCapabilities() + Capabilities = Capabilities }; } diff --git a/src/NzbDrone.Core/Indexers/Definitions/Torznab/TorznabRssParser.cs b/src/NzbDrone.Core/Indexers/Definitions/Torznab/TorznabRssParser.cs index 62369102c..24e44fe56 100644 --- a/src/NzbDrone.Core/Indexers/Definitions/Torznab/TorznabRssParser.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/Torznab/TorznabRssParser.cs @@ -12,9 +12,11 @@ namespace NzbDrone.Core.Indexers.Torznab { public const string ns = "{http://torznab.com/schemas/2015/feed}"; - public TorznabRssParser() + private readonly TorznabSettings _settings; + public TorznabRssParser(TorznabSettings settings) { UseEnclosureUrl = true; + _settings = settings; } protected override bool PreProcess(IndexerResponse indexerResponse) @@ -141,6 +143,27 @@ namespace NzbDrone.Core.Indexers.Torznab return TryGetTorznabAttribute(item, "magneturl"); } + protected override ICollection GetCategory(XElement item) + { + var cats = TryGetMultipleNewznabAttributes(item, "category"); + var results = new List(); + + foreach (var cat in cats) + { + if (int.TryParse(cat, out var intCategory)) + { + var indexerCat = _settings.Categories?.FirstOrDefault(c => c.Id == intCategory) ?? null; + + if (indexerCat != null) + { + results.Add(indexerCat); + } + } + } + + return results; + } + protected override int? GetSeeders(XElement item) { var seeders = TryGetTorznabAttribute(item, "seeders"); @@ -224,5 +247,22 @@ namespace NzbDrone.Core.Indexers.Torznab return defaultValue; } + + protected List 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(); + + foreach (var element in attrElements) + { + var attrValue = element.Attribute("value"); + if (attrValue != null) + { + results.Add(attrValue.Value); + } + } + + return results; + } } } diff --git a/src/NzbDrone.Core/Indexers/IndexerFactory.cs b/src/NzbDrone.Core/Indexers/IndexerFactory.cs index 737081f51..bb3cb5df8 100644 --- a/src/NzbDrone.Core/Indexers/IndexerFactory.cs +++ b/src/NzbDrone.Core/Indexers/IndexerFactory.cs @@ -147,7 +147,7 @@ namespace NzbDrone.Core.Indexers foreach (var provider in _providers) { var definitions = provider.DefaultDefinitions - .Where(v => v.Name != null && (v.Name != typeof(Cardigann.Cardigann).Name || v.Name != typeof(Newznab.Newznab).Name)); + .Where(v => v.Name != null && (v.Name != typeof(Cardigann.Cardigann).Name || v.Name != typeof(Newznab.Newznab).Name || v.Name != typeof(Torznab.Torznab).Name)); foreach (IndexerDefinition definition in definitions) { @@ -256,7 +256,7 @@ namespace NzbDrone.Core.Indexers SetProviderCharacteristics(provider, definition); - if (definition.Implementation == typeof(Newznab.Newznab).Name) + if (definition.Implementation == typeof(Newznab.Newznab).Name || definition.Implementation == typeof(Torznab.Torznab).Name) { var settings = (NewznabSettings)definition.Settings; settings.Categories = _newznabCapabilitiesProvider.GetCapabilities(settings)?.Categories.GetTorznabCategoryList() ?? null; @@ -276,7 +276,7 @@ namespace NzbDrone.Core.Indexers SetProviderCharacteristics(provider, definition); - if (definition.Implementation == typeof(Newznab.Newznab).Name) + if (definition.Implementation == typeof(Newznab.Newznab).Name || definition.Implementation == typeof(Torznab.Torznab).Name) { var settings = (NewznabSettings)definition.Settings; settings.Categories = _newznabCapabilitiesProvider.GetCapabilities(settings)?.Categories.GetTorznabCategoryList() ?? null;