Validate newznab indexers when adding

pull/4/head
Mark McDowall 11 years ago
parent 34b5a833f5
commit f0e721ee80

@ -4,11 +4,11 @@ namespace NzbDrone.Core.Exceptions
{ {
public class BadRequestException : DownstreamException public class BadRequestException : DownstreamException
{ {
public BadRequestException(HttpStatusCode statusCode, string message) : base(statusCode, message) public BadRequestException(string message) : base(HttpStatusCode.BadRequest, message)
{ {
} }
public BadRequestException(HttpStatusCode statusCode, string message, params object[] args) : base(statusCode, message, args) public BadRequestException(string message, params object[] args) : base(HttpStatusCode.BadRequest, message, args)
{ {
} }
} }

@ -15,7 +15,7 @@ namespace NzbDrone.Core.Exceptions
switch (statusCode) switch (statusCode)
{ {
case HttpStatusCode.BadRequest: case HttpStatusCode.BadRequest:
throw new BadRequestException(statusCode, message); throw new BadRequestException(message);
case HttpStatusCode.Unauthorized: case HttpStatusCode.Unauthorized:
throw new UnauthorizedAccessException(message); throw new UnauthorizedAccessException(message);

@ -37,14 +37,20 @@ namespace NzbDrone.Core.Indexers
{ {
private readonly IIndexerRepository _indexerRepository; private readonly IIndexerRepository _indexerRepository;
private readonly IConfigFileProvider _configFileProvider; private readonly IConfigFileProvider _configFileProvider;
private readonly INewznabTestService _newznabTestService;
private readonly Logger _logger; private readonly Logger _logger;
private readonly List<IIndexer> _indexers; private readonly List<IIndexer> _indexers;
public IndexerService(IIndexerRepository indexerRepository, IEnumerable<IIndexer> indexers, IConfigFileProvider configFileProvider, Logger logger) public IndexerService(IIndexerRepository indexerRepository,
IEnumerable<IIndexer> indexers,
IConfigFileProvider configFileProvider,
INewznabTestService newznabTestService,
Logger logger)
{ {
_indexerRepository = indexerRepository; _indexerRepository = indexerRepository;
_configFileProvider = configFileProvider; _configFileProvider = configFileProvider;
_newznabTestService = newznabTestService;
_logger = logger; _logger = logger;
@ -104,6 +110,9 @@ namespace NzbDrone.Core.Indexers
Settings = indexer.Settings.ToJson() Settings = indexer.Settings.ToJson()
}; };
var instance = ToIndexer(definition).Instance;
_newznabTestService.Test(instance);
definition = _indexerRepository.Insert(definition); definition = _indexerRepository.Insert(definition);
indexer.Id = definition.Id; indexer.Id = definition.Id;

@ -114,7 +114,6 @@ namespace NzbDrone.Core.Indexers.Newznab
return RecentFeed.Select(url => String.Format("{0}&limit=100&q={1}&season={2}&offset={3}", url, NewsnabifyTitle(seriesTitle), seasonNumber, offset)); return RecentFeed.Select(url => String.Format("{0}&limit=100&q={1}&season={2}&offset={3}", url, NewsnabifyTitle(seriesTitle), seasonNumber, offset));
} }
public override string Name public override string Name
{ {
get get
@ -131,7 +130,6 @@ namespace NzbDrone.Core.Indexers.Newznab
} }
} }
private static string NewsnabifyTitle(string title) private static string NewsnabifyTitle(string title)
{ {
return title.Replace("+", "%20"); return title.Replace("+", "%20");

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FluentValidation;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common;
namespace NzbDrone.Core.Indexers
{
public interface INewznabTestService
{
void Test(IIndexer indexer);
}
public class NewznabTestService : INewznabTestService
{
private readonly IFetchFeedFromIndexers _feedFetcher;
private readonly IHttpProvider _httpProvider;
private readonly Logger _logger;
public NewznabTestService(IFetchFeedFromIndexers feedFetcher, IHttpProvider httpProvider, Logger logger)
{
_feedFetcher = feedFetcher;
_httpProvider = httpProvider;
_logger = logger;
}
public void Test(IIndexer indexer)
{
var releases = _feedFetcher.FetchRss(indexer);
if (releases.Any()) return;
try
{
_httpProvider.DownloadString(indexer.RecentFeed.First());
}
catch (Exception)
{
_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");
var apiKeyFailure = new ValidationFailure("ApiKey", "Invalid API Key");
throw new ValidationException(new List<ValidationFailure> { apiKeyFailure }.ToArray());
}
}
}

@ -238,6 +238,7 @@
<Compile Include="Indexers\FetchAndParseRssService.cs" /> <Compile Include="Indexers\FetchAndParseRssService.cs" />
<Compile Include="Indexers\IIndexer.cs" /> <Compile Include="Indexers\IIndexer.cs" />
<Compile Include="Indexers\IndexerSettingUpdatedEvent.cs" /> <Compile Include="Indexers\IndexerSettingUpdatedEvent.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\SizeParsingException.cs" /> <Compile Include="Indexers\Newznab\SizeParsingException.cs" />

@ -39,6 +39,9 @@
{{#if id}} {{#if id}}
<button class="btn btn-danger pull-left x-remove">delete</button> <button class="btn btn-danger pull-left x-remove">delete</button>
{{/if}} {{/if}}
<span class="x-activity"></span>
<button class="btn" data-dismiss="modal">cancel</button> <button class="btn" data-dismiss="modal">cancel</button>
<div class="btn-group"> <div class="btn-group">

@ -11,6 +11,10 @@ define(
var view = Marionette.ItemView.extend({ var view = Marionette.ItemView.extend({
template: 'Settings/Indexers/EditTemplate', template: 'Settings/Indexers/EditTemplate',
ui : {
activity: '.x-activity'
},
events: { events: {
'click .x-save' : '_save', 'click .x-save' : '_save',
'click .x-save-and-add': '_saveAndAdd' 'click .x-save-and-add': '_saveAndAdd'
@ -21,6 +25,8 @@ define(
}, },
_save: function () { _save: function () {
this.ui.activity.html('<i class="icon-nd-spinner"></i>');
var self = this; var self = this;
var promise = this.model.saveSettings(); var promise = this.model.saveSettings();
@ -29,10 +35,16 @@ define(
self.indexerCollection.add(self.model, { merge: true }); self.indexerCollection.add(self.model, { merge: true });
App.vent.trigger(App.Commands.CloseModalCommand); App.vent.trigger(App.Commands.CloseModalCommand);
}); });
promise.always(function () {
self.ui.activity.empty();
});
} }
}, },
_saveAndAdd: function () { _saveAndAdd: function () {
this.ui.activity.html('<i class="icon-nd-spinner"></i>');
var self = this; var self = this;
var promise = this.model.saveSettings(); var promise = this.model.saveSettings();
@ -50,6 +62,10 @@ define(
self.model.set('fields.' + key + '.value', ''); self.model.set('fields.' + key + '.value', '');
}); });
}); });
promise.always(function () {
self.ui.activity.empty();
});
} }
} }
}); });

Loading…
Cancel
Save