diff --git a/NzbDrone.Core/Exceptions/BadRequestException.cs b/NzbDrone.Core/Exceptions/BadRequestException.cs index 212b69e87..adf8bf57f 100644 --- a/NzbDrone.Core/Exceptions/BadRequestException.cs +++ b/NzbDrone.Core/Exceptions/BadRequestException.cs @@ -4,11 +4,11 @@ namespace NzbDrone.Core.Exceptions { 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) { } } diff --git a/NzbDrone.Core/Exceptions/StatusCodeToExceptions.cs b/NzbDrone.Core/Exceptions/StatusCodeToExceptions.cs index 10513d9c6..8deb955bb 100644 --- a/NzbDrone.Core/Exceptions/StatusCodeToExceptions.cs +++ b/NzbDrone.Core/Exceptions/StatusCodeToExceptions.cs @@ -15,7 +15,7 @@ namespace NzbDrone.Core.Exceptions switch (statusCode) { case HttpStatusCode.BadRequest: - throw new BadRequestException(statusCode, message); + throw new BadRequestException(message); case HttpStatusCode.Unauthorized: throw new UnauthorizedAccessException(message); diff --git a/NzbDrone.Core/Indexers/IndexerService.cs b/NzbDrone.Core/Indexers/IndexerService.cs index 2c87569e3..e1b49c2dd 100644 --- a/NzbDrone.Core/Indexers/IndexerService.cs +++ b/NzbDrone.Core/Indexers/IndexerService.cs @@ -37,14 +37,20 @@ namespace NzbDrone.Core.Indexers { private readonly IIndexerRepository _indexerRepository; private readonly IConfigFileProvider _configFileProvider; + private readonly INewznabTestService _newznabTestService; private readonly Logger _logger; private readonly List _indexers; - public IndexerService(IIndexerRepository indexerRepository, IEnumerable indexers, IConfigFileProvider configFileProvider, Logger logger) + public IndexerService(IIndexerRepository indexerRepository, + IEnumerable indexers, + IConfigFileProvider configFileProvider, + INewznabTestService newznabTestService, + Logger logger) { _indexerRepository = indexerRepository; _configFileProvider = configFileProvider; + _newznabTestService = newznabTestService; _logger = logger; @@ -104,6 +110,9 @@ namespace NzbDrone.Core.Indexers Settings = indexer.Settings.ToJson() }; + var instance = ToIndexer(definition).Instance; + _newznabTestService.Test(instance); + definition = _indexerRepository.Insert(definition); indexer.Id = definition.Id; diff --git a/NzbDrone.Core/Indexers/Newznab/Newznab.cs b/NzbDrone.Core/Indexers/Newznab/Newznab.cs index 4341c22f7..8a13d2282 100644 --- a/NzbDrone.Core/Indexers/Newznab/Newznab.cs +++ b/NzbDrone.Core/Indexers/Newznab/Newznab.cs @@ -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)); } - public override string Name { get @@ -131,7 +130,6 @@ namespace NzbDrone.Core.Indexers.Newznab } } - private static string NewsnabifyTitle(string title) { return title.Replace("+", "%20"); diff --git a/NzbDrone.Core/Indexers/NewznabTestService.cs b/NzbDrone.Core/Indexers/NewznabTestService.cs new file mode 100644 index 000000000..dd5fea38c --- /dev/null +++ b/NzbDrone.Core/Indexers/NewznabTestService.cs @@ -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 { 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/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 08803f3fa..205b6c817 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -238,6 +238,7 @@ + diff --git a/UI/Settings/Indexers/EditTemplate.html b/UI/Settings/Indexers/EditTemplate.html index e433b1a29..f9c3779ca 100644 --- a/UI/Settings/Indexers/EditTemplate.html +++ b/UI/Settings/Indexers/EditTemplate.html @@ -39,6 +39,9 @@ {{#if id}} {{/if}} + + +
diff --git a/UI/Settings/Indexers/EditView.js b/UI/Settings/Indexers/EditView.js index 1d49366cb..0e4f227f2 100644 --- a/UI/Settings/Indexers/EditView.js +++ b/UI/Settings/Indexers/EditView.js @@ -11,6 +11,10 @@ define( var view = Marionette.ItemView.extend({ template: 'Settings/Indexers/EditTemplate', + ui : { + activity: '.x-activity' + }, + events: { 'click .x-save' : '_save', 'click .x-save-and-add': '_saveAndAdd' @@ -21,6 +25,8 @@ define( }, _save: function () { + this.ui.activity.html(''); + var self = this; var promise = this.model.saveSettings(); @@ -29,10 +35,16 @@ define( self.indexerCollection.add(self.model, { merge: true }); App.vent.trigger(App.Commands.CloseModalCommand); }); + + promise.always(function () { + self.ui.activity.empty(); + }); } }, _saveAndAdd: function () { + this.ui.activity.html(''); + var self = this; var promise = this.model.saveSettings(); @@ -50,6 +62,10 @@ define( self.model.set('fields.' + key + '.value', ''); }); }); + + promise.always(function () { + self.ui.activity.empty(); + }); } } });