Now checking for errors before parsing newznab feeds
This commit is contained in:
parent
ca429cf5de
commit
9fa4cedb71
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<error code="100" description="Incorrect user credentials"/>
|
|
@ -252,6 +252,7 @@
|
||||||
<Content Include="App_Data\Config.xml">
|
<Content Include="App_Data\Config.xml">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Files\Indexers\Newznab\error.xml" />
|
||||||
<Content Include="Files\Media\H264_sample.mp4">
|
<Content Include="Files\Media\H264_sample.mp4">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -351,7 +352,6 @@
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Files\Indexers\" />
|
|
||||||
<Folder Include="ProviderTests\UpdateProviderTests\" />
|
<Folder Include="ProviderTests\UpdateProviderTests\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
|
|
@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common;
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Core.Indexers.Exceptions;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -30,7 +31,6 @@ namespace NzbDrone.Core.Indexers
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public virtual IList<ReleaseInfo> FetchRss(IIndexer indexer)
|
public virtual IList<ReleaseInfo> FetchRss(IIndexer indexer)
|
||||||
{
|
{
|
||||||
_logger.Debug("Fetching feeds from " + indexer.Name);
|
_logger.Debug("Fetching feeds from " + indexer.Name);
|
||||||
|
@ -53,7 +53,6 @@ namespace NzbDrone.Core.Indexers
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private IList<ReleaseInfo> Fetch(IIndexer indexer, SeasonSearchCriteria searchCriteria, int offset)
|
private IList<ReleaseInfo> Fetch(IIndexer indexer, SeasonSearchCriteria searchCriteria, int offset)
|
||||||
{
|
{
|
||||||
_logger.Debug("Searching for {0} offset: {1}", searchCriteria, offset);
|
_logger.Debug("Searching for {0} offset: {1}", searchCriteria, offset);
|
||||||
|
@ -117,15 +116,21 @@ namespace NzbDrone.Core.Indexers
|
||||||
}
|
}
|
||||||
catch (WebException webException)
|
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
|
else
|
||||||
{
|
{
|
||||||
_logger.Warn("{0} {1} {2}", indexer.Name, url, webException.Message);
|
_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)
|
catch (Exception feedEx)
|
||||||
{
|
{
|
||||||
feedEx.Data.Add("FeedUrl", url);
|
feedEx.Data.Add("FeedUrl", url);
|
||||||
|
|
|
@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Xml;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using NzbDrone.Core.Indexers.Exceptions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers.Newznab
|
namespace NzbDrone.Core.Indexers.Newznab
|
||||||
|
@ -46,5 +48,10 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||||
|
|
||||||
return currentResult;
|
return currentResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void PreProcess(string source, string url)
|
||||||
|
{
|
||||||
|
NewznabPreProcessor.Process(source, url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common;
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Core.Indexers.Exceptions;
|
||||||
|
using NzbDrone.Core.Indexers.Newznab;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers
|
namespace NzbDrone.Core.Indexers
|
||||||
{
|
{
|
||||||
|
@ -34,21 +36,25 @@ namespace NzbDrone.Core.Indexers
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_httpProvider.DownloadString(indexer.RecentFeed.First());
|
var url = indexer.RecentFeed.First();
|
||||||
}
|
var xml = _httpProvider.DownloadString(url);
|
||||||
|
|
||||||
catch (Exception)
|
NewznabPreProcessor.Process(xml, url);
|
||||||
|
}
|
||||||
|
catch (ApiKeyException apiKeyException)
|
||||||
{
|
{
|
||||||
_logger.Warn("No result returned from RSS Feed, please confirm you're using a newznab indexer");
|
|
||||||
|
|
||||||
var failure = new ValidationFailure("Url", "Invalid Newznab URL entered");
|
|
||||||
throw new ValidationException(new List<ValidationFailure> { failure }.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.Warn("Indexer returned result for Newznab RSS URL, API Key appears to be invalid");
|
_logger.Warn("Indexer returned result for Newznab RSS URL, API Key appears to be invalid");
|
||||||
|
|
||||||
var apiKeyFailure = new ValidationFailure("ApiKey", "Invalid API Key");
|
var apiKeyFailure = new ValidationFailure("ApiKey", "Invalid API Key");
|
||||||
throw new ValidationException(new List<ValidationFailure> { apiKeyFailure }.ToArray());
|
throw new ValidationException(new List<ValidationFailure> { apiKeyFailure }.ToArray());
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Warn("Indexer doesn't appear to be Newznab based");
|
||||||
|
|
||||||
|
var failure = new ValidationFailure("Url", "Invalid Newznab URL entered");
|
||||||
|
throw new ValidationException(new List<ValidationFailure> { failure }.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ namespace NzbDrone.Core.Indexers
|
||||||
|
|
||||||
public IEnumerable<ReleaseInfo> Process(string xml, string url)
|
public IEnumerable<ReleaseInfo> Process(string xml, string url)
|
||||||
{
|
{
|
||||||
|
PreProcess(xml, url);
|
||||||
|
|
||||||
using (var xmlTextReader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { ProhibitDtd = false, IgnoreComments = true }))
|
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 abstract long GetSize(XElement item);
|
||||||
|
|
||||||
|
protected virtual void PreProcess(string source, string url)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual ReleaseInfo PostProcessor(XElement item, ReleaseInfo currentResult)
|
protected virtual ReleaseInfo PostProcessor(XElement item, ReleaseInfo currentResult)
|
||||||
{
|
{
|
||||||
return currentResult;
|
return currentResult;
|
||||||
|
|
|
@ -234,6 +234,7 @@
|
||||||
<Compile Include="IndexerSearch\SeasonSearchService.cs" />
|
<Compile Include="IndexerSearch\SeasonSearchService.cs" />
|
||||||
<Compile Include="Indexers\BasicTorrentRssParser.cs" />
|
<Compile Include="Indexers\BasicTorrentRssParser.cs" />
|
||||||
<Compile Include="Indexers\DownloadProtocols.cs" />
|
<Compile Include="Indexers\DownloadProtocols.cs" />
|
||||||
|
<Compile Include="Indexers\Exceptions\ApiKeyException.cs" />
|
||||||
<Compile Include="Indexers\Eztv\Eztv.cs" />
|
<Compile Include="Indexers\Eztv\Eztv.cs" />
|
||||||
<Compile Include="Indexers\FetchAndParseRssService.cs" />
|
<Compile Include="Indexers\FetchAndParseRssService.cs" />
|
||||||
<Compile Include="Indexers\IIndexer.cs" />
|
<Compile Include="Indexers\IIndexer.cs" />
|
||||||
|
@ -241,6 +242,8 @@
|
||||||
<Compile Include="Indexers\NewznabTestService.cs" />
|
<Compile Include="Indexers\NewznabTestService.cs" />
|
||||||
<Compile Include="Indexers\IndexerWithSetting.cs" />
|
<Compile Include="Indexers\IndexerWithSetting.cs" />
|
||||||
<Compile Include="Indexers\IParseFeed.cs" />
|
<Compile Include="Indexers\IParseFeed.cs" />
|
||||||
|
<Compile Include="Indexers\Newznab\NewznabException.cs" />
|
||||||
|
<Compile Include="Indexers\Newznab\NewznabPreProcessor.cs" />
|
||||||
<Compile Include="Indexers\Newznab\SizeParsingException.cs" />
|
<Compile Include="Indexers\Newznab\SizeParsingException.cs" />
|
||||||
<Compile Include="Indexers\NullSetting.cs" />
|
<Compile Include="Indexers\NullSetting.cs" />
|
||||||
<Compile Include="Indexers\RssSyncCommand.cs" />
|
<Compile Include="Indexers\RssSyncCommand.cs" />
|
||||||
|
|
|
@ -36,7 +36,7 @@ define(
|
||||||
App.vent.trigger(App.Commands.CloseModalCommand);
|
App.vent.trigger(App.Commands.CloseModalCommand);
|
||||||
});
|
});
|
||||||
|
|
||||||
promise.always(function () {
|
promise.fail(function () {
|
||||||
self.ui.activity.empty();
|
self.ui.activity.empty();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ define(
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
promise.always(function () {
|
promise.fail(function () {
|
||||||
self.ui.activity.empty();
|
self.ui.activity.empty();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue