mirror of
https://github.com/Sonarr/Sonarr.git
synced 2025-03-05 15:15:59 +02:00
Download clients now use thingy provider
This commit is contained in:
parent
ba22600412
commit
606d78f5e1
18
src/NzbDrone.Api/DownloadClient/DownloadClientModule.cs
Normal file
18
src/NzbDrone.Api/DownloadClient/DownloadClientModule.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using NzbDrone.Core.Download;
|
||||
|
||||
namespace NzbDrone.Api.DownloadClient
|
||||
{
|
||||
public class DownloadClientModule : ProviderModuleBase<DownloadClientResource, IDownloadClient, DownloadClientDefinition>
|
||||
{
|
||||
public DownloadClientModule(IDownloadClientFactory downloadClientFactory)
|
||||
: base(downloadClientFactory, "downloadclient")
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Validate(DownloadClientDefinition definition)
|
||||
{
|
||||
if (!definition.Enable) return;
|
||||
base.Validate(definition);
|
||||
}
|
||||
}
|
||||
}
|
10
src/NzbDrone.Api/DownloadClient/DownloadClientResource.cs
Normal file
10
src/NzbDrone.Api/DownloadClient/DownloadClientResource.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace NzbDrone.Api.DownloadClient
|
||||
{
|
||||
public class DownloadClientResource : ProviderResource
|
||||
{
|
||||
public Boolean Enable { get; set; }
|
||||
public Int32 Protocol { get; set; }
|
||||
}
|
||||
}
|
@ -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<DownloadClientResource>
|
||||
{
|
||||
private readonly IDownloadClientFactory _notificationFactory;
|
||||
|
||||
public DownloadClientSchemaModule(IDownloadClientFactory notificationFactory)
|
||||
: base("downloadclient/schema")
|
||||
{
|
||||
_notificationFactory = notificationFactory;
|
||||
GetResourceAll = GetSchema;
|
||||
}
|
||||
|
||||
private List<DownloadClientResource> GetSchema()
|
||||
{
|
||||
var notifications = _notificationFactory.Templates();
|
||||
|
||||
var result = new List<DownloadClientResource>(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;
|
||||
}
|
||||
}
|
||||
}
|
@ -94,6 +94,8 @@
|
||||
<Compile Include="Commands\CommandResource.cs" />
|
||||
<Compile Include="Config\NamingConfigResource.cs" />
|
||||
<Compile Include="Config\NamingModule.cs" />
|
||||
<Compile Include="DownloadClient\DownloadClientModule.cs" />
|
||||
<Compile Include="DownloadClient\DownloadClientResource.cs" />
|
||||
<Compile Include="DiskSpace\DiskSpaceModule.cs" />
|
||||
<Compile Include="DiskSpace\DiskSpaceResource.cs" />
|
||||
<Compile Include="EpisodeFiles\EpisodeFileModule.cs" />
|
||||
@ -122,6 +124,7 @@
|
||||
<Compile Include="History\HistoryModule.cs" />
|
||||
<Compile Include="Metadata\MetadataResource.cs" />
|
||||
<Compile Include="Metadata\MetadataModule.cs" />
|
||||
<Compile Include="Notifications\NotificationSchemaModule.cs" />
|
||||
<Compile Include="ProviderResource.cs" />
|
||||
<Compile Include="ProviderModuleBase.cs" />
|
||||
<Compile Include="Indexers\IndexerSchemaModule.cs" />
|
||||
@ -145,7 +148,7 @@
|
||||
<Compile Include="Queue\QueueModule.cs" />
|
||||
<Compile Include="Queue\QueueResource.cs" />
|
||||
<Compile Include="ResourceChangeMessage.cs" />
|
||||
<Compile Include="Notifications\NotificationSchemaModule.cs" />
|
||||
<Compile Include="DownloadClient\DownloadClientSchemaModule.cs" />
|
||||
<Compile Include="Notifications\NotificationModule.cs" />
|
||||
<Compile Include="Notifications\NotificationResource.cs" />
|
||||
<Compile Include="NzbDroneRestModule.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()
|
||||
|
@ -83,7 +83,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
private void GivenSabnzbdDownloadClient()
|
||||
{
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(c => c.GetDownloadClient()).Returns(Mocker.Resolve<SabnzbdClient>());
|
||||
.Setup(c => c.GetDownloadClient()).Returns(Mocker.Resolve<Sabnzbd>());
|
||||
}
|
||||
|
||||
private void GivenMostRecentForEpisode(HistoryEventType eventType)
|
||||
|
@ -56,9 +56,6 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClient())
|
||||
.Returns(_downloadClient.Object);
|
||||
|
||||
_downloadClient.SetupGet(s => s.IsConfigured)
|
||||
.Returns(true);
|
||||
}
|
||||
|
||||
private void GivenEmptyQueue()
|
||||
|
@ -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<BlackholeProvider>
|
||||
public class BlackholeProviderFixture : CoreTest<Blackhole>
|
||||
{
|
||||
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<IConfigService>().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()
|
||||
|
@ -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<Nzbget>
|
||||
{
|
||||
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<INzbGetCommunicationProxy>()
|
||||
.Setup(s => s.AddNzb(p))
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.AddNzb(It.IsAny<NzbgetSettings>(), p))
|
||||
.Returns(true);
|
||||
|
||||
Mocker.Resolve<NzbgetClient>().DownloadNzb(_remoteEpisode);
|
||||
Subject.DownloadNzb(_remoteEpisode);
|
||||
|
||||
Mocker.GetMock<INzbGetCommunicationProxy>()
|
||||
.Verify(v => v.AddNzb(It.IsAny<object []>()), Times.Once());
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Verify(v => v.AddNzb(It.IsAny<NzbgetSettings>(), It.IsAny<object []>()), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
@ -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<NzbgetClient>
|
||||
public class QueueFixture : CoreTest<Nzbget>
|
||||
{
|
||||
private List<NzbGetQueueItem> _queue;
|
||||
private List<NzbgetQueueItem> _queue;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_queue = Builder<NzbGetQueueItem>.CreateListOfSize(5)
|
||||
_queue = Builder<NzbgetQueueItem>.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<INzbGetCommunicationProxy>()
|
||||
.Setup(s => s.GetQueue())
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.GetQueue(It.IsAny<NzbgetSettings>()))
|
||||
.Returns(_queue);
|
||||
}
|
||||
|
||||
private void WithEmptyQueue()
|
||||
{
|
||||
Mocker.GetMock<INzbGetCommunicationProxy>()
|
||||
.Setup(s => s.GetQueue())
|
||||
.Returns(new List<NzbGetQueueItem>());
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.GetQueue(It.IsAny<NzbgetSettings>()))
|
||||
.Returns(new List<NzbgetQueueItem>());
|
||||
}
|
||||
|
||||
[Test]
|
@ -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<PneumaticClient>
|
||||
public class PneumaticProviderFixture : CoreTest<Pneumatic>
|
||||
{
|
||||
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<IConfigService>().SetupGet(c => c.PneumaticFolder).Returns(_pneumaticFolder);
|
||||
Mocker.GetMock<IConfigService>().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()
|
||||
|
@ -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<SabnzbdClient>
|
||||
{
|
||||
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<IConfigService>();
|
||||
|
||||
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<Episode>.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<IHttpProvider>(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<IHttpProvider>(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<IHttpProvider>()
|
||||
.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<IHttpProvider>()
|
||||
.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<IHttpProvider>()
|
||||
.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<ApplicationException>(() => 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<IHttpProvider>()
|
||||
.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<IHttpProvider>()
|
||||
.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<IHttpProvider>()
|
||||
.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<IConfigService>()
|
||||
.SetupGet(s => s.SabRecentTvPriority)
|
||||
.Returns(SabPriorityType.High);
|
||||
|
||||
Mocker.GetMock<ISabCommunicationProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), (int)SabPriorityType.High))
|
||||
.Returns(new SabAddResponse());
|
||||
|
||||
Subject.DownloadNzb(_remoteEpisode);
|
||||
|
||||
Mocker.GetMock<ISabCommunicationProxy>()
|
||||
.Verify(v => v.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), (int)SabPriorityType.High), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
@ -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<Sabnzbd>
|
||||
{
|
||||
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<Episode>.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<IHttpProvider>()
|
||||
.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<IHttpProvider>()
|
||||
.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<IHttpProvider>()
|
||||
.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<ApplicationException>(() => Subject.GetHistory(), "API Key Incorrect");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void downloadNzb_should_use_sabRecentTvPriority_when_recentEpisode_is_true()
|
||||
{
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), (int)SabnzbdPriority.High, It.IsAny<SabnzbdSettings>()))
|
||||
.Returns(new SabnzbdAddResponse());
|
||||
|
||||
Subject.DownloadNzb(_remoteEpisode);
|
||||
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Verify(v => v.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), (int)SabnzbdPriority.High, It.IsAny<SabnzbdSettings>()), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
@ -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<ReleaseInfo>.CreateNew().Build())
|
||||
.With(c => c.Episodes = episodes)
|
||||
.Build();
|
||||
|
||||
|
||||
Mocker.GetMock<IDownloadClient>().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<IDownloadClient>().Setup(c => c.IsConfigured).Returns(false);
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(c => c.GetDownloadClient()).Returns((IDownloadClient)null);
|
||||
|
||||
Subject.DownloadReport(_parseResult);
|
||||
|
||||
|
@ -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"
|
||||
]
|
||||
}
|
@ -122,10 +122,10 @@
|
||||
<Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" />
|
||||
<Compile Include="Download\DownloadApprovedReportsTests\GetQualifiedReportsFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\BlackholeProviderFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\NzbgetProviderTests\DownloadNzbFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\NzbgetProviderTests\QueueFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\NzbgetTests\DownloadNzbFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\NzbgetTests\QueueFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\PneumaticProviderFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\SabProviderTests\SabProviderFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\SabnzbdTests\SabnzbdFixture.cs" />
|
||||
<Compile Include="Download\DownloadServiceFixture.cs" />
|
||||
<Compile Include="Download\FailedDownloadServiceFixture.cs" />
|
||||
<Compile Include="Framework\CoreTest.cs" />
|
||||
@ -330,9 +330,6 @@
|
||||
<Content Include="Files\RSS\newznab.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Files\Categories_json.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Files\RSS\SizeParsing\newznab.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
@ -23,6 +23,7 @@ namespace NzbDrone.Core.Annotations
|
||||
Textbox,
|
||||
Password,
|
||||
Checkbox,
|
||||
Select
|
||||
Select,
|
||||
Path
|
||||
}
|
||||
}
|
@ -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'); }
|
||||
|
@ -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<Config> All();
|
||||
Dictionary<String, Object> 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; }
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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<string, string>();
|
||||
|
||||
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<T>(Dictionary<string, string> 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
|
||||
}
|
||||
}
|
||||
}
|
@ -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<ScheduledTask>().RegisterModel("ScheduledTasks");
|
||||
Mapper.Entity<NotificationDefinition>().RegisterModel("Notifications");
|
||||
Mapper.Entity<MetadataDefinition>().RegisterModel("Metadata");
|
||||
Mapper.Entity<DownloadClientDefinition>().RegisterModel("DownloadClients");
|
||||
|
||||
Mapper.Entity<SceneMapping>().RegisterModel("SceneMappings");
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
69
src/NzbDrone.Core/Download/Clients/Blackhole/Blackhole.cs
Normal file
69
src/NzbDrone.Core/Download/Clients/Blackhole/Blackhole.cs
Normal file
@ -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<FolderSettings>, IExecute<TestBlackholeCommand>
|
||||
{
|
||||
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<QueueItem> GetQueue()
|
||||
{
|
||||
return new QueueItem[0];
|
||||
}
|
||||
|
||||
public override IEnumerable<HistoryItem> 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
@ -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<QueueItem> GetQueue()
|
||||
{
|
||||
return new QueueItem[0];
|
||||
}
|
||||
|
||||
public IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0)
|
||||
{
|
||||
return new HistoryItem[0];
|
||||
}
|
||||
|
||||
public void RemoveFromQueue(string id)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveFromHistory(string id)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
29
src/NzbDrone.Core/Download/Clients/FolderSettings.cs
Normal file
29
src/NzbDrone.Core/Download/Clients/FolderSettings.cs
Normal file
@ -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<FolderSettings>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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<NzbGetQueueItem> QueueItems { get; set; }
|
||||
public List<NzbgetQueueItem> QueueItems { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
|
96
src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs
Normal file
96
src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs
Normal file
@ -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<NzbgetSettings>, IExecute<TestNzbgetCommand>
|
||||
{
|
||||
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<QueueItem> 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<HistoryItem> 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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<QueueItem> 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<HistoryItem> 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<VersionModel>(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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
{
|
||||
public enum PriorityType
|
||||
public enum NzbgetPriority
|
||||
{
|
||||
VeryLow = -100,
|
||||
Low = -50,
|
@ -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<NzbGetQueueItem> GetQueue();
|
||||
string GetVersion();
|
||||
bool AddNzb(NzbgetSettings settings, params object[] parameters);
|
||||
List<NzbgetQueueItem> 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<EnqueueResponse>(ProcessRequest(request)).Result;
|
||||
return Json.Deserialize<EnqueueResponse>(ProcessRequest(request, settings)).Result;
|
||||
}
|
||||
|
||||
public List<NzbGetQueueItem> GetQueue()
|
||||
public List<NzbgetQueueItem> GetQueue(NzbgetSettings settings)
|
||||
{
|
||||
var request = BuildRequest(new JsonRequest("listgroups"));
|
||||
var request = BuildRequest(new JsonRequest("listgroups"));
|
||||
|
||||
return Json.Deserialize<NzbGetQueue>(ProcessRequest(request)).QueueItems;
|
||||
return Json.Deserialize<NzbgetQueue>(ProcessRequest(request, settings)).QueueItems;
|
||||
}
|
||||
|
||||
public string GetVersion()
|
||||
public VersionResponse GetVersion(NzbgetSettings settings)
|
||||
{
|
||||
var request = BuildRequest(new JsonRequest("version"));
|
||||
|
||||
return ProcessRequest(request);
|
||||
return Json.Deserialize<VersionResponse>(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;
|
||||
}
|
59
src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetSettings.cs
Normal file
59
src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetSettings.cs
Normal file
@ -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<NzbgetSettings>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
@ -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; }
|
@ -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<FolderSettings>, IExecute<TestPneumaticCommand>
|
||||
{
|
||||
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<QueueItem> GetQueue()
|
||||
public override IEnumerable<QueueItem> GetQueue()
|
||||
{
|
||||
return new QueueItem[0];
|
||||
}
|
||||
|
||||
public IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0)
|
||||
public override IEnumerable<HistoryItem> 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
public class ConnectionInfoModel
|
||||
{
|
||||
public string Address { get; set; }
|
||||
public int Port { get; set; }
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<string>();
|
||||
}
|
||||
|
||||
public bool Status { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "nzo_ids")]
|
||||
public List<string> Ids { get; set; }
|
||||
}
|
||||
}
|
@ -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<String>();
|
||||
}
|
||||
|
||||
public List<String> Categories { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd.Responses
|
||||
{
|
||||
public class SabnzbdVersionResponse
|
||||
{
|
||||
public string Version { get; set; }
|
||||
}
|
||||
}
|
@ -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<String>();
|
||||
}
|
||||
|
||||
public bool Status { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "nzo_ids")]
|
||||
public List<String> Ids { get; set; }
|
||||
}
|
||||
}
|
@ -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<ConnectionInfoModel> 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<ConnectionInfoModel> 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("\\<input\\Wtype\\=\\\"text\\\"\\Wid\\=\\\"apikey\\\"\\Wvalue\\=\\\"(?<apikey>\\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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
public class SabCategoryModel
|
||||
{
|
||||
public List<string> categories { get; set; }
|
||||
}
|
||||
}
|
@ -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<SabAddResponse>(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<SabJsonError>(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
public class SabVersionModel
|
||||
{
|
||||
public string Version { get; set; }
|
||||
}
|
||||
}
|
133
src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs
Normal file
133
src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs
Normal file
@ -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<SabnzbdSettings>, IExecute<TestSabnzbdCommand>
|
||||
{
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly ISabnzbdProxy _sabnzbdProxy;
|
||||
private readonly ICached<IEnumerable<QueueItem>> _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<IEnumerable<QueueItem>>(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<QueueItem> GetQueue()
|
||||
{
|
||||
return _queueCache.Get("queue", () =>
|
||||
{
|
||||
var sabQueue = _sabnzbdProxy.GetQueue(0, 0, Settings).Items;
|
||||
|
||||
var queueItems = new List<QueueItem>();
|
||||
|
||||
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<HistoryItem> GetHistory(int start = 0, int limit = 0)
|
||||
{
|
||||
var items = _sabnzbdProxy.GetHistory(start, limit, Settings).Items;
|
||||
var historyItems = new List<HistoryItem>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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<IEnumerable<QueueItem>> _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<IEnumerable<QueueItem>>(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<QueueItem> 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<SabQueue>(JObject.Parse(response).SelectToken("queue").ToString()).Items;
|
||||
|
||||
var queueItems = new List<QueueItem>();
|
||||
|
||||
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<HistoryItem> 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<SabHistory>(JObject.Parse(response).SelectToken("history").ToString()).Items;
|
||||
var historyItems = new List<HistoryItem>();
|
||||
|
||||
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<string>() };
|
||||
|
||||
var categories = Json.Deserialize<SabCategoryModel>(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<SabVersionModel>(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<SabJsonError>(response);
|
||||
|
||||
if (result.Failed)
|
||||
throw new ApplicationException(result.Error);
|
||||
}
|
||||
}
|
||||
}
|
@ -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<SabQueueItem> Items { get; set; }
|
||||
public List<SabnzbdHistoryItem> Items { get; set; }
|
||||
}
|
||||
}
|
@ -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; }
|
@ -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; }
|
@ -1,6 +1,6 @@
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
public enum SabPriorityType
|
||||
public enum SabnzbdPriority
|
||||
{
|
||||
Default = -100,
|
||||
Paused = -2,
|
182
src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdProxy.cs
Normal file
182
src/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdProxy.cs
Normal file
@ -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<SabnzbdAddResponse>(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<SabnzbdVersionResponse>(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<SabnzbdCategoryResponse>(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<SabnzbdQueue>(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<SabnzbdHistory>(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<SabnzbdJsonError>(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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<SabHistoryItem> Items { get; set; }
|
||||
public List<SabnzbdQueueItem> Items { get; set; }
|
||||
}
|
||||
}
|
@ -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; }
|
@ -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<SabnzbdSettings>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
48
src/NzbDrone.Core/Download/DownloadClientBase.cs
Normal file
48
src/NzbDrone.Core/Download/DownloadClientBase.cs
Normal file
@ -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<TSettings> : IDownloadClient where TSettings : IProviderConfig, new()
|
||||
{
|
||||
public Type ConfigContract
|
||||
{
|
||||
get
|
||||
{
|
||||
return typeof(TSettings);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ProviderDefinition> DefaultDefinitions
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<ProviderDefinition>();
|
||||
}
|
||||
}
|
||||
|
||||
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<QueueItem> GetQueue();
|
||||
public abstract IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0);
|
||||
public abstract void RemoveFromQueue(string id);
|
||||
public abstract void RemoveFromHistory(string id);
|
||||
}
|
||||
}
|
12
src/NzbDrone.Core/Download/DownloadClientDefinition.cs
Normal file
12
src/NzbDrone.Core/Download/DownloadClientDefinition.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
29
src/NzbDrone.Core/Download/DownloadClientFactory.cs
Normal file
29
src/NzbDrone.Core/Download/DownloadClientFactory.cs
Normal file
@ -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<IDownloadClient, DownloadClientDefinition>
|
||||
{
|
||||
List<IDownloadClient> Enabled();
|
||||
}
|
||||
|
||||
public class DownloadClientFactory : ProviderFactory<IDownloadClient, DownloadClientDefinition>, IDownloadClientFactory
|
||||
{
|
||||
private readonly IDownloadClientRepository _providerRepository;
|
||||
|
||||
public DownloadClientFactory(IDownloadClientRepository providerRepository, IEnumerable<IDownloadClient> providers, IContainer container, Logger logger)
|
||||
: base(providerRepository, providers, container, logger)
|
||||
{
|
||||
_providerRepository = providerRepository;
|
||||
}
|
||||
|
||||
public List<IDownloadClient> Enabled()
|
||||
{
|
||||
return GetAvailableProviders().Where(n => ((DownloadClientDefinition)n.Definition).Enable).ToList();
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
20
src/NzbDrone.Core/Download/DownloadClientRepository.cs
Normal file
20
src/NzbDrone.Core/Download/DownloadClientRepository.cs
Normal file
@ -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<DownloadClientDefinition>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class DownloadClientRepository : ProviderRepository<DownloadClientDefinition>, IDownloadClientRepository
|
||||
{
|
||||
public DownloadClientRepository(IDatabase database, IEventAggregator eventAggregator)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
18
src/NzbDrone.Core/Download/Events/DownloadFailedEvent.cs
Normal file
18
src/NzbDrone.Core/Download/Events/DownloadFailedEvent.cs
Normal file
@ -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<Int32> 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; }
|
||||
}
|
||||
}
|
18
src/NzbDrone.Core/Download/Events/EpisodeGrabbedEvent.cs
Normal file
18
src/NzbDrone.Core/Download/Events/EpisodeGrabbedEvent.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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<QueueItem> GetQueue();
|
||||
IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0);
|
||||
void RemoveFromQueue(string id);
|
||||
|
@ -59,7 +59,7 @@ namespace NzbDrone.Core.Indexers
|
||||
|
||||
public enum DownloadProtocol
|
||||
{
|
||||
Usenet,
|
||||
Torrent
|
||||
Usenet = 1,
|
||||
Torrent = 2
|
||||
}
|
||||
}
|
@ -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<SeriesRenamedEvent>
|
||||
{
|
||||
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;
|
||||
|
@ -198,6 +198,8 @@
|
||||
<Compile Include="Datastore\Migration\040_add_metadata_to_episodes_and_series.cs" />
|
||||
<Compile Include="Datastore\Migration\039_add_metadata_tables.cs" />
|
||||
<Compile Include="Datastore\Migration\041_fix_xbmc_season_images_metadata.cs" />
|
||||
<Compile Include="Datastore\Migration\041_add_download_clients_table.cs" />
|
||||
<Compile Include="Datastore\Migration\042_convert_config_to_download_clients.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />
|
||||
@ -240,13 +242,27 @@
|
||||
<Compile Include="DecisionEngine\Specifications\RssSync\HistorySpecification.cs" />
|
||||
<Compile Include="DiskSpace\DiskSpace.cs" />
|
||||
<Compile Include="DiskSpace\DiskSpaceService.cs" />
|
||||
<Compile Include="Download\Clients\Blackhole\Blackhole.cs" />
|
||||
<Compile Include="Download\Clients\Blackhole\TestBlackholeCommand.cs" />
|
||||
<Compile Include="Download\Clients\FolderSettings.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\NzbgetSettings.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\TestNzbgetCommand.cs" />
|
||||
<Compile Include="Download\Clients\Pneumatic\Pneumatic.cs" />
|
||||
<Compile Include="Download\Clients\Pneumatic\TestPneumaticCommand.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\Responses\SabnzbdAddResponse.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\Responses\SabnzbdCategoryResponse.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\Responses\SabnzbdVersionResponse.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdSettings.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\TestSabnzbdCommand.cs" />
|
||||
<Compile Include="Download\DownloadClientBase.cs" />
|
||||
<Compile Include="Download\DownloadClientDefinition.cs" />
|
||||
<Compile Include="Download\DownloadClientFactory.cs" />
|
||||
<Compile Include="Download\DownloadClientRepository.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\JsonRequest.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\NzbGetCommunicationProxy.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\ConnectionInfoModel.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\NzbgetProxy.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\JsonConverters\SabnzbdPriorityTypeConverter.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\JsonConverters\SabnzbdQueueTimeConverter.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabAutoConfigureService.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabCommunicationProxy.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdProxy.cs" />
|
||||
<Compile Include="Download\CheckForFailedDownloadCommand.cs" />
|
||||
<Compile Include="Download\HistoryItem.cs" />
|
||||
<Compile Include="Download\DownloadFailedEvent.cs" />
|
||||
@ -476,10 +492,10 @@
|
||||
<Compile Include="Download\Clients\Nzbget\EnqueueResponse.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\ErrorModel.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\JsonError.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\NzbGetQueue.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\NzbGetQueueItem.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\PriorityType.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\VersionModel.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\NzbgetQueue.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\NzbgetQueueItem.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\NzbgetPriority.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\VersionResponse.cs" />
|
||||
<Compile Include="Organizer\NamingConfig.cs" />
|
||||
<Compile Include="Parser\Language.cs" />
|
||||
<Compile Include="Parser\Model\LocalEpisode.cs" />
|
||||
@ -529,18 +545,13 @@
|
||||
<Compile Include="Tv\RefreshEpisodeService.cs" />
|
||||
<Compile Include="Tv\SeriesRepository.cs" />
|
||||
<Compile Include="Qualities\QualityModel.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabAddResponse.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabHistoryItem.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabHistory.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabJsonError.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabQueue.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabCategoryModel.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabModel.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabQueueItem.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabVersionModel.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdHistoryItem.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdHistory.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdJsonError.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdQueue.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdQueueItem.cs" />
|
||||
<Compile Include="MediaCover\MediaCoverService.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\NzbgetClient.cs" />
|
||||
<Compile Include="Download\Clients\PneumaticClient.cs" />
|
||||
<Compile Include="Download\Clients\Nzbget\Nzbget.cs" />
|
||||
<Compile Include="MediaFiles\RecycleBinProvider.cs" />
|
||||
<Compile Include="SeriesStats\SeriesStatistics.cs" />
|
||||
<Compile Include="SeriesStats\SeriesStatisticsRepository.cs" />
|
||||
@ -556,13 +567,10 @@
|
||||
<Compile Include="MediaFiles\DiskScanService.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Download\Clients\BlackholeProvider.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Download\IDownloadClient.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdClient.cs">
|
||||
<Compile Include="Download\Clients\Sabnzbd\Sabnzbd.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Download\DownloadService.cs">
|
||||
@ -631,7 +639,7 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Notifications\NotificationDefinition.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabPriorityType.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdPriority.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeFile.cs" />
|
||||
<Compile Include="Tv\Episode.cs" />
|
||||
<Compile Include="Instrumentation\Log.cs" />
|
||||
|
@ -23,6 +23,13 @@ namespace NzbDrone.Core.Queue
|
||||
public List<Queue> GetQueue()
|
||||
{
|
||||
var downloadClient = _downloadClientProvider.GetDownloadClient();
|
||||
|
||||
if (downloadClient == null)
|
||||
{
|
||||
_logger.Trace("Download client is not configured.");
|
||||
return new List<Queue>();
|
||||
}
|
||||
|
||||
var queueItems = downloadClient.GetQueue();
|
||||
|
||||
return MapQueue(queueItems);
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
4
src/UI/.idea/jsLinters/jshint.xml
generated
4
src/UI/.idea/jsLinters/jshint.xml
generated
@ -8,16 +8,16 @@
|
||||
<option es3="false" />
|
||||
<option forin="true" />
|
||||
<option immed="true" />
|
||||
<option latedef="true" />
|
||||
<option newcap="true" />
|
||||
<option noarg="true" />
|
||||
<option noempty="false" />
|
||||
<option nonew="true" />
|
||||
<option plusplus="false" />
|
||||
<option undef="true" />
|
||||
<option unused="true" />
|
||||
<option strict="true" />
|
||||
<option trailing="false" />
|
||||
<option latedef="true" />
|
||||
<option unused="true" />
|
||||
<option quotmark="single" />
|
||||
<option maxdepth="3" />
|
||||
<option asi="false" />
|
||||
|
@ -35,6 +35,13 @@ define(
|
||||
]);
|
||||
}
|
||||
|
||||
if (field.type === 'path') {
|
||||
return _templateRenderer.apply(field,
|
||||
[
|
||||
'Form/PathTemplate'
|
||||
]);
|
||||
}
|
||||
|
||||
return _templateRenderer.apply(field,
|
||||
[
|
||||
'Form/TextboxTemplate'
|
||||
|
12
src/UI/Form/PathTemplate.html
Normal file
12
src/UI/Form/PathTemplate.html
Normal file
@ -0,0 +1,12 @@
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{label}}</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="fields.{{order}}.value" validation-name="{{name}}" class="x-path"/>
|
||||
{{#if helpText}}
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="{{helpText}}"/>
|
||||
</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Add/DownloadClientAddItemView'
|
||||
], function (Marionette, AddItemView) {
|
||||
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : AddItemView,
|
||||
itemViewContainer: '.add-download-client .items',
|
||||
template : 'Settings/DownloadClient/Add/DownloadClientAddCollectionViewTemplate',
|
||||
|
||||
itemViewOptions: function () {
|
||||
return {
|
||||
downloadClientCollection: this.downloadClientCollection
|
||||
};
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.downloadClientCollection = options.downloadClientCollection;
|
||||
}
|
||||
});
|
||||
});
|
@ -0,0 +1,12 @@
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Add Download Client</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="add-download-client add-thingies">
|
||||
<ul class="items"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal">close</button>
|
||||
</div>
|
@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Edit/DownloadClientEditView'
|
||||
], function (AppLayout, Marionette, EditView) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/Add/DownloadClientAddItemViewTemplate',
|
||||
tagName : 'li',
|
||||
|
||||
events: {
|
||||
'click': '_add'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.downloadClientCollection = options.downloadClientCollection;
|
||||
},
|
||||
|
||||
_add: function (e) {
|
||||
if (this.$(e.target).hasClass('icon-info-sign')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.model.set({
|
||||
id : undefined,
|
||||
name : this.model.get('implementationName'),
|
||||
onGrab : true,
|
||||
onDownload : true,
|
||||
onUpgrade : true
|
||||
});
|
||||
|
||||
var editView = new EditView({ model: this.model, downloadClientCollection: this.downloadClientCollection });
|
||||
AppLayout.modalRegion.show(editView);
|
||||
}
|
||||
});
|
||||
});
|
@ -0,0 +1,10 @@
|
||||
<div class="add-thingy span3">
|
||||
<div class="row">
|
||||
<div class="span3">
|
||||
{{implementation}}
|
||||
{{#if link}}
|
||||
<a href="{{link}}"><i class="icon-info-sign"/></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
20
src/UI/Settings/DownloadClient/Add/SchemaModal.js
Normal file
20
src/UI/Settings/DownloadClient/Add/SchemaModal.js
Normal file
@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
define([
|
||||
'AppLayout',
|
||||
'Settings/DownloadClient/DownloadClientCollection',
|
||||
'Settings/DownloadClient/Add/DownloadClientAddCollectionView'
|
||||
], function (AppLayout, DownloadClientCollection, DownloadClientAddCollectionView) {
|
||||
return ({
|
||||
|
||||
open: function (collection) {
|
||||
var schemaCollection = new DownloadClientCollection();
|
||||
var originalUrl = schemaCollection.url;
|
||||
schemaCollection.url = schemaCollection.url + '/schema';
|
||||
schemaCollection.fetch();
|
||||
schemaCollection.url = originalUrl;
|
||||
|
||||
var view = new DownloadClientAddCollectionView({ collection: schemaCollection, downloadClientCollection: collection});
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
});
|
@ -1,24 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (Marionette, AsModelBoundView) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template : 'Settings/DownloadClient/BlackholeViewTemplate',
|
||||
|
||||
ui: {
|
||||
'blackholeFolder': '.x-path'
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.ui.blackholeFolder.autoComplete('/directories');
|
||||
}
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(view);
|
||||
});
|
@ -1,13 +0,0 @@
|
||||
<fieldset>
|
||||
<legend>Blackhole</legend>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Blackhole Folder</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="blackholeFolder" class="x-path"/>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="The folder where your download client will pickup .nzb files"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'vent',
|
||||
'marionette'
|
||||
], function (vent, Marionette) {
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/Delete/DownloadClientDeleteViewTemplate',
|
||||
|
||||
events: {
|
||||
'click .x-confirm-delete': '_delete'
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
this.model.destroy({
|
||||
wait : true,
|
||||
success: function () {
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
@ -0,0 +1,11 @@
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Delete Download Client</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Are you sure you want to delete '{{name}}'?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal">cancel</button>
|
||||
<button class="btn btn-danger x-confirm-delete">delete</button>
|
||||
</div>
|
12
src/UI/Settings/DownloadClient/DownloadClientCollection.js
Normal file
12
src/UI/Settings/DownloadClient/DownloadClientCollection.js
Normal file
@ -0,0 +1,12 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'Settings/DownloadClient/DownloadClientModel'
|
||||
], function (Backbone, DownloadClientModel) {
|
||||
|
||||
return Backbone.Collection.extend({
|
||||
model: DownloadClientModel,
|
||||
url : window.NzbDrone.ApiRoot + '/downloadclient'
|
||||
});
|
||||
});
|
@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'underscore',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/DownloadClientItemView',
|
||||
'Settings/DownloadClient/Add/SchemaModal'
|
||||
], function (_, AppLayout, Marionette, DownloadClientItemView, SchemaModal) {
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : DownloadClientItemView,
|
||||
itemViewContainer: '#x-download-clients',
|
||||
template : 'Settings/DownloadClient/DownloadClientCollectionViewTemplate',
|
||||
|
||||
ui: {
|
||||
'addCard': '.x-add-card'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-add-card': '_openSchemaModal'
|
||||
},
|
||||
|
||||
appendHtml: function (collectionView, itemView, index) {
|
||||
collectionView.ui.addCard.parent('li').before(itemView.el);
|
||||
},
|
||||
|
||||
_openSchemaModal: function () {
|
||||
SchemaModal.open(this.collection);
|
||||
}
|
||||
});
|
||||
});
|
@ -0,0 +1,16 @@
|
||||
<fieldset>
|
||||
<legend>Download Clients</legend>
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<ul id="x-download-clients" class="download-client-list">
|
||||
<li>
|
||||
<div class="download-client-item thingy add-card x-add-card">
|
||||
<span class="center well">
|
||||
<i class="icon-plus" title="Add Download Client"/>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
34
src/UI/Settings/DownloadClient/DownloadClientItemView.js
Normal file
34
src/UI/Settings/DownloadClient/DownloadClientItemView.js
Normal file
@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Edit/DownloadClientEditView',
|
||||
'Settings/DownloadClient/Delete/DownloadClientDeleteView'
|
||||
], function (AppLayout, Marionette, EditView, DeleteView) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/DownloadClientItemViewTemplate',
|
||||
tagName : 'li',
|
||||
|
||||
events: {
|
||||
'click .x-edit' : '_edit',
|
||||
'click .x-delete' : '_delete'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.listenTo(this.model, 'sync', this.render);
|
||||
},
|
||||
|
||||
_edit: function () {
|
||||
var view = new EditView({ model: this.model});
|
||||
AppLayout.modalRegion.show(view);
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
var view = new DeleteView({ model: this.model});
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
});
|
@ -0,0 +1,17 @@
|
||||
<div class="download-client-item thingy">
|
||||
<div>
|
||||
<h3>{{name}}</h3>
|
||||
<span class="btn-group pull-right">
|
||||
<button class="btn btn-mini btn-icon-only x-edit"><i class="icon-nd-edit"/></button>
|
||||
<button class="btn btn-mini btn-icon-only x-delete"><i class="icon-nd-delete"/></button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="settings">
|
||||
{{#if enable}}
|
||||
<span class="label label-success">Enabled</span>
|
||||
{{else}}
|
||||
<span class="label">Not Enabled</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
40
src/UI/Settings/DownloadClient/DownloadClientLayout.js
Normal file
40
src/UI/Settings/DownloadClient/DownloadClientLayout.js
Normal file
@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Settings/DownloadClient/DownloadClientCollection',
|
||||
'Settings/DownloadClient/DownloadClientCollectionView',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (Marionette, DownloadClientCollection, DownloadClientCollectionView, AsModelBoundView) {
|
||||
|
||||
var view = Marionette.Layout.extend({
|
||||
template : 'Settings/DownloadClient/DownloadClientLayoutTemplate',
|
||||
|
||||
regions: {
|
||||
downloadClients: '#x-download-clients-region'
|
||||
},
|
||||
|
||||
ui: {
|
||||
droneFactory: '.x-path'
|
||||
},
|
||||
|
||||
events: {
|
||||
'change .x-download-client': 'downloadClientChanged'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.downloadClientCollection = new DownloadClientCollection();
|
||||
this.downloadClientCollection.fetch();
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.downloadClients.show(new DownloadClientCollectionView({ collection: this.downloadClientCollection }));
|
||||
this.ui.droneFactory.autoComplete('/directories');
|
||||
}
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(view);
|
||||
});
|
@ -0,0 +1,16 @@
|
||||
<div id="x-download-clients-region"></div>
|
||||
|
||||
<fieldset class="form-horizontal">
|
||||
<legend>Options</legend>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Drone Factory</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="downloadedEpisodesFolder" class="x-path"/>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="The folder where your download client downloads TV shows to (Completed Download Directory)"/>
|
||||
<i class="icon-nd-form-warning" title="Do not use the folder that contains some or all of your sorted and named TV shows - doing so could cause data loss"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
10
src/UI/Settings/DownloadClient/DownloadClientModel.js
Normal file
10
src/UI/Settings/DownloadClient/DownloadClientModel.js
Normal file
@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone.deepmodel'
|
||||
], function (DeepModel) {
|
||||
return DeepModel.DeepModel.extend({
|
||||
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,93 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'vent',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Delete/DownloadClientDeleteView',
|
||||
'Commands/CommandController',
|
||||
'Mixins/AsModelBoundView',
|
||||
'underscore',
|
||||
'Form/FormBuilder',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (vent, AppLayout, Marionette, DeleteView, CommandController, AsModelBoundView, _) {
|
||||
|
||||
var model = Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/Edit/DownloadClientEditViewTemplate',
|
||||
|
||||
ui: {
|
||||
path : '.x-path',
|
||||
modalBody : '.modal-body'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-save' : '_save',
|
||||
'click .x-save-and-add': '_saveAndAdd',
|
||||
'click .x-delete' : '_delete',
|
||||
'click .x-back' : '_back',
|
||||
'click .x-test' : '_test'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.downloadClientCollection = options.downloadClientCollection;
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
//Hack to deal with modals not overflowing
|
||||
if (this.ui.path.length > 0) {
|
||||
this.ui.modalBody.addClass('modal-overflow');
|
||||
}
|
||||
|
||||
this.ui.path.autoComplete('/directories');
|
||||
},
|
||||
|
||||
_save: function () {
|
||||
var self = this;
|
||||
var promise = this.model.save();
|
||||
|
||||
if (promise) {
|
||||
promise.done(function () {
|
||||
self.downloadClientCollection.add(self.model, { merge: true });
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_saveAndAdd: function () {
|
||||
var self = this;
|
||||
var promise = this.model.save();
|
||||
|
||||
if (promise) {
|
||||
promise.done(function () {
|
||||
self.notificationCollection.add(self.model, { merge: true });
|
||||
|
||||
require('Settings/DownloadClient/Add/SchemaModal').open(self.downloadClientCollection);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
var view = new DeleteView({ model: this.model });
|
||||
AppLayout.modalRegion.show(view);
|
||||
},
|
||||
|
||||
_back: function () {
|
||||
require('Settings/DownloadClient/Add/SchemaModal').open(this.downloadClientCollection);
|
||||
},
|
||||
|
||||
_test: function () {
|
||||
var testCommand = 'test{0}'.format(this.model.get('implementation'));
|
||||
var properties = {};
|
||||
|
||||
_.each(this.model.get('fields'), function (field) {
|
||||
properties[field.name] = field.value;
|
||||
});
|
||||
|
||||
CommandController.Execute(testCommand, properties);
|
||||
}
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(model);
|
||||
});
|
@ -0,0 +1,59 @@
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
{{#if id}}
|
||||
<h3>Edit - {{implementation}}</h3>
|
||||
{{else}}
|
||||
<h3>Add - {{implementation}}</h3>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="modal-body download-client-modal">
|
||||
<div class="form-horizontal">
|
||||
<div class="control-group">
|
||||
<label class="control-label">Name</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="name"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Enable</label>
|
||||
|
||||
<div class="controls">
|
||||
<label class="checkbox toggle well">
|
||||
<input type="checkbox" name="enable"/>
|
||||
<p>
|
||||
<span>Yes</span>
|
||||
<span>No</span>
|
||||
</p>
|
||||
|
||||
<div class="btn btn-primary slide-button"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{formBuilder}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
{{#if id}}
|
||||
<button class="btn btn-danger pull-left x-delete">delete</button>
|
||||
{{else}}
|
||||
<button class="btn pull-left x-back">back</button>
|
||||
{{/if}}
|
||||
|
||||
<button class="btn x-test">test <i class="x-test-icon icon-nd-test"/></button>
|
||||
<button class="btn" data-dismiss="modal">cancel</button>
|
||||
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-primary x-save">save</button>
|
||||
<button class="btn btn-icon-only btn-primary dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="save-and-add x-save-and-add">
|
||||
save and add
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
@ -1,78 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Settings/DownloadClient/SabView',
|
||||
'Settings/DownloadClient/BlackholeView',
|
||||
'Settings/DownloadClient/PneumaticView',
|
||||
'Settings/DownloadClient/NzbgetView',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (Marionette, SabView, BlackholeView, PneumaticView, NzbgetView, AsModelBoundView) {
|
||||
|
||||
var view = Marionette.Layout.extend({
|
||||
template : 'Settings/DownloadClient/LayoutTemplate',
|
||||
|
||||
regions: {
|
||||
downloadClient: '#download-client-settings-region'
|
||||
},
|
||||
|
||||
ui: {
|
||||
downloadClientSelect: '.x-download-client',
|
||||
downloadedEpisodesFolder: '.x-path'
|
||||
},
|
||||
|
||||
events: {
|
||||
'change .x-download-client': 'downloadClientChanged'
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.sabView = new SabView({ model: this.model});
|
||||
this.blackholeView = new BlackholeView({ model: this.model});
|
||||
this.pneumaticView = new PneumaticView({ model: this.model});
|
||||
this.nzbgetView = new NzbgetView({ model: this.model});
|
||||
|
||||
this.ui.downloadedEpisodesFolder.autoComplete('/directories');
|
||||
|
||||
var client = this.model.get('downloadClient');
|
||||
this.refreshUIVisibility(client);
|
||||
},
|
||||
|
||||
downloadClientChanged: function () {
|
||||
var clientId = this.ui.downloadClientSelect.val();
|
||||
this.refreshUIVisibility(clientId);
|
||||
},
|
||||
|
||||
refreshUIVisibility: function (clientId) {
|
||||
|
||||
if (!clientId) {
|
||||
clientId = 'sabnzbd';
|
||||
}
|
||||
|
||||
switch (clientId.toString()) {
|
||||
case 'sabnzbd':
|
||||
this.downloadClient.show(this.sabView);
|
||||
break;
|
||||
|
||||
case 'blackhole':
|
||||
this.downloadClient.show(this.blackholeView);
|
||||
break;
|
||||
|
||||
case 'pneumatic':
|
||||
this.downloadClient.show(this.pneumaticView);
|
||||
break;
|
||||
|
||||
case 'nzbget':
|
||||
this.downloadClient.show(this.nzbgetView);
|
||||
break;
|
||||
|
||||
default :
|
||||
throw 'unknown download client id' + clientId;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(view);
|
||||
});
|
@ -1,29 +0,0 @@
|
||||
<fieldset class="form-horizontal">
|
||||
<legend>General</legend>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Download Client</label>
|
||||
|
||||
<div class="controls">
|
||||
<select class="inputClass x-download-client" name="downloadClient">
|
||||
<option value="sabnzbd">SABnzbd</option>
|
||||
<option value="blackhole">Blackhole</option>
|
||||
<option value="pneumatic">Pneumatic</option>
|
||||
<option value="nzbget">NZBGet</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Drone Factory</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="downloadedEpisodesFolder" class="x-path"/>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="The folder where your download client downloads TV shows to (Completed Download Directory)"/>
|
||||
<i class="icon-nd-form-warning" title="Do not use the folder that contains some or all of your sorted and named TV shows - doing so could cause data loss"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div id="download-client-settings-region" class="form-horizontal"></div>
|
@ -1,15 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Mixins/AsModelBoundView',
|
||||
'bootstrap'
|
||||
], function (Marionette, AsModelBoundView) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template : 'Settings/DownloadClient/NzbgetViewTemplate'
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(view);
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user