From 606d78f5e14af5afd806471c3b46222d39fabf18 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Thu, 13 Feb 2014 21:31:49 -0800 Subject: [PATCH] Download clients now use thingy provider --- .../DownloadClient/DownloadClientModule.cs | 18 ++ .../DownloadClient/DownloadClientResource.cs | 10 + .../DownloadClientSchemaModule.cs | 37 +++ src/NzbDrone.Api/NzbDrone.Api.csproj | 5 +- .../Configuration/ConfigServiceFixture.cs | 10 - .../HistorySpecificationFixture.cs | 2 +- .../NotInQueueSpecificationFixture.cs | 3 - .../BlackholeProviderFixture.cs | 14 +- .../DownloadNzbFixture.cs | 29 +- .../QueueFixture.cs | 30 ++- .../PneumaticProviderFixture.cs | 11 +- .../SabProviderTests/SabProviderFixture.cs | 191 ------------- .../SabnzbdTests/SabnzbdFixture.cs | 104 ++++++++ .../Download/DownloadServiceFixture.cs | 7 +- .../Files/Categories_json.txt | 25 -- .../NzbDrone.Core.Test.csproj | 9 +- .../Annotations/FieldDefinitionAttribute.cs | 3 +- .../Configuration/ConfigService.cs | 131 --------- .../Configuration/IConfigService.cs | 22 -- .../041_add_download_clients_table.cs | 20 ++ .../042_convert_config_to_download_clients.cs | 198 ++++++++++++++ src/NzbDrone.Core/Datastore/TableMapping.cs | 2 + .../Specifications/NotInQueueSpecification.cs | 5 +- .../RssSync/HistorySpecification.cs | 2 +- .../Download/Clients/Blackhole/Blackhole.cs | 69 +++++ .../Clients/Blackhole/TestBlackholeCommand.cs | 18 ++ .../Download/Clients/BlackholeProvider.cs | 68 ----- .../Download/Clients/FolderSettings.cs | 29 ++ .../Download/Clients/Nzbget/NzbGetQueue.cs | 4 +- .../Clients/Nzbget/NzbGetQueueItem.cs | 5 +- .../Download/Clients/Nzbget/Nzbget.cs | 96 +++++++ .../Download/Clients/Nzbget/NzbgetClient.cs | 136 ---------- .../{PriorityType.cs => NzbgetPriority.cs} | 2 +- ...etCommunicationProxy.cs => NzbgetProxy.cs} | 43 ++- .../Download/Clients/Nzbget/NzbgetSettings.cs | 59 +++++ .../Clients/Nzbget/TestNzbgetCommand.cs | 21 ++ .../{VersionModel.cs => VersionResponse.cs} | 2 +- .../Pneumatic.cs} | 29 +- .../Clients/Pneumatic/TestPneumaticCommand.cs | 18 ++ .../Clients/Sabnzbd/ConnectionInfoModel.cs | 8 - .../SabnzbdPriorityTypeConverter.cs | 6 +- .../Sabnzbd/Responses/SabnzbdAddResponse.cs | 18 ++ .../Responses/SabnzbdCategoryResponse.cs | 15 ++ .../Responses/SabnzbdVersionResponse.cs | 7 + .../Clients/Sabnzbd/SabAddResponse.cs | 19 -- .../Sabnzbd/SabAutoConfigureService.cs | 100 ------- .../Clients/Sabnzbd/SabCategoryModel.cs | 9 - .../Clients/Sabnzbd/SabCommunicationProxy.cs | 130 --------- .../Download/Clients/Sabnzbd/SabModel.cs | 9 - .../Clients/Sabnzbd/SabVersionModel.cs | 7 - .../Download/Clients/Sabnzbd/Sabnzbd.cs | 133 ++++++++++ .../Download/Clients/Sabnzbd/SabnzbdClient.cs | 250 ------------------ .../{SabQueue.cs => SabnzbdHistory.cs} | 4 +- ...abHistoryItem.cs => SabnzbdHistoryItem.cs} | 2 +- .../{SabJsonError.cs => SabnzbdJsonError.cs} | 2 +- ...{SabPriorityType.cs => SabnzbdPriority.cs} | 2 +- .../Download/Clients/Sabnzbd/SabnzbdProxy.cs | 182 +++++++++++++ .../{SabHistory.cs => SabnzbdQueue.cs} | 4 +- .../{SabQueueItem.cs => SabnzbdQueueItem.cs} | 4 +- .../Clients/Sabnzbd/SabnzbdSettings.cs | 66 +++++ .../Clients/Sabnzbd/TestSabnzbdCommand.cs | 23 ++ .../Download/DownloadClientBase.cs | 48 ++++ .../Download/DownloadClientDefinition.cs | 12 + .../Download/DownloadClientFactory.cs | 29 ++ .../Download/DownloadClientProvider.cs | 38 +-- .../Download/DownloadClientRepository.cs | 20 ++ src/NzbDrone.Core/Download/DownloadService.cs | 4 +- .../Download/Events/DownloadFailedEvent.cs | 18 ++ .../Download/Events/EpisodeGrabbedEvent.cs | 18 ++ src/NzbDrone.Core/Download/IDownloadClient.cs | 4 +- src/NzbDrone.Core/Indexers/IndexerBase.cs | 4 +- src/NzbDrone.Core/MetaData/MetadataService.cs | 9 +- src/NzbDrone.Core/NzbDrone.Core.csproj | 56 ++-- src/NzbDrone.Core/Queue/QueueService.cs | 7 + src/NzbDrone.Core/Tv/SeriesService.cs | 2 + src/UI/.idea/jsLinters/jshint.xml | 4 +- src/UI/Form/FormBuilder.js | 7 + src/UI/Form/PathTemplate.html | 12 + .../Add/DownloadClientAddCollectionView.js | 23 ++ ...wnloadClientAddCollectionViewTemplate.html | 12 + .../Add/DownloadClientAddItemView.js | 38 +++ .../DownloadClientAddItemViewTemplate.html | 10 + .../DownloadClient/Add/SchemaModal.js | 20 ++ .../Settings/DownloadClient/BlackholeView.js | 24 -- .../DownloadClient/BlackholeViewTemplate.html | 13 - .../Delete/DownloadClientDeleteView.js | 23 ++ .../DownloadClientDeleteViewTemplate.html | 11 + .../DownloadClientCollection.js | 12 + .../DownloadClientCollectionView.js | 31 +++ .../DownloadClientCollectionViewTemplate.html | 16 ++ .../DownloadClient/DownloadClientItemView.js | 34 +++ .../DownloadClientItemViewTemplate.html | 17 ++ .../DownloadClient/DownloadClientLayout.js | 40 +++ .../DownloadClientLayoutTemplate.html | 16 ++ .../DownloadClient/DownloadClientModel.js | 10 + .../Edit/DownloadClientEditView.js | 93 +++++++ .../Edit/DownloadClientEditViewTemplate.html | 59 +++++ src/UI/Settings/DownloadClient/Layout.js | 78 ------ .../DownloadClient/LayoutTemplate.html | 29 -- src/UI/Settings/DownloadClient/NzbgetView.js | 15 -- .../DownloadClient/NzbgetViewTemplate.html | 86 ------ .../Settings/DownloadClient/PneumaticView.js | 24 -- .../DownloadClient/PneumaticViewTemplate.html | 13 - src/UI/Settings/DownloadClient/SabView.js | 15 -- .../DownloadClient/SabViewTemplate.html | 120 --------- .../DownloadClient/downloadclient.less | 27 ++ .../Settings/Indexers/CollectionTemplate.html | 2 +- src/UI/Settings/Indexers/CollectionView.js | 11 +- src/UI/Settings/Indexers/ItemTemplate.html | 2 +- src/UI/Settings/Indexers/indexers.less | 20 -- .../Notifications/AddItemTemplate.html | 2 +- .../Settings/Notifications/AddTemplate.html | 2 +- .../Notifications/CollectionTemplate.html | 4 +- .../Settings/Notifications/ItemTemplate.html | 2 +- .../Notifications/NotificationEditView.js | 4 +- src/UI/Settings/Notifications/SchemaModal.js | 10 +- .../Settings/Notifications/notifications.less | 55 +--- .../QualityProfileCollectionTemplate.html | 4 +- .../Profile/QualityProfileViewTemplate.html | 2 +- src/UI/Settings/Quality/quality.less | 19 -- src/UI/Settings/SettingsLayout.js | 2 +- src/UI/Settings/settings.less | 2 + src/UI/Settings/thingy.less | 65 +++++ 123 files changed, 2076 insertions(+), 1820 deletions(-) create mode 100644 src/NzbDrone.Api/DownloadClient/DownloadClientModule.cs create mode 100644 src/NzbDrone.Api/DownloadClient/DownloadClientResource.cs create mode 100644 src/NzbDrone.Api/DownloadClient/DownloadClientSchemaModule.cs rename src/NzbDrone.Core.Test/Download/DownloadClientTests/{NzbgetProviderTests => NzbgetTests}/DownloadNzbFixture.cs (63%) rename src/NzbDrone.Core.Test/Download/DownloadClientTests/{NzbgetProviderTests => NzbgetTests}/QueueFixture.cs (63%) delete mode 100644 src/NzbDrone.Core.Test/Download/DownloadClientTests/SabProviderTests/SabProviderFixture.cs create mode 100644 src/NzbDrone.Core.Test/Download/DownloadClientTests/SabnzbdTests/SabnzbdFixture.cs delete mode 100644 src/NzbDrone.Core.Test/Files/Categories_json.txt create mode 100644 src/NzbDrone.Core/Datastore/Migration/041_add_download_clients_table.cs create mode 100644 src/NzbDrone.Core/Datastore/Migration/042_convert_config_to_download_clients.cs create mode 100644 src/NzbDrone.Core/Download/Clients/Blackhole/Blackhole.cs create mode 100644 src/NzbDrone.Core/Download/Clients/Blackhole/TestBlackholeCommand.cs delete mode 100644 src/NzbDrone.Core/Download/Clients/BlackholeProvider.cs create mode 100644 src/NzbDrone.Core/Download/Clients/FolderSettings.cs create mode 100644 src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs delete mode 100644 src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetClient.cs rename src/NzbDrone.Core/Download/Clients/Nzbget/{PriorityType.cs => NzbgetPriority.cs} (84%) rename src/NzbDrone.Core/Download/Clients/Nzbget/{NzbGetCommunicationProxy.cs => NzbgetProxy.cs} (60%) create mode 100644 src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetSettings.cs create mode 100644 src/NzbDrone.Core/Download/Clients/Nzbget/TestNzbgetCommand.cs rename src/NzbDrone.Core/Download/Clients/Nzbget/{VersionModel.cs => VersionResponse.cs} (83%) rename src/NzbDrone.Core/Download/Clients/{PneumaticClient.cs => Pneumatic/Pneumatic.cs} (63%) create mode 100644 src/NzbDrone.Core/Download/Clients/Pneumatic/TestPneumaticCommand.cs delete mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/ConnectionInfoModel.cs create mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdAddResponse.cs create mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdCategoryResponse.cs create mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdVersionResponse.cs delete mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/SabAddResponse.cs delete mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/SabAutoConfigureService.cs delete mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/SabCategoryModel.cs delete mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/SabCommunicationProxy.cs delete mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/SabModel.cs delete mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/SabVersionModel.cs create mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs delete mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdClient.cs rename src/NzbDrone.Core/Download/Clients/Sabnzbd/{SabQueue.cs => SabnzbdHistory.cs} (70%) rename src/NzbDrone.Core/Download/Clients/Sabnzbd/{SabHistoryItem.cs => SabnzbdHistoryItem.cs} (95%) rename src/NzbDrone.Core/Download/Clients/Sabnzbd/{SabJsonError.cs => SabnzbdJsonError.cs} (92%) rename src/NzbDrone.Core/Download/Clients/Sabnzbd/{SabPriorityType.cs => SabnzbdPriority.cs} (84%) create mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdProxy.cs rename src/NzbDrone.Core/Download/Clients/Sabnzbd/{SabHistory.cs => SabnzbdQueue.cs} (70%) rename src/NzbDrone.Core/Download/Clients/Sabnzbd/{SabQueueItem.cs => SabnzbdQueueItem.cs} (91%) create mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdSettings.cs create mode 100644 src/NzbDrone.Core/Download/Clients/Sabnzbd/TestSabnzbdCommand.cs create mode 100644 src/NzbDrone.Core/Download/DownloadClientBase.cs create mode 100644 src/NzbDrone.Core/Download/DownloadClientDefinition.cs create mode 100644 src/NzbDrone.Core/Download/DownloadClientFactory.cs create mode 100644 src/NzbDrone.Core/Download/DownloadClientRepository.cs create mode 100644 src/NzbDrone.Core/Download/Events/DownloadFailedEvent.cs create mode 100644 src/NzbDrone.Core/Download/Events/EpisodeGrabbedEvent.cs create mode 100644 src/UI/Form/PathTemplate.html create mode 100644 src/UI/Settings/DownloadClient/Add/DownloadClientAddCollectionView.js create mode 100644 src/UI/Settings/DownloadClient/Add/DownloadClientAddCollectionViewTemplate.html create mode 100644 src/UI/Settings/DownloadClient/Add/DownloadClientAddItemView.js create mode 100644 src/UI/Settings/DownloadClient/Add/DownloadClientAddItemViewTemplate.html create mode 100644 src/UI/Settings/DownloadClient/Add/SchemaModal.js delete mode 100644 src/UI/Settings/DownloadClient/BlackholeView.js delete mode 100644 src/UI/Settings/DownloadClient/BlackholeViewTemplate.html create mode 100644 src/UI/Settings/DownloadClient/Delete/DownloadClientDeleteView.js create mode 100644 src/UI/Settings/DownloadClient/Delete/DownloadClientDeleteViewTemplate.html create mode 100644 src/UI/Settings/DownloadClient/DownloadClientCollection.js create mode 100644 src/UI/Settings/DownloadClient/DownloadClientCollectionView.js create mode 100644 src/UI/Settings/DownloadClient/DownloadClientCollectionViewTemplate.html create mode 100644 src/UI/Settings/DownloadClient/DownloadClientItemView.js create mode 100644 src/UI/Settings/DownloadClient/DownloadClientItemViewTemplate.html create mode 100644 src/UI/Settings/DownloadClient/DownloadClientLayout.js create mode 100644 src/UI/Settings/DownloadClient/DownloadClientLayoutTemplate.html create mode 100644 src/UI/Settings/DownloadClient/DownloadClientModel.js create mode 100644 src/UI/Settings/DownloadClient/Edit/DownloadClientEditView.js create mode 100644 src/UI/Settings/DownloadClient/Edit/DownloadClientEditViewTemplate.html delete mode 100644 src/UI/Settings/DownloadClient/Layout.js delete mode 100644 src/UI/Settings/DownloadClient/LayoutTemplate.html delete mode 100644 src/UI/Settings/DownloadClient/NzbgetView.js delete mode 100644 src/UI/Settings/DownloadClient/NzbgetViewTemplate.html delete mode 100644 src/UI/Settings/DownloadClient/PneumaticView.js delete mode 100644 src/UI/Settings/DownloadClient/PneumaticViewTemplate.html delete mode 100644 src/UI/Settings/DownloadClient/SabView.js delete mode 100644 src/UI/Settings/DownloadClient/SabViewTemplate.html create mode 100644 src/UI/Settings/DownloadClient/downloadclient.less create mode 100644 src/UI/Settings/thingy.less diff --git a/src/NzbDrone.Api/DownloadClient/DownloadClientModule.cs b/src/NzbDrone.Api/DownloadClient/DownloadClientModule.cs new file mode 100644 index 000000000..cdef47a78 --- /dev/null +++ b/src/NzbDrone.Api/DownloadClient/DownloadClientModule.cs @@ -0,0 +1,18 @@ +using NzbDrone.Core.Download; + +namespace NzbDrone.Api.DownloadClient +{ + public class DownloadClientModule : ProviderModuleBase + { + public DownloadClientModule(IDownloadClientFactory downloadClientFactory) + : base(downloadClientFactory, "downloadclient") + { + } + + protected override void Validate(DownloadClientDefinition definition) + { + if (!definition.Enable) return; + base.Validate(definition); + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Api/DownloadClient/DownloadClientResource.cs b/src/NzbDrone.Api/DownloadClient/DownloadClientResource.cs new file mode 100644 index 000000000..cb1054168 --- /dev/null +++ b/src/NzbDrone.Api/DownloadClient/DownloadClientResource.cs @@ -0,0 +1,10 @@ +using System; + +namespace NzbDrone.Api.DownloadClient +{ + public class DownloadClientResource : ProviderResource + { + public Boolean Enable { get; set; } + public Int32 Protocol { get; set; } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Api/DownloadClient/DownloadClientSchemaModule.cs b/src/NzbDrone.Api/DownloadClient/DownloadClientSchemaModule.cs new file mode 100644 index 000000000..58c1a2149 --- /dev/null +++ b/src/NzbDrone.Api/DownloadClient/DownloadClientSchemaModule.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using NzbDrone.Api.ClientSchema; +using NzbDrone.Core.Download; +using Omu.ValueInjecter; + +namespace NzbDrone.Api.DownloadClient +{ + public class DownloadClientSchemaModule : NzbDroneRestModule + { + private readonly IDownloadClientFactory _notificationFactory; + + public DownloadClientSchemaModule(IDownloadClientFactory notificationFactory) + : base("downloadclient/schema") + { + _notificationFactory = notificationFactory; + GetResourceAll = GetSchema; + } + + private List GetSchema() + { + var notifications = _notificationFactory.Templates(); + + var result = new List(notifications.Count); + + foreach (var notification in notifications) + { + var notificationResource = new DownloadClientResource(); + notificationResource.InjectFrom(notification); + notificationResource.Fields = SchemaBuilder.ToSchema(notification.Settings); + + result.Add(notificationResource); + } + + return result; + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Api/NzbDrone.Api.csproj b/src/NzbDrone.Api/NzbDrone.Api.csproj index bda4694cc..04dd817d4 100644 --- a/src/NzbDrone.Api/NzbDrone.Api.csproj +++ b/src/NzbDrone.Api/NzbDrone.Api.csproj @@ -94,6 +94,8 @@ + + @@ -122,6 +124,7 @@ + @@ -145,7 +148,7 @@ - + diff --git a/src/NzbDrone.Core.Test/Configuration/ConfigServiceFixture.cs b/src/NzbDrone.Core.Test/Configuration/ConfigServiceFixture.cs index aaf562c7f..35caa1216 100644 --- a/src/NzbDrone.Core.Test/Configuration/ConfigServiceFixture.cs +++ b/src/NzbDrone.Core.Test/Configuration/ConfigServiceFixture.cs @@ -105,16 +105,6 @@ namespace NzbDrone.Core.Test.Configuration Subject.GetValue(key, value2).Should().Be(value2); } - [Test] - public void updating_a_vakye_should_update_its_value() - { - Subject.SabHost = "Test"; - Subject.SabHost.Should().Be("Test"); - - Subject.SabHost = "Test2"; - Subject.SabHost.Should().Be("Test2"); - } - [Test] [Description("This test will use reflection to ensure each config property read/writes to a unique key")] public void config_properties_should_write_and_read_using_same_key() diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/HistorySpecificationFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/HistorySpecificationFixture.cs index 54c8ff6e0..48710e6f9 100644 --- a/src/NzbDrone.Core.Test/DecisionEngineTests/HistorySpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/DecisionEngineTests/HistorySpecificationFixture.cs @@ -83,7 +83,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests private void GivenSabnzbdDownloadClient() { Mocker.GetMock() - .Setup(c => c.GetDownloadClient()).Returns(Mocker.Resolve()); + .Setup(c => c.GetDownloadClient()).Returns(Mocker.Resolve()); } private void GivenMostRecentForEpisode(HistoryEventType eventType) diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/NotInQueueSpecificationFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/NotInQueueSpecificationFixture.cs index baa24d5b4..4a3be3627 100644 --- a/src/NzbDrone.Core.Test/DecisionEngineTests/NotInQueueSpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/DecisionEngineTests/NotInQueueSpecificationFixture.cs @@ -56,9 +56,6 @@ namespace NzbDrone.Core.Test.DecisionEngineTests Mocker.GetMock() .Setup(s => s.GetDownloadClient()) .Returns(_downloadClient.Object); - - _downloadClient.SetupGet(s => s.IsConfigured) - .Returns(true); } private void GivenEmptyQueue() diff --git a/src/NzbDrone.Core.Test/Download/DownloadClientTests/BlackholeProviderFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadClientTests/BlackholeProviderFixture.cs index 2b0639019..9f1c9d317 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadClientTests/BlackholeProviderFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadClientTests/BlackholeProviderFixture.cs @@ -4,8 +4,9 @@ using Moq; using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Common.Disk; -using NzbDrone.Core.Configuration; +using NzbDrone.Core.Download; using NzbDrone.Core.Download.Clients; +using NzbDrone.Core.Download.Clients.Blackhole; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common; @@ -13,7 +14,7 @@ using NzbDrone.Test.Common; namespace NzbDrone.Core.Test.Download.DownloadClientTests { [TestFixture] - public class BlackholeProviderFixture : CoreTest + public class BlackholeProviderFixture : CoreTest { private const string _nzbUrl = "http://www.nzbs.com/url"; private const string _title = "some_nzb_title"; @@ -27,13 +28,16 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests _blackHoleFolder = @"c:\nzb\blackhole\".AsOsAgnostic(); _nzbPath = @"c:\nzb\blackhole\some_nzb_title.nzb".AsOsAgnostic(); - - Mocker.GetMock().SetupGet(c => c.BlackholeFolder).Returns(_blackHoleFolder); - _remoteEpisode = new RemoteEpisode(); _remoteEpisode.Release = new ReleaseInfo(); _remoteEpisode.Release.Title = _title; _remoteEpisode.Release.DownloadUrl = _nzbUrl; + + Subject.Definition = new DownloadClientDefinition(); + Subject.Definition.Settings = new FolderSettings + { + Folder = _blackHoleFolder + }; } private void WithExistingFile() diff --git a/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetProviderTests/DownloadNzbFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetTests/DownloadNzbFixture.cs similarity index 63% rename from src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetProviderTests/DownloadNzbFixture.cs rename to src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetTests/DownloadNzbFixture.cs index 397eb531a..b0c8d2efb 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetProviderTests/DownloadNzbFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetTests/DownloadNzbFixture.cs @@ -3,17 +3,15 @@ using System.Linq; using FizzWare.NBuilder; using Moq; using NUnit.Framework; -using NzbDrone.Common; -using NzbDrone.Common.Serializer; -using NzbDrone.Core.Configuration; +using NzbDrone.Core.Download; using NzbDrone.Core.Download.Clients.Nzbget; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Tv; -namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetProviderTests +namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests { - public class DownloadNzbFixture : CoreTest + public class DownloadNzbFixture : CoreTest { private const string _url = "http://www.nzbdrone.com"; private const string _title = "30.Rock.S01E01.Pilot.720p.hdtv"; @@ -32,6 +30,17 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetProviderTests .With(e => e.AirDate = DateTime.Today.ToString(Episode.AIR_DATE_FORMAT)) .Build() .ToList(); + + Subject.Definition = new DownloadClientDefinition(); + Subject.Definition.Settings = new NzbgetSettings + { + Host = "localhost", + Port = 6789, + Username = "nzbget", + Password = "pass", + TvCategory = "tv", + RecentTvPriority = (int)NzbgetPriority.High + }; } [Test] @@ -39,14 +48,14 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetProviderTests { var p = new object[] {"30.Rock.S01E01.Pilot.720p.hdtv.nzb", "TV", 50, false, "http://www.nzbdrone.com"}; - Mocker.GetMock() - .Setup(s => s.AddNzb(p)) + Mocker.GetMock() + .Setup(s => s.AddNzb(It.IsAny(), p)) .Returns(true); - Mocker.Resolve().DownloadNzb(_remoteEpisode); + Subject.DownloadNzb(_remoteEpisode); - Mocker.GetMock() - .Verify(v => v.AddNzb(It.IsAny()), Times.Once()); + Mocker.GetMock() + .Verify(v => v.AddNzb(It.IsAny(), It.IsAny()), Times.Once()); } } } diff --git a/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetProviderTests/QueueFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetTests/QueueFixture.cs similarity index 63% rename from src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetProviderTests/QueueFixture.cs rename to src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetTests/QueueFixture.cs index a152e9cdf..4fbbbad74 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetProviderTests/QueueFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetTests/QueueFixture.cs @@ -5,40 +5,52 @@ using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.Download; using NzbDrone.Core.Download.Clients.Nzbget; using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Tv; -namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetProviderTests +namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests { - public class QueueFixture : CoreTest + public class QueueFixture : CoreTest { - private List _queue; + private List _queue; [SetUp] public void Setup() { - _queue = Builder.CreateListOfSize(5) + _queue = Builder.CreateListOfSize(5) .All() .With(q => q.NzbName = "30.Rock.S01E01.Pilot.720p.hdtv.nzb") .Build() .ToList(); + + Subject.Definition = new DownloadClientDefinition(); + Subject.Definition.Settings = new NzbgetSettings + { + Host = "localhost", + Port = 6789, + Username = "nzbget", + Password = "pass", + TvCategory = "tv", + RecentTvPriority = (int)NzbgetPriority.High + }; } private void WithFullQueue() { - Mocker.GetMock() - .Setup(s => s.GetQueue()) + Mocker.GetMock() + .Setup(s => s.GetQueue(It.IsAny())) .Returns(_queue); } private void WithEmptyQueue() { - Mocker.GetMock() - .Setup(s => s.GetQueue()) - .Returns(new List()); + Mocker.GetMock() + .Setup(s => s.GetQueue(It.IsAny())) + .Returns(new List()); } [Test] diff --git a/src/NzbDrone.Core.Test/Download/DownloadClientTests/PneumaticProviderFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadClientTests/PneumaticProviderFixture.cs index dfb27a5f7..3d564a69f 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadClientTests/PneumaticProviderFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadClientTests/PneumaticProviderFixture.cs @@ -6,7 +6,9 @@ using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Common.Disk; using NzbDrone.Core.Configuration; +using NzbDrone.Core.Download; using NzbDrone.Core.Download.Clients; +using NzbDrone.Core.Download.Clients.Pneumatic; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common; @@ -14,7 +16,7 @@ using NzbDrone.Test.Common; namespace NzbDrone.Core.Test.Download.DownloadClientTests { [TestFixture] - public class PneumaticProviderFixture : CoreTest + public class PneumaticProviderFixture : CoreTest { private const string _nzbUrl = "http://www.nzbs.com/url"; private const string _title = "30.Rock.S01E05.hdtv.xvid-LoL"; @@ -31,7 +33,6 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests _nzbPath = Path.Combine(_pneumaticFolder, _title + ".nzb").AsOsAgnostic(); _sabDrop = @"d:\unsorted tv\".AsOsAgnostic(); - Mocker.GetMock().SetupGet(c => c.PneumaticFolder).Returns(_pneumaticFolder); Mocker.GetMock().SetupGet(c => c.DownloadedEpisodesFolder).Returns(_sabDrop); _remoteEpisode = new RemoteEpisode(); @@ -41,6 +42,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests _remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo(); _remoteEpisode.ParsedEpisodeInfo.FullSeason = false; + + Subject.Definition = new DownloadClientDefinition(); + Subject.Definition.Settings = new FolderSettings + { + Folder = _pneumaticFolder + }; } private void WithExistingFile() diff --git a/src/NzbDrone.Core.Test/Download/DownloadClientTests/SabProviderTests/SabProviderFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadClientTests/SabProviderTests/SabProviderFixture.cs deleted file mode 100644 index 9c4943ace..000000000 --- a/src/NzbDrone.Core.Test/Download/DownloadClientTests/SabProviderTests/SabProviderFixture.cs +++ /dev/null @@ -1,191 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using FizzWare.NBuilder; -using FluentAssertions; -using Moq; -using NUnit.Framework; -using NzbDrone.Common; -using NzbDrone.Core.Configuration; -using NzbDrone.Core.Download.Clients.Sabnzbd; -using NzbDrone.Core.Parser.Model; -using NzbDrone.Core.Test.Framework; -using NzbDrone.Core.Tv; - -namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabProviderTests -{ - [TestFixture] - - public class SabProviderFixture : CoreTest - { - private const string URL = "http://www.nzbclub.com/nzb_download.aspx?mid=1950232"; - private const string TITLE = "My Series Name - 5x2-5x3 - My title [Bluray720p] [Proper]"; - private RemoteEpisode _remoteEpisode; - - [SetUp] - public void Setup() - { - var fakeConfig = Mocker.GetMock(); - - fakeConfig.SetupGet(c => c.SabHost).Returns("192.168.5.55"); - fakeConfig.SetupGet(c => c.SabPort).Returns(2222); - fakeConfig.SetupGet(c => c.SabApiKey).Returns("5c770e3197e4fe763423ee7c392c25d1"); - fakeConfig.SetupGet(c => c.SabUsername).Returns("admin"); - fakeConfig.SetupGet(c => c.SabPassword).Returns("pass"); - fakeConfig.SetupGet(c => c.SabTvCategory).Returns("tv"); - - _remoteEpisode = new RemoteEpisode(); - _remoteEpisode.Release = new ReleaseInfo(); - _remoteEpisode.Release.Title = TITLE; - _remoteEpisode.Release.DownloadUrl = URL; - - _remoteEpisode.Episodes = Builder.CreateListOfSize(1) - .All() - .With(e => e.AirDate = DateTime.Today.ToString(Episode.AIR_DATE_FORMAT)) - .Build() - .ToList(); - } - - [Test] - public void should_be_able_to_get_categories_when_config_is_passed_in() - { - - const string host = "192.168.5.22"; - const int port = 1111; - const string apikey = "5c770e3197e4fe763423ee7c392c25d2"; - const string username = "admin2"; - const string password = "pass2"; - - Mocker.GetMock(MockBehavior.Strict) - .Setup(s => s.DownloadString("http://192.168.5.22:1111/api?mode=get_cats&output=json&apikey=5c770e3197e4fe763423ee7c392c25d2&ma_username=admin2&ma_password=pass2")) - .Returns(ReadAllText("Files", "Categories_json.txt")); - - var result = Subject.GetCategories(host, port, apikey, username, password); - - - result.Should().NotBeNull(); - result.categories.Should().NotBeEmpty(); - } - - [Test] - public void should_be_able_to_get_categories_using_config() - { - Mocker.GetMock(MockBehavior.Strict) - .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=get_cats&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(ReadAllText("Files", "Categories_json.txt")); - - - var result = Subject.GetCategories(); - - - result.Should().NotBeNull(); - result.categories.Should().NotBeEmpty(); - } - - [Test] - public void GetHistory_should_return_a_list_with_items_when_the_history_has_items() - { - Mocker.GetMock() - .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(ReadAllText("Files", "History.txt")); - - - var result = Subject.GetHistory(); - - - result.Should().HaveCount(1); - } - - [Test] - public void GetHistory_should_return_an_empty_list_when_the_queue_is_empty() - { - Mocker.GetMock() - .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(ReadAllText("Files", "HistoryEmpty.txt")); - - - var result = Subject.GetHistory(); - - - result.Should().BeEmpty(); - } - - [Test] - public void GetHistory_should_return_an_empty_list_when_there_is_an_error_getting_the_queue() - { - Mocker.GetMock() - .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(ReadAllText("Files", "JsonError.txt")); - - - Assert.Throws(() => Subject.GetHistory(), "API Key Incorrect"); - } - - [Test] - public void GetVersion_should_return_the_version_using_passed_in_values() - { - var response = "{ \"version\": \"0.6.9\" }"; - - Mocker.GetMock() - .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=version&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(response); - - - var result = Subject.GetVersion("192.168.5.55", 2222, "5c770e3197e4fe763423ee7c392c25d1", "admin", "pass"); - - - result.Should().NotBeNull(); - result.Version.Should().Be("0.6.9"); - } - - [Test] - public void GetVersion_should_return_the_version_using_saved_values() - { - var response = "{ \"version\": \"0.6.9\" }"; - - Mocker.GetMock() - .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=version&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(response); - - - var result = Subject.GetVersion(); - - - result.Should().NotBeNull(); - result.Version.Should().Be("0.6.9"); - } - - [Test] - public void Test_should_return_version_as_a_string() - { - const string response = "{ \"version\": \"0.6.9\" }"; - - Mocker.GetMock() - .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=version&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) - .Returns(response); - - - var result = Subject.Test("192.168.5.55", 2222, "5c770e3197e4fe763423ee7c392c25d1", "admin", "pass"); - - - result.Should().Be("0.6.9"); - } - - [Test] - public void downloadNzb_should_use_sabRecentTvPriority_when_recentEpisode_is_true() - { - Mocker.GetMock() - .SetupGet(s => s.SabRecentTvPriority) - .Returns(SabPriorityType.High); - - Mocker.GetMock() - .Setup(s => s.DownloadNzb(It.IsAny(), It.IsAny(), It.IsAny(), (int)SabPriorityType.High)) - .Returns(new SabAddResponse()); - - Subject.DownloadNzb(_remoteEpisode); - - Mocker.GetMock() - .Verify(v => v.DownloadNzb(It.IsAny(), It.IsAny(), It.IsAny(), (int)SabPriorityType.High), Times.Once()); - } - } -} diff --git a/src/NzbDrone.Core.Test/Download/DownloadClientTests/SabnzbdTests/SabnzbdFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadClientTests/SabnzbdTests/SabnzbdFixture.cs new file mode 100644 index 000000000..8b05eac12 --- /dev/null +++ b/src/NzbDrone.Core.Test/Download/DownloadClientTests/SabnzbdTests/SabnzbdFixture.cs @@ -0,0 +1,104 @@ +using System; +using System.IO; +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using Moq; +using NUnit.Framework; +using NzbDrone.Common; +using NzbDrone.Core.Download; +using NzbDrone.Core.Download.Clients.Sabnzbd; +using NzbDrone.Core.Download.Clients.Sabnzbd.Responses; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests +{ + [TestFixture] + public class SabnzbdFixture : CoreTest + { + private const string URL = "http://www.nzbclub.com/nzb_download.aspx?mid=1950232"; + private const string TITLE = "My Series Name - 5x2-5x3 - My title [Bluray720p] [Proper]"; + private RemoteEpisode _remoteEpisode; + + [SetUp] + public void Setup() + { + _remoteEpisode = new RemoteEpisode(); + _remoteEpisode.Release = new ReleaseInfo(); + _remoteEpisode.Release.Title = TITLE; + _remoteEpisode.Release.DownloadUrl = URL; + + _remoteEpisode.Episodes = Builder.CreateListOfSize(1) + .All() + .With(e => e.AirDate = DateTime.Today.ToString(Episode.AIR_DATE_FORMAT)) + .Build() + .ToList(); + + Subject.Definition = new DownloadClientDefinition(); + Subject.Definition.Settings = new SabnzbdSettings + { + Host = "192.168.5.55", + Port = 2222, + ApiKey = "5c770e3197e4fe763423ee7c392c25d1", + Username = "admin", + Password = "pass", + TvCategory = "tv", + RecentTvPriority = (int)SabnzbdPriority.High + }; + } + + [Test] + public void GetHistory_should_return_a_list_with_items_when_the_history_has_items() + { + Mocker.GetMock() + .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) + .Returns(ReadAllText("Files", "History.txt")); + + + var result = Subject.GetHistory(); + + + result.Should().HaveCount(1); + } + + [Test] + public void GetHistory_should_return_an_empty_list_when_the_queue_is_empty() + { + Mocker.GetMock() + .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) + .Returns(ReadAllText("Files", "HistoryEmpty.txt")); + + + var result = Subject.GetHistory(); + + + result.Should().BeEmpty(); + } + + [Test] + public void GetHistory_should_return_an_empty_list_when_there_is_an_error_getting_the_queue() + { + Mocker.GetMock() + .Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) + .Returns(ReadAllText("Files", "JsonError.txt")); + + + Assert.Throws(() => Subject.GetHistory(), "API Key Incorrect"); + } + + [Test] + public void downloadNzb_should_use_sabRecentTvPriority_when_recentEpisode_is_true() + { + Mocker.GetMock() + .Setup(s => s.DownloadNzb(It.IsAny(), It.IsAny(), It.IsAny(), (int)SabnzbdPriority.High, It.IsAny())) + .Returns(new SabnzbdAddResponse()); + + Subject.DownloadNzb(_remoteEpisode); + + Mocker.GetMock() + .Verify(v => v.DownloadNzb(It.IsAny(), It.IsAny(), It.IsAny(), (int)SabnzbdPriority.High, It.IsAny()), Times.Once()); + } + } +} diff --git a/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs index f1a64dd7b..0d3755468 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using System.Net; using FizzWare.NBuilder; @@ -33,9 +34,6 @@ namespace NzbDrone.Core.Test.Download .With(c => c.Release = Builder.CreateNew().Build()) .With(c => c.Episodes = episodes) .Build(); - - - Mocker.GetMock().Setup(c => c.IsConfigured).Returns(true); } private void WithSuccessfulAdd() @@ -85,7 +83,8 @@ namespace NzbDrone.Core.Test.Download [Test] public void should_not_attempt_download_if_client_isnt_configure() { - Mocker.GetMock().Setup(c => c.IsConfigured).Returns(false); + Mocker.GetMock() + .Setup(c => c.GetDownloadClient()).Returns((IDownloadClient)null); Subject.DownloadReport(_parseResult); diff --git a/src/NzbDrone.Core.Test/Files/Categories_json.txt b/src/NzbDrone.Core.Test/Files/Categories_json.txt deleted file mode 100644 index 5759a90e5..000000000 --- a/src/NzbDrone.Core.Test/Files/Categories_json.txt +++ /dev/null @@ -1,25 +0,0 @@ -{ - "categories":[ - "*", - "anime", - "apps", - "books", - "consoles", - "ds-games", - "emulation", - "games", - "misc", - "movies", - "music", - "pda", - "resources", - "test", - "tv", - "tv-dvd", - "unknown", - "wii-games", - "xbox-dlc", - "xbox-xbla", - "xxx" - ] -} \ 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 bb3fa1367..f50f25adf 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -122,10 +122,10 @@ - - + + - + @@ -330,9 +330,6 @@ Always - - Always - Always diff --git a/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs b/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs index 794a00c43..de22c722f 100644 --- a/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs +++ b/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs @@ -23,6 +23,7 @@ namespace NzbDrone.Core.Annotations Textbox, Password, Checkbox, - Select + Select, + Path } } \ No newline at end of file diff --git a/src/NzbDrone.Core/Configuration/ConfigService.cs b/src/NzbDrone.Core/Configuration/ConfigService.cs index 6ebe823ff..6e197460e 100644 --- a/src/NzbDrone.Core/Configuration/ConfigService.cs +++ b/src/NzbDrone.Core/Configuration/ConfigService.cs @@ -73,69 +73,6 @@ namespace NzbDrone.Core.Configuration _eventAggregator.PublishEvent(new ConfigSavedEvent()); } - public String SabHost - { - get { return GetValue("SabHost", "localhost"); } - - set { SetValue("SabHost", value); } - } - - public int SabPort - { - get { return GetValueInt("SabPort", 8080); } - - set { SetValue("SabPort", value); } - } - - public String SabApiKey - { - get { return GetValue("SabApiKey"); } - - set { SetValue("SabApiKey", value); } - } - - public String SabUsername - { - get { return GetValue("SabUsername"); } - - set { SetValue("SabUsername", value); } - } - - public String SabPassword - { - get { return GetValue("SabPassword"); } - - set { SetValue("SabPassword", value); } - } - - public String SabTvCategory - { - get { return GetValue("SabTvCategory", "tv"); } - - set { SetValue("SabTvCategory", value); } - } - - public SabPriorityType SabRecentTvPriority - { - get { return GetValueEnum("SabRecentTvPriority", SabPriorityType.Default); } - - set { SetValue("SabRecentTvPriority", value); } - } - - public SabPriorityType SabOlderTvPriority - { - get { return GetValueEnum("SabOlderTvPriority", SabPriorityType.Default); } - - set { SetValue("SabOlderTvPriority", value); } - } - - public bool SabUseSsl - { - get { return GetValueBoolean("SabUseSsl", false); } - - set { SetValue("SabUseSsl", value); } - } - public String DownloadedEpisodesFolder { get { return GetValue(ConfigKey.DownloadedEpisodesFolder.ToString()); } @@ -155,80 +92,12 @@ namespace NzbDrone.Core.Configuration set { SetValue("Retention", value); } } - public DownloadClientType DownloadClient - { - get { return GetValueEnum("DownloadClient", DownloadClientType.Blackhole); } - - set { SetValue("DownloadClient", value); } - } - - public string BlackholeFolder - { - get { return GetValue("BlackholeFolder", String.Empty); } - set { SetValue("BlackholeFolder", value); } - } - - public string PneumaticFolder - { - get { return GetValue("PneumaticFolder", String.Empty); } - set { SetValue("PneumaticFolder", value); } - } - public string RecycleBin { get { return GetValue("RecycleBin", String.Empty); } set { SetValue("RecycleBin", value); } } - public String NzbgetUsername - { - get { return GetValue("NzbgetUsername", "nzbget"); } - - set { SetValue("NzbgetUsername", value); } - } - - public String NzbgetPassword - { - get { return GetValue("NzbgetPassword", ""); } - - set { SetValue("NzbgetPassword", value); } - } - - public String NzbgetHost - { - get { return GetValue("NzbgetHost", "localhost"); } - - set { SetValue("NzbgetHost", value); } - } - - public Int32 NzbgetPort - { - get { return GetValueInt("NzbgetPort", 6789); } - - set { SetValue("NzbgetPort", value); } - } - - public String NzbgetTvCategory - { - get { return GetValue("NzbgetTvCategory", ""); } - - set { SetValue("NzbgetTvCategory", value); } - } - - public PriorityType NzbgetRecentTvPriority - { - get { return GetValueEnum("NzbgetRecentTvPriority", PriorityType.Normal); } - - set { SetValue("NzbgetRecentTvPriority", value); } - } - - public PriorityType NzbgetOlderTvPriority - { - get { return GetValueEnum("NzbgetOlderTvPriority", PriorityType.Normal); } - - set { SetValue("NzbgetOlderTvPriority", value); } - } - public string ReleaseRestrictions { get { return GetValue("ReleaseRestrictions", String.Empty).Trim('\r', '\n'); } diff --git a/src/NzbDrone.Core/Configuration/IConfigService.cs b/src/NzbDrone.Core/Configuration/IConfigService.cs index 6c19d6c36..a9d121e2f 100644 --- a/src/NzbDrone.Core/Configuration/IConfigService.cs +++ b/src/NzbDrone.Core/Configuration/IConfigService.cs @@ -1,8 +1,5 @@ using System; using System.Collections.Generic; -using NzbDrone.Core.Download; -using NzbDrone.Core.Download.Clients.Nzbget; -using NzbDrone.Core.Download.Clients.Sabnzbd; namespace NzbDrone.Core.Configuration { @@ -10,29 +7,10 @@ namespace NzbDrone.Core.Configuration { IEnumerable All(); Dictionary AllWithDefaults(); - String SabHost { get; set; } - int SabPort { get; set; } - String SabApiKey { get; set; } - String SabUsername { get; set; } - String SabPassword { get; set; } - String SabTvCategory { get; set; } - SabPriorityType SabRecentTvPriority { get; set; } - SabPriorityType SabOlderTvPriority { get; set; } - Boolean SabUseSsl { get; set; } String DownloadedEpisodesFolder { get; set; } bool AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; } int Retention { get; set; } - DownloadClientType DownloadClient { get; set; } - string BlackholeFolder { get; set; } - string PneumaticFolder { get; set; } string RecycleBin { get; set; } - String NzbgetUsername { get; set; } - String NzbgetPassword { get; set; } - String NzbgetHost { get; set; } - Int32 NzbgetPort { get; set; } - String NzbgetTvCategory { get; set; } - PriorityType NzbgetRecentTvPriority { get; set; } - PriorityType NzbgetOlderTvPriority { get; set; } string ReleaseRestrictions { get; set; } Int32 RssSyncInterval { get; set; } Boolean AutoDownloadPropers { get; set; } diff --git a/src/NzbDrone.Core/Datastore/Migration/041_add_download_clients_table.cs b/src/NzbDrone.Core/Datastore/Migration/041_add_download_clients_table.cs new file mode 100644 index 000000000..7c11b9e21 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/041_add_download_clients_table.cs @@ -0,0 +1,20 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(41)] + public class add_download_clients_table : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Create.TableForModel("DownloadClients") + .WithColumn("Enable").AsBoolean().NotNullable() + .WithColumn("Name").AsString().NotNullable() + .WithColumn("Implementation").AsString().NotNullable() + .WithColumn("Settings").AsString().NotNullable() + .WithColumn("ConfigContract").AsString().NotNullable() + .WithColumn("Protocol").AsInt32().NotNullable(); + } + } +} diff --git a/src/NzbDrone.Core/Datastore/Migration/042_convert_config_to_download_clients.cs b/src/NzbDrone.Core/Datastore/Migration/042_convert_config_to_download_clients.cs new file mode 100644 index 000000000..807dca491 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/042_convert_config_to_download_clients.cs @@ -0,0 +1,198 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Runtime.Remoting.Messaging; +using FluentMigrator; +using NzbDrone.Common.Serializer; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(42)] + public class convert_config_to_download_clients : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Execute.WithConnection(ConvertToThingyProvder); + } + + private void ConvertToThingyProvder(IDbConnection conn, IDbTransaction tran) + { + var config = new Dictionary(); + + using (IDbCommand configCmd = conn.CreateCommand()) + { + configCmd.Transaction = tran; + configCmd.CommandText = @"SELECT * FROM Config"; + using (IDataReader configReader = configCmd.ExecuteReader()) + { + var keyIndex = configReader.GetOrdinal("Key"); + var valueIndex = configReader.GetOrdinal("Value"); + + while (configReader.Read()) + { + var key = configReader.GetString(keyIndex); + var value = configReader.GetString(valueIndex); + + config.Add(key.ToLowerInvariant(), value); + } + } + } + + var client = GetConfigValue(config, "DownloadClient", ""); + + if (String.IsNullOrWhiteSpace(client)) + { + return; + } + + if (client.Equals("sabnzbd", StringComparison.InvariantCultureIgnoreCase)) + { + var settings = new ClientSettingsForMigration + { + Host = GetConfigValue(config, "SabHost", "localhost"), + Port = GetConfigValue(config, "SabPort", 8080), + ApiKey = GetConfigValue(config, "SabApiKey", ""), + Username = GetConfigValue(config, "SabUsername", ""), + Password = GetConfigValue(config, "SabPassword", ""), + TvCategory = GetConfigValue(config, "SabTvCategory", "tv"), + RecentTvPriority = GetSabnzbdPriority(GetConfigValue(config, "NzbgetRecentTvPriority", "Default")), + OlderTvPriority = GetSabnzbdPriority(GetConfigValue(config, "NzbgetOlderTvPriority", "Default")), + UseSsl = GetConfigValue(config, "SabUseSsl", false) + }; + + AddDownloadClient(conn, tran, "Sabnzbd", "Sabnzbd", settings.ToJson(), "SabnzbdSettings", 1); + } + + else if (client.Equals("nzbget", StringComparison.InvariantCultureIgnoreCase)) + { + var settings = new ClientSettingsForMigration + { + Host = GetConfigValue(config, "NzbGetHost", "localhost"), + Port = GetConfigValue(config, "NzbgetPort", 6789), + Username = GetConfigValue(config, "NzbgetUsername", "nzbget"), + Password = GetConfigValue(config, "NzbgetPassword", ""), + TvCategory = GetConfigValue(config, "NzbgetTvCategory", "tv"), + RecentTvPriority = GetNzbgetPriority(GetConfigValue(config, "NzbgetRecentTvPriority", "Normal")), + OlderTvPriority = GetNzbgetPriority(GetConfigValue(config, "NzbgetOlderTvPriority", "Normal")), + }; + + AddDownloadClient(conn, tran, "Nzbget", "Nzbget", settings.ToJson(), "NzbgetSettings", 1); + } + + else if (client.Equals("pneumatic", StringComparison.InvariantCultureIgnoreCase)) + { + var settings = new FolderSettingsForMigration + { + Folder = GetConfigValue(config, "PneumaticFolder", "") + }; + + AddDownloadClient(conn, tran, "Pneumatic", "Pneumatic", settings.ToJson(), "FolderSettings", 1); + } + + else if (client.Equals("blackhole", StringComparison.InvariantCultureIgnoreCase)) + { + var settings = new FolderSettingsForMigration + { + Folder = GetConfigValue(config, "BlackholeFolder", "") + }; + + AddDownloadClient(conn, tran, "Blackhole", "Blackhole", settings.ToJson(), "FolderSettings", 1); + } + + DeleteOldConfigValues(conn, tran); + } + + private T GetConfigValue(Dictionary config, string key, T defaultValue) + { + key = key.ToLowerInvariant(); + + if (config.ContainsKey(key)) + { + return (T) Convert.ChangeType(config[key], typeof (T)); + } + + return defaultValue; + } + + private void AddDownloadClient(IDbConnection conn, IDbTransaction tran, string name, string implementation, string settings, + string configContract, int protocol) + { + using (IDbCommand updateCmd = conn.CreateCommand()) + { + var text = String.Format("INSERT INTO DownloadClients (Enable, Name, Implementation, Settings, ConfigContract, Protocol) VALUES (1, ?, ?, ?, ?, ?)"); + updateCmd.AddParameter(name); + updateCmd.AddParameter(implementation); + updateCmd.AddParameter(settings); + updateCmd.AddParameter(configContract); + updateCmd.AddParameter(protocol); + + updateCmd.Transaction = tran; + updateCmd.CommandText = text; + updateCmd.ExecuteNonQuery(); + } + } + + private void DeleteOldConfigValues(IDbConnection conn, IDbTransaction tran) + { + using (IDbCommand updateCmd = conn.CreateCommand()) + { + var text = "DELETE FROM Config WHERE [KEY] IN ('nzbgetusername', 'nzbgetpassword', 'nzbgethost', 'nzbgetport', " + + "'nzbgettvcategory', 'nzbgetrecenttvpriority', 'nzbgetoldertvpriority', 'sabhost', 'sabport', " + + "'sabapikey', 'sabusername', 'sabpassword', 'sabtvcategory', 'sabrecenttvpriority', " + + "'saboldertvpriority', 'sabusessl', 'downloadclient', 'blackholefolder', 'pneumaticfolder')"; + + updateCmd.Transaction = tran; + updateCmd.CommandText = text; + updateCmd.ExecuteNonQuery(); + } + } + + private int GetSabnzbdPriority(string priority) + { + return (int)Enum.Parse(typeof(SabnzbdPriorityForMigration), priority, true); + } + + private int GetNzbgetPriority(string priority) + { + return (int)Enum.Parse(typeof(NzbGetPriorityForMigration), priority, true); + } + + private class ClientSettingsForMigration + { + public String Host { get; set; } + public Int32 Port { get; set; } + public String ApiKey { get; set; } + public String Username { get; set; } + public String Password { get; set; } + public String TvCategory { get; set; } + public Int32 RecentTvPriority { get; set; } + public Int32 OlderTvPriority { get; set; } + public Boolean UseSsl { get; set; } + } + + private class FolderSettingsForMigration + { + public String Folder { get; set; } + } + + private enum SabnzbdPriorityForMigration + { + Default = -100, + Paused = -2, + Low = -1, + Normal = 0, + High = 1, + Force = 2 + } + + private enum NzbGetPriorityForMigration + { + VeryLow = -100, + Low = -50, + Normal = 0, + High = 50, + VeryHigh = 100 + } + } +} diff --git a/src/NzbDrone.Core/Datastore/TableMapping.cs b/src/NzbDrone.Core/Datastore/TableMapping.cs index b5711cd18..78c6fa0fb 100644 --- a/src/NzbDrone.Core/Datastore/TableMapping.cs +++ b/src/NzbDrone.Core/Datastore/TableMapping.cs @@ -7,6 +7,7 @@ using NzbDrone.Core.Blacklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.DataAugmentation.Scene; using NzbDrone.Core.Datastore.Converters; +using NzbDrone.Core.Download; using NzbDrone.Core.Indexers; using NzbDrone.Core.Instrumentation; using NzbDrone.Core.Jobs; @@ -39,6 +40,7 @@ namespace NzbDrone.Core.Datastore Mapper.Entity().RegisterModel("ScheduledTasks"); Mapper.Entity().RegisterModel("Notifications"); Mapper.Entity().RegisterModel("Metadata"); + Mapper.Entity().RegisterModel("DownloadClients"); Mapper.Entity().RegisterModel("SceneMappings"); diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/NotInQueueSpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/NotInQueueSpecification.cs index fa6312258..7e4f34551 100644 --- a/src/NzbDrone.Core/DecisionEngine/Specifications/NotInQueueSpecification.cs +++ b/src/NzbDrone.Core/DecisionEngine/Specifications/NotInQueueSpecification.cs @@ -5,7 +5,6 @@ using NzbDrone.Core.Download; using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Qualities; -using NzbDrone.Core.Tv; namespace NzbDrone.Core.DecisionEngine.Specifications { @@ -32,9 +31,9 @@ namespace NzbDrone.Core.DecisionEngine.Specifications { var downloadClient = _downloadClientProvider.GetDownloadClient(); - if (!downloadClient.IsConfigured) + if (downloadClient == null) { - _logger.Warn("Download client {0} isn't configured yet.", downloadClient.GetType().Name); + _logger.Warn("Download client isn't configured yet."); return true; } diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/HistorySpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/HistorySpecification.cs index b2e034cac..1624c6296 100644 --- a/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/HistorySpecification.cs +++ b/src/NzbDrone.Core/DecisionEngine/Specifications/RssSync/HistorySpecification.cs @@ -41,7 +41,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync return true; } - if (_downloadClientProvider.GetDownloadClient().GetType() == typeof (SabnzbdClient)) + if (_downloadClientProvider.GetDownloadClient().GetType() == typeof (Sabnzbd)) { _logger.Trace("Performing history status check on report"); foreach (var episode in subject.Episodes) diff --git a/src/NzbDrone.Core/Download/Clients/Blackhole/Blackhole.cs b/src/NzbDrone.Core/Download/Clients/Blackhole/Blackhole.cs new file mode 100644 index 000000000..4cfc0cf2d --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Blackhole/Blackhole.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.IO; +using NLog; +using NzbDrone.Common; +using NzbDrone.Common.Disk; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Messaging.Commands; +using NzbDrone.Core.Organizer; +using NzbDrone.Core.Parser.Model; + +namespace NzbDrone.Core.Download.Clients.Blackhole +{ + public class Blackhole : DownloadClientBase, IExecute + { + private readonly IDiskProvider _diskProvider; + private readonly IHttpProvider _httpProvider; + private readonly Logger _logger; + + public Blackhole(IDiskProvider diskProvider, IHttpProvider httpProvider, Logger logger) + { + _diskProvider = diskProvider; + _httpProvider = httpProvider; + _logger = logger; + } + + public override string DownloadNzb(RemoteEpisode remoteEpisode) + { + var url = remoteEpisode.Release.DownloadUrl; + var title = remoteEpisode.Release.Title; + + title = FileNameBuilder.CleanFilename(title); + + var filename = Path.Combine(Settings.Folder, title + ".nzb"); + + + _logger.Trace("Downloading NZB from: {0} to: {1}", url, filename); + _httpProvider.DownloadFile(url, filename); + _logger.Trace("NZB Download succeeded, saved to: {0}", filename); + + return null; + } + + public override IEnumerable GetQueue() + { + return new QueueItem[0]; + } + + public override IEnumerable GetHistory(int start = 0, int limit = 0) + { + return new HistoryItem[0]; + } + + public override void RemoveFromQueue(string id) + { + } + + public override void RemoveFromHistory(string id) + { + } + + public void Execute(TestBlackholeCommand message) + { + var testPath = Path.Combine(message.Folder, "drone_test.txt"); + _diskProvider.WriteAllText(testPath, DateTime.Now.ToString()); + _diskProvider.DeleteFile(testPath); + } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Blackhole/TestBlackholeCommand.cs b/src/NzbDrone.Core/Download/Clients/Blackhole/TestBlackholeCommand.cs new file mode 100644 index 000000000..10898f80a --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Blackhole/TestBlackholeCommand.cs @@ -0,0 +1,18 @@ +using System; +using NzbDrone.Core.Messaging.Commands; + +namespace NzbDrone.Core.Download.Clients.Blackhole +{ + public class TestBlackholeCommand : Command + { + public override bool SendUpdatesToClient + { + get + { + return true; + } + } + + public String Folder { get; set; } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/BlackholeProvider.cs b/src/NzbDrone.Core/Download/Clients/BlackholeProvider.cs deleted file mode 100644 index 1f5a5c93d..000000000 --- a/src/NzbDrone.Core/Download/Clients/BlackholeProvider.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using NLog; -using NzbDrone.Common; -using NzbDrone.Core.Configuration; -using NzbDrone.Core.Organizer; -using NzbDrone.Core.Parser.Model; - -namespace NzbDrone.Core.Download.Clients -{ - public class BlackholeProvider : IDownloadClient - { - private readonly IConfigService _configService; - private readonly IHttpProvider _httpProvider; - private readonly Logger _logger; - - - public BlackholeProvider(IConfigService configService, IHttpProvider httpProvider, Logger logger) - { - _configService = configService; - _httpProvider = httpProvider; - _logger = logger; - } - - public string DownloadNzb(RemoteEpisode remoteEpisode) - { - var url = remoteEpisode.Release.DownloadUrl; - var title = remoteEpisode.Release.Title; - - title = FileNameBuilder.CleanFilename(title); - - var filename = Path.Combine(_configService.BlackholeFolder, title + ".nzb"); - - - _logger.Trace("Downloading NZB from: {0} to: {1}", url, filename); - _httpProvider.DownloadFile(url, filename); - _logger.Trace("NZB Download succeeded, saved to: {0}", filename); - - return null; - } - - public bool IsConfigured - { - get - { - return !string.IsNullOrWhiteSpace(_configService.BlackholeFolder); - } - } - - public IEnumerable GetQueue() - { - return new QueueItem[0]; - } - - public IEnumerable GetHistory(int start = 0, int limit = 0) - { - return new HistoryItem[0]; - } - - public void RemoveFromQueue(string id) - { - } - - public void RemoveFromHistory(string id) - { - } - } -} diff --git a/src/NzbDrone.Core/Download/Clients/FolderSettings.cs b/src/NzbDrone.Core/Download/Clients/FolderSettings.cs new file mode 100644 index 000000000..f11169203 --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/FolderSettings.cs @@ -0,0 +1,29 @@ +using System; +using FluentValidation; +using FluentValidation.Results; +using NzbDrone.Core.Annotations; +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.Download.Clients +{ + public class FolderSettingsValidator : AbstractValidator + { + public FolderSettingsValidator() + { + RuleFor(c => c.Folder).NotEmpty(); + } + } + + public class FolderSettings : IProviderConfig + { + private static readonly FolderSettingsValidator Validator = new FolderSettingsValidator(); + + [FieldDefinition(0, Label = "Folder", Type = FieldType.Path)] + public String Folder { get; set; } + + public ValidationResult Validate() + { + return Validator.Validate(this); + } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueue.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueue.cs index 86cd09843..f7ec8a1be 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueue.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueue.cs @@ -4,11 +4,11 @@ using Newtonsoft.Json; namespace NzbDrone.Core.Download.Clients.Nzbget { - public class NzbGetQueue + public class NzbgetQueue { public String Version { get; set; } [JsonProperty(PropertyName = "result")] - public List QueueItems { get; set; } + public List QueueItems { get; set; } } } diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueueItem.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueueItem.cs index 8e2de535d..39bc8eb51 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueueItem.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueueItem.cs @@ -2,14 +2,11 @@ namespace NzbDrone.Core.Download.Clients.Nzbget { - public class NzbGetQueueItem + public class NzbgetQueueItem { private string _nzbName; - public Int32 NzbId { get; set; } - public string NzbName { get; set; } - public String Category { get; set; } public Int32 FileSizeMb { get; set; } public Int32 RemainingSizeMb { get; set; } diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs new file mode 100644 index 000000000..6133a631f --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using NLog; +using NzbDrone.Core.Messaging.Commands; +using NzbDrone.Core.Parser; +using NzbDrone.Core.Parser.Model; +using Omu.ValueInjecter; + +namespace NzbDrone.Core.Download.Clients.Nzbget +{ + public class Nzbget : DownloadClientBase, IExecute + { + private readonly INzbgetProxy _proxy; + private readonly IParsingService _parsingService; + private readonly Logger _logger; + + public Nzbget(INzbgetProxy proxy, + IParsingService parsingService, + Logger logger) + { + _proxy = proxy; + _parsingService = parsingService; + _logger = logger; + } + + public override string DownloadNzb(RemoteEpisode remoteEpisode) + { + var url = remoteEpisode.Release.DownloadUrl; + var title = remoteEpisode.Release.Title + ".nzb"; + + string cat = Settings.TvCategory; + int priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority; + + _logger.Info("Adding report [{0}] to the queue.", title); + + var success = _proxy.AddNzb(Settings, title, cat, priority, false, url); + + _logger.Debug("Queue Response: [{0}]", success); + + return null; + } + + public override IEnumerable GetQueue() + { + var items = _proxy.GetQueue(Settings); + + foreach (var nzbGetQueueItem in items) + { + var queueItem = new QueueItem(); + queueItem.Id = nzbGetQueueItem.NzbId.ToString(); + queueItem.Title = nzbGetQueueItem.NzbName; + queueItem.Size = nzbGetQueueItem.FileSizeMb; + queueItem.Sizeleft = nzbGetQueueItem.RemainingSizeMb; + queueItem.Status = nzbGetQueueItem.FileSizeMb == nzbGetQueueItem.PausedSizeMb ? "paused" : "queued"; + + var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title); + if (parsedEpisodeInfo == null) continue; + + var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0); + if (remoteEpisode.Series == null) continue; + + queueItem.RemoteEpisode = remoteEpisode; + + yield return queueItem; + } + } + + public override IEnumerable GetHistory(int start = 0, int limit = 0) + { + return new HistoryItem[0]; + } + + public override void RemoveFromQueue(string id) + { + throw new NotImplementedException(); + } + + public override void RemoveFromHistory(string id) + { + throw new NotImplementedException(); + } + + public VersionResponse GetVersion(string host = null, int port = 0, string username = null, string password = null) + { + return _proxy.GetVersion(Settings); + } + + public void Execute(TestNzbgetCommand message) + { + var settings = new NzbgetSettings(); + settings.InjectFrom(message); + + _proxy.GetVersion(settings); + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetClient.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetClient.cs deleted file mode 100644 index 5431d0355..000000000 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetClient.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.Collections.Generic; -using NLog; -using NzbDrone.Common; -using NzbDrone.Common.Serializer; -using NzbDrone.Core.Configuration; -using NzbDrone.Core.Parser; -using NzbDrone.Core.Parser.Model; - -namespace NzbDrone.Core.Download.Clients.Nzbget -{ - public class NzbgetClient : IDownloadClient - { - private readonly IConfigService _configService; - private readonly IHttpProvider _httpProvider; - private readonly INzbGetCommunicationProxy _proxy; - private readonly IParsingService _parsingService; - private readonly Logger _logger; - - public NzbgetClient(IConfigService configService, - IHttpProvider httpProvider, - INzbGetCommunicationProxy proxy, - IParsingService parsingService, - Logger logger) - { - _configService = configService; - _httpProvider = httpProvider; - _proxy = proxy; - _parsingService = parsingService; - _logger = logger; - } - - public string DownloadNzb(RemoteEpisode remoteEpisode) - { - var url = remoteEpisode.Release.DownloadUrl; - var title = remoteEpisode.Release.Title + ".nzb"; - - string cat = _configService.NzbgetTvCategory; - int priority = remoteEpisode.IsRecentEpisode() ? (int)_configService.NzbgetRecentTvPriority : (int)_configService.NzbgetOlderTvPriority; - - _logger.Info("Adding report [{0}] to the queue.", title); - - var success = _proxy.AddNzb(title, cat, priority, false, url); - - _logger.Debug("Queue Response: [{0}]", success); - - return null; - } - - public bool IsConfigured - { - get - { - return !string.IsNullOrWhiteSpace(_configService.NzbgetHost) && _configService.NzbgetPort != 0; - } - } - - public virtual IEnumerable GetQueue() - { - var items = _proxy.GetQueue(); - - foreach (var nzbGetQueueItem in items) - { - var queueItem = new QueueItem(); - queueItem.Id = nzbGetQueueItem.NzbId.ToString(); - queueItem.Title = nzbGetQueueItem.NzbName; - queueItem.Size = nzbGetQueueItem.FileSizeMb; - queueItem.Sizeleft = nzbGetQueueItem.RemainingSizeMb; - queueItem.Status = nzbGetQueueItem.FileSizeMb == nzbGetQueueItem.PausedSizeMb ? "paused" : "queued"; - - var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title); - if (parsedEpisodeInfo == null) continue; - - var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0); - if (remoteEpisode.Series == null) continue; - - queueItem.RemoteEpisode = remoteEpisode; - - yield return queueItem; - } - } - - public IEnumerable GetHistory(int start = 0, int limit = 0) - { - return new HistoryItem[0]; - } - - public void RemoveFromQueue(string id) - { - throw new NotImplementedException(); - } - - public void RemoveFromHistory(string id) - { - throw new NotImplementedException(); - } - - public virtual VersionModel GetVersion(string host = null, int port = 0, string username = null, string password = null) - { - throw new NotImplementedException(); - - //Get saved values if any of these are defaults - if (host == null) - host = _configService.NzbgetHost; - - if (port == 0) - port = _configService.NzbgetPort; - - if (username == null) - username = _configService.NzbgetUsername; - - if (password == null) - password = _configService.NzbgetPassword; - - - var response = _proxy.GetVersion(); - - return Json.Deserialize(response); - } - - public virtual string Test(string host, int port, string username, string password) - { - try - { - var version = GetVersion(host, port, username, password); - return version.Result; - } - catch (Exception ex) - { - _logger.DebugException("Failed to Test Nzbget", ex); - } - - return String.Empty; - } - } -} \ No newline at end of file diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/PriorityType.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetPriority.cs similarity index 84% rename from src/NzbDrone.Core/Download/Clients/Nzbget/PriorityType.cs rename to src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetPriority.cs index 7235f375a..c7e121805 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/PriorityType.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetPriority.cs @@ -1,6 +1,6 @@ namespace NzbDrone.Core.Download.Clients.Nzbget { - public enum PriorityType + public enum NzbgetPriority { VeryLow = -100, Low = -50, diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetCommunicationProxy.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetProxy.cs similarity index 60% rename from src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetCommunicationProxy.cs rename to src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetProxy.cs index 1b733ad69..0376dfad9 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetCommunicationProxy.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetProxy.cs @@ -1,57 +1,52 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using NLog; using NzbDrone.Common.Serializer; -using NzbDrone.Core.Configuration; using NzbDrone.Core.Rest; using RestSharp; namespace NzbDrone.Core.Download.Clients.Nzbget { - public interface INzbGetCommunicationProxy + public interface INzbgetProxy { - bool AddNzb(params object[] parameters); - List GetQueue(); - string GetVersion(); + bool AddNzb(NzbgetSettings settings, params object[] parameters); + List GetQueue(NzbgetSettings settings); + VersionResponse GetVersion(NzbgetSettings settings); } - public class NzbGetCommunicationProxy : INzbGetCommunicationProxy + public class NzbgetProxy : INzbgetProxy { - private readonly IConfigService _configService; private readonly Logger _logger; - public NzbGetCommunicationProxy(IConfigService configService, Logger logger) + public NzbgetProxy(Logger logger) { - _configService = configService; _logger = logger; } - public bool AddNzb(params object[] parameters) + public bool AddNzb(NzbgetSettings settings, params object[] parameters) { var request = BuildRequest(new JsonRequest("appendurl", parameters)); - return Json.Deserialize(ProcessRequest(request)).Result; + return Json.Deserialize(ProcessRequest(request, settings)).Result; } - public List GetQueue() + public List GetQueue(NzbgetSettings settings) { - var request = BuildRequest(new JsonRequest("listgroups")); + var request = BuildRequest(new JsonRequest("listgroups")); - return Json.Deserialize(ProcessRequest(request)).QueueItems; + return Json.Deserialize(ProcessRequest(request, settings)).QueueItems; } - public string GetVersion() + public VersionResponse GetVersion(NzbgetSettings settings) { var request = BuildRequest(new JsonRequest("version")); - return ProcessRequest(request); + return Json.Deserialize(ProcessRequest(request, settings)); } - private string ProcessRequest(IRestRequest restRequest) + private string ProcessRequest(IRestRequest restRequest, NzbgetSettings settings) { - var client = BuildClient(); + var client = BuildClient(settings); var response = client.Execute(restRequest); _logger.Trace("Response: {0}", response.Content); @@ -60,14 +55,14 @@ namespace NzbDrone.Core.Download.Clients.Nzbget return response.Content; } - private IRestClient BuildClient() + private IRestClient BuildClient(NzbgetSettings settings) { var url = String.Format("http://{0}:{1}/jsonrpc", - _configService.NzbgetHost, - _configService.NzbgetPort); + settings.Host, + settings.Port); var client = new RestClient(url); - client.Authenticator = new HttpBasicAuthenticator(_configService.NzbgetUsername, _configService.NzbgetPassword); + client.Authenticator = new HttpBasicAuthenticator(settings.Username, settings.Password); return client; } diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetSettings.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetSettings.cs new file mode 100644 index 000000000..383622cef --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetSettings.cs @@ -0,0 +1,59 @@ +using System; +using FluentValidation; +using FluentValidation.Results; +using NzbDrone.Core.Annotations; +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.Download.Clients.Nzbget +{ + public class NzbgetSettingsValidator : AbstractValidator + { + public NzbgetSettingsValidator() + { + RuleFor(c => c.Host).NotEmpty(); + RuleFor(c => c.Port).GreaterThan(0); + RuleFor(c => c.Username).NotEmpty(); + RuleFor(c => c.Password).NotEmpty(); + } + } + + public class NzbgetSettings : IProviderConfig + { + private static readonly NzbgetSettingsValidator Validator = new NzbgetSettingsValidator(); + + public NzbgetSettings() + { + Host = "localhost"; + Port = 6789; + TvCategory = "tv"; + RecentTvPriority = (int)NzbgetPriority.Normal; + OlderTvPriority = (int)NzbgetPriority.Normal; + } + + [FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)] + public String Host { get; set; } + + [FieldDefinition(1, Label = "Port", Type = FieldType.Textbox)] + public Int32 Port { get; set; } + + [FieldDefinition(2, Label = "Username", Type = FieldType.Textbox)] + public String Username { get; set; } + + [FieldDefinition(3, Label = "Password", Type = FieldType.Password)] + public String Password { get; set; } + + [FieldDefinition(4, Label = "Category", Type = FieldType.Textbox)] + public String TvCategory { get; set; } + + [FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority))] + public Int32 RecentTvPriority { get; set; } + + [FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority))] + public Int32 OlderTvPriority { get; set; } + + public ValidationResult Validate() + { + return Validator.Validate(this); + } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/TestNzbgetCommand.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/TestNzbgetCommand.cs new file mode 100644 index 000000000..805b4d19a --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/TestNzbgetCommand.cs @@ -0,0 +1,21 @@ +using System; +using NzbDrone.Core.Messaging.Commands; + +namespace NzbDrone.Core.Download.Clients.Nzbget +{ + public class TestNzbgetCommand : Command + { + public override bool SendUpdatesToClient + { + get + { + return true; + } + } + + public String Host { get; set; } + public Int32 Port { get; set; } + public String Username { get; set; } + public String Password { get; set; } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/VersionModel.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/VersionResponse.cs similarity index 83% rename from src/NzbDrone.Core/Download/Clients/Nzbget/VersionModel.cs rename to src/NzbDrone.Core/Download/Clients/Nzbget/VersionResponse.cs index 9e7d90064..780fd90ad 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/VersionModel.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/VersionResponse.cs @@ -2,7 +2,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget { - public class VersionModel + public class VersionResponse { public String Version { get; set; } public String Result { get; set; } diff --git a/src/NzbDrone.Core/Download/Clients/PneumaticClient.cs b/src/NzbDrone.Core/Download/Clients/Pneumatic/Pneumatic.cs similarity index 63% rename from src/NzbDrone.Core/Download/Clients/PneumaticClient.cs rename to src/NzbDrone.Core/Download/Clients/Pneumatic/Pneumatic.cs index 8ebc5b409..3b63d5383 100644 --- a/src/NzbDrone.Core/Download/Clients/PneumaticClient.cs +++ b/src/NzbDrone.Core/Download/Clients/Pneumatic/Pneumatic.cs @@ -6,12 +6,13 @@ using NzbDrone.Common; using NzbDrone.Common.Disk; using NzbDrone.Common.Instrumentation; using NzbDrone.Core.Configuration; +using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Organizer; using NzbDrone.Core.Parser.Model; -namespace NzbDrone.Core.Download.Clients +namespace NzbDrone.Core.Download.Clients.Pneumatic { - public class PneumaticClient : IDownloadClient + public class Pneumatic : DownloadClientBase, IExecute { private readonly IConfigService _configService; private readonly IHttpProvider _httpProvider; @@ -19,7 +20,7 @@ namespace NzbDrone.Core.Download.Clients private static readonly Logger logger = NzbDroneLogger.GetLogger(); - public PneumaticClient(IConfigService configService, IHttpProvider httpProvider, + public Pneumatic(IConfigService configService, IHttpProvider httpProvider, IDiskProvider diskProvider) { _configService = configService; @@ -27,20 +28,20 @@ namespace NzbDrone.Core.Download.Clients _diskProvider = diskProvider; } - public string DownloadNzb(RemoteEpisode remoteEpisode) + public override string DownloadNzb(RemoteEpisode remoteEpisode) { var url = remoteEpisode.Release.DownloadUrl; var title = remoteEpisode.Release.Title; if (remoteEpisode.ParsedEpisodeInfo.FullSeason) { - throw new NotImplementedException("Full season Pneumatic releases are not supported."); + throw new NotImplementedException("Full season releases are not supported with Pneumatic."); } title = FileNameBuilder.CleanFilename(title); //Save to the Pneumatic directory (The user will need to ensure its accessible by XBMC) - var filename = Path.Combine(_configService.PneumaticFolder, title + ".nzb"); + var filename = Path.Combine(Settings.Folder, title + ".nzb"); logger.Trace("Downloading NZB from: {0} to: {1}", url, filename); _httpProvider.DownloadFile(url, filename); @@ -57,31 +58,33 @@ namespace NzbDrone.Core.Download.Clients { get { - return !string.IsNullOrWhiteSpace(_configService.PneumaticFolder); + return !string.IsNullOrWhiteSpace(Settings.Folder); } } - public IEnumerable GetQueue() + public override IEnumerable GetQueue() { return new QueueItem[0]; } - public IEnumerable GetHistory(int start = 0, int limit = 0) + public override IEnumerable GetHistory(int start = 0, int limit = 0) { return new HistoryItem[0]; } - public void RemoveFromQueue(string id) + public override void RemoveFromQueue(string id) { } - public void RemoveFromHistory(string id) + public override void RemoveFromHistory(string id) { } - public virtual bool IsInQueue(RemoteEpisode newEpisode) + public void Execute(TestPneumaticCommand message) { - return false; + var testPath = Path.Combine(message.Folder, "drone_test.txt"); + _diskProvider.WriteAllText(testPath, DateTime.Now.ToString()); + _diskProvider.DeleteFile(testPath); } } } diff --git a/src/NzbDrone.Core/Download/Clients/Pneumatic/TestPneumaticCommand.cs b/src/NzbDrone.Core/Download/Clients/Pneumatic/TestPneumaticCommand.cs new file mode 100644 index 000000000..097a39aa5 --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Pneumatic/TestPneumaticCommand.cs @@ -0,0 +1,18 @@ +using System; +using NzbDrone.Core.Messaging.Commands; + +namespace NzbDrone.Core.Download.Clients.Pneumatic +{ + public class TestPneumaticCommand : Command + { + public override bool SendUpdatesToClient + { + get + { + return true; + } + } + + public String Folder { get; set; } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/ConnectionInfoModel.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/ConnectionInfoModel.cs deleted file mode 100644 index cb03c1953..000000000 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/ConnectionInfoModel.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace NzbDrone.Core.Download.Clients.Sabnzbd -{ - public class ConnectionInfoModel - { - public string Address { get; set; } - public int Port { get; set; } - } -} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/JsonConverters/SabnzbdPriorityTypeConverter.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/JsonConverters/SabnzbdPriorityTypeConverter.cs index e5c5f8b74..17557abcc 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/JsonConverters/SabnzbdPriorityTypeConverter.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/JsonConverters/SabnzbdPriorityTypeConverter.cs @@ -7,7 +7,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd.JsonConverters { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - var priorityType = (SabPriorityType)value; + var priorityType = (SabnzbdPriority)value; writer.WriteValue(priorityType.ToString()); } @@ -15,7 +15,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd.JsonConverters { var queuePriority = reader.Value.ToString(); - SabPriorityType output; + SabnzbdPriority output; Enum.TryParse(queuePriority, out output); return output; @@ -23,7 +23,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd.JsonConverters public override bool CanConvert(Type objectType) { - return objectType == typeof(SabPriorityType); + return objectType == typeof(SabnzbdPriority); } } } diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdAddResponse.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdAddResponse.cs new file mode 100644 index 000000000..147bfce68 --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdAddResponse.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace NzbDrone.Core.Download.Clients.Sabnzbd.Responses +{ + public class SabnzbdAddResponse + { + public SabnzbdAddResponse() + { + Ids = new List(); + } + + public bool Status { get; set; } + + [JsonProperty(PropertyName = "nzo_ids")] + public List Ids { get; set; } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdCategoryResponse.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdCategoryResponse.cs new file mode 100644 index 000000000..03d71bee5 --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdCategoryResponse.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace NzbDrone.Core.Download.Clients.Sabnzbd.Responses +{ + public class SabnzbdCategoryResponse + { + public SabnzbdCategoryResponse() + { + Categories = new List(); + } + + public List Categories { get; set; } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdVersionResponse.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdVersionResponse.cs new file mode 100644 index 000000000..fd281a58f --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Responses/SabnzbdVersionResponse.cs @@ -0,0 +1,7 @@ +namespace NzbDrone.Core.Download.Clients.Sabnzbd.Responses +{ + public class SabnzbdVersionResponse + { + public string Version { get; set; } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabAddResponse.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabAddResponse.cs deleted file mode 100644 index 040b2b2b4..000000000 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabAddResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace NzbDrone.Core.Download.Clients.Sabnzbd -{ - public class SabAddResponse - { - public SabAddResponse() - { - Ids = new List(); - } - - public bool Status { get; set; } - - [JsonProperty(PropertyName = "nzo_ids")] - public List Ids { get; set; } - } -} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabAutoConfigureService.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabAutoConfigureService.cs deleted file mode 100644 index 224cae5c5..000000000 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabAutoConfigureService.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.NetworkInformation; -using System.Text.RegularExpressions; -using NLog; -using NzbDrone.Common.Instrumentation; - -namespace NzbDrone.Core.Download.Clients.Sabnzbd -{ - public class SabAutoConfigureService - { - private static readonly Logger Logger = NzbDroneLogger.GetLogger(); - - public SabModel AutoConfigureSab() - { - var info = GetConnectionList(); - return FindApiKey(info); - } - - private List GetConnectionList() - { - IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties(); - var info = - ipProperties.GetActiveTcpListeners().Select( - p => - new ConnectionInfoModel { Address = p.Address.ToString().Replace("0.0.0.0", "127.0.0.1"), Port = p.Port }).Distinct(). - ToList(); - - info.RemoveAll(i => i.Port == 135); - info.RemoveAll(i => i.Port == 139); - info.RemoveAll(i => i.Port == 445); - info.RemoveAll(i => i.Port == 3389); - info.RemoveAll(i => i.Port == 5900); - info.RemoveAll(i => i.Address.Contains("::")); - - info.Reverse(); - - return info; - } - - private SabModel FindApiKey(List info) - { - foreach (var connection in info) - { - var apiKey = GetApiKey(connection.Address, connection.Port); - if (!String.IsNullOrEmpty(apiKey)) - return new SabModel - { - Host = connection.Address, - Port = connection.Port, - ApiKey = apiKey - }; - } - return null; - } - - private string GetApiKey(string ipAddress, int port) - { - var request = String.Format("http://{0}:{1}/config/general/", ipAddress, port); - var result = DownloadString(request); - - Regex regex = - new Regex("\\\\w+)\\W", - RegexOptions.IgnoreCase - | RegexOptions.Compiled); - var match = regex.Match(result); - - if (match.Success) - { - return match.Groups["apikey"].Value; - } - - return String.Empty; - } - - private string DownloadString(string url) - { - try - { - var request = WebRequest.Create(url); - request.Timeout = 2000; - - var response = request.GetResponse(); - - var reader = new StreamReader(response.GetResponseStream()); - return reader.ReadToEnd(); - } - catch (Exception ex) - { - Logger.Trace("Failed to get response from: {0}", url); - Logger.Trace(ex.Message, ex); - } - - return String.Empty; - } - } -} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabCategoryModel.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabCategoryModel.cs deleted file mode 100644 index 83d7b3e03..000000000 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabCategoryModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace NzbDrone.Core.Download.Clients.Sabnzbd -{ - public class SabCategoryModel - { - public List categories { get; set; } - } -} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabCommunicationProxy.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabCommunicationProxy.cs deleted file mode 100644 index 8e181a25e..000000000 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabCommunicationProxy.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.IO; -using NLog; -using NzbDrone.Common.Serializer; -using NzbDrone.Core.Configuration; -using RestSharp; - -namespace NzbDrone.Core.Download.Clients.Sabnzbd -{ - public interface ISabCommunicationProxy - { - SabAddResponse DownloadNzb(Stream nzb, string name, string category, int priority); - void RemoveFrom(string source, string id); - string ProcessRequest(IRestRequest restRequest, string action); - } - - public class SabCommunicationProxy : ISabCommunicationProxy - { - private readonly IConfigService _configService; - private readonly Logger _logger; - - public SabCommunicationProxy(IConfigService configService, Logger logger) - { - _configService = configService; - _logger = logger; - } - - public SabAddResponse DownloadNzb(Stream nzb, string title, string category, int priority) - { - var request = new RestRequest(Method.POST); - var action = String.Format("mode=addfile&cat={0}&priority={1}", category, priority); - - request.AddFile("name", ReadFully(nzb), title, "application/x-nzb"); - - SabAddResponse response; - - if (!Json.TryDeserialize(ProcessRequest(request, action), out response)) - { - response = new SabAddResponse(); - response.Status = true; - } - - return response; - } - - public void RemoveFrom(string source, string id) - { - var request = new RestRequest(); - var action = String.Format("mode={0}&name=delete&del_files=1&value={1}", source, id); - - ProcessRequest(request, action); - } - - public string ProcessRequest(IRestRequest restRequest, string action) - { - var client = BuildClient(action); - var response = client.Execute(restRequest); - _logger.Trace("Response: {0}", response.Content); - - CheckForError(response); - - return response.Content; - } - - private IRestClient BuildClient(string action) - { - var protocol = _configService.SabUseSsl ? "https" : "http"; - - var url = string.Format(@"{0}://{1}:{2}/api?{3}&apikey={4}&ma_username={5}&ma_password={6}&output=json", - protocol, - _configService.SabHost, - _configService.SabPort, - action, - _configService.SabApiKey, - _configService.SabUsername, - _configService.SabPassword); - - _logger.Trace(url); - - return new RestClient(url); - } - - private void CheckForError(IRestResponse response) - { - if (response.ResponseStatus != ResponseStatus.Completed) - { - throw new ApplicationException("Unable to connect to SABnzbd, please check your settings"); - } - - SabJsonError result; - - if (!Json.TryDeserialize(response.Content, out result)) - { - //Handle plain text responses from SAB - result = new SabJsonError(); - - if (response.Content.StartsWith("error", StringComparison.InvariantCultureIgnoreCase)) - { - result.Status = "false"; - result.Error = response.Content.Replace("error: ", ""); - } - - else - { - result.Status = "true"; - } - - result.Error = response.Content.Replace("error: ", ""); - } - - if (result.Failed) - throw new ApplicationException(result.Error); - } - - //TODO: Find a better home for this - private byte[] ReadFully(Stream input) - { - byte[] buffer = new byte[16 * 1024]; - using (MemoryStream ms = new MemoryStream()) - { - int read; - while ((read = input.Read(buffer, 0, buffer.Length)) > 0) - { - ms.Write(buffer, 0, read); - } - return ms.ToArray(); - } - } - } -} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabModel.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabModel.cs deleted file mode 100644 index 158535065..000000000 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace NzbDrone.Core.Download.Clients.Sabnzbd -{ - public class SabModel - { - public string Host { get; set; } - public int Port { get; set; } - public string ApiKey { get; set; } - } -} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabVersionModel.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabVersionModel.cs deleted file mode 100644 index 9d8cad8fd..000000000 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabVersionModel.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace NzbDrone.Core.Download.Clients.Sabnzbd -{ - public class SabVersionModel - { - public string Version { get; set; } - } -} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs new file mode 100644 index 000000000..c9c7ef395 --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Linq; +using NLog; +using NzbDrone.Common; +using NzbDrone.Common.Cache; +using NzbDrone.Common.Serializer; +using NzbDrone.Core.Download.Clients.Sabnzbd.Responses; +using NzbDrone.Core.Messaging.Commands; +using NzbDrone.Core.Parser; +using NzbDrone.Core.Parser.Model; +using Omu.ValueInjecter; + +namespace NzbDrone.Core.Download.Clients.Sabnzbd +{ + public class Sabnzbd : DownloadClientBase, IExecute + { + private readonly IHttpProvider _httpProvider; + private readonly IParsingService _parsingService; + private readonly ISabnzbdProxy _sabnzbdProxy; + private readonly ICached> _queueCache; + private readonly Logger _logger; + + public Sabnzbd(IHttpProvider httpProvider, + ICacheManger cacheManger, + IParsingService parsingService, + ISabnzbdProxy sabnzbdProxy, + Logger logger) + { + _httpProvider = httpProvider; + _parsingService = parsingService; + _sabnzbdProxy = sabnzbdProxy; + _queueCache = cacheManger.GetCache>(GetType(), "queue"); + _logger = logger; + } + + public override string DownloadNzb(RemoteEpisode remoteEpisode) + { + var url = remoteEpisode.Release.DownloadUrl; + var title = remoteEpisode.Release.Title; + var category = Settings.TvCategory; + var priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority; + + using (var nzb = _httpProvider.DownloadStream(url)) + { + _logger.Info("Adding report [{0}] to the queue.", title); + var response = _sabnzbdProxy.DownloadNzb(nzb, title, category, priority, Settings); + + if (response != null && response.Ids.Any()) + { + return response.Ids.First(); + } + + return null; + } + } + + public override IEnumerable GetQueue() + { + return _queueCache.Get("queue", () => + { + var sabQueue = _sabnzbdProxy.GetQueue(0, 0, Settings).Items; + + var queueItems = new List(); + + foreach (var sabQueueItem in sabQueue) + { + var queueItem = new QueueItem(); + queueItem.Id = sabQueueItem.Id; + queueItem.Title = sabQueueItem.Title; + queueItem.Size = sabQueueItem.Size; + queueItem.Sizeleft = sabQueueItem.Sizeleft; + queueItem.Timeleft = sabQueueItem.Timeleft; + queueItem.Status = sabQueueItem.Status; + + var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title.Replace("ENCRYPTED / ", "")); + if (parsedEpisodeInfo == null) continue; + + var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0); + if (remoteEpisode.Series == null) continue; + + queueItem.RemoteEpisode = remoteEpisode; + + queueItems.Add(queueItem); + } + + return queueItems; + }, TimeSpan.FromSeconds(10)); + } + + public override IEnumerable GetHistory(int start = 0, int limit = 0) + { + var items = _sabnzbdProxy.GetHistory(start, limit, Settings).Items; + var historyItems = new List(); + + foreach (var sabHistoryItem in items) + { + var historyItem = new HistoryItem(); + historyItem.Id = sabHistoryItem.Id; + historyItem.Title = sabHistoryItem.Title; + historyItem.Size = sabHistoryItem.Size; + historyItem.DownloadTime = sabHistoryItem.DownloadTime; + historyItem.Storage = sabHistoryItem.Storage; + historyItem.Category = sabHistoryItem.Category; + historyItem.Message = sabHistoryItem.FailMessage; + historyItem.Status = sabHistoryItem.Status == "Failed" ? HistoryStatus.Failed : HistoryStatus.Completed; + + historyItems.Add(historyItem); + } + + return historyItems; + } + + public override void RemoveFromQueue(string id) + { + _sabnzbdProxy.RemoveFrom("queue", id, Settings); + } + + public override void RemoveFromHistory(string id) + { + _sabnzbdProxy.RemoveFrom("history", id, Settings); + } + + public void Execute(TestSabnzbdCommand message) + { + var settings = new SabnzbdSettings(); + settings.InjectFrom(message); + + _sabnzbdProxy.GetVersion(settings); + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdClient.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdClient.cs deleted file mode 100644 index 5535eb00b..000000000 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdClient.cs +++ /dev/null @@ -1,250 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json.Linq; -using NLog; -using NzbDrone.Common; -using NzbDrone.Common.Cache; -using NzbDrone.Common.Serializer; -using NzbDrone.Core.Configuration; -using NzbDrone.Core.Parser; -using NzbDrone.Core.Parser.Model; - -namespace NzbDrone.Core.Download.Clients.Sabnzbd -{ - public class SabnzbdClient : IDownloadClient - { - private readonly IConfigService _configService; - private readonly IHttpProvider _httpProvider; - private readonly IParsingService _parsingService; - private readonly ISabCommunicationProxy _sabCommunicationProxy; - private readonly ICached> _queueCache; - private readonly Logger _logger; - - public SabnzbdClient(IConfigService configService, - IHttpProvider httpProvider, - ICacheManger cacheManger, - IParsingService parsingService, - ISabCommunicationProxy sabCommunicationProxy, - Logger logger) - { - _configService = configService; - _httpProvider = httpProvider; - _parsingService = parsingService; - _sabCommunicationProxy = sabCommunicationProxy; - _queueCache = cacheManger.GetCache>(GetType(), "queue"); - _logger = logger; - } - - public bool IsConfigured - { - get - { - return !string.IsNullOrWhiteSpace(_configService.SabHost) - && _configService.SabPort != 0; - } - } - - public string DownloadNzb(RemoteEpisode remoteEpisode) - { - var url = remoteEpisode.Release.DownloadUrl; - var title = remoteEpisode.Release.Title; - var category = _configService.SabTvCategory; - var priority = remoteEpisode.IsRecentEpisode() ? (int)_configService.SabRecentTvPriority : (int)_configService.SabOlderTvPriority; - - using (var nzb = _httpProvider.DownloadStream(url)) - { - _logger.Info("Adding report [{0}] to the queue.", title); - var response = _sabCommunicationProxy.DownloadNzb(nzb, title, category, priority); - - if (response != null && response.Ids.Any()) - { - return response.Ids.First(); - } - - return null; - } - } - - public IEnumerable GetQueue() - { - return _queueCache.Get("queue", () => - { - string action = String.Format("mode=queue&output=json&start={0}&limit={1}", 0, 0); - string request = GetSabRequest(action); - string response = _httpProvider.DownloadString(request); - - CheckForError(response); - - var sabQueue = Json.Deserialize(JObject.Parse(response).SelectToken("queue").ToString()).Items; - - var queueItems = new List(); - - foreach (var sabQueueItem in sabQueue) - { - var queueItem = new QueueItem(); - queueItem.Id = sabQueueItem.Id; - queueItem.Title = sabQueueItem.Title; - queueItem.Size = sabQueueItem.Size; - queueItem.Sizeleft = sabQueueItem.Sizeleft; - queueItem.Timeleft = sabQueueItem.Timeleft; - queueItem.Status = sabQueueItem.Status; - - var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title.Replace("ENCRYPTED / ", "")); - if (parsedEpisodeInfo == null) continue; - - var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0); - if (remoteEpisode.Series == null) continue; - - queueItem.RemoteEpisode = remoteEpisode; - - queueItems.Add(queueItem); - } - - return queueItems; - }, TimeSpan.FromSeconds(10)); - } - - public IEnumerable GetHistory(int start = 0, int limit = 0) - { - string action = String.Format("mode=history&output=json&start={0}&limit={1}", start, limit); - string request = GetSabRequest(action); - string response = _httpProvider.DownloadString(request); - - CheckForError(response); - - var items = Json.Deserialize(JObject.Parse(response).SelectToken("history").ToString()).Items; - var historyItems = new List(); - - foreach (var sabHistoryItem in items) - { - var historyItem = new HistoryItem(); - historyItem.Id = sabHistoryItem.Id; - historyItem.Title = sabHistoryItem.Title; - historyItem.Size = sabHistoryItem.Size; - historyItem.DownloadTime = sabHistoryItem.DownloadTime; - historyItem.Storage = sabHistoryItem.Storage; - historyItem.Category = sabHistoryItem.Category; - historyItem.Message = sabHistoryItem.FailMessage; - historyItem.Status = sabHistoryItem.Status == "Failed" ? HistoryStatus.Failed : HistoryStatus.Completed; - - historyItems.Add(historyItem); - } - - return historyItems; - } - - public void RemoveFromQueue(string id) - { - _sabCommunicationProxy.RemoveFrom("queue", id); - } - - public void RemoveFromHistory(string id) - { - _sabCommunicationProxy.RemoveFrom("history", id); - } - - public virtual SabCategoryModel GetCategories(string host = null, int port = 0, string apiKey = null, string username = null, string password = null) - { - //Get saved values if any of these are defaults - if (host == null) - host = _configService.SabHost; - - if (port == 0) - port = _configService.SabPort; - - if (apiKey == null) - apiKey = _configService.SabApiKey; - - if (username == null) - username = _configService.SabUsername; - - if (password == null) - password = _configService.SabPassword; - - const string action = "mode=get_cats&output=json"; - - var command = string.Format(@"http://{0}:{1}/api?{2}&apikey={3}&ma_username={4}&ma_password={5}", - host, port, action, apiKey, username, password); - - var response = _httpProvider.DownloadString(command); - - if (String.IsNullOrWhiteSpace(response)) - return new SabCategoryModel { categories = new List() }; - - var categories = Json.Deserialize(response); - - return categories; - } - - public virtual SabVersionModel GetVersion(string host = null, int port = 0, string apiKey = null, string username = null, string password = null) - { - //Get saved values if any of these are defaults - if (host == null) - host = _configService.SabHost; - - if (port == 0) - port = _configService.SabPort; - - if (apiKey == null) - apiKey = _configService.SabApiKey; - - if (username == null) - username = _configService.SabUsername; - - if (password == null) - password = _configService.SabPassword; - - const string action = "mode=version&output=json"; - - var command = string.Format(@"http://{0}:{1}/api?{2}&apikey={3}&ma_username={4}&ma_password={5}", - host, port, action, apiKey, username, password); - - var response = _httpProvider.DownloadString(command); - - if (String.IsNullOrWhiteSpace(response)) - return null; - - var version = Json.Deserialize(response); - - return version; - } - - public virtual string Test(string host, int port, string apiKey, string username, string password) - { - try - { - var version = GetVersion(host, port, apiKey, username, password); - return version.Version; - } - catch (Exception ex) - { - _logger.DebugException("Failed to Test SABnzbd", ex); - } - - return String.Empty; - } - - private string GetSabRequest(string action) - { - var protocol = _configService.SabUseSsl ? "https" : "http"; - - return string.Format(@"{0}://{1}:{2}/api?{3}&apikey={4}&ma_username={5}&ma_password={6}", - protocol, - _configService.SabHost, - _configService.SabPort, - action, - _configService.SabApiKey, - _configService.SabUsername, - _configService.SabPassword); - } - - private void CheckForError(string response) - { - var result = Json.Deserialize(response); - - if (result.Failed) - throw new ApplicationException(result.Error); - } - } -} \ No newline at end of file diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabQueue.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdHistory.cs similarity index 70% rename from src/NzbDrone.Core/Download/Clients/Sabnzbd/SabQueue.cs rename to src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdHistory.cs index d19fa608c..b19786739 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabQueue.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdHistory.cs @@ -3,11 +3,11 @@ using Newtonsoft.Json; namespace NzbDrone.Core.Download.Clients.Sabnzbd { - public class SabQueue + public class SabnzbdHistory { public bool Paused { get; set; } [JsonProperty(PropertyName = "slots")] - public List Items { get; set; } + public List Items { get; set; } } } diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabHistoryItem.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdHistoryItem.cs similarity index 95% rename from src/NzbDrone.Core/Download/Clients/Sabnzbd/SabHistoryItem.cs rename to src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdHistoryItem.cs index fa94cbc2f..166b25c94 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabHistoryItem.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdHistoryItem.cs @@ -2,7 +2,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd { - public class SabHistoryItem + public class SabnzbdHistoryItem { [JsonProperty(PropertyName = "fail_message")] public string FailMessage { get; set; } diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabJsonError.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdJsonError.cs similarity index 92% rename from src/NzbDrone.Core/Download/Clients/Sabnzbd/SabJsonError.cs rename to src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdJsonError.cs index 8ad40b398..853c7e104 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabJsonError.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdJsonError.cs @@ -2,7 +2,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd { - public class SabJsonError + public class SabnzbdJsonError { public string Status { get; set; } public string Error { get; set; } diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabPriorityType.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdPriority.cs similarity index 84% rename from src/NzbDrone.Core/Download/Clients/Sabnzbd/SabPriorityType.cs rename to src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdPriority.cs index d16be5f2f..b769a78db 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabPriorityType.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdPriority.cs @@ -1,6 +1,6 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd { - public enum SabPriorityType + public enum SabnzbdPriority { Default = -100, Paused = -2, diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdProxy.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdProxy.cs new file mode 100644 index 000000000..59fac17dd --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdProxy.cs @@ -0,0 +1,182 @@ +using System; +using System.IO; +using Newtonsoft.Json.Linq; +using NLog; +using NzbDrone.Common.Serializer; +using NzbDrone.Core.Download.Clients.Sabnzbd.Responses; +using RestSharp; + +namespace NzbDrone.Core.Download.Clients.Sabnzbd +{ + public interface ISabnzbdProxy + { + SabnzbdAddResponse DownloadNzb(Stream nzb, string name, string category, int priority, SabnzbdSettings settings); + void RemoveFrom(string source, string id, SabnzbdSettings settings); + string ProcessRequest(IRestRequest restRequest, string action, SabnzbdSettings settings); + SabnzbdVersionResponse GetVersion(SabnzbdSettings settings); + SabnzbdCategoryResponse GetCategories(SabnzbdSettings settings); + SabnzbdQueue GetQueue(int start, int limit, SabnzbdSettings settings); + SabnzbdHistory GetHistory(int start, int limit, SabnzbdSettings settings); + } + + public class SabnzbdProxy : ISabnzbdProxy + { + private readonly Logger _logger; + + public SabnzbdProxy(Logger logger) + { + _logger = logger; + } + + public SabnzbdAddResponse DownloadNzb(Stream nzb, string title, string category, int priority, SabnzbdSettings settings) + { + var request = new RestRequest(Method.POST); + var action = String.Format("mode=addfile&cat={0}&priority={1}", category, priority); + + request.AddFile("name", ReadFully(nzb), title, "application/x-nzb"); + + SabnzbdAddResponse response; + + if (!Json.TryDeserialize(ProcessRequest(request, action, settings), out response)) + { + response = new SabnzbdAddResponse(); + response.Status = true; + } + + return response; + } + + public void RemoveFrom(string source, string id, SabnzbdSettings settings) + { + var request = new RestRequest(); + var action = String.Format("mode={0}&name=delete&del_files=1&value={1}", source, id); + + ProcessRequest(request, action, settings); + } + + public string ProcessRequest(IRestRequest restRequest, string action, SabnzbdSettings settings) + { + var client = BuildClient(action, settings); + var response = client.Execute(restRequest); + _logger.Trace("Response: {0}", response.Content); + + CheckForError(response); + + return response.Content; + } + + public SabnzbdVersionResponse GetVersion(SabnzbdSettings settings) + { + var request = new RestRequest(); + var action = "mode=version"; + + SabnzbdVersionResponse response; + + if (!Json.TryDeserialize(ProcessRequest(request, action, settings), out response)) + { + response = new SabnzbdVersionResponse(); + } + + return response; + } + + public SabnzbdCategoryResponse GetCategories(SabnzbdSettings settings) + { + var request = new RestRequest(); + var action = "mode=get_cats"; + + SabnzbdCategoryResponse response; + + if (!Json.TryDeserialize(ProcessRequest(request, action, settings), out response)) + { + response = new SabnzbdCategoryResponse(); + } + + return response; + } + + public SabnzbdQueue GetQueue(int start, int limit, SabnzbdSettings settings) + { + var request = new RestRequest(); + var action = String.Format("mode=queue&start={0}&limit={1}", start, limit); + + var response = ProcessRequest(request, action, settings); + return Json.Deserialize(JObject.Parse(response).SelectToken("queue").ToString()); + + } + + public SabnzbdHistory GetHistory(int start, int limit, SabnzbdSettings settings) + { + var request = new RestRequest(); + var action = String.Format("mode=queue&start={0}&limit={1}", start, limit); + + var response = ProcessRequest(request, action, settings); + return Json.Deserialize(JObject.Parse(response).SelectToken("history").ToString()); + } + + private IRestClient BuildClient(string action, SabnzbdSettings settings) + { + var protocol = settings.UseSsl ? "https" : "http"; + + var url = string.Format(@"{0}://{1}:{2}/api?{3}&apikey={4}&ma_username={5}&ma_password={6}&output=json", + protocol, + settings.Host, + settings.Port, + action, + settings.ApiKey, + settings.Username, + settings.Password); + + _logger.Trace(url); + + return new RestClient(url); + } + + private void CheckForError(IRestResponse response) + { + if (response.ResponseStatus != ResponseStatus.Completed) + { + throw new ApplicationException("Unable to connect to SABnzbd, please check your settings"); + } + + SabnzbdJsonError result; + + if (!Json.TryDeserialize(response.Content, out result)) + { + //Handle plain text responses from SAB + result = new SabnzbdJsonError(); + + if (response.Content.StartsWith("error", StringComparison.InvariantCultureIgnoreCase)) + { + result.Status = "false"; + result.Error = response.Content.Replace("error: ", ""); + } + + else + { + result.Status = "true"; + } + + result.Error = response.Content.Replace("error: ", ""); + } + + if (result.Failed) + throw new ApplicationException(result.Error); + } + + //TODO: Find a better home for this + private byte[] ReadFully(Stream input) + { + byte[] buffer = new byte[16 * 1024]; + using (MemoryStream ms = new MemoryStream()) + { + int read; + while ((read = input.Read(buffer, 0, buffer.Length)) > 0) + { + ms.Write(buffer, 0, read); + } + return ms.ToArray(); + } + } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabHistory.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdQueue.cs similarity index 70% rename from src/NzbDrone.Core/Download/Clients/Sabnzbd/SabHistory.cs rename to src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdQueue.cs index f90a2d1ce..edbdab5da 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabHistory.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdQueue.cs @@ -3,11 +3,11 @@ using Newtonsoft.Json; namespace NzbDrone.Core.Download.Clients.Sabnzbd { - public class SabHistory + public class SabnzbdQueue { public bool Paused { get; set; } [JsonProperty(PropertyName = "slots")] - public List Items { get; set; } + public List Items { get; set; } } } diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabQueueItem.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdQueueItem.cs similarity index 91% rename from src/NzbDrone.Core/Download/Clients/Sabnzbd/SabQueueItem.cs rename to src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdQueueItem.cs index bc233eb84..a3a74452f 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabQueueItem.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdQueueItem.cs @@ -4,7 +4,7 @@ using NzbDrone.Core.Download.Clients.Sabnzbd.JsonConverters; namespace NzbDrone.Core.Download.Clients.Sabnzbd { - public class SabQueueItem + public class SabnzbdQueueItem { public string Status { get; set; } public int Index { get; set; } @@ -21,7 +21,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd public string Title { get; set; } [JsonConverter(typeof(SabnzbdPriorityTypeConverter))] - public SabPriorityType Priority { get; set; } + public SabnzbdPriority Priority { get; set; } [JsonProperty(PropertyName = "cat")] public string Category { get; set; } diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdSettings.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdSettings.cs new file mode 100644 index 000000000..a6373b379 --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdSettings.cs @@ -0,0 +1,66 @@ +using System; +using FluentValidation; +using FluentValidation.Results; +using NzbDrone.Core.Annotations; +using NzbDrone.Core.Download.Clients.Nzbget; +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.Download.Clients.Sabnzbd +{ + public class SabnzbdSettingsValidator : AbstractValidator + { + public SabnzbdSettingsValidator() + { + RuleFor(c => c.Host).NotEmpty(); + RuleFor(c => c.Port).GreaterThan(0); + + //Todo: either API key or Username/Password needs to be valid + } + } + + public class SabnzbdSettings : IProviderConfig + { + private static readonly SabnzbdSettingsValidator Validator = new SabnzbdSettingsValidator(); + + public SabnzbdSettings() + { + Host = "localhost"; + Port = 8080; + TvCategory = "tv"; + RecentTvPriority = (int)SabnzbdPriority.Default; + OlderTvPriority = (int)SabnzbdPriority.Default; + } + + [FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)] + public String Host { get; set; } + + [FieldDefinition(1, Label = "Port", Type = FieldType.Textbox)] + public Int32 Port { get; set; } + + [FieldDefinition(2, Label = "API Key", Type = FieldType.Textbox)] + public String ApiKey { get; set; } + + [FieldDefinition(3, Label = "Username", Type = FieldType.Textbox)] + public String Username { get; set; } + + [FieldDefinition(4, Label = "Password", Type = FieldType.Password)] + public String Password { get; set; } + + [FieldDefinition(5, Label = "Category", Type = FieldType.Textbox)] + public String TvCategory { get; set; } + + [FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority))] + public Int32 RecentTvPriority { get; set; } + + [FieldDefinition(7, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority))] + public Int32 OlderTvPriority { get; set; } + + [FieldDefinition(8, Label = "Use SSL", Type = FieldType.Checkbox)] + public Boolean UseSsl { get; set; } + + public ValidationResult Validate() + { + return Validator.Validate(this); + } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/TestSabnzbdCommand.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/TestSabnzbdCommand.cs new file mode 100644 index 000000000..2c1d2eb9d --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/TestSabnzbdCommand.cs @@ -0,0 +1,23 @@ +using System; +using NzbDrone.Core.Messaging.Commands; + +namespace NzbDrone.Core.Download.Clients.Sabnzbd +{ + public class TestSabnzbdCommand : Command + { + public override bool SendUpdatesToClient + { + get + { + return true; + } + } + + public String Host { get; set; } + public Int32 Port { get; set; } + public String ApiKey { get; set; } + public String Username { get; set; } + public String Password { get; set; } + public Boolean UseSsl { get; set; } + } +} diff --git a/src/NzbDrone.Core/Download/DownloadClientBase.cs b/src/NzbDrone.Core/Download/DownloadClientBase.cs new file mode 100644 index 000000000..b86eda48f --- /dev/null +++ b/src/NzbDrone.Core/Download/DownloadClientBase.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using NLog; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.Download +{ + public abstract class DownloadClientBase : IDownloadClient where TSettings : IProviderConfig, new() + { + public Type ConfigContract + { + get + { + return typeof(TSettings); + } + } + + public IEnumerable DefaultDefinitions + { + get + { + return new List(); + } + } + + public ProviderDefinition Definition { get; set; } + + protected TSettings Settings + { + get + { + return (TSettings)Definition.Settings; + } + } + + public override string ToString() + { + return GetType().Name; + } + + public abstract string DownloadNzb(RemoteEpisode remoteEpisode); + public abstract IEnumerable GetQueue(); + public abstract IEnumerable GetHistory(int start = 0, int limit = 0); + public abstract void RemoveFromQueue(string id); + public abstract void RemoveFromHistory(string id); + } +} diff --git a/src/NzbDrone.Core/Download/DownloadClientDefinition.cs b/src/NzbDrone.Core/Download/DownloadClientDefinition.cs new file mode 100644 index 000000000..479d10925 --- /dev/null +++ b/src/NzbDrone.Core/Download/DownloadClientDefinition.cs @@ -0,0 +1,12 @@ +using System; +using NzbDrone.Core.Indexers; +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.Download +{ + public class DownloadClientDefinition : ProviderDefinition + { + public Boolean Enable { get; set; } + public DownloadProtocol Protocol { get; set; } + } +} diff --git a/src/NzbDrone.Core/Download/DownloadClientFactory.cs b/src/NzbDrone.Core/Download/DownloadClientFactory.cs new file mode 100644 index 000000000..07c56096e --- /dev/null +++ b/src/NzbDrone.Core/Download/DownloadClientFactory.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using System.Linq; +using NLog; +using NzbDrone.Common.Composition; +using NzbDrone.Core.ThingiProvider; + +namespace NzbDrone.Core.Download +{ + public interface IDownloadClientFactory : IProviderFactory + { + List Enabled(); + } + + public class DownloadClientFactory : ProviderFactory, IDownloadClientFactory + { + private readonly IDownloadClientRepository _providerRepository; + + public DownloadClientFactory(IDownloadClientRepository providerRepository, IEnumerable providers, IContainer container, Logger logger) + : base(providerRepository, providers, container, logger) + { + _providerRepository = providerRepository; + } + + public List Enabled() + { + return GetAvailableProviders().Where(n => ((DownloadClientDefinition)n.Definition).Enable).ToList(); + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/Download/DownloadClientProvider.cs b/src/NzbDrone.Core/Download/DownloadClientProvider.cs index 12f9260b8..8a220d8b0 100644 --- a/src/NzbDrone.Core/Download/DownloadClientProvider.cs +++ b/src/NzbDrone.Core/Download/DownloadClientProvider.cs @@ -1,4 +1,6 @@ -using NzbDrone.Core.Configuration; +using System.Collections.Generic; +using System.Linq; +using NzbDrone.Core.Configuration; using NzbDrone.Core.Download.Clients; using NzbDrone.Core.Download.Clients.Nzbget; using NzbDrone.Core.Download.Clients.Sabnzbd; @@ -12,42 +14,16 @@ namespace NzbDrone.Core.Download public class DownloadClientProvider : IProvideDownloadClient { + private readonly IDownloadClientFactory _downloadClientFactory; - private readonly SabnzbdClient _sabnzbdClient; - private readonly IConfigService _configService; - private readonly BlackholeProvider _blackholeProvider; - private readonly PneumaticClient _pneumaticClient; - private readonly NzbgetClient _nzbgetClient; - - - public DownloadClientProvider(SabnzbdClient sabnzbdClient, IConfigService configService, - BlackholeProvider blackholeProvider, - PneumaticClient pneumaticClient, - NzbgetClient nzbgetClient) + public DownloadClientProvider(IDownloadClientFactory downloadClientFactory) { - _sabnzbdClient = sabnzbdClient; - _configService = configService; - _blackholeProvider = blackholeProvider; - _pneumaticClient = pneumaticClient; - _nzbgetClient = nzbgetClient; + _downloadClientFactory = downloadClientFactory; } public IDownloadClient GetDownloadClient() { - switch (_configService.DownloadClient) - { - case DownloadClientType.Blackhole: - return _blackholeProvider; - - case DownloadClientType.Pneumatic: - return _pneumaticClient; - - case DownloadClientType.Nzbget: - return _nzbgetClient; - - default: - return _sabnzbdClient; - } + return _downloadClientFactory.Enabled().FirstOrDefault(); } } } \ No newline at end of file diff --git a/src/NzbDrone.Core/Download/DownloadClientRepository.cs b/src/NzbDrone.Core/Download/DownloadClientRepository.cs new file mode 100644 index 000000000..25c1ea15c --- /dev/null +++ b/src/NzbDrone.Core/Download/DownloadClientRepository.cs @@ -0,0 +1,20 @@ +using NzbDrone.Core.Datastore; +using NzbDrone.Core.Messaging.Events; +using NzbDrone.Core.ThingiProvider; + + +namespace NzbDrone.Core.Download +{ + public interface IDownloadClientRepository : IProviderRepository + { + + } + + public class DownloadClientRepository : ProviderRepository, IDownloadClientRepository + { + public DownloadClientRepository(IDatabase database, IEventAggregator eventAggregator) + : base(database, eventAggregator) + { + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/Download/DownloadService.cs b/src/NzbDrone.Core/Download/DownloadService.cs index 15acf13b2..71e633d47 100644 --- a/src/NzbDrone.Core/Download/DownloadService.cs +++ b/src/NzbDrone.Core/Download/DownloadService.cs @@ -36,9 +36,9 @@ namespace NzbDrone.Core.Download var downloadTitle = remoteEpisode.Release.Title; var downloadClient = _downloadClientProvider.GetDownloadClient(); - if (!downloadClient.IsConfigured) + if (downloadClient == null) { - _logger.Warn("Download client {0} isn't configured yet.", downloadClient.GetType().Name); + _logger.Warn("Download client isn't configured yet."); return; } diff --git a/src/NzbDrone.Core/Download/Events/DownloadFailedEvent.cs b/src/NzbDrone.Core/Download/Events/DownloadFailedEvent.cs new file mode 100644 index 000000000..0475ceaf2 --- /dev/null +++ b/src/NzbDrone.Core/Download/Events/DownloadFailedEvent.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using NzbDrone.Common.Messaging; +using NzbDrone.Core.Qualities; + +namespace NzbDrone.Core.Download.Events +{ + public class DownloadFailedEvent : IEvent + { + public Int32 SeriesId { get; set; } + public List EpisodeIds { get; set; } + public QualityModel Quality { get; set; } + public String SourceTitle { get; set; } + public String DownloadClient { get; set; } + public String DownloadClientId { get; set; } + public String Message { get; set; } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/Download/Events/EpisodeGrabbedEvent.cs b/src/NzbDrone.Core/Download/Events/EpisodeGrabbedEvent.cs new file mode 100644 index 000000000..887e42362 --- /dev/null +++ b/src/NzbDrone.Core/Download/Events/EpisodeGrabbedEvent.cs @@ -0,0 +1,18 @@ +using System; +using NzbDrone.Common.Messaging; +using NzbDrone.Core.Parser.Model; + +namespace NzbDrone.Core.Download.Events +{ + public class EpisodeGrabbedEvent : IEvent + { + public RemoteEpisode Episode { get; private set; } + public String DownloadClient { get; set; } + public String DownloadClientId { get; set; } + + public EpisodeGrabbedEvent(RemoteEpisode episode) + { + Episode = episode; + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/Download/IDownloadClient.cs b/src/NzbDrone.Core/Download/IDownloadClient.cs index 42107372b..d13fe243e 100644 --- a/src/NzbDrone.Core/Download/IDownloadClient.cs +++ b/src/NzbDrone.Core/Download/IDownloadClient.cs @@ -1,12 +1,12 @@ using System.Collections.Generic; using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.ThingiProvider; namespace NzbDrone.Core.Download { - public interface IDownloadClient + public interface IDownloadClient : IProvider { string DownloadNzb(RemoteEpisode remoteEpisode); - bool IsConfigured { get; } IEnumerable GetQueue(); IEnumerable GetHistory(int start = 0, int limit = 0); void RemoveFromQueue(string id); diff --git a/src/NzbDrone.Core/Indexers/IndexerBase.cs b/src/NzbDrone.Core/Indexers/IndexerBase.cs index e59bcf4c9..0aead1b89 100644 --- a/src/NzbDrone.Core/Indexers/IndexerBase.cs +++ b/src/NzbDrone.Core/Indexers/IndexerBase.cs @@ -59,7 +59,7 @@ namespace NzbDrone.Core.Indexers public enum DownloadProtocol { - Usenet, - Torrent + Usenet = 1, + Torrent = 2 } } \ No newline at end of file diff --git a/src/NzbDrone.Core/MetaData/MetadataService.cs b/src/NzbDrone.Core/MetaData/MetadataService.cs index 08708ab3e..461b992d2 100644 --- a/src/NzbDrone.Core/MetaData/MetadataService.cs +++ b/src/NzbDrone.Core/MetaData/MetadataService.cs @@ -1,12 +1,9 @@ -using System.IO; -using System.Linq; +using System.Linq; using NLog; -using NzbDrone.Common; using NzbDrone.Core.MediaCover; using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Metadata.Files; -using NzbDrone.Core.Tv.Events; namespace NzbDrone.Core.Metadata { @@ -16,10 +13,10 @@ namespace NzbDrone.Core.Metadata IHandle { private readonly IMetadataFactory _metadataFactory; - private readonly MetadataFileService _metadataFileService; + private readonly IMetadataFileService _metadataFileService; private readonly Logger _logger; - public NotificationService(IMetadataFactory metadataFactory, MetadataFileService metadataFileService, Logger logger) + public NotificationService(IMetadataFactory metadataFactory, IMetadataFileService metadataFileService, Logger logger) { _metadataFactory = metadataFactory; _metadataFileService = metadataFileService; diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 89cb0b967..4391b60eb 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -198,6 +198,8 @@ + + @@ -240,13 +242,27 @@ + + + + + + + + + + + + + + + + - - + - - + @@ -476,10 +492,10 @@ - - - - + + + + @@ -529,18 +545,13 @@ - - - - - - - - - + + + + + - - + @@ -556,13 +567,10 @@ Code - - Code - Code - + Code @@ -631,7 +639,7 @@ Code - + diff --git a/src/NzbDrone.Core/Queue/QueueService.cs b/src/NzbDrone.Core/Queue/QueueService.cs index 070c90fb6..ce81a1bfd 100644 --- a/src/NzbDrone.Core/Queue/QueueService.cs +++ b/src/NzbDrone.Core/Queue/QueueService.cs @@ -23,6 +23,13 @@ namespace NzbDrone.Core.Queue public List GetQueue() { var downloadClient = _downloadClientProvider.GetDownloadClient(); + + if (downloadClient == null) + { + _logger.Trace("Download client is not configured."); + return new List(); + } + var queueItems = downloadClient.GetQueue(); return MapQueue(queueItems); diff --git a/src/NzbDrone.Core/Tv/SeriesService.cs b/src/NzbDrone.Core/Tv/SeriesService.cs index ee7af6841..47e5fedf9 100644 --- a/src/NzbDrone.Core/Tv/SeriesService.cs +++ b/src/NzbDrone.Core/Tv/SeriesService.cs @@ -97,6 +97,8 @@ namespace NzbDrone.Core.Tv return FindByTvdbId(tvdbId.Value); } + var clean = Parser.Parser.CleanSeriesTitle(title); + return _seriesRepository.FindByTitle(Parser.Parser.CleanSeriesTitle(title)); } diff --git a/src/UI/.idea/jsLinters/jshint.xml b/src/UI/.idea/jsLinters/jshint.xml index e85398a55..4e0df49ad 100644 --- a/src/UI/.idea/jsLinters/jshint.xml +++ b/src/UI/.idea/jsLinters/jshint.xml @@ -8,16 +8,16 @@