From e9bf78a97df4a2b43fc301ceed604a00131119d4 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 19 May 2013 16:17:32 -0700 Subject: [PATCH] Notifications wired up server sided --- NzbDrone.Api/Commands/CommandModule.cs | 2 + .../ProviderTests/EventClientProviderTest.cs | 2 +- .../ProviderTests/GrowlProviderTest.cs | 3 +- .../ProviderTests/PlexProviderTest.cs | 92 ++--------- .../ProviderTests/ProwlProviderTest.cs | 1 + .../ProviderTests/XbmcProviderTest.cs | 38 ++--- NzbDrone.Core/Configuration/ConfigService.cs | 137 ---------------- NzbDrone.Core/Configuration/IConfigService.cs | 25 +-- .../Datastore/Migration/Migration20130324.cs | 10 +- NzbDrone.Core/Datastore/TableMapping.cs | 4 +- NzbDrone.Core/Download/DownloadService.cs | 8 +- .../ExternalNotificationBase.cs | 148 ------------------ .../ExternalNotificationDefinition.cs | 13 -- .../ExternalNotificationRepository.cs | 25 --- NzbDrone.Core/ExternalNotification/Growl.cs | 48 ------ NzbDrone.Core/ExternalNotification/Plex.cs | 51 ------ NzbDrone.Core/ExternalNotification/Prowl.cs | 48 ------ NzbDrone.Core/ExternalNotification/Xbmc.cs | 59 ------- .../IndexerSearch/NzbSearchService.cs | 2 - ...IIndexerSettings.cs => IIndexerSetting.cs} | 0 NzbDrone.Core/Indexers/IndexerBase.cs | 3 +- NzbDrone.Core/Indexers/NzbsRUs/NzbsRUs.cs | 2 - NzbDrone.Core/Notifications/Growl/Growl.cs | 40 +++++ .../Growl}/GrowlProvider.cs | 5 +- .../Notifications/Growl/GrowlSettings.cs | 28 ++++ .../Notifications/INotifcationSettings.cs | 30 ++++ NzbDrone.Core/Notifications/INotification.cs | 19 +++ NzbDrone.Core/Notifications/Notification.cs | 17 ++ .../Notifications/NotificationBase.cs | 17 ++ .../Notifications/NotificationDefinition.cs | 14 ++ .../Notifications/NotificationRepository.cs | 31 ++++ .../Notifications/NotificationService.cs | 106 +++++++++++++ .../NotificationSettingsProvider.cs | 31 ++++ .../Notifications/NotificationWithSetting.cs | 20 +++ .../Notifications/Plex/PlexClient.cs | 37 +++++ .../Notifications/Plex/PlexClientSettings.cs | 31 ++++ .../Plex}/PlexProvider.cs | 46 ++---- .../Notifications/Plex/PlexServer.cs | 43 +++++ .../Notifications/Plex/PlexServerSettings.cs | 25 +++ NzbDrone.Core/Notifications/Prowl/Prowl.cs | 38 +++++ .../Prowl}/ProwlProvider.cs | 12 +- .../Notifications/Prowl/ProwlSettings.cs | 25 +++ .../Smtp}/Smtp.cs | 23 +-- .../Notifications/Smtp/SmtpProvider.cs | 66 ++++++++ .../Notifications/Smtp/SmtpSettings.cs | 40 +++++ .../Xbmc/EventClientProvider.cs | 4 +- .../Xbmc/ResourceManager.cs | 2 +- NzbDrone.Core/Notifications/Xbmc/Xbmc.cs | 53 +++++++ .../Xbmc}/XbmcProvider.cs | 148 ++++++++---------- .../Notifications/Xbmc/XbmcSettings.cs | 40 +++++ NzbDrone.Core/NzbDrone.Core.csproj | 45 ++++-- NzbDrone.Core/Providers/SmtpProvider.cs | 111 ------------- NzbDrone/MainAppContainerBuilder.cs | 4 +- UI/Form/CheckboxTemplate.html | 19 +++ UI/Form/TextboxTemplate.html | 10 ++ UI/Mixins/handlebars.mixin.js | 8 + UI/Settings/Indexers/ItemTemplate.html | 11 +- 57 files changed, 973 insertions(+), 947 deletions(-) delete mode 100644 NzbDrone.Core/ExternalNotification/ExternalNotificationBase.cs delete mode 100644 NzbDrone.Core/ExternalNotification/ExternalNotificationDefinition.cs delete mode 100644 NzbDrone.Core/ExternalNotification/ExternalNotificationRepository.cs delete mode 100644 NzbDrone.Core/ExternalNotification/Growl.cs delete mode 100644 NzbDrone.Core/ExternalNotification/Plex.cs delete mode 100644 NzbDrone.Core/ExternalNotification/Prowl.cs delete mode 100644 NzbDrone.Core/ExternalNotification/Xbmc.cs rename NzbDrone.Core/Indexers/{IIndexerSettings.cs => IIndexerSetting.cs} (100%) create mode 100644 NzbDrone.Core/Notifications/Growl/Growl.cs rename NzbDrone.Core/{ExternalNotification => Notifications/Growl}/GrowlProvider.cs (90%) create mode 100644 NzbDrone.Core/Notifications/Growl/GrowlSettings.cs create mode 100644 NzbDrone.Core/Notifications/INotifcationSettings.cs create mode 100644 NzbDrone.Core/Notifications/INotification.cs create mode 100644 NzbDrone.Core/Notifications/Notification.cs create mode 100644 NzbDrone.Core/Notifications/NotificationBase.cs create mode 100644 NzbDrone.Core/Notifications/NotificationDefinition.cs create mode 100644 NzbDrone.Core/Notifications/NotificationRepository.cs create mode 100644 NzbDrone.Core/Notifications/NotificationService.cs create mode 100644 NzbDrone.Core/Notifications/NotificationSettingsProvider.cs create mode 100644 NzbDrone.Core/Notifications/NotificationWithSetting.cs create mode 100644 NzbDrone.Core/Notifications/Plex/PlexClient.cs create mode 100644 NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs rename NzbDrone.Core/{ExternalNotification => Notifications/Plex}/PlexProvider.cs (61%) create mode 100644 NzbDrone.Core/Notifications/Plex/PlexServer.cs create mode 100644 NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs create mode 100644 NzbDrone.Core/Notifications/Prowl/Prowl.cs rename NzbDrone.Core/{Providers => Notifications/Prowl}/ProwlProvider.cs (84%) create mode 100644 NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs rename NzbDrone.Core/{ExternalNotification => Notifications/Smtp}/Smtp.cs (54%) create mode 100644 NzbDrone.Core/Notifications/Smtp/SmtpProvider.cs create mode 100644 NzbDrone.Core/Notifications/Smtp/SmtpSettings.cs rename NzbDrone.Core/{Providers => Notifications}/Xbmc/EventClientProvider.cs (95%) rename NzbDrone.Core/{Providers => Notifications}/Xbmc/ResourceManager.cs (97%) create mode 100644 NzbDrone.Core/Notifications/Xbmc/Xbmc.cs rename NzbDrone.Core/{Providers => Notifications/Xbmc}/XbmcProvider.cs (76%) create mode 100644 NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs delete mode 100644 NzbDrone.Core/Providers/SmtpProvider.cs create mode 100644 UI/Form/CheckboxTemplate.html create mode 100644 UI/Form/TextboxTemplate.html diff --git a/NzbDrone.Api/Commands/CommandModule.cs b/NzbDrone.Api/Commands/CommandModule.cs index 514d3b9e4..e80852a2f 100644 --- a/NzbDrone.Api/Commands/CommandModule.cs +++ b/NzbDrone.Api/Commands/CommandModule.cs @@ -4,6 +4,8 @@ using System.Linq; using NzbDrone.Api.Extensions; using NzbDrone.Common.Composition; using NzbDrone.Common.Messaging; +using NzbDrone.Core.Download; +using NzbDrone.Core.Parser.Model; namespace NzbDrone.Api.Commands { diff --git a/NzbDrone.Core.Test/ProviderTests/EventClientProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/EventClientProviderTest.cs index d259a3a08..bb049c679 100644 --- a/NzbDrone.Core.Test/ProviderTests/EventClientProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/EventClientProviderTest.cs @@ -5,7 +5,7 @@ using Moq; using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Core.Model.Xbmc; -using NzbDrone.Core.Providers.Xbmc; +using NzbDrone.Core.Notifications.Xbmc; using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common.AutoMoq; diff --git a/NzbDrone.Core.Test/ProviderTests/GrowlProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/GrowlProviderTest.cs index 7dc91e90a..f8e69d6c8 100644 --- a/NzbDrone.Core.Test/ProviderTests/GrowlProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/GrowlProviderTest.cs @@ -4,8 +4,9 @@ using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; -using NzbDrone.Core.ExternalNotification; using NzbDrone.Core.Model; +using NzbDrone.Core.Notifications; +using NzbDrone.Core.Notifications.Growl; using NzbDrone.Core.Providers; using NzbDrone.Core.Test.Framework; diff --git a/NzbDrone.Core.Test/ProviderTests/PlexProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/PlexProviderTest.cs index dcdbee8ea..d933d71e7 100644 --- a/NzbDrone.Core.Test/ProviderTests/PlexProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/PlexProviderTest.cs @@ -1,6 +1,4 @@ - - -using System; +using System; using System.IO; using System.Linq; using System.Net; @@ -10,14 +8,8 @@ using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Common; -using NzbDrone.Core.Configuration; -using NzbDrone.Core.ExternalNotification; -using NzbDrone.Core.Model.Xbmc; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Providers.Xbmc; - +using NzbDrone.Core.Notifications.Plex; using NzbDrone.Core.Test.Framework; -using NzbDrone.Test.Common.AutoMoq; namespace NzbDrone.Core.Test.ProviderTests { @@ -25,32 +17,27 @@ namespace NzbDrone.Core.Test.ProviderTests public class PlexProviderTest : CoreTest { - private void WithSingleClient() - { - Mocker.GetMock().SetupGet(s => s.PlexClientHosts) - .Returns("localhost:3000"); - } + private PlexClientSettings _clientSettings; - private void WithMultipleClients() + public void WithClientCredentials() { - Mocker.GetMock().SetupGet(s => s.PlexClientHosts) - .Returns("localhost:3000, 192.168.0.10:3000"); + _clientSettings.Username = "plex"; + _clientSettings.Password = "plex"; } - public void WithClientCredentials() + [SetUp] + public void Setup() { - Mocker.GetMock().SetupGet(s => s.PlexUsername) - .Returns("plex"); - - Mocker.GetMock().SetupGet(s => s.PlexPassword) - .Returns("plex"); + _clientSettings = new PlexClientSettings + { + Host = "localhost", + Port = 3000 + }; } [Test] public void GetSectionKeys_should_return_single_section_key_when_only_one_show_section() - { - - + { var response = ""; Stream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(response)); @@ -123,10 +110,8 @@ namespace NzbDrone.Core.Test.ProviderTests } [Test] - public void Notify_should_send_notification_for_single_client_when_only_one_is_configured() + public void Notify_should_send_notification() { - - WithSingleClient(); const string header = "Test Header"; const string message = "Test Message"; @@ -138,37 +123,15 @@ namespace NzbDrone.Core.Test.ProviderTests .Returns("ok"); - Mocker.Resolve().Notify(header, message); + Mocker.Resolve().Notify(_clientSettings, header, message); fakeHttp.Verify(v => v.DownloadString(expectedUrl), Times.Once()); } - [Test] - public void Notify_should_send_notifcation_to_all_configured_clients() - { - - WithMultipleClients(); - - const string header = "Test Header"; - const string message = "Test Message"; - - var fakeHttp = Mocker.GetMock(); - fakeHttp.Setup(s => s.DownloadString(It.IsAny())) - .Returns("ok"); - - - Mocker.Resolve().Notify(header, message); - - - fakeHttp.Verify(v => v.DownloadString(It.IsAny()), Times.Exactly(2)); - } - [Test] public void Notify_should_send_notification_with_credentials_when_configured() { - - WithSingleClient(); WithClientCredentials(); const string header = "Test Header"; @@ -181,31 +144,10 @@ namespace NzbDrone.Core.Test.ProviderTests .Returns("ok"); - Mocker.Resolve().Notify(header, message); + Mocker.Resolve().Notify(_clientSettings, header, message); fakeHttp.Verify(v => v.DownloadString(expectedUrl, "plex", "plex"), Times.Once()); } - - [Test] - public void Notify_should_send_notification_with_credentials_when_configured_for_all_clients() - { - - WithMultipleClients(); - WithClientCredentials(); - - const string header = "Test Header"; - const string message = "Test Message"; - - var fakeHttp = Mocker.GetMock(); - fakeHttp.Setup(s => s.DownloadString(It.IsAny(), "plex", "plex")) - .Returns("ok"); - - - Mocker.Resolve().Notify(header, message); - - - fakeHttp.Verify(v => v.DownloadString(It.IsAny(), "plex", "plex"), Times.Exactly(2)); - } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/ProwlProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/ProwlProviderTest.cs index 03ae3a293..3fdd2d419 100644 --- a/NzbDrone.Core.Test/ProviderTests/ProwlProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/ProwlProviderTest.cs @@ -5,6 +5,7 @@ using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Core.Model; +using NzbDrone.Core.Notifications.Prowl; using NzbDrone.Core.Providers; using NzbDrone.Core.Test.Framework; diff --git a/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs index 249d84f88..52de941e3 100644 --- a/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs @@ -8,11 +8,10 @@ using Moq; using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Core.Configuration; +using NzbDrone.Core.Notifications.Xbmc; using NzbDrone.Core.Tv; using NzbDrone.Core.Model.Xbmc; using NzbDrone.Core.Providers; -using NzbDrone.Core.Providers.Xbmc; - using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common.AutoMoq; @@ -22,6 +21,7 @@ namespace NzbDrone.Core.Test.ProviderTests public class XbmcProviderTest : CoreTest { + private XbmcSettings _settings; private string EdenActivePlayers; private void WithNoActivePlayers() @@ -49,6 +49,19 @@ namespace NzbDrone.Core.Test.ProviderTests EdenActivePlayers = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"audio\"},{\"playerid\":2,\"type\":\"picture\"},{\"playerid\":3,\"type\":\"video\"}]}"; } + [SetUp] + public void Setup() + { + _settings = new XbmcSettings + { + Host = "localhost", + Port = 8080, + AlwaysUpdate = false, + CleanLibrary = false, + UpdateLibrary = true + }; + } + [Test] public void JsonError_true() { @@ -290,21 +303,13 @@ namespace NzbDrone.Core.Test.ProviderTests [Test] public void Notify_true() { - - - var header = "NzbDrone Test"; var message = "Test Message!"; - var fakeConfig = Mocker.GetMock(); - fakeConfig.SetupGet(s => s.XbmcHosts).Returns("localhost:8080"); - - //var fakeUdpProvider = Mocker.GetMock(); var fakeEventClient = Mocker.GetMock(); fakeEventClient.Setup(s => s.SendNotification(header, message, IconType.Jpeg, "NzbDrone.jpg", "localhost")).Returns(true); - - Mocker.Resolve().Notify(header, message); + Mocker.Resolve().Notify(_settings, header, message); Mocker.VerifyAllMocks(); @@ -437,19 +442,10 @@ namespace NzbDrone.Core.Test.ProviderTests [Test] public void Clean() { - - - - var fakeConfig = Mocker.GetMock(); - fakeConfig.SetupGet(s => s.XbmcHosts).Returns("localhost:8080"); - var fakeEventClient = Mocker.GetMock(); fakeEventClient.Setup(s => s.SendAction("localhost", ActionType.ExecBuiltin, "ExecBuiltIn(CleanLibrary(video))")).Returns(true); - - Mocker.Resolve().Clean(); - - + Mocker.Resolve().Clean(_settings); Mocker.VerifyAllMocks(); } diff --git a/NzbDrone.Core/Configuration/ConfigService.cs b/NzbDrone.Core/Configuration/ConfigService.cs index 8cbae1a1a..381782444 100644 --- a/NzbDrone.Core/Configuration/ConfigService.cs +++ b/NzbDrone.Core/Configuration/ConfigService.cs @@ -126,94 +126,12 @@ namespace NzbDrone.Core.Configuration set { SetValue("DefaultQualityProfile", value); } } - public Boolean XbmcUpdateLibrary - { - get { return GetValueBoolean("XbmcUpdateLibrary"); } - - set { SetValue("XbmcUpdateLibrary", value); } - } - - public Boolean XbmcCleanLibrary - { - get { return GetValueBoolean("XbmcCleanLibrary"); } - - set { SetValue("XbmcCleanLibrary", value); } - } - - public Boolean XbmcUpdateWhenPlaying - { - get { return GetValueBoolean("XbmcUpdateWhenPlaying"); } - - set { SetValue("XbmcUpdateWhenPlaying", value); } - } - - public string XbmcHosts - { - get { return GetValue("XbmcHosts", "localhost:8080"); } - set { SetValue("XbmcHosts", value); } - } - - public string XbmcUsername - { - get { return GetValue("XbmcUsername", "xbmc"); } - set { SetValue("XbmcUsername", value); } - } - - public string XbmcPassword - { - get { return GetValue("XbmcPassword", String.Empty); } - set { SetValue("XbmcPassword", value); } - } - public string UpdateUrl { get { return GetValue("UpdateUrl", "http://update.nzbdrone.com/vnext/"); } set { SetValue("UpdateUrl", value); } } - public string SmtpServer - { - get { return GetValue("SmtpServer", String.Empty); } - set { SetValue("SmtpServer", value); } - } - - public int SmtpPort - { - get { return GetValueInt("SmtpPort", 25); } - set { SetValue("SmtpPort", value); } - } - - public Boolean SmtpUseSsl - { - get { return GetValueBoolean("SmtpUseSsl"); } - - set { SetValue("SmtpUseSsl", value); } - } - - public string SmtpUsername - { - get { return GetValue("SmtpUsername", String.Empty); } - set { SetValue("SmtpUsername", value); } - } - - public string SmtpPassword - { - get { return GetValue("SmtpPassword", String.Empty); } - set { SetValue("SmtpPassword", value); } - } - - public string SmtpFromAddress - { - get { return GetValue("SmtpFromAddress", String.Empty); } - set { SetValue("SmtpFromAddress", value); } - } - - public string SmtpToAddresses - { - get { return GetValue("SmtpToAddresses", String.Empty); } - set { SetValue("SmtpToAddresses", value); } - } - public string TwitterAccessToken { get { return GetValue("TwitterAccessToken", String.Empty); } @@ -226,30 +144,6 @@ namespace NzbDrone.Core.Configuration set { SetValue("TwitterAccessTokenSecret", value); } } - public string GrowlHost - { - get { return GetValue("GrowlHost", "localhost:23053"); } - set { SetValue("GrowlHost", value); } - } - - public string GrowlPassword - { - get { return GetValue("GrowlPassword", String.Empty); } - set { SetValue("GrowlPassword", value); } - } - - public string ProwlApiKeys - { - get { return GetValue("ProwlApiKeys", String.Empty); } - set { SetValue("ProwlApiKeys", value); } - } - - public int ProwlPriority - { - get { return GetValueInt("ProwlPriority", 0); } - set { SetValue("ProwlPriority", value); } - } - public bool EnableBacklogSearching { get { return GetValueBoolean("EnableBacklogSearching"); } @@ -291,37 +185,6 @@ namespace NzbDrone.Core.Configuration get { return "http://services.nzbdrone.com"; } } - public Boolean PlexUpdateLibrary - { - get { return GetValueBoolean("PlexUpdateLibrary"); } - - set { SetValue("PlexUpdateLibrary", value); } - } - - public string PlexServerHost - { - get { return GetValue("PlexServerHost", "localhost:32400"); } - set { SetValue("PlexServerHost", value); } - } - - public string PlexClientHosts - { - get { return GetValue("PlexClientHosts", "localhost:3000"); } - set { SetValue("PlexClientHosts", value); } - } - - public string PlexUsername - { - get { return GetValue("PlexUsername"); } - set { SetValue("PlexUsername", value); } - } - - public string PlexPassword - { - get { return GetValue("PlexPassword"); } - set { SetValue("PlexPassword", value); } - } - public Boolean MetadataUseBanners { get { return GetValueBoolean("MetadataUseBanners"); } diff --git a/NzbDrone.Core/Configuration/IConfigService.cs b/NzbDrone.Core/Configuration/IConfigService.cs index df0265b86..4570a7d14 100644 --- a/NzbDrone.Core/Configuration/IConfigService.cs +++ b/NzbDrone.Core/Configuration/IConfigService.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using NzbDrone.Core.Download; -using NzbDrone.Core.Model; using NzbDrone.Core.Download.Clients.Nzbget; using NzbDrone.Core.Download.Clients.Sabnzbd; @@ -11,6 +10,7 @@ namespace NzbDrone.Core.Configuration { IEnumerable All(); Dictionary AllWithDefaults(); + string UpdateUrl { get; set; } String SabHost { get; set; } int SabPort { get; set; } String SabApiKey { get; set; } @@ -23,26 +23,8 @@ namespace NzbDrone.Core.Configuration bool UseSeasonFolder { get; set; } string SortingSeasonFolderFormat { get; set; } int DefaultQualityProfile { get; set; } - Boolean XbmcUpdateLibrary { get; set; } - Boolean XbmcCleanLibrary { get; set; } - Boolean XbmcUpdateWhenPlaying { get; set; } - string XbmcHosts { get; set; } - string XbmcUsername { get; set; } - string XbmcPassword { get; set; } - string UpdateUrl { get; set; } - string SmtpServer { get; set; } - int SmtpPort { get; set; } - Boolean SmtpUseSsl { get; set; } - string SmtpUsername { get; set; } - string SmtpPassword { get; set; } - string SmtpFromAddress { get; set; } - string SmtpToAddresses { get; set; } string TwitterAccessToken { get; set; } string TwitterAccessTokenSecret { get; set; } - string GrowlHost { get; set; } - string GrowlPassword { get; set; } - string ProwlApiKeys { get; set; } - int ProwlPriority { get; set; } bool EnableBacklogSearching { get; set; } bool AutoIgnorePreviouslyDownloadedEpisodes { get; set; } int Retention { get; set; } @@ -50,11 +32,6 @@ namespace NzbDrone.Core.Configuration DownloadClientType DownloadClient { get; set; } string BlackholeDirectory { get; set; } string ServiceRootUrl { get; } - Boolean PlexUpdateLibrary { get; set; } - string PlexServerHost { get; set; } - string PlexClientHosts { get; set; } - string PlexUsername { get; set; } - string PlexPassword { get; set; } Boolean MetadataUseBanners { get; set; } string PneumaticDirectory { get; set; } string RecycleBin { get; set; } diff --git a/NzbDrone.Core/Datastore/Migration/Migration20130324.cs b/NzbDrone.Core/Datastore/Migration/Migration20130324.cs index 46055442d..bf9868a90 100644 --- a/NzbDrone.Core/Datastore/Migration/Migration20130324.cs +++ b/NzbDrone.Core/Datastore/Migration/Migration20130324.cs @@ -83,10 +83,12 @@ namespace NzbDrone.Core.Datastore.Migration .WithColumn("NzbInfoUrl").AsString().Nullable() .WithColumn("ReleaseGroup").AsString().Nullable(); - Create.TableForModel("ExternalNotificationDefinitions") - .WithColumn("Enable").AsBoolean() - .WithColumn("Type").AsString().Unique() - .WithColumn("Name").AsString().Unique(); + Create.TableForModel("NotificationDefinitions") + .WithColumn("Name").AsString() + .WithColumn("OnGrab").AsBoolean() + .WithColumn("OnDownload").AsBoolean() + .WithColumn("Settings").AsString() + .WithColumn("Implementation").AsString(); Create.TableForModel("ScheduledTasks") .WithColumn("TypeName").AsString().Unique() diff --git a/NzbDrone.Core/Datastore/TableMapping.cs b/NzbDrone.Core/Datastore/TableMapping.cs index c8019c0f9..2bc00929a 100644 --- a/NzbDrone.Core/Datastore/TableMapping.cs +++ b/NzbDrone.Core/Datastore/TableMapping.cs @@ -8,11 +8,11 @@ using NzbDrone.Common.Serializer; using NzbDrone.Core.Configuration; using NzbDrone.Core.DataAugmentation.Scene; using NzbDrone.Core.Datastore.Converters; -using NzbDrone.Core.ExternalNotification; using NzbDrone.Core.Indexers; using NzbDrone.Core.Instrumentation; using NzbDrone.Core.Jobs; using NzbDrone.Core.MediaFiles; +using NzbDrone.Core.Notifications; using NzbDrone.Core.Organizer; using NzbDrone.Core.Qualities; using NzbDrone.Core.RootFolders; @@ -35,7 +35,7 @@ namespace NzbDrone.Core.Datastore Mapper.Entity().RegisterModel("IndexerDefinitions"); Mapper.Entity().RegisterModel("ScheduledTasks"); - Mapper.Entity().RegisterModel("ExternalNotificationDefinitions"); + Mapper.Entity().RegisterModel("NotificationDefinitions"); Mapper.Entity().RegisterModel("SceneMappings"); diff --git a/NzbDrone.Core/Download/DownloadService.cs b/NzbDrone.Core/Download/DownloadService.cs index d2889faba..84a3b73e6 100644 --- a/NzbDrone.Core/Download/DownloadService.cs +++ b/NzbDrone.Core/Download/DownloadService.cs @@ -4,11 +4,7 @@ using System.Linq; using NLog; using NzbDrone.Common.Messaging; using NzbDrone.Core.Configuration; -using NzbDrone.Core.DecisionEngine; -using NzbDrone.Core.Model; -using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; -using NzbDrone.Core.Tv; namespace NzbDrone.Core.Download { @@ -20,16 +16,14 @@ namespace NzbDrone.Core.Download public class DownloadService : IDownloadService { private readonly IProvideDownloadClient _downloadClientProvider; - private readonly IConfigService _configService; private readonly IMessageAggregator _messageAggregator; private readonly Logger _logger; - public DownloadService(IProvideDownloadClient downloadClientProvider, IConfigService configService, + public DownloadService(IProvideDownloadClient downloadClientProvider, IMessageAggregator messageAggregator, Logger logger) { _downloadClientProvider = downloadClientProvider; - _configService = configService; _messageAggregator = messageAggregator; _logger = logger; } diff --git a/NzbDrone.Core/ExternalNotification/ExternalNotificationBase.cs b/NzbDrone.Core/ExternalNotification/ExternalNotificationBase.cs deleted file mode 100644 index dd4e6a824..000000000 --- a/NzbDrone.Core/ExternalNotification/ExternalNotificationBase.cs +++ /dev/null @@ -1,148 +0,0 @@ -using System; -using NLog; -using NzbDrone.Common.Messaging; -using NzbDrone.Core.Download; -using NzbDrone.Core.MediaFiles.Events; -using NzbDrone.Core.Tv; - -namespace NzbDrone.Core.ExternalNotification -{ - public abstract class ExternalNotificationBase - : IHandle, - IHandle, - IHandle - { - private readonly IExternalNotificationRepository _externalNotificationRepository; - private readonly Logger _logger; - - protected ExternalNotificationBase(IExternalNotificationRepository externalNotificationRepository, Logger logger) - { - _externalNotificationRepository = externalNotificationRepository; - _logger = logger; - } - - public abstract string Name { get; } - - public bool NotifyOnGrab - { - get - { - return GetEnableStatus(c => c.OnGrab); - } - set - { - SetEnableStatus(c => c.OnGrab = value); - } - } - - public bool NotifyOnDownload - { - get - { - return GetEnableStatus(c => c.OnDownload); - } - set - { - SetEnableStatus(c => c.OnDownload = value); - } - } - - public bool NotifyOnRename - { - get - { - return GetEnableStatus(c => c.OnRename); - } - set - { - SetEnableStatus(c => c.OnRename = value); - } - } - - private void SetEnableStatus(Action updateAction) - { - var def = _externalNotificationRepository.Get(Name) ?? - new ExternalNotificationDefinition { Name = Name }; - - updateAction(def); - _externalNotificationRepository.Upsert(def); - } - - private bool GetEnableStatus(Func readFunction) - { - var def = _externalNotificationRepository.Get(Name) ?? - new ExternalNotificationDefinition { Name = Name }; - - return readFunction(def); - } - - public void Handle(EpisodeGrabbedEvent message) - { - if (NotifyOnGrab) - { - try - { - _logger.Trace("Sending grab notification to {0}", Name); - //todo: pass all the info to grab event and let the handlers deal with it. - OnGrab(message.Episode.ToString()); - - } - catch (Exception e) - { - _logger.WarnException("Couldn't send grab notification to " + Name, e); - } - } - } - - public void Handle(EpisodeDownloadedEvent message) - { - if (NotifyOnDownload) - { - try - { - _logger.Trace("Sending download notification to {0}", Name); - OnDownload(message.ParsedEpisodeInfo.ToString(), message.Series); - } - catch (Exception e) - { - _logger.WarnException("Couldn't send download notification to " + Name, e); - } - } - } - - public void Handle(SeriesRenamedEvent message) - { - if (NotifyOnRename) - { - try - { - _logger.Trace("Sending rename notification to {0}", Name); - AfterRename(message.Series); - - } - catch (Exception e) - { - _logger.WarnException("Couldn't send rename notification to " + Name, e); - } - } - } - - - protected virtual void OnGrab(string message) - { - - } - - protected virtual void OnDownload(string message, Series series) - { - - } - - protected virtual void AfterRename(Series series) - { - - } - - - } -} diff --git a/NzbDrone.Core/ExternalNotification/ExternalNotificationDefinition.cs b/NzbDrone.Core/ExternalNotification/ExternalNotificationDefinition.cs deleted file mode 100644 index a0fac5405..000000000 --- a/NzbDrone.Core/ExternalNotification/ExternalNotificationDefinition.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Linq; -using NzbDrone.Core.Datastore; - -namespace NzbDrone.Core.ExternalNotification -{ - public class ExternalNotificationDefinition : ModelBase - { - public string Name { get; set; } - public bool OnGrab { get; set; } - public bool OnDownload { get; set; } - public bool OnRename { get; set; } - } -} \ No newline at end of file diff --git a/NzbDrone.Core/ExternalNotification/ExternalNotificationRepository.cs b/NzbDrone.Core/ExternalNotification/ExternalNotificationRepository.cs deleted file mode 100644 index 03df97fee..000000000 --- a/NzbDrone.Core/ExternalNotification/ExternalNotificationRepository.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Data; -using System.Linq; -using NzbDrone.Common.Messaging; -using NzbDrone.Core.Datastore; - -namespace NzbDrone.Core.ExternalNotification -{ - public interface IExternalNotificationRepository : IBasicRepository - { - ExternalNotificationDefinition Get(string name); - } - - public class ExternalNotificationRepository : BasicRepository, IExternalNotificationRepository - { - public ExternalNotificationRepository(IDatabase database, IMessageAggregator messageAggregator) - : base(database, messageAggregator) - { - } - - public ExternalNotificationDefinition Get(string name) - { - return Query.SingleOrDefault(c => c.Name.ToLower() == name.ToLower()); - } - } -} \ No newline at end of file diff --git a/NzbDrone.Core/ExternalNotification/Growl.cs b/NzbDrone.Core/ExternalNotification/Growl.cs deleted file mode 100644 index 9b28df48b..000000000 --- a/NzbDrone.Core/ExternalNotification/Growl.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Linq; -using System; -using NLog; -using NzbDrone.Core.Configuration; -using NzbDrone.Core.Tv; - -namespace NzbDrone.Core.ExternalNotification -{ - public class Growl : ExternalNotificationBase - { - private readonly IConfigService _configService; - private readonly GrowlProvider _growlProvider; - - public Growl(IExternalNotificationRepository repository, IConfigService configService, GrowlProvider growlProvider, Logger logger) - : base(repository, logger) - { - _configService = configService; - _growlProvider = growlProvider; - } - - public override string Name - { - get { return "Growl"; } - } - - protected override void OnGrab(string message) - { - const string title = "Episode Grabbed"; - - var growlHost = _configService.GrowlHost.Split(':'); - var host = growlHost[0]; - var port = Convert.ToInt32(growlHost[1]); - - _growlProvider.SendNotification(title, message, "GRAB", host, port, _configService.GrowlPassword); - } - - protected override void OnDownload(string message, Series series) - { - const string title = "Episode Downloaded"; - - var growlHost = _configService.GrowlHost.Split(':'); - var host = growlHost[0]; - var port = Convert.ToInt32(growlHost[1]); - - _growlProvider.SendNotification(title, message, "DOWNLOAD", host, port, _configService.GrowlPassword); - } - } -} diff --git a/NzbDrone.Core/ExternalNotification/Plex.cs b/NzbDrone.Core/ExternalNotification/Plex.cs deleted file mode 100644 index b9169b742..000000000 --- a/NzbDrone.Core/ExternalNotification/Plex.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Linq; -using NLog; -using NzbDrone.Core.Configuration; -using NzbDrone.Core.Tv; - -namespace NzbDrone.Core.ExternalNotification -{ - public class Plex : ExternalNotificationBase - { - private readonly IConfigService _configService; - private readonly PlexProvider _plexProvider; - - public Plex(IConfigService configService, IExternalNotificationRepository repository, PlexProvider plexProvider, Logger logger) - : base(repository, logger) - { - _configService = configService; - _plexProvider = plexProvider; - } - - public override string Name - { - get { return "Plex"; } - } - - protected override void OnGrab(string message) - { - const string header = "NzbDrone [TV] - Grabbed"; - _plexProvider.Notify(header, message); - } - - protected override void OnDownload(string message, Series series) - { - const string header = "NzbDrone [TV] - Downloaded"; - _plexProvider.Notify(header, message); - UpdateIfEnabled(); - } - - protected override void AfterRename( Series series) - { - UpdateIfEnabled(); - } - - private void UpdateIfEnabled() - { - if (_configService.PlexUpdateLibrary) - { - _plexProvider.UpdateLibrary(); - } - } - } -} diff --git a/NzbDrone.Core/ExternalNotification/Prowl.cs b/NzbDrone.Core/ExternalNotification/Prowl.cs deleted file mode 100644 index df4d5f261..000000000 --- a/NzbDrone.Core/ExternalNotification/Prowl.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Linq; -using System; -using NLog; -using NzbDrone.Core.Configuration; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Tv; -using Prowlin; - -namespace NzbDrone.Core.ExternalNotification -{ - public class Prowl : ExternalNotificationBase - { - private readonly IConfigService _configService; - private readonly ProwlProvider _prowlProvider; - - public Prowl(IConfigService configService, IExternalNotificationRepository repository, ProwlProvider prowlProvider, Logger logger) - : base(repository, logger) - { - _configService = configService; - _prowlProvider = prowlProvider; - } - - public override string Name - { - get { return "Prowl"; } - } - - protected override void OnGrab(string message) - { - const string title = "Episode Grabbed"; - - var apiKeys = _configService.ProwlApiKeys; - var priority = _configService.ProwlPriority; - - _prowlProvider.SendNotification(title, message, apiKeys, (NotificationPriority)priority); - } - - protected override void OnDownload(string message, Series series) - { - const string title = "Episode Downloaded"; - - var apiKeys = _configService.ProwlApiKeys; - var priority = _configService.ProwlPriority; - - _prowlProvider.SendNotification(title, message, apiKeys, (NotificationPriority)priority); - } - } -} diff --git a/NzbDrone.Core/ExternalNotification/Xbmc.cs b/NzbDrone.Core/ExternalNotification/Xbmc.cs deleted file mode 100644 index 7cc22ae27..000000000 --- a/NzbDrone.Core/ExternalNotification/Xbmc.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Linq; -using NLog; -using NzbDrone.Core.Configuration; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Tv; - -namespace NzbDrone.Core.ExternalNotification -{ - public class Xbmc : ExternalNotificationBase - { - private readonly IConfigService _configService; - private readonly XbmcProvider _xbmcProvider; - - public Xbmc(IConfigService configService, IExternalNotificationRepository repository, XbmcProvider xbmcProvider, Logger logger) - : base(repository, logger) - { - _configService = configService; - _xbmcProvider = xbmcProvider; - } - - public override string Name - { - get { return "XBMC"; } - } - - protected override void OnGrab(string message) - { - const string header = "NzbDrone [TV] - Grabbed"; - - _xbmcProvider.Notify(header, message); - } - - protected override void OnDownload(string message, Series series) - { - const string header = "NzbDrone [TV] - Downloaded"; - - _xbmcProvider.Notify(header, message); - UpdateAndClean(series); - } - - protected override void AfterRename(Series series) - { - UpdateAndClean(series); - } - - private void UpdateAndClean(Series series) - { - if (_configService.XbmcUpdateLibrary) - { - _xbmcProvider.Update(series); - } - - if (_configService.XbmcCleanLibrary) - { - _xbmcProvider.Clean(); - } - } - } -} diff --git a/NzbDrone.Core/IndexerSearch/NzbSearchService.cs b/NzbDrone.Core/IndexerSearch/NzbSearchService.cs index 09ea801c2..728dfb9d5 100644 --- a/NzbDrone.Core/IndexerSearch/NzbSearchService.cs +++ b/NzbDrone.Core/IndexerSearch/NzbSearchService.cs @@ -134,7 +134,5 @@ namespace NzbDrone.Core.IndexerSearch return _makeDownloadDecision.GetSearchDecision(reports, definitionBase).ToList(); } - - } } \ No newline at end of file diff --git a/NzbDrone.Core/Indexers/IIndexerSettings.cs b/NzbDrone.Core/Indexers/IIndexerSetting.cs similarity index 100% rename from NzbDrone.Core/Indexers/IIndexerSettings.cs rename to NzbDrone.Core/Indexers/IIndexerSetting.cs diff --git a/NzbDrone.Core/Indexers/IndexerBase.cs b/NzbDrone.Core/Indexers/IndexerBase.cs index 055663464..19e58df02 100644 --- a/NzbDrone.Core/Indexers/IndexerBase.cs +++ b/NzbDrone.Core/Indexers/IndexerBase.cs @@ -18,7 +18,7 @@ namespace NzbDrone.Core.Indexers Name = Name, Enable = true, Implementation = GetType().Name, - Settings = string.Empty + Settings = String.Empty }; } } @@ -32,7 +32,6 @@ namespace NzbDrone.Core.Indexers } public abstract IEnumerable RecentFeed { get; } - public abstract IEnumerable GetEpisodeSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber); public abstract IEnumerable GetDailyEpisodeSearchUrls(string seriesTitle, DateTime date); public abstract IEnumerable GetSeasonSearchUrls(string seriesTitle, int seasonNumber); diff --git a/NzbDrone.Core/Indexers/NzbsRUs/NzbsRUs.cs b/NzbDrone.Core/Indexers/NzbsRUs/NzbsRUs.cs index 7f19c8542..2d08e190a 100644 --- a/NzbDrone.Core/Indexers/NzbsRUs/NzbsRUs.cs +++ b/NzbDrone.Core/Indexers/NzbsRUs/NzbsRUs.cs @@ -40,7 +40,5 @@ namespace NzbDrone.Core.Indexers.NzbsRUs { return new List(); } - - } } \ No newline at end of file diff --git a/NzbDrone.Core/Notifications/Growl/Growl.cs b/NzbDrone.Core/Notifications/Growl/Growl.cs new file mode 100644 index 000000000..2f6dfc7f2 --- /dev/null +++ b/NzbDrone.Core/Notifications/Growl/Growl.cs @@ -0,0 +1,40 @@ +using System; +using NLog; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Notifications.Growl +{ + public class Growl : NotificationWithSetting + { + private readonly GrowlProvider _growlProvider; + + public Growl(GrowlProvider growlProvider) + { + _growlProvider = growlProvider; + } + + public override string Name + { + get { return "Growl"; } + } + + public override void OnGrab(string message) + { + const string title = "Episode Grabbed"; + + _growlProvider.SendNotification(title, message, "GRAB", Settings.Host, Settings.Port, Settings.Password); + } + + public override void OnDownload(string message, Series series) + { + const string title = "Episode Downloaded"; + + _growlProvider.SendNotification(title, message, "DOWNLOAD", Settings.Host, Settings.Port, Settings.Password); + } + + public override void AfterRename(Series series) + { + } + } +} diff --git a/NzbDrone.Core/ExternalNotification/GrowlProvider.cs b/NzbDrone.Core/Notifications/Growl/GrowlProvider.cs similarity index 90% rename from NzbDrone.Core/ExternalNotification/GrowlProvider.cs rename to NzbDrone.Core/Notifications/Growl/GrowlProvider.cs index bdbb12046..4d81e1f75 100644 --- a/NzbDrone.Core/ExternalNotification/GrowlProvider.cs +++ b/NzbDrone.Core/Notifications/Growl/GrowlProvider.cs @@ -3,8 +3,9 @@ using System.Collections.Generic; using System.Linq; using Growl.Connector; using NLog; +using GrowlNotification = Growl.Connector.Notification; -namespace NzbDrone.Core.ExternalNotification +namespace NzbDrone.Core.Notifications.Growl { public class GrowlProvider { @@ -39,7 +40,7 @@ namespace NzbDrone.Core.ExternalNotification { var notificationType = _notificationTypes.Single(n => n.Name == notificationTypeName); - var notification = new Notification("NzbDrone", notificationType.Name, DateTime.Now.Ticks.ToString(), title, message); + var notification = new GrowlNotification("NzbDrone", notificationType.Name, DateTime.Now.Ticks.ToString(), title, message); _growlConnector = new GrowlConnector(password, hostname, port); diff --git a/NzbDrone.Core/Notifications/Growl/GrowlSettings.cs b/NzbDrone.Core/Notifications/Growl/GrowlSettings.cs new file mode 100644 index 000000000..87c6f2f55 --- /dev/null +++ b/NzbDrone.Core/Notifications/Growl/GrowlSettings.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Core.Annotations; + +namespace NzbDrone.Core.Notifications.Growl +{ + public class GrowlSettings : INotifcationSettings + { + [FieldDefinition(0, Label = "Host", HelpText = "Growl Host (IP or Hostname)")] + public String Host { get; set; } + + [FieldDefinition(1, Label = "Port", HelpText = "Growl Port")] + public Int32 Port { get; set; } + + [FieldDefinition(2, Label = "Password", HelpText = "Password for Growl")] + public String Password { get; set; } + + public bool IsValid + { + get + { + return !string.IsNullOrWhiteSpace(Host) && !string.IsNullOrWhiteSpace(Password) && Port > 0; + } + } + } +} diff --git a/NzbDrone.Core/Notifications/INotifcationSettings.cs b/NzbDrone.Core/Notifications/INotifcationSettings.cs new file mode 100644 index 000000000..93770d959 --- /dev/null +++ b/NzbDrone.Core/Notifications/INotifcationSettings.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Notifications +{ + public interface INotifcationSettings + { + bool IsValid { get; } + } + + public class NullSetting : INotifcationSettings + { + public static NullSetting Instance = new NullSetting(); + + private NullSetting() + { + + } + + public bool IsValid + { + get + { + return true; + } + } + } +} diff --git a/NzbDrone.Core/Notifications/INotification.cs b/NzbDrone.Core/Notifications/INotification.cs new file mode 100644 index 000000000..2280aa830 --- /dev/null +++ b/NzbDrone.Core/Notifications/INotification.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Notifications +{ + public interface INotification + { + string Name { get; } + + NotificationDefinition InstanceDefinition { get; set; } + + void OnGrab(string message); + void OnDownload(string message, Series series); + void AfterRename(Series series); + } +} diff --git a/NzbDrone.Core/Notifications/Notification.cs b/NzbDrone.Core/Notifications/Notification.cs new file mode 100644 index 000000000..a5bd2be43 --- /dev/null +++ b/NzbDrone.Core/Notifications/Notification.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Notifications +{ + public class Notification + { + public int Id { get; set; } + public string Name { get; set; } + public bool OnGrab { get; set; } + public bool OnDownload { get; set; } + public INotifcationSettings Settings { get; set; } + public INotification Instance { get; set; } + } +} diff --git a/NzbDrone.Core/Notifications/NotificationBase.cs b/NzbDrone.Core/Notifications/NotificationBase.cs new file mode 100644 index 000000000..be9377725 --- /dev/null +++ b/NzbDrone.Core/Notifications/NotificationBase.cs @@ -0,0 +1,17 @@ +using System; +using NLog; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Notifications +{ + public abstract class NotificationBase : INotification + { + public abstract string Name { get; } + + public NotificationDefinition InstanceDefinition { get; set; } + + public abstract void OnGrab(string message); + public abstract void OnDownload(string message, Series series); + public abstract void AfterRename(Series series); + } +} diff --git a/NzbDrone.Core/Notifications/NotificationDefinition.cs b/NzbDrone.Core/Notifications/NotificationDefinition.cs new file mode 100644 index 000000000..7456c7783 --- /dev/null +++ b/NzbDrone.Core/Notifications/NotificationDefinition.cs @@ -0,0 +1,14 @@ +using System; +using NzbDrone.Core.Datastore; + +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; } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Notifications/NotificationRepository.cs b/NzbDrone.Core/Notifications/NotificationRepository.cs new file mode 100644 index 000000000..f9f9feb0d --- /dev/null +++ b/NzbDrone.Core/Notifications/NotificationRepository.cs @@ -0,0 +1,31 @@ +using System; +using System.Linq; +using NzbDrone.Common.Messaging; +using NzbDrone.Core.Datastore; + +namespace NzbDrone.Core.Notifications +{ + public interface INotificationRepository : IBasicRepository + { + NotificationDefinition Get(string name); + NotificationDefinition Find(string name); + } + + public class NotificationRepository : BasicRepository, INotificationRepository + { + public NotificationRepository(IDatabase database, IMessageAggregator messageAggregator) + : base(database, messageAggregator) + { + } + + 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/NzbDrone.Core/Notifications/NotificationService.cs b/NzbDrone.Core/Notifications/NotificationService.cs new file mode 100644 index 000000000..b086cb378 --- /dev/null +++ b/NzbDrone.Core/Notifications/NotificationService.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NLog; +using NzbDrone.Common; +using NzbDrone.Common.Composition; +using NzbDrone.Common.Messaging; +using NzbDrone.Core.Download; +using NzbDrone.Core.MediaFiles.Events; + +namespace NzbDrone.Core.Notifications +{ + public interface INotificationService + { + List All(); + } + + 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(); + } + + 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; + + if (notification.Instance.GetType().GetMethod("ImportSettingsFromJson") != null) + { + notification.Settings = ((dynamic)notification.Instance).ImportSettingsFromJson(definition.Settings); + } + else + { + notification.Settings = NullSetting.Instance; + } + + 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; + } + + public void Handle(EpisodeGrabbedEvent message) + { + All().Where(n => n.OnGrab) + .ToList() + .ForEach(notification => + notification.Instance + .OnGrab("Grabbed!") + ); + } + + public void Handle(EpisodeDownloadedEvent message) + { + All().Where(n => n.OnDownload) + .ToList() + .ForEach(notification => + notification.Instance + .OnDownload("Downloaded!", message.Series) + ); + } + + public void Handle(SeriesRenamedEvent message) + { + All().Where(n => n.OnDownload) + .ToList() + .ForEach(notification => + notification.Instance + .OnDownload("Renamed!", message.Series) + ); + } + } +} diff --git a/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs b/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs new file mode 100644 index 000000000..2ee5d7443 --- /dev/null +++ b/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs @@ -0,0 +1,31 @@ +using Newtonsoft.Json; + +namespace NzbDrone.Core.Notifications +{ + public interface INotificationSettingsProvider + { + TSetting Get(INotification indexer) where TSetting : INotifcationSettings, new(); + } + + public class NotificationSettingsProvider : INotificationSettingsProvider + { + private readonly INotificationRepository _notificationRepository; + + public NotificationSettingsProvider(INotificationRepository notificationRepository) + { + _notificationRepository = notificationRepository; + } + + public TSetting Get(INotification indexer) where TSetting : INotifcationSettings, new() + { + var indexerDef = _notificationRepository.Find(indexer.Name); + + if (indexerDef == null || string.IsNullOrWhiteSpace(indexerDef.Settings)) + { + return new TSetting(); + } + + return JsonConvert.DeserializeObject(indexerDef.Settings); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Notifications/NotificationWithSetting.cs b/NzbDrone.Core/Notifications/NotificationWithSetting.cs new file mode 100644 index 000000000..109310c75 --- /dev/null +++ b/NzbDrone.Core/Notifications/NotificationWithSetting.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Common.Serializer; + +namespace NzbDrone.Core.Notifications +{ + public abstract class NotificationWithSetting : NotificationBase where TSetting : class, INotifcationSettings, new() + { + public TSetting Settings { get; private set; } + + public TSetting ImportSettingsFromJson(string json) + { + Settings = Json.Deserialize(json) ?? new TSetting(); + + return Settings; + } + } +} diff --git a/NzbDrone.Core/Notifications/Plex/PlexClient.cs b/NzbDrone.Core/Notifications/Plex/PlexClient.cs new file mode 100644 index 000000000..8640f9ecc --- /dev/null +++ b/NzbDrone.Core/Notifications/Plex/PlexClient.cs @@ -0,0 +1,37 @@ +using NLog; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Notifications.Plex +{ + public class PlexClient : NotificationWithSetting + { + private readonly PlexProvider _plexProvider; + + public PlexClient(PlexProvider plexProvider) + { + _plexProvider = plexProvider; + } + + public override string Name + { + get { return "Plex Client"; } + } + + public override void OnGrab(string message) + { + const string header = "NzbDrone [TV] - Grabbed"; + _plexProvider.Notify(Settings, header, message); + } + + public override void OnDownload(string message, Series series) + { + const string header = "NzbDrone [TV] - Downloaded"; + _plexProvider.Notify(Settings, header, message); + } + + public override void AfterRename(Series series) + { + } + } +} diff --git a/NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs b/NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs new file mode 100644 index 000000000..96c959c7d --- /dev/null +++ b/NzbDrone.Core/Notifications/Plex/PlexClientSettings.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Core.Annotations; + +namespace NzbDrone.Core.Notifications.Plex +{ + public class PlexClientSettings : INotifcationSettings + { + [FieldDefinition(0, Label = "Host", HelpText = "Plex Client Host (IP or Hostname)")] + public String Host { get; set; } + + [FieldDefinition(1, Label = "Port", HelpText = "Plex Client Port")] + public Int32 Port { get; set; } + + [FieldDefinition(2, Label = "Username", HelpText = "Username for Plex")] + public String Username { get; set; } + + [FieldDefinition(3, Label = "Password", HelpText = "Password for Plex")] + public String Password { get; set; } + + public bool IsValid + { + get + { + return !string.IsNullOrWhiteSpace(Host); + } + } + } +} diff --git a/NzbDrone.Core/ExternalNotification/PlexProvider.cs b/NzbDrone.Core/Notifications/Plex/PlexProvider.cs similarity index 61% rename from NzbDrone.Core/ExternalNotification/PlexProvider.cs rename to NzbDrone.Core/Notifications/Plex/PlexProvider.cs index 3110c18b1..ed921fca5 100644 --- a/NzbDrone.Core/ExternalNotification/PlexProvider.cs +++ b/NzbDrone.Core/Notifications/Plex/PlexProvider.cs @@ -6,46 +6,33 @@ using NLog; using NzbDrone.Common; using NzbDrone.Core.Configuration; -namespace NzbDrone.Core.ExternalNotification +namespace NzbDrone.Core.Notifications.Plex { public class PlexProvider { private readonly IHttpProvider _httpProvider; - private readonly IConfigService _configService; private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - public PlexProvider(IHttpProvider httpProvider, IConfigService configService) + public PlexProvider(IHttpProvider httpProvider) { _httpProvider = httpProvider; - _configService = configService; } - public PlexProvider() + public virtual void Notify(PlexClientSettings settings, string header, string message) { - - } - - public virtual void Notify(string header, string message) - { - //Foreach plex client send a notification - foreach(var host in _configService.PlexClientHosts.Split(',')) + try + { + var command = String.Format("ExecBuiltIn(Notification({0}, {1}))", header, message); + SendCommand(settings.Host, command, settings.Username, settings.Password); + } + catch(Exception ex) { - try - { - var command = String.Format("ExecBuiltIn(Notification({0}, {1}))", header, message); - SendCommand(host.Trim(), command, _configService.PlexUsername, _configService.PlexPassword); - } - catch(Exception ex) - { - logger.WarnException("Failed to send notification to Plex Client: " + host.Trim(), ex); - } + logger.WarnException("Failed to send notification to Plex Client: " + settings.Host, ex); } } - public virtual void UpdateLibrary() + public virtual void UpdateLibrary(string host) { - var host = _configService.PlexServerHost; - try { logger.Trace("Sending Update Request to Plex Server"); @@ -91,14 +78,11 @@ namespace NzbDrone.Core.ExternalNotification return _httpProvider.DownloadString(url); } - public virtual void TestNotification(string hosts, string username, string password) + public virtual void TestNotification(string host, string username, string password) { - foreach (var host in hosts.Split(',')) - { - logger.Trace("Sending Test Notifcation to XBMC Host: {0}", host); - var command = String.Format("ExecBuiltIn(Notification({0}, {1}))", "Test Notification", "Success! Notifications are setup correctly"); - SendCommand(host.Trim(), command, _configService.PlexUsername, _configService.PlexPassword); - } + logger.Trace("Sending Test Notifcation to XBMC Host: {0}", host); + var command = String.Format("ExecBuiltIn(Notification({0}, {1}))", "Test Notification", "Success! Notifications are setup correctly"); + SendCommand(host.Trim(), command, username, password); } } } diff --git a/NzbDrone.Core/Notifications/Plex/PlexServer.cs b/NzbDrone.Core/Notifications/Plex/PlexServer.cs new file mode 100644 index 000000000..5b707efe1 --- /dev/null +++ b/NzbDrone.Core/Notifications/Plex/PlexServer.cs @@ -0,0 +1,43 @@ +using NLog; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Notifications.Plex +{ + public class PlexServer : NotificationWithSetting + { + private readonly PlexProvider _plexProvider; + + public PlexServer(PlexProvider plexProvider) + { + _plexProvider = plexProvider; + } + + public override string Name + { + get { return "Plex Server"; } + } + + public override void OnGrab(string message) + { + } + + public override void OnDownload(string message, Series series) + { + UpdateIfEnabled(); + } + + public override void AfterRename(Series series) + { + UpdateIfEnabled(); + } + + private void UpdateIfEnabled() + { + if (Settings.UpdateLibrary) + { + _plexProvider.UpdateLibrary(Settings.Host); + } + } + } +} diff --git a/NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs b/NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs new file mode 100644 index 000000000..51cccfdc5 --- /dev/null +++ b/NzbDrone.Core/Notifications/Plex/PlexServerSettings.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Core.Annotations; + +namespace NzbDrone.Core.Notifications.Plex +{ + public class PlexServerSettings : INotifcationSettings + { + [FieldDefinition(0, Label = "Host", HelpText = "Plex Server Host (IP or Hostname)")] + public String Host { get; set; } + + [FieldDefinition(1, Label = "Update Library", HelpText = "Update Library on Download/Rename")] + public Boolean UpdateLibrary { get; set; } + + public bool IsValid + { + get + { + return !string.IsNullOrWhiteSpace(Host); + } + } + } +} diff --git a/NzbDrone.Core/Notifications/Prowl/Prowl.cs b/NzbDrone.Core/Notifications/Prowl/Prowl.cs new file mode 100644 index 000000000..be4dc6997 --- /dev/null +++ b/NzbDrone.Core/Notifications/Prowl/Prowl.cs @@ -0,0 +1,38 @@ +using NzbDrone.Core.Tv; +using Prowlin; + +namespace NzbDrone.Core.Notifications.Prowl +{ + public class Prowl : NotificationWithSetting + { + private readonly ProwlProvider _prowlProvider; + + public Prowl(ProwlProvider prowlProvider) + { + _prowlProvider = prowlProvider; + } + + public override string Name + { + get { return "Prowl"; } + } + + public override void OnGrab(string message) + { + const string title = "Episode Grabbed"; + + _prowlProvider.SendNotification(title, message, Settings.ApiKey, (NotificationPriority)Settings.Priority); + } + + public override void OnDownload(string message, Series series) + { + const string title = "Episode Downloaded"; + + _prowlProvider.SendNotification(title, message, Settings.ApiKey, (NotificationPriority)Settings.Priority); + } + + public override void AfterRename(Series series) + { + } + } +} diff --git a/NzbDrone.Core/Providers/ProwlProvider.cs b/NzbDrone.Core/Notifications/Prowl/ProwlProvider.cs similarity index 84% rename from NzbDrone.Core/Providers/ProwlProvider.cs rename to NzbDrone.Core/Notifications/Prowl/ProwlProvider.cs index 463d13c90..4bbf9a220 100644 --- a/NzbDrone.Core/Providers/ProwlProvider.cs +++ b/NzbDrone.Core/Notifications/Prowl/ProwlProvider.cs @@ -1,9 +1,8 @@ using System; -using System.Linq; using NLog; using Prowlin; -namespace NzbDrone.Core.Providers +namespace NzbDrone.Core.Notifications.Prowl { public class ProwlProvider { @@ -34,11 +33,11 @@ namespace NzbDrone.Core.Providers return false; } - public virtual bool SendNotification(string title, string message, string apiKeys, NotificationPriority priority = NotificationPriority.Normal, string url = null) + public virtual bool SendNotification(string title, string message, string apiKey, NotificationPriority priority = NotificationPriority.Normal, string url = null) { try { - var notification = new Notification + var notification = new Prowlin.Notification { Application = "NzbDrone", Description = message, @@ -47,8 +46,7 @@ namespace NzbDrone.Core.Providers Url = url }; - foreach (var apiKey in apiKeys.Split(',')) - notification.AddApiKey(apiKey.Trim()); + notification.AddApiKey(apiKey.Trim()); var client = new ProwlClient(); @@ -63,7 +61,7 @@ namespace NzbDrone.Core.Providers catch (Exception ex) { Logger.TraceException(ex.Message, ex); - Logger.Warn("Invalid API Key(s): {0}", apiKeys); + Logger.Warn("Invalid API Key: {0}", apiKey); } return false; diff --git a/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs b/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs new file mode 100644 index 000000000..7dd087d8b --- /dev/null +++ b/NzbDrone.Core/Notifications/Prowl/ProwlSettings.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Core.Annotations; + +namespace NzbDrone.Core.Notifications.Prowl +{ + public class ProwlSettings : INotifcationSettings + { + [FieldDefinition(0, Label = "API Key", HelpText = "API Key for Prowl")] + public String ApiKey { get; set; } + + [FieldDefinition(1, Label = "Priority", HelpText = "Priority to send messages at")] + public Int32 Priority { get; set; } + + public bool IsValid + { + get + { + return !string.IsNullOrWhiteSpace(ApiKey) && Priority > 0; + } + } + } +} diff --git a/NzbDrone.Core/ExternalNotification/Smtp.cs b/NzbDrone.Core/Notifications/Smtp/Smtp.cs similarity index 54% rename from NzbDrone.Core/ExternalNotification/Smtp.cs rename to NzbDrone.Core/Notifications/Smtp/Smtp.cs index b9e511b01..aadec4a59 100644 --- a/NzbDrone.Core/ExternalNotification/Smtp.cs +++ b/NzbDrone.Core/Notifications/Smtp/Smtp.cs @@ -1,17 +1,15 @@ -using System.Linq; -using System; +using System; using NLog; using NzbDrone.Core.Providers; using NzbDrone.Core.Tv; -namespace NzbDrone.Core.ExternalNotification +namespace NzbDrone.Core.Notifications.Smtp { - public class Smtp : ExternalNotificationBase + public class Smtp : NotificationWithSetting { private readonly SmtpProvider _smtpProvider; - public Smtp(IExternalNotificationRepository repository, SmtpProvider smtpProvider, Logger logger) - : base(repository, logger) + public Smtp(SmtpProvider smtpProvider) { _smtpProvider = smtpProvider; } @@ -21,19 +19,24 @@ namespace NzbDrone.Core.ExternalNotification get { return "SMTP"; } } - protected override void OnGrab(string message) + public override void OnGrab(string message) { const string subject = "NzbDrone [TV] - Grabbed"; var body = String.Format("{0} sent to SABnzbd queue.", message); - _smtpProvider.SendEmail(subject, body); + + _smtpProvider.SendEmail(Settings, subject, body); } - protected override void OnDownload(string message, Series series) + public override void OnDownload(string message, Series series) { const string subject = "NzbDrone [TV] - Downloaded"; var body = String.Format("{0} Downloaded and sorted.", message); - _smtpProvider.SendEmail(subject, body); + _smtpProvider.SendEmail(Settings, subject, body); + } + + public override void AfterRename(Series series) + { } } } diff --git a/NzbDrone.Core/Notifications/Smtp/SmtpProvider.cs b/NzbDrone.Core/Notifications/Smtp/SmtpProvider.cs new file mode 100644 index 000000000..694b91830 --- /dev/null +++ b/NzbDrone.Core/Notifications/Smtp/SmtpProvider.cs @@ -0,0 +1,66 @@ +using System; +using System.Net; +using System.Net.Mail; +using NLog; + +namespace NzbDrone.Core.Notifications.Smtp +{ + public class SmtpProvider + { + private readonly Logger _logger; + + public SmtpProvider(Logger logger) + { + _logger = logger; + } + +// var subject = "NzbDrone SMTP Test Notification"; +// var body = "This is a test email from NzbDrone, if you received this message you properly configured your SMTP settings! (Now save them!)"; + public virtual void SendEmail(SmtpSettings settings, string subject, string body, bool htmlBody = false) + { + var email = new MailMessage(); + email.From = new MailAddress(settings.From); + + email.To.Add(settings.To); + + email.Subject = subject; + email.Body = body; + email.IsBodyHtml = htmlBody; + + NetworkCredential credentials = null; + + if (!String.IsNullOrWhiteSpace(settings.Username)) + credentials = new NetworkCredential(settings.Username, settings.Password); + + try + { + Send(email, settings.Server, settings.Port, settings.UseSsl, credentials); + } + catch(Exception ex) + { + _logger.Error("Error sending email. Subject: {0}", email.Subject); + _logger.TraceException(ex.Message, ex); + } + } + + public virtual void Send(MailMessage email, string server, int port, bool ssl, NetworkCredential credentials) + { + try + { + var smtp = new SmtpClient(server, port); + + smtp.EnableSsl = ssl; + + smtp.Credentials = credentials; + + smtp.Send(email); + } + + catch (Exception ex) + { + _logger.ErrorException("There was an error sending an email.", ex); + throw; + } + } + } +} diff --git a/NzbDrone.Core/Notifications/Smtp/SmtpSettings.cs b/NzbDrone.Core/Notifications/Smtp/SmtpSettings.cs new file mode 100644 index 000000000..7b172329a --- /dev/null +++ b/NzbDrone.Core/Notifications/Smtp/SmtpSettings.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Core.Annotations; + +namespace NzbDrone.Core.Notifications.Smtp +{ + public class SmtpSettings : INotifcationSettings + { + [FieldDefinition(0, Label = "Server", HelpText = "Hostname or IP of SMTP server")] + public String Server { get; set; } + + [FieldDefinition(1, Label = "Port", HelpText = "SMTP Server Port")] + public Int32 Port { get; set; } + + [FieldDefinition(2, Label = "Use SSL", HelpText = "Does your SMTP server use SSL?")] + public Boolean UseSsl { get; set; } + + [FieldDefinition(3, Label = "Username", HelpText = "SMTP Server Username")] + public String Username { get; set; } + + [FieldDefinition(4, Label = "Password", HelpText = "SMTP Server Password")] + public String Password { get; set; } + + [FieldDefinition(5, Label = "From Address", HelpText = "Sender's address")] + public String From { get; set; } + + [FieldDefinition(6, Label = "To Address", HelpText = "Recipient address")] + public String To { get; set; } + + public bool IsValid + { + get + { + return !string.IsNullOrWhiteSpace(Server) && Port > 0 && !string.IsNullOrWhiteSpace(From) && !string.IsNullOrWhiteSpace(To); + } + } + } +} diff --git a/NzbDrone.Core/Providers/Xbmc/EventClientProvider.cs b/NzbDrone.Core/Notifications/Xbmc/EventClientProvider.cs similarity index 95% rename from NzbDrone.Core/Providers/Xbmc/EventClientProvider.cs rename to NzbDrone.Core/Notifications/Xbmc/EventClientProvider.cs index 081bcbec6..738ab9281 100644 --- a/NzbDrone.Core/Providers/Xbmc/EventClientProvider.cs +++ b/NzbDrone.Core/Notifications/Xbmc/EventClientProvider.cs @@ -1,10 +1,8 @@ using System; -using System.Collections.Generic; -using System.Text; using NzbDrone.Common; using NzbDrone.Core.Model.Xbmc; -namespace NzbDrone.Core.Providers.Xbmc +namespace NzbDrone.Core.Notifications.Xbmc { public class EventClientProvider { diff --git a/NzbDrone.Core/Providers/Xbmc/ResourceManager.cs b/NzbDrone.Core/Notifications/Xbmc/ResourceManager.cs similarity index 97% rename from NzbDrone.Core/Providers/Xbmc/ResourceManager.cs rename to NzbDrone.Core/Notifications/Xbmc/ResourceManager.cs index ee717841d..2eed6b1f9 100644 --- a/NzbDrone.Core/Providers/Xbmc/ResourceManager.cs +++ b/NzbDrone.Core/Notifications/Xbmc/ResourceManager.cs @@ -1,7 +1,7 @@ using System.Drawing; using System.IO; -namespace NzbDrone.Core.Providers.Xbmc +namespace NzbDrone.Core.Notifications.Xbmc { public class ResourceManager { diff --git a/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs b/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs new file mode 100644 index 000000000..f6bbc446b --- /dev/null +++ b/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs @@ -0,0 +1,53 @@ +using NLog; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Notifications.Xbmc +{ + public class Xbmc : NotificationWithSetting + { + private readonly XbmcProvider _xbmcProvider; + + public Xbmc(XbmcProvider xbmcProvider, Logger logger) + { + _xbmcProvider = xbmcProvider; + } + + public override string Name + { + get { return "XBMC"; } + } + + public override void OnGrab(string message) + { + const string header = "NzbDrone [TV] - Grabbed"; + + _xbmcProvider.Notify(Settings, header, message); + } + + public override void OnDownload(string message, Series series) + { + const string header = "NzbDrone [TV] - Downloaded"; + + _xbmcProvider.Notify(Settings, header, message); + UpdateAndClean(series); + } + + public override void AfterRename(Series series) + { + UpdateAndClean(series); + } + + private void UpdateAndClean(Series series) + { + if (Settings.UpdateLibrary) + { + _xbmcProvider.Update(Settings, series); + } + + if (Settings.CleanLibrary) + { + _xbmcProvider.Clean(Settings); + } + } + } +} diff --git a/NzbDrone.Core/Providers/XbmcProvider.cs b/NzbDrone.Core/Notifications/Xbmc/XbmcProvider.cs similarity index 76% rename from NzbDrone.Core/Providers/XbmcProvider.cs rename to NzbDrone.Core/Notifications/Xbmc/XbmcProvider.cs index 861931549..1ea546f71 100644 --- a/NzbDrone.Core/Providers/XbmcProvider.cs +++ b/NzbDrone.Core/Notifications/Xbmc/XbmcProvider.cs @@ -7,118 +7,105 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NLog; using NzbDrone.Common; -using NzbDrone.Core.Configuration; using NzbDrone.Core.Tv; using NzbDrone.Core.Model.Xbmc; -using NzbDrone.Core.Providers.Xbmc; -namespace NzbDrone.Core.Providers +namespace NzbDrone.Core.Notifications.Xbmc { public class XbmcProvider { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - private readonly IConfigService _configService; private readonly IHttpProvider _httpProvider; private readonly EventClientProvider _eventClientProvider; - public XbmcProvider(IConfigService configService, IHttpProvider httpProvider, EventClientProvider eventClientProvider) + public XbmcProvider(IHttpProvider httpProvider, EventClientProvider eventClientProvider) { - _configService = configService; _httpProvider = httpProvider; _eventClientProvider = eventClientProvider; } - public XbmcProvider() - { - - } - - public virtual void Notify(string header, string message) + public virtual void Notify(XbmcSettings settings, string header, string message) { //Always use EventServer, until Json has real support for it - foreach (var host in _configService.XbmcHosts.Split(',')) - { - Logger.Trace("Sending Notifcation to XBMC Host: {0}", host); - _eventClientProvider.SendNotification(header, message, IconType.Jpeg, "NzbDrone.jpg", GetHostWithoutPort(host)); - } + var host = settings.Host; + Logger.Trace("Sending Notifcation to XBMC Host: {0}", host); + _eventClientProvider.SendNotification(header, message, IconType.Jpeg, "NzbDrone.jpg", host); } - public virtual void Update(Series series) + public virtual void Update(XbmcSettings settings, Series series) { //Use Json for Eden/Nightly or depricated HTTP for 10.x (Dharma) to get the proper path //Perform update with EventServer (Json currently doesn't support updating a specific path only - July 2011) - var username = _configService.XbmcUsername; - var password = _configService.XbmcPassword; + var username = settings.Username; + var password = settings.Password; + var host = settings.Host; - foreach (var host in _configService.XbmcHosts.Split(',')) - { - Logger.Trace("Determining version of XBMC Host: {0}", host); - var version = GetJsonVersion(host, username, password); + Logger.Trace("Determining version of XBMC Host: {0}", host); + var version = GetJsonVersion(host, username, password); - //If Dharma - if (version == new XbmcVersion(2)) + //If Dharma + if (version == new XbmcVersion(2)) + { + //Check for active player only when we should skip updates when playing + if (!settings.AlwaysUpdate) { - //Check for active player only when we should skip updates when playing - if (!_configService.XbmcUpdateWhenPlaying) + Logger.Trace("Determining if there are any active players on XBMC host: {0}", host); + var activePlayers = GetActivePlayersDharma(host, username, password); + + //If video is currently playing, then skip update + if (activePlayers["video"]) { - Logger.Trace("Determining if there are any active players on XBMC host: {0}", host); - var activePlayers = GetActivePlayersDharma(host, username, password); - - //If video is currently playing, then skip update - if (activePlayers["video"]) - { - Logger.Debug("Video is currently playing, skipping library update"); - continue; - } + Logger.Debug("Video is currently playing, skipping library update"); + return; } - - UpdateWithHttp(series, host, username, password); } + UpdateWithHttp(series, host, username, password); + } - //If Eden or newer (attempting to make it future compatible) - else if (version == new XbmcVersion(3) || version == new XbmcVersion(4)) + //If Eden or newer (attempting to make it future compatible) + else if (version == new XbmcVersion(3) || version == new XbmcVersion(4)) + { + //Check for active player only when we should skip updates when playing + if (!settings.AlwaysUpdate) { - //Check for active player only when we should skip updates when playing - if (!_configService.XbmcUpdateWhenPlaying) + Logger.Trace("Determining if there are any active players on XBMC host: {0}", host); + var activePlayers = GetActivePlayersEden(host, username, password); + + //If video is currently playing, then skip update + if (activePlayers.Any(a => a.Type.Equals("video"))) { - Logger.Trace("Determining if there are any active players on XBMC host: {0}", host); - var activePlayers = GetActivePlayersEden(host, username, password); - - //If video is currently playing, then skip update - if (activePlayers.Any(a => a.Type.Equals("video"))) - { - Logger.Debug("Video is currently playing, skipping library update"); - continue; - } + Logger.Debug("Video is currently playing, skipping library update"); + return; } - - UpdateWithJsonExecBuiltIn(series, host, username, password); } - else if (version >= new XbmcVersion(5)) + UpdateWithJsonExecBuiltIn(series, host, username, password); + } + + else if (version >= new XbmcVersion(5)) + { + //Check for active player only when we should skip updates when playing + if (!settings.AlwaysUpdate) { - //Check for active player only when we should skip updates when playing - if (!_configService.XbmcUpdateWhenPlaying) + Logger.Trace("Determining if there are any active players on XBMC host: {0}", host); + var activePlayers = GetActivePlayersEden(host, username, password); + + //If video is currently playing, then skip update + if (activePlayers.Any(a => a.Type.Equals("video"))) { - Logger.Trace("Determining if there are any active players on XBMC host: {0}", host); - var activePlayers = GetActivePlayersEden(host, username, password); - - //If video is currently playing, then skip update - if (activePlayers.Any(a => a.Type.Equals("video"))) - { - Logger.Debug("Video is currently playing, skipping library update"); - continue; - } + Logger.Debug("Video is currently playing, skipping library update"); + return; } - - UpdateWithJsonVideoLibraryScan(series, host, username, password); } - //Log Version zero if check failed - else - Logger.Trace("Unknown version: [{0}], skipping.", version); + UpdateWithJsonVideoLibraryScan(series, host, username, password); } + + //Log Version zero if check failed + else + Logger.Trace("Unknown version: [{0}], skipping.", version); + } public virtual bool UpdateWithJsonExecBuiltIn(Series series, string host, string username, string password) @@ -245,16 +232,14 @@ namespace NzbDrone.Core.Providers return true; } - public virtual void Clean() + public virtual void Clean(XbmcSettings settings) { //Use EventServer, once Dharma is extinct use Json? - foreach (var host in _configService.XbmcHosts.Split(',')) - { - Logger.Trace("Sending DB Clean Request to XBMC Host: {0}", host); - var command = "ExecBuiltIn(CleanLibrary(video))"; - _eventClientProvider.SendAction(GetHostWithoutPort(host), ActionType.ExecBuiltin, command); - } + var host = settings.Host; + Logger.Trace("Sending DB Clean Request to XBMC Host: {0}", host); + var command = "ExecBuiltIn(CleanLibrary(video))"; + _eventClientProvider.SendAction(host, ActionType.ExecBuiltin, command); } public virtual string SendCommand(string host, string command, string username, string password) @@ -451,7 +436,7 @@ namespace NzbDrone.Core.Providers foreach (var host in hosts.Split(',')) { Logger.Trace("Sending Test Notifcation to XBMC Host: {0}", host); - _eventClientProvider.SendNotification("Test Notification", "Success! Notifications are setup correctly", IconType.Jpeg, "NzbDrone.jpg", GetHostWithoutPort(host)); + _eventClientProvider.SendNotification("Test Notification", "Success! Notifications are setup correctly", IconType.Jpeg, "NzbDrone.jpg", host); } } @@ -465,10 +450,5 @@ namespace NzbDrone.Core.Providers throw new Exception("Failed to get JSON version in test"); } } - - private string GetHostWithoutPort(string address) - { - return address.Split(':')[0]; - } } } \ No newline at end of file diff --git a/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs b/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs new file mode 100644 index 000000000..f24ff2ae6 --- /dev/null +++ b/NzbDrone.Core/Notifications/Xbmc/XbmcSettings.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Core.Annotations; + +namespace NzbDrone.Core.Notifications.Xbmc +{ + public class XbmcSettings : INotifcationSettings + { + [FieldDefinition(0, Label = "Host", HelpText = "XBMC Hostnname or IP")] + public String Host { get; set; } + + [FieldDefinition(1, Label = "Port", HelpText = "Webserver port")] + public Int32 Port { get; set; } + + [FieldDefinition(2, Label = "Username", HelpText = "Webserver Username")] + public String Username { get; set; } + + [FieldDefinition(3, Label = "Password", HelpText = "Webserver Password ")] + public String Password { get; set; } + + [FieldDefinition(4, Label = "Update Library", HelpText = "Update Library on Download & Rename?")] + public Boolean UpdateLibrary { get; set; } + + [FieldDefinition(5, Label = "Update Library", HelpText = "Clean Library after update?")] + public Boolean CleanLibrary { get; set; } + + [FieldDefinition(6, Label = "Always Update", HelpText = "Update Library even when a video is playing?")] + public Boolean AlwaysUpdate { get; set; } + + public bool IsValid + { + get + { + return !string.IsNullOrWhiteSpace(Host) && Port > 0; + } + } + } +} diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 4f070b805..a27d9a8cc 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -254,7 +254,12 @@ - + + + + + + @@ -282,7 +287,7 @@ - + @@ -307,6 +312,14 @@ + + + + + + + + @@ -417,25 +430,25 @@ Code - + Code - + Code - + Code - + Code - + Code - + Code - + Code @@ -459,11 +472,11 @@ Code - + Code - + Code @@ -479,19 +492,19 @@ Code - + Code - + Code - + Code - + Code - + diff --git a/NzbDrone.Core/Providers/SmtpProvider.cs b/NzbDrone.Core/Providers/SmtpProvider.cs deleted file mode 100644 index 4f8716ec8..000000000 --- a/NzbDrone.Core/Providers/SmtpProvider.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using System.Net.Mail; -using NLog; -using NzbDrone.Core.Configuration; - -namespace NzbDrone.Core.Providers -{ - public class SmtpProvider - { - private readonly IConfigService _configService; - private readonly Logger _logger; - - public SmtpProvider(IConfigService configService, Logger logger) - { - _configService = configService; - _logger = logger; - } - - public virtual void SendEmail(string subject, string body, bool htmlBody = false) - { - var email = new MailMessage(); - email.From = new MailAddress(_configService.SmtpFromAddress); - - foreach (var toAddress in _configService.SmtpToAddresses.Split(',')) - { - email.To.Add(toAddress.Trim()); - } - - email.Subject = subject; - email.Body = body; - email.IsBodyHtml = htmlBody; - - var username = _configService.SmtpUsername; - var password = _configService.SmtpPassword; - - NetworkCredential credentials = null; - - if (!String.IsNullOrWhiteSpace(username)) - credentials = new NetworkCredential(username, password); - - try - { - Send(email, _configService.SmtpServer, _configService.SmtpPort, _configService.SmtpUseSsl, credentials); - } - catch(Exception ex) - { - _logger.Error("Error sending email. Subject: {0}", email.Subject); - _logger.TraceException(ex.Message, ex); - } - } - - public virtual bool SendTestEmail(string server, int port, bool ssl, string username, string password, string fromAddress, string toAddresses) - { - var subject = "NzbDrone SMTP Test Notification"; - var body = "This is a test email from NzbDrone, if you received this message you properly configured your SMTP settings! (Now save them!)"; - - var email = new MailMessage(); - - email.From = new MailAddress(fromAddress); - - foreach (var toAddress in toAddresses.Split(',')) - { - email.To.Add(toAddress.Trim()); - } - - email.Subject = subject; - - email.Body = body; - - email.IsBodyHtml = false; - - NetworkCredential credentials = null; - - if (!String.IsNullOrWhiteSpace(username)) - credentials = new NetworkCredential(username, password); - - try - { - Send(email, server, port, ssl, credentials); - } - catch(Exception ex) - { - _logger.TraceException("Failed to send test email", ex); - return false; - } - return true; - } - - public virtual void Send(MailMessage email, string server, int port, bool ssl, NetworkCredential credentials) - { - try - { - var smtp = new SmtpClient(server, port); - - smtp.EnableSsl = ssl; - - smtp.Credentials = credentials; - - smtp.Send(email); - } - - catch (Exception ex) - { - _logger.ErrorException("There was an error sending an email.", ex); - throw; - } - } - } -} diff --git a/NzbDrone/MainAppContainerBuilder.cs b/NzbDrone/MainAppContainerBuilder.cs index 53c14de48..ab60ffd0a 100644 --- a/NzbDrone/MainAppContainerBuilder.cs +++ b/NzbDrone/MainAppContainerBuilder.cs @@ -6,7 +6,7 @@ using NzbDrone.Api.SignalR; using NzbDrone.Common; using NzbDrone.Common.Composition; using NzbDrone.Core.Datastore; -using NzbDrone.Core.ExternalNotification; +using NzbDrone.Core.Notifications; using NzbDrone.Core.Organizer; using NzbDrone.Core.RootFolders; @@ -25,7 +25,7 @@ namespace NzbDrone private MainAppContainerBuilder() : base("NzbDrone", "NzbDrone.Common", "NzbDrone.Core", "NzbDrone.Api") { - AutoRegisterImplementations(); + AutoRegisterImplementations(); AutoRegisterImplementations(); Container.Register(typeof(IBasicRepository), typeof(BasicRepository)); diff --git a/UI/Form/CheckboxTemplate.html b/UI/Form/CheckboxTemplate.html new file mode 100644 index 000000000..3c155e43f --- /dev/null +++ b/UI/Form/CheckboxTemplate.html @@ -0,0 +1,19 @@ +
+ + +
+ + + + + +
+
\ No newline at end of file diff --git a/UI/Form/TextboxTemplate.html b/UI/Form/TextboxTemplate.html new file mode 100644 index 000000000..c5466fd98 --- /dev/null +++ b/UI/Form/TextboxTemplate.html @@ -0,0 +1,10 @@ +
+ + +
+ + + + +
+
\ No newline at end of file diff --git a/UI/Mixins/handlebars.mixin.js b/UI/Mixins/handlebars.mixin.js index dcbfd488a..838136c52 100644 --- a/UI/Mixins/handlebars.mixin.js +++ b/UI/Mixins/handlebars.mixin.js @@ -7,6 +7,14 @@ Handlebars.registerHelper('partial', function (templateName) { return new Handlebars.SafeString(templateFunction(this)); }); +Handlebars.registerHelper('formField', function () { + if (!this.type) { + return Handlebars.helpers.partial.apply(this, ['Form/TextboxTemplate']); + } + + return Handlebars.helpers.partial.apply(this, ['Form/TextboxTemplate']); +}); + Handlebars.registerHelper("debug", function(optionalValue) { console.log("Current Context"); console.log("===================="); diff --git a/UI/Settings/Indexers/ItemTemplate.html b/UI/Settings/Indexers/ItemTemplate.html index 3cc96a821..c3461c4f1 100644 --- a/UI/Settings/Indexers/ItemTemplate.html +++ b/UI/Settings/Indexers/ItemTemplate.html @@ -22,15 +22,6 @@ {{#each fields}} -
- - -
- - - - -
-
+ {{formField}} {{/each}}