Skip to content

Commit be3ec7d

Browse files
committed
new: smarter validation for newznab indexer settings
1 parent 53cebde commit be3ec7d

File tree

8 files changed

+98
-7
lines changed

8 files changed

+98
-7
lines changed

NzbDrone.sln.DotSettings

+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:Boolean x:Key="/Default/Environment/ExternalSources/Decompiler/DecompileMethodBodies/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using FluentAssertions;
2+
using NUnit.Framework;
3+
using NzbDrone.Core.Indexers.Newznab;
4+
using NzbDrone.Core.Test.Framework;
5+
6+
namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
7+
{
8+
public class NewznabSettingFixture : CoreTest
9+
{
10+
11+
[TestCase("http://nzbs.org")]
12+
[TestCase("http:///www.nzbplanet.net")]
13+
public void requires_apikey(string url)
14+
{
15+
var setting = new NewznabSettings()
16+
{
17+
ApiKey = "",
18+
Url = url
19+
};
20+
21+
22+
setting.Validate().IsValid.Should().BeFalse();
23+
setting.Validate().Errors.Should().Contain(c => c.PropertyName == "ApiKey");
24+
25+
}
26+
27+
28+
[TestCase("http://nzbs2.org")]
29+
public void doesnt_requires_apikey(string url)
30+
{
31+
var setting = new NewznabSettings()
32+
{
33+
ApiKey = "",
34+
Url = url
35+
};
36+
37+
38+
setting.Validate().IsValid.Should().BeTrue();
39+
}
40+
}
41+
}

src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
<Compile Include="IndexerTests\BasicRssParserFixture.cs" />
139139
<Compile Include="IndexerTests\IndexerServiceFixture.cs" />
140140
<Compile Include="IndexerTests\IntegrationTests\IndexerIntegrationTests.cs" />
141+
<Compile Include="IndexerTests\NewznabTests\NewznabSettingFixture.cs" />
141142
<Compile Include="IndexerTests\XElementExtensionsFixture.cs" />
142143
<Compile Include="JobTests\JobRepositoryFixture.cs" />
143144
<Compile Include="DecisionEngineTests\LanguageSpecificationFixture.cs" />

src/NzbDrone.Core/Indexers/Newznab/NewznabParser.cs

+24
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Xml.Linq;
45
using NzbDrone.Core.Parser.Model;
@@ -7,6 +8,12 @@ namespace NzbDrone.Core.Indexers.Newznab
78
{
89
public class NewznabParser : RssParserBase
910
{
11+
12+
private static readonly string[] IgnoredErrors =
13+
{
14+
"Request limit reached",
15+
};
16+
1017
protected override string GetNzbInfoUrl(XElement item)
1118
{
1219
return item.Comments().Replace("#comments", "");
@@ -25,6 +32,23 @@ protected override long GetSize(XElement item)
2532
return ParseSize(item.Description());
2633
}
2734

35+
public override IEnumerable<ReleaseInfo> Process(string xml, string url)
36+
{
37+
try
38+
{
39+
return base.Process(xml, url);
40+
}
41+
catch (NewznabException e)
42+
{
43+
if (!IgnoredErrors.Any(ignoredError => e.Message.Contains(ignoredError)))
44+
{
45+
throw;
46+
}
47+
_logger.Error(e.Message);
48+
return new List<ReleaseInfo>();
49+
}
50+
}
51+
2852
protected override ReleaseInfo PostProcessor(XElement item, ReleaseInfo currentResult)
2953
{
3054
if (currentResult != null)

src/NzbDrone.Core/Indexers/Newznab/NewznabPreProcessor.cs

+9-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,17 @@ public static void Process(string source, string url)
1515
if (error == null) return;
1616

1717
var code = Convert.ToInt32(error.Attribute("code").Value);
18+
var errorMessage = error.Attribute("description").Value;
1819

19-
if (code >= 100 && code <= 199) throw new ApiKeyException("Invalid API key: {0}");
2020

21-
throw new NewznabException("Newznab error detected: {0}", error.Attribute("description").Value);
21+
if (code >= 100 && code <= 199) throw new ApiKeyException("Invalid API key");
22+
23+
if (!url.Contains("apikey=") && errorMessage == "Missing parameter")
24+
{
25+
throw new ApiKeyException("Indexer requires and API key");
26+
}
27+
28+
throw new NewznabException("Newznab error detected: {0}", errorMessage);
2229
}
2330
}
2431
}

src/NzbDrone.Core/Indexers/Newznab/NewznabSettings.cs

+17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
34
using FluentValidation;
45
using FluentValidation.Results;
56
using NzbDrone.Core.Annotations;
@@ -10,9 +11,25 @@ namespace NzbDrone.Core.Indexers.Newznab
1011
{
1112
public class NewznabSettingsValidator : AbstractValidator<NewznabSettings>
1213
{
14+
private static readonly string[] ApiKeyWhiteList =
15+
{
16+
"nzbs.org",
17+
"nzb.su",
18+
"dognzb.cr",
19+
"nzbplanet.net",
20+
"nzbid.org",
21+
"nzbndx.com",
22+
};
23+
24+
private static bool ShouldHaveApiKey(NewznabSettings settings)
25+
{
26+
return ApiKeyWhiteList.Any(c => settings.Url.ToLowerInvariant().Contains(c));
27+
}
28+
1329
public NewznabSettingsValidator()
1430
{
1531
RuleFor(c => c.Url).ValidRootUrl();
32+
RuleFor(c => c.ApiKey).NotEmpty().When(ShouldHaveApiKey);
1633
}
1734
}
1835

src/NzbDrone.Core/Indexers/NewznabTestService.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ public void Test(IIndexer indexer)
4141

4242
NewznabPreProcessor.Process(xml, url);
4343
}
44-
catch (ApiKeyException apiKeyException)
44+
catch (ApiKeyException)
4545
{
4646
_logger.Warn("Indexer returned result for Newznab RSS URL, API Key appears to be invalid");
4747

4848
var apiKeyFailure = new ValidationFailure("ApiKey", "Invalid API Key");
4949
throw new ValidationException(new List<ValidationFailure> { apiKeyFailure }.ToArray());
5050
}
51-
catch (Exception ex)
51+
catch (Exception)
5252
{
5353
_logger.Warn("Indexer doesn't appear to be Newznab based");
5454

src/NzbDrone.Core/Indexers/RssParserBase.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace NzbDrone.Core.Indexers
1515
{
1616
public abstract class RssParserBase : IParseFeed
1717
{
18-
private readonly Logger _logger;
18+
protected readonly Logger _logger;
1919

2020
protected virtual ReleaseInfo CreateNewReleaseInfo()
2121
{
@@ -27,7 +27,7 @@ protected RssParserBase()
2727
_logger = NzbDroneLogger.GetLogger(this);
2828
}
2929

30-
public IEnumerable<ReleaseInfo> Process(string xml, string url)
30+
public virtual IEnumerable<ReleaseInfo> Process(string xml, string url)
3131
{
3232
PreProcess(xml, url);
3333

0 commit comments

Comments
 (0)