From 27da44ba45e66c00cd75dab1b30f29dac1891277 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sat, 12 Oct 2013 11:44:40 -0700 Subject: [PATCH] Converted notifications to thingi provider Fixed: Issues creating and saving Connects --- src/NzbDrone.Api/Indexers/IndexerModule.cs | 8 +- src/NzbDrone.Api/Indexers/IndexerResource.cs | 9 +- .../Indexers/IndexerSchemaModule.cs | 2 - .../Notifications/NotificationModule.cs | 77 +------ .../Notifications/NotificationResource.cs | 9 +- .../Notifications/NotificationSchemaModule.cs | 12 +- src/NzbDrone.Api/NzbDrone.Api.csproj | 2 +- src/NzbDrone.Api/ProviderModuleBase.cs | 59 ++--- ...IndexerResource.cs => ProviderResource.cs} | 1 - .../NotificationServiceFixture.cs | 130 ----------- .../NzbDrone.Core.Test.csproj | 1 - .../022_move_indexer_to_generic_provider.cs | 18 ++ ...2_move_notification_to_generic_provider.cs | 68 ------ ...5_move_notification_to_generic_provider.cs | 14 ++ ...26_add_config_contract_to_notifications.cs | 24 ++ src/NzbDrone.Core/Datastore/TableMapping.cs | 6 +- .../Indexers/IndexerDefinition.cs | 1 + src/NzbDrone.Core/Indexers/IndexerFactory.cs | 1 - .../Indexers/Newznab/NewznabSettings.cs | 1 - .../Notifications/Email/Email.cs | 10 - .../Notifications/Email/EmailSettings.cs | 16 +- .../Notifications/Growl/Growl.cs | 10 - .../Notifications/Growl/GrowlSettings.cs | 14 +- .../Notifications/INotification.cs | 9 +- .../Notifications/NotificationBase.cs | 41 +++- .../Notifications/NotificationDefinition.cs | 13 +- .../Notifications/NotificationFactory.cs | 20 ++ .../Notifications/NotificationRepository.cs | 22 +- .../Notifications/NotificationService.cs | 214 ------------------ .../NotificationSettingsProvider.cs | 32 --- .../NotifyMyAndroid/NotifyMyAndroid.cs | 10 - .../NotifyMyAndroidSettings.cs | 13 +- .../Notifications/Plex/PlexClient.cs | 10 - .../Notifications/Plex/PlexClientSettings.cs | 14 +- .../Notifications/Plex/PlexServer.cs | 10 - .../Notifications/Plex/PlexServerSettings.cs | 14 +- .../Notifications/Prowl/Prowl.cs | 10 - .../Notifications/Prowl/ProwlSettings.cs | 13 +- .../Notifications/PushBullet/PushBullet.cs | 10 - .../PushBullet/PushBulletSettings.cs | 14 +- .../Notifications/Pushover/Pushover.cs | 10 - .../Pushover/PushoverSettings.cs | 13 +- src/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs | 10 - .../Notifications/Xbmc/XbmcSettings.cs | 14 +- src/NzbDrone.Core/NzbDrone.Core.csproj | 7 +- .../ThingiProvider/ProviderDefinition.cs | 1 - .../ThingiProvider/ProviderFactory.cs | 2 +- .../Notifications/AddItemTemplate.html | 2 +- src/UI/Settings/Notifications/AddItemView.js | 2 +- .../{EditView.js => NotificationEditView.js} | 33 +-- ...html => NotificationEditViewTemplate.html} | 4 +- 51 files changed, 299 insertions(+), 761 deletions(-) rename src/NzbDrone.Api/{IndexerResource.cs => ProviderResource.cs} (89%) delete mode 100644 src/NzbDrone.Core.Test/NotificationTests/NotificationServiceFixture.cs create mode 100644 src/NzbDrone.Core/Datastore/Migration/022_move_indexer_to_generic_provider.cs delete mode 100644 src/NzbDrone.Core/Datastore/Migration/022_move_notification_to_generic_provider.cs create mode 100644 src/NzbDrone.Core/Datastore/Migration/025_move_notification_to_generic_provider.cs create mode 100644 src/NzbDrone.Core/Datastore/Migration/026_add_config_contract_to_notifications.cs create mode 100644 src/NzbDrone.Core/Notifications/NotificationFactory.cs delete mode 100644 src/NzbDrone.Core/Notifications/NotificationService.cs delete mode 100644 src/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs rename src/UI/Settings/Notifications/{EditView.js => NotificationEditView.js} (72%) rename src/UI/Settings/Notifications/{EditTemplate.html => NotificationEditViewTemplate.html} (96%) diff --git a/src/NzbDrone.Api/Indexers/IndexerModule.cs b/src/NzbDrone.Api/Indexers/IndexerModule.cs index 33c56a108..521ce0bfa 100644 --- a/src/NzbDrone.Api/Indexers/IndexerModule.cs +++ b/src/NzbDrone.Api/Indexers/IndexerModule.cs @@ -2,11 +2,17 @@ namespace NzbDrone.Api.Indexers { - public class IndexerModule : ProviderModuleBase + public class IndexerModule : ProviderModuleBase { public IndexerModule(IndexerFactory indexerFactory) : base(indexerFactory, "indexer") { } + + protected override void Validate(IndexerDefinition definition) + { + if (!definition.Enable) return; + base.Validate(definition); + } } } \ No newline at end of file diff --git a/src/NzbDrone.Api/Indexers/IndexerResource.cs b/src/NzbDrone.Api/Indexers/IndexerResource.cs index a613526fe..dbb55c3f0 100644 --- a/src/NzbDrone.Api/Indexers/IndexerResource.cs +++ b/src/NzbDrone.Api/Indexers/IndexerResource.cs @@ -1,16 +1,9 @@ using System; -using System.Collections.Generic; -using NzbDrone.Api.ClientSchema; -using NzbDrone.Api.REST; namespace NzbDrone.Api.Indexers { - public class IndexerResource : RestResource + public class IndexerResource : ProviderResource { public Boolean Enable { get; set; } - public String Name { get; set; } - public List Fields { get; set; } - public String Implementation { get; set; } - public String ConfigContract { get; set; } } } \ No newline at end of file diff --git a/src/NzbDrone.Api/Indexers/IndexerSchemaModule.cs b/src/NzbDrone.Api/Indexers/IndexerSchemaModule.cs index a0312bdc4..d433102c8 100644 --- a/src/NzbDrone.Api/Indexers/IndexerSchemaModule.cs +++ b/src/NzbDrone.Api/Indexers/IndexerSchemaModule.cs @@ -19,10 +19,8 @@ namespace NzbDrone.Api.Indexers private List GetSchema() { - var indexers = _indexerFactory.Templates().Where(c => c.Implementation =="Newznab"); - var result = new List(indexers.Count()); foreach (var indexer in indexers) diff --git a/src/NzbDrone.Api/Notifications/NotificationModule.cs b/src/NzbDrone.Api/Notifications/NotificationModule.cs index c8be13f67..25bf43419 100644 --- a/src/NzbDrone.Api/Notifications/NotificationModule.cs +++ b/src/NzbDrone.Api/Notifications/NotificationModule.cs @@ -10,82 +10,17 @@ using Omu.ValueInjecter; namespace NzbDrone.Api.Notifications { - public class NotificationModule : NzbDroneRestModule + public class IndexerModule : ProviderModuleBase { - private readonly INotificationService _notificationService; - - public NotificationModule(INotificationService notificationService) - { - _notificationService = notificationService; - - GetResourceAll = GetAll; - GetResourceById = GetNotification; - CreateResource = Create; - UpdateResource = Update; - DeleteResource = DeleteNotification; - } - - private NotificationResource GetNotification(int id) - { - return _notificationService.Get(id).InjectTo(); - } - - private List GetAll() - { - var notifications = _notificationService.All(); - - var result = new List(notifications.Count); - - foreach (var notification in notifications) - { - var notificationResource = new NotificationResource(); - notificationResource.InjectFrom(notification); - notificationResource.Fields = SchemaBuilder.ToSchema(notification.Settings); - notificationResource.TestCommand = String.Format("test{0}", notification.Implementation.ToLowerInvariant()); - - result.Add(notificationResource); - } - - return result; - } - - private int Create(NotificationResource notificationResource) + public IndexerModule(NotificationFactory notificationrFactory) + : base(notificationrFactory, "notification") { - var notification = ConvertToNotification(notificationResource); - return _notificationService.Create(notification).Id; } - private void Update(NotificationResource notificationResource) + protected override void Validate(NotificationDefinition definition) { - var notification = ConvertToNotification(notificationResource); - notification.Id = notificationResource.Id; - _notificationService.Update(notification); - } - - private void DeleteNotification(int id) - { - _notificationService.Delete(id); - } - - private Notification ConvertToNotification(NotificationResource notificationResource) - { - var notification = _notificationService.Schema() - .SingleOrDefault(i => - i.Implementation.Equals(notificationResource.Implementation, - StringComparison.InvariantCultureIgnoreCase)); - - if (notification == null) - { - throw new BadRequestException("Invalid Notification Implementation"); - } - - notification.InjectFrom(notificationResource); - - //var configType = ReflectionExtensions.CoreAssembly.FindTypeByName(notification) - - //notification.Settings = SchemaBuilder.ReadFormSchema(notification.Settings, notificationResource.Fields); - - return notification; + if (!definition.OnGrab && !definition.OnDownload) return; + base.Validate(definition); } } } \ No newline at end of file diff --git a/src/NzbDrone.Api/Notifications/NotificationResource.cs b/src/NzbDrone.Api/Notifications/NotificationResource.cs index d96539de8..54ffe720a 100644 --- a/src/NzbDrone.Api/Notifications/NotificationResource.cs +++ b/src/NzbDrone.Api/Notifications/NotificationResource.cs @@ -1,19 +1,12 @@ using System; -using System.Collections.Generic; -using NzbDrone.Api.ClientSchema; -using NzbDrone.Api.REST; namespace NzbDrone.Api.Notifications { - public class NotificationResource : RestResource + public class NotificationResource : ProviderResource { - public String Name { get; set; } - public String ImplementationName { get; set; } public String Link { get; set; } public Boolean OnGrab { get; set; } public Boolean OnDownload { get; set; } - public List Fields { get; set; } - public String Implementation { get; set; } public String TestCommand { get; set; } } } \ No newline at end of file diff --git a/src/NzbDrone.Api/Notifications/NotificationSchemaModule.cs b/src/NzbDrone.Api/Notifications/NotificationSchemaModule.cs index 68a5bd594..db661b5c1 100644 --- a/src/NzbDrone.Api/Notifications/NotificationSchemaModule.cs +++ b/src/NzbDrone.Api/Notifications/NotificationSchemaModule.cs @@ -7,20 +7,19 @@ using Omu.ValueInjecter; namespace NzbDrone.Api.Notifications { public class NotificationSchemaModule : NzbDroneRestModule - { - private readonly INotificationService _notificationService; + { + private readonly INotificationFactory _notificationFactory; - public NotificationSchemaModule(INotificationService notificationService) + public NotificationSchemaModule(INotificationFactory notificationFactory) : base("notification/schema") { - _notificationService = notificationService; - + _notificationFactory = notificationFactory; GetResourceAll = GetSchema; } private List GetSchema() { - var notifications = _notificationService.Schema(); + var notifications = _notificationFactory.Templates(); var result = new List(notifications.Count); @@ -29,7 +28,6 @@ namespace NzbDrone.Api.Notifications var notificationResource = new NotificationResource(); notificationResource.InjectFrom(notification); notificationResource.Fields = SchemaBuilder.ToSchema(notification.Settings); - notificationResource.TestCommand = String.Format("test{0}", notification.Implementation.ToLowerInvariant()); result.Add(notificationResource); } diff --git a/src/NzbDrone.Api/NzbDrone.Api.csproj b/src/NzbDrone.Api/NzbDrone.Api.csproj index 7b885fe48..653555dd9 100644 --- a/src/NzbDrone.Api/NzbDrone.Api.csproj +++ b/src/NzbDrone.Api/NzbDrone.Api.csproj @@ -109,7 +109,7 @@ - + diff --git a/src/NzbDrone.Api/ProviderModuleBase.cs b/src/NzbDrone.Api/ProviderModuleBase.cs index f379f598a..41e2ebe20 100644 --- a/src/NzbDrone.Api/ProviderModuleBase.cs +++ b/src/NzbDrone.Api/ProviderModuleBase.cs @@ -4,7 +4,6 @@ using FluentValidation; using Nancy; using NzbDrone.Api.ClientSchema; using NzbDrone.Api.Extensions; -using NzbDrone.Api.Indexers; using NzbDrone.Api.Mapping; using NzbDrone.Common.Reflection; using NzbDrone.Core.ThingiProvider; @@ -30,8 +29,6 @@ namespace NzbDrone.Api UpdateResource = UpdateProvider; DeleteResource = DeleteProvider; - - SharedValidator.RuleFor(c => c.Name).NotEmpty(); SharedValidator.RuleFor(c => c.Implementation).NotEmpty(); SharedValidator.RuleFor(c => c.ConfigContract).NotEmpty(); @@ -69,39 +66,25 @@ namespace NzbDrone.Api return indexer.Id; } - private void UpdateProvider(TProviderResource indexerResource) - { - var indexer = GetDefinition(indexerResource); - - ValidateIndexer(indexer); - - _providerFactory.Update(indexer); - } - - - private static void ValidateIndexer(ProviderDefinition definition) + private void UpdateProvider(TProviderResource providerResource) { - if (!definition.Enable) return; + var providerDefinition = GetDefinition(providerResource); - var validationResult = definition.Settings.Validate(); + Validate(providerDefinition); - if (!validationResult.IsValid) - { - throw new ValidationException(validationResult.Errors); - } + _providerFactory.Update(providerDefinition); } - private TProviderDefinition GetDefinition(TProviderResource indexerResource) + private TProviderDefinition GetDefinition(TProviderResource providerResource) { - var definition = new TProviderDefinition(); - definition.InjectFrom(indexerResource); + definition.InjectFrom(providerResource); var configContract = ReflectionExtensions.CoreAssembly.FindTypeByName(definition.ConfigContract); - definition.Settings = (IProviderConfig)SchemaBuilder.ReadFormSchema(indexerResource.Fields, configContract); + definition.Settings = (IProviderConfig)SchemaBuilder.ReadFormSchema(providerResource.Fields, configContract); - ValidateIndexer(definition); + Validate(definition); return definition; } @@ -113,22 +96,30 @@ namespace NzbDrone.Api private Response GetTemplates() { + var templates = _providerFactory.Templates(); - var indexers = _providerFactory.Templates(); - + var result = new List(templates.Count()); - var result = new List(indexers.Count()); - - foreach (var indexer in indexers) + foreach (var providerDefinition in templates) { - var indexerResource = new IndexerResource(); - indexerResource.InjectFrom(indexer); - indexerResource.Fields = SchemaBuilder.ToSchema(indexer.Settings); + var providerResource = new TProviderResource(); + providerResource.InjectFrom(providerDefinition); + providerResource.Fields = SchemaBuilder.ToSchema(providerDefinition.Settings); - result.Add(indexerResource); + result.Add(providerResource); } return result.AsResponse(); } + + protected virtual void Validate(TProviderDefinition definition) + { + var validationResult = definition.Settings.Validate(); + + if (!validationResult.IsValid) + { + throw new ValidationException(validationResult.Errors); + } + } } } \ No newline at end of file diff --git a/src/NzbDrone.Api/IndexerResource.cs b/src/NzbDrone.Api/ProviderResource.cs similarity index 89% rename from src/NzbDrone.Api/IndexerResource.cs rename to src/NzbDrone.Api/ProviderResource.cs index 65c5bad64..f866341e0 100644 --- a/src/NzbDrone.Api/IndexerResource.cs +++ b/src/NzbDrone.Api/ProviderResource.cs @@ -7,7 +7,6 @@ namespace NzbDrone.Api { public class ProviderResource : RestResource { - public Boolean Enable { get; set; } public String Name { get; set; } public List Fields { get; set; } public String Implementation { get; set; } diff --git a/src/NzbDrone.Core.Test/NotificationTests/NotificationServiceFixture.cs b/src/NzbDrone.Core.Test/NotificationTests/NotificationServiceFixture.cs deleted file mode 100644 index 80875d24f..000000000 --- a/src/NzbDrone.Core.Test/NotificationTests/NotificationServiceFixture.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net.Sockets; -using FizzWare.NBuilder; -using FluentAssertions; -using Moq; -using NUnit.Framework; -using NzbDrone.Common.Composition; -using NzbDrone.Core.MediaFiles.Events; -using NzbDrone.Core.Notifications; -using NzbDrone.Core.Notifications.Email; -using NzbDrone.Core.Notifications.Growl; -using NzbDrone.Core.Notifications.Plex; -using NzbDrone.Core.Notifications.Prowl; -using NzbDrone.Core.Parser.Model; -using NzbDrone.Core.Test.Framework; -using NzbDrone.Core.Tv; - -namespace NzbDrone.Core.Test.NotificationTests -{ - public class NotificationServiceFixture : DbTest - { - private List _notifications; - - [SetUp] - public void Setup() - { - _notifications = new List(); - - _notifications.Add(new Notifications.Xbmc.Xbmc(null)); - _notifications.Add(new PlexClient(null)); - _notifications.Add(new PlexServer(null)); - _notifications.Add(new Email(null)); - _notifications.Add(new Growl(null)); - _notifications.Add(new Prowl(null)); - - Mocker.SetConstant>(_notifications); - } - - [Test] - public void getting_list_of_indexers_should_be_empty_by_default() - { - Mocker.SetConstant(Mocker.Resolve()); - - var notifications = Subject.All().ToList(); - notifications.Should().BeEmpty(); - } - - [Test] - public void should_be_able_to_get_schema_for_all_notifications() - { - Mocker.SetConstant(Mocker.Resolve()); - - Mocker.GetMock().Setup(s => s.Resolve(typeof(Notifications.Xbmc.Xbmc))) - .Returns(new Notifications.Xbmc.Xbmc(null)); - - Mocker.GetMock().Setup(s => s.Resolve(typeof(PlexClient))) - .Returns(new PlexClient(null)); - - Mocker.GetMock().Setup(s => s.Resolve(typeof(PlexServer))) - .Returns(new PlexServer(null)); - - Mocker.GetMock().Setup(s => s.Resolve(typeof(Email))) - .Returns(new Email(null)); - - Mocker.GetMock().Setup(s => s.Resolve(typeof(Growl))) - .Returns(new Growl(null)); - - Mocker.GetMock().Setup(s => s.Resolve(typeof(Prowl))) - .Returns(new Prowl(null)); - - var notifications = Subject.Schema().ToList(); - notifications.Should().NotBeEmpty(); - notifications.Should().NotContain(c => c.Settings == null); - notifications.Should().NotContain(c => c.Instance == null); - notifications.Should().NotContain(c => c.ImplementationName == null); - notifications.Select(c => c.ImplementationName).Should().OnlyHaveUniqueItems(); - notifications.Select(c => c.Instance).Should().OnlyHaveUniqueItems(); - notifications.Select(c => c.Id).Should().OnlyHaveUniqueItems(); - } - - [Test] - [Explicit] - public void should_try_other_notifiers_when_one_fails() - { - var notifications = Builder.CreateListOfSize(2) - .All() - .With(n => n.OnGrab = true) - .With(n => n.OnDownload = true) - .TheFirst(1) - .With(n => n.Implementation = "Xbmc") - .TheLast(1) - .With(n => n.Implementation = "Email") - .Build() - .ToList(); - - var series = Builder.CreateNew() - .With(s => s.SeriesType = SeriesTypes.Standard) - .Build(); - - var parsedEpisodeInfo = Builder.CreateNew() - .With(p => p.EpisodeNumbers = new int[] {1}) - .Build(); - - var localEpisode = Builder.CreateNew() - .With(e => e.Series = series) - .With(e => e.ParsedEpisodeInfo = parsedEpisodeInfo) - .With(e => e.Episodes = Builder.CreateListOfSize(1) - .Build().ToList()) - .Build(); - - Mocker.GetMock() - .Setup(s => s.All()) - .Returns(notifications); - - //Todo: How can we test this, right now without an empty constructor it won't work - Mocker.GetMock() - .Setup(s => s.OnDownload(It.IsAny(), series)) - .Throws(new SocketException()); - - Subject.Handle(new EpisodeDownloadedEvent(localEpisode)); - - Mocker.GetMock() - .Verify(v => v.OnDownload(It.IsAny(), series), Times.Once()); - - Mocker.GetMock() - .Verify(v => v.OnDownload(It.IsAny(), series), Times.Once()); - } - } -} \ No newline at end of file diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 98115ab31..e75b4d0ac 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -156,7 +156,6 @@ - diff --git a/src/NzbDrone.Core/Datastore/Migration/022_move_indexer_to_generic_provider.cs b/src/NzbDrone.Core/Datastore/Migration/022_move_indexer_to_generic_provider.cs new file mode 100644 index 000000000..5d867f8a8 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/022_move_indexer_to_generic_provider.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Data; +using FluentMigrator; +using NzbDrone.Common.Serializer; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(22)] + public class move_indexer_to_generic_provider : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Alter.Table("Indexers").AddColumn("ConfigContract").AsString().Nullable(); + } + } +} diff --git a/src/NzbDrone.Core/Datastore/Migration/022_move_notification_to_generic_provider.cs b/src/NzbDrone.Core/Datastore/Migration/022_move_notification_to_generic_provider.cs deleted file mode 100644 index 2b5182419..000000000 --- a/src/NzbDrone.Core/Datastore/Migration/022_move_notification_to_generic_provider.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using FluentMigrator; -using NzbDrone.Common.Serializer; -using NzbDrone.Core.Datastore.Migration.Framework; - -namespace NzbDrone.Core.Datastore.Migration -{ - [Migration(22)] - public class move_indexer_to_generic_provider : NzbDroneMigrationBase - { - protected override void MainDbUpgrade() - { - Alter.Table("Indexers").AddColumn("ConfigContract").AsString().Nullable(); - - //Execute.WithConnection(ConvertSeasons); - } - - private void ConvertSeasons(IDbConnection conn, IDbTransaction tran) - { - using (IDbCommand allSeriesCmd = conn.CreateCommand()) - { - allSeriesCmd.Transaction = tran; - allSeriesCmd.CommandText = @"SELECT Id FROM Series"; - using (IDataReader allSeriesReader = allSeriesCmd.ExecuteReader()) - { - while (allSeriesReader.Read()) - { - int seriesId = allSeriesReader.GetInt32(0); - var seasons = new List(); - - using (IDbCommand seasonsCmd = conn.CreateCommand()) - { - seasonsCmd.Transaction = tran; - seasonsCmd.CommandText = String.Format(@"SELECT SeasonNumber, Monitored FROM Seasons WHERE SeriesId = {0}", seriesId); - - using (IDataReader seasonReader = seasonsCmd.ExecuteReader()) - { - while (seasonReader.Read()) - { - int seasonNumber = seasonReader.GetInt32(0); - bool monitored = seasonReader.GetBoolean(1); - - if (seasonNumber == 0) - { - monitored = false; - } - - seasons.Add(new { seasonNumber, monitored }); - } - } - } - - using (IDbCommand updateCmd = conn.CreateCommand()) - { - var text = String.Format("UPDATE Series SET Seasons = '{0}' WHERE Id = {1}", seasons.ToJson(), seriesId); - - updateCmd.Transaction = tran; - updateCmd.CommandText = text; - updateCmd.ExecuteNonQuery(); - } - } - } - } - } - } -} diff --git a/src/NzbDrone.Core/Datastore/Migration/025_move_notification_to_generic_provider.cs b/src/NzbDrone.Core/Datastore/Migration/025_move_notification_to_generic_provider.cs new file mode 100644 index 000000000..1937f76eb --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/025_move_notification_to_generic_provider.cs @@ -0,0 +1,14 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(25)] + public class move_notification_to_generic_provider : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Alter.Table("Notifications").AddColumn("ConfigContract").AsString().Nullable(); + } + } +} diff --git a/src/NzbDrone.Core/Datastore/Migration/026_add_config_contract_to_notifications.cs b/src/NzbDrone.Core/Datastore/Migration/026_add_config_contract_to_notifications.cs new file mode 100644 index 000000000..8eb24daae --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/026_add_config_contract_to_notifications.cs @@ -0,0 +1,24 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(26)] + public class add_config_contract_to_notifications : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Update.Table("Notifications").Set(new { ConfigContract = "EmailSettings" }).Where(new { Implementation = "Email" }); + Update.Table("Notifications").Set(new { ConfigContract = "GrowlSettings" }).Where(new { Implementation = "Growl" }); + Update.Table("Notifications").Set(new { ConfigContract = "NotifyMyAndroidSettings" }).Where(new { Implementation = "NotifyMyAndroid" }); + Update.Table("Notifications").Set(new { ConfigContract = "PlexClientSettings" }).Where(new { Implementation = "PlexClient" }); + Update.Table("Notifications").Set(new { ConfigContract = "PlexServerSettings" }).Where(new { Implementation = "PlexServer" }); + Update.Table("Notifications").Set(new { ConfigContract = "ProwlSettings" }).Where(new { Implementation = "Prowl" }); + Update.Table("Notifications").Set(new { ConfigContract = "PushBulletSettings" }).Where(new { Implementation = "PushBullet" }); + Update.Table("Notifications").Set(new { ConfigContract = "PushoverSettings" }).Where(new { Implementation = "Pushover" }); + Update.Table("Notifications").Set(new { ConfigContract = "XbmcSettings" }).Where(new { Implementation = "Xbmc" }); + + Delete.FromTable("Notifications").IsNull("ConfigContract"); + } + } +} diff --git a/src/NzbDrone.Core/Datastore/TableMapping.cs b/src/NzbDrone.Core/Datastore/TableMapping.cs index bade3c2d6..ec341d6dc 100644 --- a/src/NzbDrone.Core/Datastore/TableMapping.cs +++ b/src/NzbDrone.Core/Datastore/TableMapping.cs @@ -35,12 +35,13 @@ namespace NzbDrone.Core.Datastore Mapper.Entity().RegisterModel("Indexers"); Mapper.Entity().RegisterModel("ScheduledTasks"); - Mapper.Entity().RegisterModel("Notifications"); + Mapper.Entity() + .RegisterModel("Notifications"); Mapper.Entity().RegisterModel("SceneMappings"); Mapper.Entity().RegisterModel("History") - .AutoMapChildModels(); + .AutoMapChildModels(); Mapper.Entity().RegisterModel("Series") .Ignore(s => s.RootFolderPath) @@ -96,7 +97,6 @@ namespace NzbDrone.Core.Datastore { var embeddedTypes = typeof(IEmbeddedDocument).Assembly.ImplementationsOf(); - var embeddedConvertor = new EmbeddedDocumentConverter(); var genericListDefinition = typeof(List<>).GetGenericTypeDefinition(); foreach (var embeddedType in embeddedTypes) diff --git a/src/NzbDrone.Core/Indexers/IndexerDefinition.cs b/src/NzbDrone.Core/Indexers/IndexerDefinition.cs index 5909532b4..4a061129e 100644 --- a/src/NzbDrone.Core/Indexers/IndexerDefinition.cs +++ b/src/NzbDrone.Core/Indexers/IndexerDefinition.cs @@ -4,5 +4,6 @@ namespace NzbDrone.Core.Indexers { public class IndexerDefinition : ProviderDefinition { + public bool Enable { get; set; } } } \ No newline at end of file diff --git a/src/NzbDrone.Core/Indexers/IndexerFactory.cs b/src/NzbDrone.Core/Indexers/IndexerFactory.cs index b89f0d539..c7763be91 100644 --- a/src/NzbDrone.Core/Indexers/IndexerFactory.cs +++ b/src/NzbDrone.Core/Indexers/IndexerFactory.cs @@ -31,7 +31,6 @@ namespace NzbDrone.Core.Indexers var newProviders = definitions.Where(def => currentProviders.All(c => c.Implementation != def.Implementation)).ToList(); - if (newProviders.Any()) { _providerRepository.InsertMany(newProviders.Cast().ToList()); diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabSettings.cs b/src/NzbDrone.Core/Indexers/Newznab/NewznabSettings.cs index 5f05ba96d..c66dcf56e 100644 --- a/src/NzbDrone.Core/Indexers/Newznab/NewznabSettings.cs +++ b/src/NzbDrone.Core/Indexers/Newznab/NewznabSettings.cs @@ -16,7 +16,6 @@ namespace NzbDrone.Core.Indexers.Newznab } } - public class NewznabSettings : IProviderConfig { private static readonly NewznabSettingsValidator Validator = new NewznabSettingsValidator(); diff --git a/src/NzbDrone.Core/Notifications/Email/Email.cs b/src/NzbDrone.Core/Notifications/Email/Email.cs index 87ddabc59..30a4e2d23 100644 --- a/src/NzbDrone.Core/Notifications/Email/Email.cs +++ b/src/NzbDrone.Core/Notifications/Email/Email.cs @@ -12,16 +12,6 @@ namespace NzbDrone.Core.Notifications.Email _smtpProvider = smtpProvider; } - public override string Name - { - get { return "Email"; } - } - - public override string ImplementationName - { - get { return "Email"; } - } - public override string Link { get { return null; } diff --git a/src/NzbDrone.Core/Notifications/Email/EmailSettings.cs b/src/NzbDrone.Core/Notifications/Email/EmailSettings.cs index 42aa725cd..3fd19a59f 100644 --- a/src/NzbDrone.Core/Notifications/Email/EmailSettings.cs +++ b/src/NzbDrone.Core/Notifications/Email/EmailSettings.cs @@ -1,12 +1,26 @@ using System; +using FluentValidation; using FluentValidation.Results; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Notifications.Email { + public class EmailSettingsValidator : AbstractValidator + { + public EmailSettingsValidator() + { + RuleFor(c => c.Server).NotEmpty(); + RuleFor(c => c.Port).GreaterThan(0); + RuleFor(c => c.From).NotEmpty(); + RuleFor(c => c.To).NotEmpty(); + } + } + public class EmailSettings : IProviderConfig { + private static readonly EmailSettingsValidator Validator = new EmailSettingsValidator(); + public EmailSettings() { Port = 25; @@ -43,7 +57,7 @@ namespace NzbDrone.Core.Notifications.Email public ValidationResult Validate() { - throw new NotImplementedException(); + return Validator.Validate(this); } } } diff --git a/src/NzbDrone.Core/Notifications/Growl/Growl.cs b/src/NzbDrone.Core/Notifications/Growl/Growl.cs index 23c9620d8..ac8bef299 100644 --- a/src/NzbDrone.Core/Notifications/Growl/Growl.cs +++ b/src/NzbDrone.Core/Notifications/Growl/Growl.cs @@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Growl _growlProvider = growlProvider; } - public override string Name - { - get { return "Growl"; } - } - - public override string ImplementationName - { - get { return "Growl"; } - } - public override string Link { get { return "http://growl.info/"; } diff --git a/src/NzbDrone.Core/Notifications/Growl/GrowlSettings.cs b/src/NzbDrone.Core/Notifications/Growl/GrowlSettings.cs index dd049268d..d6444e6cd 100644 --- a/src/NzbDrone.Core/Notifications/Growl/GrowlSettings.cs +++ b/src/NzbDrone.Core/Notifications/Growl/GrowlSettings.cs @@ -1,12 +1,24 @@ using System; +using FluentValidation; using FluentValidation.Results; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Notifications.Growl { + public class GrowlSettingsValidator : AbstractValidator + { + public GrowlSettingsValidator() + { + RuleFor(c => c.Host).NotEmpty(); + RuleFor(c => c.Port).GreaterThan(0); + } + } + public class GrowlSettings : IProviderConfig { + private static readonly GrowlSettingsValidator Validator = new GrowlSettingsValidator(); + public GrowlSettings() { Port = 23053; @@ -31,7 +43,7 @@ namespace NzbDrone.Core.Notifications.Growl public ValidationResult Validate() { - throw new NotImplementedException(); + return Validator.Validate(this); } } } diff --git a/src/NzbDrone.Core/Notifications/INotification.cs b/src/NzbDrone.Core/Notifications/INotification.cs index 86f1bcc03..5b5fd5a13 100644 --- a/src/NzbDrone.Core/Notifications/INotification.cs +++ b/src/NzbDrone.Core/Notifications/INotification.cs @@ -1,15 +1,12 @@ -using NzbDrone.Core.Tv; +using NzbDrone.Core.ThingiProvider; +using NzbDrone.Core.Tv; namespace NzbDrone.Core.Notifications { - public interface INotification + public interface INotification : IProvider { - string Name { get; } - string ImplementationName { get; } string Link { get; } - NotificationDefinition InstanceDefinition { get; set; } - void OnGrab(string message); void OnDownload(string message, Series series); void AfterRename(Series series); diff --git a/src/NzbDrone.Core/Notifications/NotificationBase.cs b/src/NzbDrone.Core/Notifications/NotificationBase.cs index d121bd44b..22e992ded 100644 --- a/src/NzbDrone.Core/Notifications/NotificationBase.cs +++ b/src/NzbDrone.Core/Notifications/NotificationBase.cs @@ -1,28 +1,47 @@ -using NzbDrone.Common.Serializer; +using System; +using System.Collections.Generic; using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.Tv; namespace NzbDrone.Core.Notifications { - public abstract class NotificationBase : INotification where TSetting : class, IProviderConfig, new() + public abstract class NotificationBase : INotification where TSettings : IProviderConfig, new() { - public abstract string Name { get; } - public abstract string ImplementationName { get; } - public abstract string Link { get; } + public Type ConfigContract + { + get + { + return typeof(TSettings); + } + } + + public IEnumerable DefaultDefinitions + { + get + { + return new List(); + } + } - public NotificationDefinition InstanceDefinition { get; set; } + public ProviderDefinition Definition { get; set; } + + public abstract string Link { get; } public abstract void OnGrab(string message); public abstract void OnDownload(string message, Series series); public abstract void AfterRename(Series series); - public TSetting Settings { get; private set; } - - public TSetting ImportSettingsFromJson(string json) + protected TSettings Settings { - Settings = Json.Deserialize(json) ?? new TSetting(); + get + { + return (TSettings)Definition.Settings; + } + } - return Settings; + public override string ToString() + { + return GetType().Name; } } } diff --git a/src/NzbDrone.Core/Notifications/NotificationDefinition.cs b/src/NzbDrone.Core/Notifications/NotificationDefinition.cs index 41fc64509..a48d2b28d 100644 --- a/src/NzbDrone.Core/Notifications/NotificationDefinition.cs +++ b/src/NzbDrone.Core/Notifications/NotificationDefinition.cs @@ -1,20 +1,9 @@ using System; -using NzbDrone.Core.Datastore; using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Notifications { - public class NotificationDefinition : ModelBase - { - public String Name { get; set; } - public Boolean OnGrab { get; set; } - public Boolean OnDownload { get; set; } - public String Settings { get; set; } - public String Implementation { get; set; } - } - - - public class NotificationProviderModel : ProviderDefinition + public class NotificationDefinition : ProviderDefinition { public Boolean OnGrab { get; set; } public Boolean OnDownload { get; set; } diff --git a/src/NzbDrone.Core/Notifications/NotificationFactory.cs b/src/NzbDrone.Core/Notifications/NotificationFactory.cs new file mode 100644 index 000000000..dfe5aca10 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/NotificationFactory.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using NLog; +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.Notifications +{ + public interface INotificationFactory : IProviderFactory + { + + } + + public class NotificationFactory : ProviderFactory, INotificationFactory + { + public NotificationFactory(INotificationRepository providerRepository, IEnumerable providers, Logger logger) + : base(providerRepository, providers, logger) + { + + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/Notifications/NotificationRepository.cs b/src/NzbDrone.Core/Notifications/NotificationRepository.cs index ab6d10d09..88060bdb2 100644 --- a/src/NzbDrone.Core/Notifications/NotificationRepository.cs +++ b/src/NzbDrone.Core/Notifications/NotificationRepository.cs @@ -1,32 +1,20 @@ -using System; -using System.Linq; -using NzbDrone.Core.Datastore; +using NzbDrone.Core.Datastore; using NzbDrone.Core.Messaging.Events; +using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Notifications { - public interface INotificationRepository : IBasicRepository + public interface INotificationRepository : IProviderRepository { - NotificationDefinition Get(string name); - NotificationDefinition Find(string name); + } - public class NotificationRepository : BasicRepository, INotificationRepository + public class NotificationRepository : ProviderRepository, INotificationRepository { public NotificationRepository(IDatabase database, IEventAggregator eventAggregator) : base(database, eventAggregator) { } - - public NotificationDefinition Get(string name) - { - return Query.Single(i => i.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)); - } - - public NotificationDefinition Find(string name) - { - return Query.SingleOrDefault(i => i.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)); - } } } \ No newline at end of file diff --git a/src/NzbDrone.Core/Notifications/NotificationService.cs b/src/NzbDrone.Core/Notifications/NotificationService.cs deleted file mode 100644 index 458c80d65..000000000 --- a/src/NzbDrone.Core/Notifications/NotificationService.cs +++ /dev/null @@ -1,214 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NLog; -using NzbDrone.Common.Composition; -using NzbDrone.Common.Serializer; -using NzbDrone.Core.Download; -using NzbDrone.Core.MediaFiles.Events; -using NzbDrone.Core.Messaging.Events; -using NzbDrone.Core.ThingiProvider; -using NzbDrone.Core.Tv; -using Omu.ValueInjecter; - -namespace NzbDrone.Core.Notifications -{ - public interface INotificationService - { - List All(); - Notification Get(int id); - List Schema(); - Notification Create(Notification notification); - void Update(Notification notification); - void Delete(int id); - } - - public class NotificationService - : INotificationService, - IHandle, - IHandle, - IHandle - { - private readonly INotificationRepository _notificationRepository; - private readonly IContainer _container; - private readonly List _notifications; - private readonly Logger _logger; - - public NotificationService(INotificationRepository notificationRepository, - IEnumerable notifications, - IContainer container, - Logger logger) - { - _notificationRepository = notificationRepository; - _container = container; - _notifications = notifications.ToList(); - _logger = logger; - } - - public List All() - { - return _notificationRepository.All().Select(ToNotification).ToList(); - } - - public Notification Get(int id) - { - return ToNotification(_notificationRepository.Get(id)); - } - - public List Schema() - { - var notifications = new List(); - - int i = 1; - foreach (var notification in _notifications) - { - var type = notification.GetType(); - - var newNotification = new Notification(); - newNotification.Instance = (INotification)_container.Resolve(type); - newNotification.Id = i; - newNotification.ImplementationName = notification.ImplementationName; - newNotification.Link = notification.Link; - - var instanceType = newNotification.Instance.GetType(); - var baseGenArgs = instanceType.BaseType.GetGenericArguments(); - newNotification.Settings = (IProviderConfig)Activator.CreateInstance(baseGenArgs[0]); - newNotification.Implementation = type.Name; - - notifications.Add(newNotification); - i++; - } - - return notifications.OrderBy(n => n.Name).ToList(); - } - - public Notification Create(Notification notification) - { - var definition = new NotificationDefinition(); - definition.InjectFrom(notification); - definition.Settings = notification.Settings.ToJson(); - - definition = _notificationRepository.Insert(definition); - notification.Id = definition.Id; - - return notification; - } - - public void Update(Notification notification) - { - var definition = _notificationRepository.Get(notification.Id); - definition.InjectFrom(notification); - definition.Settings = notification.Settings.ToJson(); - - _notificationRepository.Update(definition); - } - - public void Delete(int id) - { - _notificationRepository.Delete(id); - } - - private Notification ToNotification(NotificationDefinition definition) - { - var notification = new Notification(); - notification.Id = definition.Id; - notification.OnGrab = definition.OnGrab; - notification.OnDownload = definition.OnDownload; - notification.Instance = GetInstance(definition); - notification.Name = definition.Name; - notification.Implementation = definition.Implementation; - notification.ImplementationName = notification.Instance.ImplementationName; - notification.Settings = ((dynamic)notification.Instance).ImportSettingsFromJson(definition.Settings); - - return notification; - } - - private INotification GetInstance(NotificationDefinition indexerDefinition) - { - var type = _notifications.Single(c => c.GetType().Name.Equals(indexerDefinition.Implementation, StringComparison.InvariantCultureIgnoreCase)).GetType(); - - var instance = (INotification)_container.Resolve(type); - - instance.InstanceDefinition = indexerDefinition; - return instance; - } - - private string GetMessage(Series series, List episodes, QualityModel quality) - { - if (series.SeriesType == SeriesTypes.Daily) - { - var episode = episodes.First(); - - return String.Format("{0} - {1} - {2} [{3}]", - series.Title, - episode.AirDate, - episode.Title, - quality); - } - - var episodeNumbers = String.Concat(episodes.Select(e => e.EpisodeNumber) - .Select(i => String.Format("x{0:00}", i))); - - var episodeTitles = String.Join(" + ", episodes.Select(e => e.Title)); - - return String.Format("{0} - {1}{2} - {3} {4}", - series.Title, - episodes.First().SeasonNumber, - episodeNumbers, - episodeTitles, - quality); - } - - public void Handle(EpisodeGrabbedEvent message) - { - var messageBody = GetMessage(message.Episode.Series, message.Episode.Episodes, message.Episode.ParsedEpisodeInfo.Quality); - - foreach (var notification in All().Where(n => n.OnGrab)) - { - try - { - notification.Instance.OnGrab(messageBody); - } - - catch (Exception ex) - { - _logger.ErrorException("Unable to send OnGrab notification to: " + notification.Name, ex); - } - } - } - - public void Handle(EpisodeDownloadedEvent message) - { - var messageBody = GetMessage(message.Episode.Series, message.Episode.Episodes, message.Episode.ParsedEpisodeInfo.Quality); - - foreach (var notification in All().Where(n => n.OnDownload)) - { - try - { - notification.Instance.OnDownload(messageBody, message.Episode.Series); - } - - catch (Exception ex) - { - _logger.WarnException("Unable to send OnDownload notification to: " + notification.Name, ex); - } - } - } - - public void Handle(SeriesRenamedEvent message) - { - foreach (var notification in All().Where(n => n.OnDownload)) - { - try - { - notification.Instance.AfterRename(message.Series); - } - - catch (Exception ex) - { - _logger.WarnException("Unable to send AfterRename notification to: " + notification.Name, ex); - } - } - } - } -} diff --git a/src/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs b/src/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs deleted file mode 100644 index b26afa1fd..000000000 --- a/src/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs +++ /dev/null @@ -1,32 +0,0 @@ -using NzbDrone.Common.Serializer; -using NzbDrone.Core.ThingiProvider; - -namespace NzbDrone.Core.Notifications -{ - public interface INotificationSettingsProvider - { - TSetting Get(INotification indexer) where TSetting : IProviderConfig, new(); - } - - public class NotificationSettingsProvider : INotificationSettingsProvider - { - private readonly INotificationRepository _notificationRepository; - - public NotificationSettingsProvider(INotificationRepository notificationRepository) - { - _notificationRepository = notificationRepository; - } - - public TSetting Get(INotification indexer) where TSetting : IProviderConfig, new() - { - var indexerDef = _notificationRepository.Find(indexer.Name); - - if (indexerDef == null || string.IsNullOrWhiteSpace(indexerDef.Settings)) - { - return new TSetting(); - } - - return Json.Deserialize(indexerDef.Settings); - } - } -} \ No newline at end of file diff --git a/src/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroid.cs b/src/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroid.cs index 22f4656f7..d1a10a8a6 100644 --- a/src/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroid.cs +++ b/src/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroid.cs @@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.NotifyMyAndroid _notifyMyAndroidProxy = notifyMyAndroidProxy; } - public override string Name - { - get { return "NotifyMyAndroid"; } - } - - public override string ImplementationName - { - get { return "NotifyMyAndroid"; } - } - public override string Link { get { return "http://www.notifymyandroid.com/"; } diff --git a/src/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroidSettings.cs b/src/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroidSettings.cs index 48c8c6fc6..1a05d92b3 100644 --- a/src/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroidSettings.cs +++ b/src/NzbDrone.Core/Notifications/NotifyMyAndroid/NotifyMyAndroidSettings.cs @@ -1,12 +1,23 @@ using System; +using FluentValidation; using FluentValidation.Results; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Notifications.NotifyMyAndroid { + public class NotifyMyAndroidSettingsValidator : AbstractValidator + { + public NotifyMyAndroidSettingsValidator() + { + RuleFor(c => c.ApiKey).NotEmpty(); + } + } + public class NotifyMyAndroidSettings : IProviderConfig { + private static readonly NotifyMyAndroidSettingsValidator Validator = new NotifyMyAndroidSettingsValidator(); + [FieldDefinition(0, Label = "API Key", HelpLink = "http://www.notifymyandroid.com/")] public String ApiKey { get; set; } @@ -23,7 +34,7 @@ namespace NzbDrone.Core.Notifications.NotifyMyAndroid public ValidationResult Validate() { - throw new NotImplementedException(); + return Validator.Validate(this); } } } diff --git a/src/NzbDrone.Core/Notifications/Plex/PlexClient.cs b/src/NzbDrone.Core/Notifications/Plex/PlexClient.cs index b5d2a8d17..72023baa0 100644 --- a/src/NzbDrone.Core/Notifications/Plex/PlexClient.cs +++ b/src/NzbDrone.Core/Notifications/Plex/PlexClient.cs @@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Plex _plexProvider = plexProvider; } - public override string Name - { - get { return "Plex Client"; } - } - - public override string ImplementationName - { - get { return "Plex Client"; } - } - public override string Link { get { return "http://www.plexapp.com/"; } diff --git a/src/NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs b/src/NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs index a0d762406..f5672c733 100644 --- a/src/NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs +++ b/src/NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs @@ -1,12 +1,24 @@ using System; +using FluentValidation; using FluentValidation.Results; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Notifications.Plex { + public class PlexClientSettingsValidator : AbstractValidator + { + public PlexClientSettingsValidator() + { + RuleFor(c => c.Host).NotEmpty(); + RuleFor(c => c.Port).GreaterThan(0); + } + } + public class PlexClientSettings : IProviderConfig { + private static readonly PlexClientSettingsValidator Validator = new PlexClientSettingsValidator(); + public PlexClientSettings() { Port = 3000; @@ -34,7 +46,7 @@ namespace NzbDrone.Core.Notifications.Plex public ValidationResult Validate() { - throw new NotImplementedException(); + return Validator.Validate(this); } } } diff --git a/src/NzbDrone.Core/Notifications/Plex/PlexServer.cs b/src/NzbDrone.Core/Notifications/Plex/PlexServer.cs index 04d5df084..57d359880 100644 --- a/src/NzbDrone.Core/Notifications/Plex/PlexServer.cs +++ b/src/NzbDrone.Core/Notifications/Plex/PlexServer.cs @@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Plex _plexProvider = plexProvider; } - public override string Name - { - get { return "Plex Server"; } - } - - public override string ImplementationName - { - get { return "Plex Server"; } - } - public override string Link { get { return "http://www.plexapp.com/"; } diff --git a/src/NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs b/src/NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs index ed410767b..020f7f65f 100644 --- a/src/NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs +++ b/src/NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs @@ -1,12 +1,24 @@ using System; +using FluentValidation; using FluentValidation.Results; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Notifications.Plex { + public class PlexServerSettingsValidator : AbstractValidator + { + public PlexServerSettingsValidator() + { + RuleFor(c => c.Host).NotEmpty(); + RuleFor(c => c.Port).GreaterThan(0); + } + } + public class PlexServerSettings : IProviderConfig { + private static readonly PlexServerSettingsValidator Validator = new PlexServerSettingsValidator(); + public PlexServerSettings() { Port = 32400; @@ -31,7 +43,7 @@ namespace NzbDrone.Core.Notifications.Plex public ValidationResult Validate() { - throw new NotImplementedException(); + return Validator.Validate(this); } } } diff --git a/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs b/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs index 0164b222a..f8cd93e9b 100644 --- a/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs +++ b/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs @@ -12,16 +12,6 @@ namespace NzbDrone.Core.Notifications.Prowl _prowlProvider = prowlProvider; } - public override string Name - { - get { return "Prowl"; } - } - - public override string ImplementationName - { - get { return "Prowl"; } - } - public override string Link { get { return "http://www.prowlapp.com/"; } diff --git a/src/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs b/src/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs index 66b574179..3d68d3674 100644 --- a/src/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs +++ b/src/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs @@ -1,12 +1,23 @@ using System; +using FluentValidation; using FluentValidation.Results; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Notifications.Prowl { + public class ProwlSettingsValidator : AbstractValidator + { + public ProwlSettingsValidator() + { + RuleFor(c => c.ApiKey).NotEmpty(); + } + } + public class ProwlSettings : IProviderConfig { + private static readonly ProwlSettingsValidator Validator = new ProwlSettingsValidator(); + [FieldDefinition(0, Label = "API Key", HelpLink = "https://www.prowlapp.com/api_settings.php")] public String ApiKey { get; set; } @@ -23,7 +34,7 @@ namespace NzbDrone.Core.Notifications.Prowl public ValidationResult Validate() { - throw new NotImplementedException(); + return Validator.Validate(this); } } } diff --git a/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs b/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs index 82c058729..db64a7445 100644 --- a/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs +++ b/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs @@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.PushBullet _pushBulletProxy = pushBulletProxy; } - public override string Name - { - get { return "PushBullet"; } - } - - public override string ImplementationName - { - get { return "PushBullet"; } - } - public override string Link { get { return "https://www.pushbullet.com/"; } diff --git a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs index 1886991d8..3e1f75ca1 100644 --- a/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs +++ b/src/NzbDrone.Core/Notifications/PushBullet/PushBulletSettings.cs @@ -1,12 +1,24 @@ using System; +using FluentValidation; using FluentValidation.Results; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Notifications.PushBullet { + public class PushBulletSettingsValidator : AbstractValidator + { + public PushBulletSettingsValidator() + { + RuleFor(c => c.ApiKey).NotEmpty(); + RuleFor(c => c.DeviceId).GreaterThan(0); + } + } + public class PushBulletSettings : IProviderConfig { + private static readonly PushBulletSettingsValidator Validator = new PushBulletSettingsValidator(); + [FieldDefinition(0, Label = "API Key", HelpLink = "https://www.pushbullet.com/")] public String ApiKey { get; set; } @@ -23,7 +35,7 @@ namespace NzbDrone.Core.Notifications.PushBullet public ValidationResult Validate() { - throw new NotImplementedException(); + return Validator.Validate(this); } } } diff --git a/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs b/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs index b4a3e5a56..0a8f1d1c6 100644 --- a/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs +++ b/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs @@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Pushover _pushoverProxy = pushoverProxy; } - public override string Name - { - get { return "Pushover"; } - } - - public override string ImplementationName - { - get { return "Pushover"; } - } - public override string Link { get { return "https://pushover.net/"; } diff --git a/src/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs b/src/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs index ca4c332c7..debf640e2 100644 --- a/src/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs +++ b/src/NzbDrone.Core/Notifications/Pushover/PushoverSettings.cs @@ -1,12 +1,23 @@ using System; +using FluentValidation; using FluentValidation.Results; using NzbDrone.Core.Annotations; using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Notifications.Pushover { + public class PushoverSettingsValidator : AbstractValidator + { + public PushoverSettingsValidator() + { + RuleFor(c => c.UserKey).NotEmpty(); + } + } + public class PushoverSettings : IProviderConfig { + private static readonly PushoverSettingsValidator Validator = new PushoverSettingsValidator(); + [FieldDefinition(0, Label = "User Key", HelpLink = "https://pushover.net/")] public String UserKey { get; set; } @@ -23,7 +34,7 @@ namespace NzbDrone.Core.Notifications.Pushover public ValidationResult Validate() { - throw new NotImplementedException(); + return Validator.Validate(this); } } } diff --git a/src/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs b/src/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs index f42228ee6..f6b3a6abe 100644 --- a/src/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs +++ b/src/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs @@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Xbmc _xbmcProvider = xbmcProvider; } - public override string Name - { - get { return "XBMC"; } - } - - public override string ImplementationName - { - get { return "XBMC"; } - } - public override string Link { get { return "http://xbmc.org/"; } diff --git a/src/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs b/src/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs index 2c0569c89..055e02af8 100644 --- a/src/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs +++ b/src/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using FluentValidation; using FluentValidation.Results; using Newtonsoft.Json; using NzbDrone.Core.Annotations; @@ -7,8 +8,19 @@ using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Notifications.Xbmc { + public class XbmcSettingsValidator : AbstractValidator + { + public XbmcSettingsValidator() + { + RuleFor(c => c.Host).NotEmpty(); + RuleFor(c => c.DisplayTime).GreaterThan(0); + } + } + public class XbmcSettings : IProviderConfig { + private static readonly XbmcSettingsValidator Validator = new XbmcSettingsValidator(); + public XbmcSettings() { DisplayTime = 5; @@ -56,7 +68,7 @@ namespace NzbDrone.Core.Notifications.Xbmc public ValidationResult Validate() { - throw new NotImplementedException(); + return Validator.Validate(this); } } } diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 17c0af68b..186c9acb8 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -173,9 +173,11 @@ - + + + @@ -269,6 +271,7 @@ + @@ -328,10 +331,8 @@ - - diff --git a/src/NzbDrone.Core/ThingiProvider/ProviderDefinition.cs b/src/NzbDrone.Core/ThingiProvider/ProviderDefinition.cs index ef21d3206..c9b20fe47 100644 --- a/src/NzbDrone.Core/ThingiProvider/ProviderDefinition.cs +++ b/src/NzbDrone.Core/ThingiProvider/ProviderDefinition.cs @@ -7,7 +7,6 @@ namespace NzbDrone.Core.ThingiProvider private IProviderConfig _settings; public string Name { get; set; } public string Implementation { get; set; } - public bool Enable { get; set; } public string ConfigContract { get; set; } diff --git a/src/NzbDrone.Core/ThingiProvider/ProviderFactory.cs b/src/NzbDrone.Core/ThingiProvider/ProviderFactory.cs index bbd909bb3..71b0683ca 100644 --- a/src/NzbDrone.Core/ThingiProvider/ProviderFactory.cs +++ b/src/NzbDrone.Core/ThingiProvider/ProviderFactory.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Core.ThingiProvider public List GetAvailableProviders() { - return All().Where(c => c.Enable && c.Settings.Validate().IsValid) + return All().Where(c => c.Settings.Validate().IsValid) .Select(GetInstance).ToList(); } diff --git a/src/UI/Settings/Notifications/AddItemTemplate.html b/src/UI/Settings/Notifications/AddItemTemplate.html index 2d08f3370..31fb15419 100644 --- a/src/UI/Settings/Notifications/AddItemTemplate.html +++ b/src/UI/Settings/Notifications/AddItemTemplate.html @@ -1,7 +1,7 @@ 
- {{implementationName}} + {{implementation}} {{#if link}} {{/if}} diff --git a/src/UI/Settings/Notifications/AddItemView.js b/src/UI/Settings/Notifications/AddItemView.js index d1e50f5a8..c1264354b 100644 --- a/src/UI/Settings/Notifications/AddItemView.js +++ b/src/UI/Settings/Notifications/AddItemView.js @@ -3,7 +3,7 @@ define([ 'AppLayout', 'marionette', - 'Settings/Notifications/EditView' + 'Settings/Notifications/NotificationEditView' ], function (AppLayout, Marionette, EditView) { return Marionette.ItemView.extend({ diff --git a/src/UI/Settings/Notifications/EditView.js b/src/UI/Settings/Notifications/NotificationEditView.js similarity index 72% rename from src/UI/Settings/Notifications/EditView.js rename to src/UI/Settings/Notifications/NotificationEditView.js index a355df7bc..92a6f8af1 100644 --- a/src/UI/Settings/Notifications/EditView.js +++ b/src/UI/Settings/Notifications/NotificationEditView.js @@ -8,13 +8,13 @@ define( 'Settings/Notifications/DeleteView', 'Commands/CommandController', 'Mixins/AsModelBoundView', - 'Form/FormBuilder', - 'underscore' + 'underscore', + 'Form/FormBuilder' ], function (vent, AppLayout, Marionette, DeleteView, CommandController, AsModelBoundView, _) { var model = Marionette.ItemView.extend({ - template: 'Settings/Notifications/EditTemplate', + template: 'Settings/Notifications/NotificationEditViewTemplate', events: { 'click .x-save' : '_saveNotification', @@ -24,11 +24,6 @@ define( 'click .x-test' : '_test' }, - ui: { - testButton: '.x-test', - testIcon : '.x-test-icon' - }, - initialize: function (options) { this.notificationCollection = options.notificationCollection; }, @@ -68,24 +63,14 @@ define( }, _test: function () { - var testCommand = this.model.get('testCommand'); - if (testCommand) { - this.idle = false; - var properties = {}; - - _.each(this.model.get('fields'), function (field) { - properties[field.name] = field.value; - }); + var testCommand = 'test{0}'.format(this.model.get('implementation')); + var properties = {}; + _.each(this.model.get('fields'), function (field) { + properties[field.name] = field.value; + }); - CommandController.Execute(testCommand, properties); - } - }, - - _testOnAlways: function () { - if (!this.isClosed) { - this.idle = true; - } + CommandController.Execute(testCommand, properties); } }); diff --git a/src/UI/Settings/Notifications/EditTemplate.html b/src/UI/Settings/Notifications/NotificationEditViewTemplate.html similarity index 96% rename from src/UI/Settings/Notifications/EditTemplate.html rename to src/UI/Settings/Notifications/NotificationEditViewTemplate.html index 91e9ecdb7..9c1fff961 100644 --- a/src/UI/Settings/Notifications/EditTemplate.html +++ b/src/UI/Settings/Notifications/NotificationEditViewTemplate.html @@ -1,9 +1,9 @@