diff --git a/NzbDrone.Core.Test/Files/Indexers/Newznab/error.xml b/NzbDrone.Core.Test/Files/Indexers/Newznab/error.xml
new file mode 100644
index 000000000..33e46d9b6
--- /dev/null
+++ b/NzbDrone.Core.Test/Files/Indexers/Newznab/error.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
index 22ee553f8..99987c84b 100644
--- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
+++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
@@ -252,6 +252,7 @@
Always
+
Always
@@ -351,7 +352,6 @@
-
diff --git a/NzbDrone.Core/Indexers/Exceptions/ApiKeyException.cs b/NzbDrone.Core/Indexers/Exceptions/ApiKeyException.cs
new file mode 100644
index 000000000..ff97425f8
--- /dev/null
+++ b/NzbDrone.Core/Indexers/Exceptions/ApiKeyException.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NzbDrone.Common.Exceptions;
+
+namespace NzbDrone.Core.Indexers.Exceptions
+{
+ public class ApiKeyException : NzbDroneException
+ {
+ public ApiKeyException(string message, params object[] args) : base(message, args)
+ {
+ }
+
+ public ApiKeyException(string message) : base(message)
+ {
+ }
+ }
+}
diff --git a/NzbDrone.Core/Indexers/IndexerFetchService.cs b/NzbDrone.Core/Indexers/IndexerFetchService.cs
index 9814adc0d..ba284c8b7 100644
--- a/NzbDrone.Core/Indexers/IndexerFetchService.cs
+++ b/NzbDrone.Core/Indexers/IndexerFetchService.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Net;
using NLog;
using NzbDrone.Common;
+using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using System.Linq;
@@ -30,7 +31,6 @@ namespace NzbDrone.Core.Indexers
_logger = logger;
}
-
public virtual IList FetchRss(IIndexer indexer)
{
_logger.Debug("Fetching feeds from " + indexer.Name);
@@ -53,7 +53,6 @@ namespace NzbDrone.Core.Indexers
return result;
}
-
private IList Fetch(IIndexer indexer, SeasonSearchCriteria searchCriteria, int offset)
{
_logger.Debug("Searching for {0} offset: {1}", searchCriteria, offset);
@@ -117,15 +116,21 @@ namespace NzbDrone.Core.Indexers
}
catch (WebException webException)
{
- if (webException.Message.Contains("502") || webException.Message.Contains("503") || webException.Message.Contains("timed out"))
+ if (webException.Message.Contains("502") || webException.Message.Contains("503") ||
+ webException.Message.Contains("timed out"))
{
- _logger.Warn("{0} server is currently unavailable. {1} {2}", indexer.Name, url, webException.Message);
+ _logger.Warn("{0} server is currently unavailable. {1} {2}", indexer.Name, url,
+ webException.Message);
}
else
{
_logger.Warn("{0} {1} {2}", indexer.Name, url, webException.Message);
}
}
+ catch (ApiKeyException)
+ {
+ _logger.Warn("Invalid API Key for {0} {1}", indexer.Name, url);
+ }
catch (Exception feedEx)
{
feedEx.Data.Add("FeedUrl", url);
diff --git a/NzbDrone.Core/Indexers/Newznab/NewznabException.cs b/NzbDrone.Core/Indexers/Newznab/NewznabException.cs
new file mode 100644
index 000000000..df858ac24
--- /dev/null
+++ b/NzbDrone.Core/Indexers/Newznab/NewznabException.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NzbDrone.Common.Exceptions;
+
+namespace NzbDrone.Core.Indexers.Newznab
+{
+ public class NewznabException : NzbDroneException
+ {
+ public NewznabException(string message, params object[] args) : base(message, args)
+ {
+ }
+
+ public NewznabException(string message) : base(message)
+ {
+ }
+ }
+}
diff --git a/NzbDrone.Core/Indexers/Newznab/NewznabParser.cs b/NzbDrone.Core/Indexers/Newznab/NewznabParser.cs
index fc9e54d93..bd8096877 100644
--- a/NzbDrone.Core/Indexers/Newznab/NewznabParser.cs
+++ b/NzbDrone.Core/Indexers/Newznab/NewznabParser.cs
@@ -1,6 +1,8 @@
using System;
using System.Linq;
+using System.Xml;
using System.Xml.Linq;
+using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Indexers.Newznab
@@ -46,5 +48,10 @@ namespace NzbDrone.Core.Indexers.Newznab
return currentResult;
}
+
+ protected override void PreProcess(string source, string url)
+ {
+ NewznabPreProcessor.Process(source, url);
+ }
}
}
\ No newline at end of file
diff --git a/NzbDrone.Core/Indexers/Newznab/NewznabPreProcessor.cs b/NzbDrone.Core/Indexers/Newznab/NewznabPreProcessor.cs
new file mode 100644
index 000000000..3977a2c75
--- /dev/null
+++ b/NzbDrone.Core/Indexers/Newznab/NewznabPreProcessor.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Linq;
+using System.Xml.Linq;
+using NzbDrone.Core.Indexers.Exceptions;
+
+namespace NzbDrone.Core.Indexers.Newznab
+{
+ public static class NewznabPreProcessor
+ {
+ public static void Process(string source, string url)
+ {
+ var xdoc = XDocument.Parse(source);
+ var error = xdoc.Descendants("error").FirstOrDefault();
+
+ if (error == null) return;
+
+ var code = Convert.ToInt32(error.Attribute("code").Value);
+
+ if (code >= 100 && code <= 199) throw new ApiKeyException("Invalid API key: {0}");
+
+ throw new NewznabException("Newznab error detected: {0}", error.Attribute("description").Value);
+ }
+ }
+}
diff --git a/NzbDrone.Core/Indexers/NewznabTestService.cs b/NzbDrone.Core/Indexers/NewznabTestService.cs
index dd5fea38c..c56b9b464 100644
--- a/NzbDrone.Core/Indexers/NewznabTestService.cs
+++ b/NzbDrone.Core/Indexers/NewznabTestService.cs
@@ -5,6 +5,8 @@ using FluentValidation;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common;
+using NzbDrone.Core.Indexers.Exceptions;
+using NzbDrone.Core.Indexers.Newznab;
namespace NzbDrone.Core.Indexers
{
@@ -34,21 +36,25 @@ namespace NzbDrone.Core.Indexers
try
{
- _httpProvider.DownloadString(indexer.RecentFeed.First());
+ var url = indexer.RecentFeed.First();
+ var xml = _httpProvider.DownloadString(url);
+
+ NewznabPreProcessor.Process(xml, url);
}
+ catch (ApiKeyException apiKeyException)
+ {
+ _logger.Warn("Indexer returned result for Newznab RSS URL, API Key appears to be invalid");
- catch (Exception)
+ var apiKeyFailure = new ValidationFailure("ApiKey", "Invalid API Key");
+ throw new ValidationException(new List { apiKeyFailure }.ToArray());
+ }
+ catch (Exception ex)
{
- _logger.Warn("No result returned from RSS Feed, please confirm you're using a newznab indexer");
+ _logger.Warn("Indexer doesn't appear to be Newznab based");
var failure = new ValidationFailure("Url", "Invalid Newznab URL entered");
throw new ValidationException(new List { failure }.ToArray());
}
-
- _logger.Warn("Indexer returned result for Newznab RSS URL, API Key appears to be invalid");
-
- var apiKeyFailure = new ValidationFailure("ApiKey", "Invalid API Key");
- throw new ValidationException(new List { apiKeyFailure }.ToArray());
}
}
}
diff --git a/NzbDrone.Core/Indexers/RssParserBase.cs b/NzbDrone.Core/Indexers/RssParserBase.cs
index ca4bf91f8..7eae9a117 100644
--- a/NzbDrone.Core/Indexers/RssParserBase.cs
+++ b/NzbDrone.Core/Indexers/RssParserBase.cs
@@ -29,6 +29,8 @@ namespace NzbDrone.Core.Indexers
public IEnumerable Process(string xml, string url)
{
+ PreProcess(xml, url);
+
using (var xmlTextReader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { ProhibitDtd = false, IgnoreComments = true }))
{
@@ -103,6 +105,10 @@ namespace NzbDrone.Core.Indexers
protected abstract long GetSize(XElement item);
+ protected virtual void PreProcess(string source, string url)
+ {
+ }
+
protected virtual ReleaseInfo PostProcessor(XElement item, ReleaseInfo currentResult)
{
return currentResult;
diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj
index 205b6c817..34bc316bb 100644
--- a/NzbDrone.Core/NzbDrone.Core.csproj
+++ b/NzbDrone.Core/NzbDrone.Core.csproj
@@ -234,6 +234,7 @@
+
@@ -241,6 +242,8 @@
+
+
diff --git a/UI/Settings/Indexers/EditView.js b/UI/Settings/Indexers/EditView.js
index 0e4f227f2..4d0defee0 100644
--- a/UI/Settings/Indexers/EditView.js
+++ b/UI/Settings/Indexers/EditView.js
@@ -36,7 +36,7 @@ define(
App.vent.trigger(App.Commands.CloseModalCommand);
});
- promise.always(function () {
+ promise.fail(function () {
self.ui.activity.empty();
});
}
@@ -63,7 +63,7 @@ define(
});
});
- promise.always(function () {
+ promise.fail(function () {
self.ui.activity.empty();
});
}