diff --git a/NzbDrone.Core.Test/Files/JsonError.txt b/NzbDrone.Core.Test/Files/JsonError.txt
index aa32a0bdd..3c937f046 100644
--- a/NzbDrone.Core.Test/Files/JsonError.txt
+++ b/NzbDrone.Core.Test/Files/JsonError.txt
@@ -1,4 +1,8 @@
{
- "status": false,
- "error": "API Key Incorrect"
+ "version": "1.1",
+ "error": {
+ "name": "JSONRPCError",
+ "code": 1,
+ "message": "Invalid procedure"
+ }
}
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/Files/Nzbget/JsonError.txt b/NzbDrone.Core.Test/Files/Nzbget/JsonError.txt
new file mode 100644
index 000000000..3c937f046
--- /dev/null
+++ b/NzbDrone.Core.Test/Files/Nzbget/JsonError.txt
@@ -0,0 +1,8 @@
+{
+ "version": "1.1",
+ "error": {
+ "name": "JSONRPCError",
+ "code": 1,
+ "message": "Invalid procedure"
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/Files/Nzbget/Queue.txt b/NzbDrone.Core.Test/Files/Nzbget/Queue.txt
new file mode 100644
index 000000000..ff3b1f354
--- /dev/null
+++ b/NzbDrone.Core.Test/Files/Nzbget/Queue.txt
@@ -0,0 +1,33 @@
+{
+ "version": "1.1",
+ "result": [
+ {
+ "FirstID": 1,
+ "LastID": 26,
+ "FileSizeLo": 350152055,
+ "FileSizeHi": 0,
+ "FileSizeMB": 333,
+ "RemainingSizeLo": 350152055,
+ "RemainingSizeHi": 0,
+ "RemainingSizeMB": 333,
+ "PausedSizeLo": 33317835,
+ "PausedSizeHi": 0,
+ "PausedSizeMB": 31,
+ "FileCount": 26,
+ "RemainingFileCount": 26,
+ "RemainingParCount": 7,
+ "MinPostTime": 1358913959,
+ "MaxPostTime": 1358913965,
+ "NZBID": 1,
+ "NZBName": "White.Collar.S04E11.HDTV.x264-2HD",
+ "NZBNicename": "White.Collar.S04E11.HDTV.x264-2HD",
+ "NZBFilename": "C:\\Test\\Blackhole\\White.Collar.S04E11.HDTV.x264-2HD.nzb",
+ "DestDir": "C:\\test\\NzbGet\\\\dst\\TV\\White.Collar.S04E11.HDTV.x264-2HD",
+ "Category": "TV",
+ "MinPriority": 0,
+ "MaxPriority": 0,
+ "ActiveDownloads": 4,
+ "Parameters": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/Files/Nzbget/Queue_empty.txt b/NzbDrone.Core.Test/Files/Nzbget/Queue_empty.txt
new file mode 100644
index 000000000..4cd0e17ab
--- /dev/null
+++ b/NzbDrone.Core.Test/Files/Nzbget/Queue_empty.txt
@@ -0,0 +1,4 @@
+{
+ "version": "1.1",
+ "result": []
+}
\ No newline at end of file
diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
index 3323c5cfb..bcbcad378 100644
--- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
+++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
@@ -142,6 +142,8 @@
+
+
@@ -277,6 +279,15 @@
Always
+
+ Always
+
+
+ Always
+
+
+ Always
+
Always
diff --git a/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/NzbgetProviderTests/DownloadNzbFixture.cs b/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/NzbgetProviderTests/DownloadNzbFixture.cs
new file mode 100644
index 000000000..1c2fd7401
--- /dev/null
+++ b/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/NzbgetProviderTests/DownloadNzbFixture.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using FluentAssertions;
+using Moq;
+using NUnit.Framework;
+using NzbDrone.Common;
+using NzbDrone.Core.Model.Nzbget;
+using NzbDrone.Core.Providers.Core;
+using NzbDrone.Core.Providers.DownloadClients;
+using NzbDrone.Test.Common;
+
+namespace NzbDrone.Core.Test.ProviderTests.DownloadClientTests.NzbgetProviderTests
+{
+ public class DownloadNzbFixture : TestBase
+ {
+ [SetUp]
+ public void Setup()
+ {
+ var fakeConfig = Mocker.GetMock();
+ fakeConfig.SetupGet(c => c.NzbgetHost).Returns("192.168.5.55");
+ fakeConfig.SetupGet(c => c.NzbgetPort).Returns(6789);
+ fakeConfig.SetupGet(c => c.NzbgetUsername).Returns("nzbget");
+ fakeConfig.SetupGet(c => c.NzbgetPassword).Returns("pass");
+ fakeConfig.SetupGet(c => c.NzbgetTvCategory).Returns("TV");
+ fakeConfig.SetupGet(c => c.NzbgetBacklogTvPriority).Returns(PriorityType.Normal);
+ fakeConfig.SetupGet(c => c.NzbgetRecentTvPriority).Returns(PriorityType.High);
+ }
+
+
+ private void WithFailResponse()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.PostCommand("http://192.168.5.55:6789/jsonrpc", "nzbget", "pass", It.IsAny()))
+ .Returns(File.ReadAllText(@".\Files\Nzbget\JsonError.txt"));
+ }
+
+ [Test]
+ public void should_add_item_to_queue()
+ {
+ const string url = "http://www.nzbdrone.com";
+ const string title = "30 Rock - S01E01 - Pilot [HDTV-720p]";
+
+ Mocker.GetMock()
+ .Setup(s => s.PostCommand("http://192.168.5.55:6789/jsonrpc", "nzbget", "pass",
+ It.Is(c => c.Equals("{\"method\":\"appendurl\",\"params\":[\"30 Rock - S01E01 - Pilot [HDTV-720p]\",\"TV\",0,false,\"http://www.nzbdrone.com\"]}"))))
+ .Returns("{\"version\": \"1.1\",\"result\": true}");
+
+ Mocker.Resolve()
+ .DownloadNzb(url, title, false)
+ .Should()
+ .BeTrue();
+ }
+
+ [Test]
+ public void should_throw_when_error_is_returned()
+ {
+ WithFailResponse();
+
+ Assert.Throws(() => Mocker.Resolve().DownloadNzb("http://www.nzbdrone.com", "30 Rock - S01E01 - Pilot [HDTV-720p]", false));
+ }
+ }
+}
diff --git a/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/NzbgetProviderTests/QueueFixture.cs b/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/NzbgetProviderTests/QueueFixture.cs
new file mode 100644
index 000000000..20afc7cb2
--- /dev/null
+++ b/NzbDrone.Core.Test/ProviderTests/DownloadClientTests/NzbgetProviderTests/QueueFixture.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using FluentAssertions;
+using Moq;
+using NUnit.Framework;
+using NzbDrone.Common;
+using NzbDrone.Core.Model.Nzbget;
+using NzbDrone.Core.Providers.Core;
+using NzbDrone.Core.Providers.DownloadClients;
+using NzbDrone.Test.Common;
+
+namespace NzbDrone.Core.Test.ProviderTests.DownloadClientTests.NzbgetProviderTests
+{
+ public class QueueFixture : TestBase
+ {
+ [SetUp]
+ public void Setup()
+ {
+ var fakeConfig = Mocker.GetMock();
+ fakeConfig.SetupGet(c => c.NzbgetHost).Returns("192.168.5.55");
+ fakeConfig.SetupGet(c => c.NzbgetPort).Returns(6789);
+ fakeConfig.SetupGet(c => c.NzbgetUsername).Returns("nzbget");
+ fakeConfig.SetupGet(c => c.NzbgetPassword).Returns("pass");
+ fakeConfig.SetupGet(c => c.NzbgetTvCategory).Returns("TV");
+ fakeConfig.SetupGet(c => c.NzbgetBacklogTvPriority).Returns(PriorityType.Normal);
+ fakeConfig.SetupGet(c => c.NzbgetRecentTvPriority).Returns(PriorityType.High);
+ }
+
+ private void WithFullQueue()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.PostCommand("http://192.168.5.55:6789/jsonrpc", "nzbget", "pass", It.IsAny()))
+ .Returns(File.ReadAllText(@".\Files\Nzbget\Queue.txt"));
+ }
+
+ private void WithEmptyQueue()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.PostCommand("http://192.168.5.55:6789/jsonrpc", "nzbget", "pass", It.IsAny()))
+ .Returns(File.ReadAllText(@".\Files\Nzbget\Queue_empty.txt"));
+ }
+
+ private void WithFailResponse()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.PostCommand("http://192.168.5.55:6789/jsonrpc", "nzbget", "pass", It.IsAny()))
+ .Returns(File.ReadAllText(@".\Files\Nzbget\JsonError.txt"));
+ }
+
+ [Test]
+ public void should_return_no_items_when_queue_is_empty()
+ {
+ WithEmptyQueue();
+
+ Mocker.Resolve()
+ .GetQueue()
+ .Should()
+ .BeEmpty();
+ }
+
+ [Test]
+ public void should_return_item_when_queue_has_item()
+ {
+ WithFullQueue();
+
+ Mocker.Resolve()
+ .GetQueue()
+ .Should()
+ .HaveCount(1);
+ }
+
+ [Test]
+ public void should_throw_when_error_is_returned()
+ {
+ WithFailResponse();
+
+ Assert.Throws(() => Mocker.Resolve().GetQueue());
+ }
+ }
+}
diff --git a/NzbDrone.Core.Test/ProviderTests/SearchTests/GetSearchTitleFixture.cs b/NzbDrone.Core.Test/ProviderTests/SearchTests/GetSearchTitleFixture.cs
index 82f6d78a8..02ad81710 100644
--- a/NzbDrone.Core.Test/ProviderTests/SearchTests/GetSearchTitleFixture.cs
+++ b/NzbDrone.Core.Test/ProviderTests/SearchTests/GetSearchTitleFixture.cs
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchTests
private void WithSceneMapping()
{
Mocker.GetMock()
- .Setup(s => s.GetSceneName(_series.SeriesId))
+ .Setup(s => s.GetSceneName(_series.SeriesId, -1))
.Returns("Hawaii Five 0 2010");
}
@@ -48,6 +48,26 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchTests
.Should().Be("Hawaii Five 0 2010");
}
+ [Test]
+ public void should_return_season_scene_name_when_one_exists()
+ {
+ Mocker.GetMock()
+ .Setup(s => s.GetSceneName(_series.SeriesId, 5))
+ .Returns("Hawaii Five 0 2010 - Season 5");
+
+ Mocker.Resolve().GetSearchTitle(_series, 5)
+ .Should().Be("Hawaii Five 0 2010 - Season 5");
+ }
+
+ [Test]
+ public void should_return_series_scene_name_when_one_for_season_does_not_exist()
+ {
+ WithSceneMapping();
+
+ Mocker.Resolve().GetSearchTitle(_series, 5)
+ .Should().Be("Hawaii Five 0 2010");
+ }
+
[Test]
public void should_replace_ampersand_with_and()
{
@@ -65,7 +85,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchTests
_series.Title = input;
Mocker.GetMock()
- .Setup(s => s.GetSceneName(_series.SeriesId))
+ .Setup(s => s.GetSceneName(_series.SeriesId, -1))
.Returns("");
Mocker.Resolve().GetSearchTitle(_series, 5)
diff --git a/NzbDrone.Core/Model/DownloadClientType.cs b/NzbDrone.Core/Model/DownloadClientType.cs
index 53072f9e6..31fb01c0d 100644
--- a/NzbDrone.Core/Model/DownloadClientType.cs
+++ b/NzbDrone.Core/Model/DownloadClientType.cs
@@ -4,6 +4,7 @@
{
Sabnzbd = 0,
Blackhole = 1,
- Pneumatic = 2
+ Pneumatic = 2,
+ Nzbget = 3
}
}
\ No newline at end of file
diff --git a/NzbDrone.Core/Model/Nzbget/EnqueueResponse.cs b/NzbDrone.Core/Model/Nzbget/EnqueueResponse.cs
new file mode 100644
index 000000000..c4aa4b4d6
--- /dev/null
+++ b/NzbDrone.Core/Model/Nzbget/EnqueueResponse.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace NzbDrone.Core.Model.Nzbget
+{
+ public class EnqueueResponse
+ {
+ public String Version { get; set; }
+ public Boolean Result { get; set; }
+ }
+}
diff --git a/NzbDrone.Core/Model/Nzbget/ErrorModel.cs b/NzbDrone.Core/Model/Nzbget/ErrorModel.cs
new file mode 100644
index 000000000..592b8abab
--- /dev/null
+++ b/NzbDrone.Core/Model/Nzbget/ErrorModel.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace NzbDrone.Core.Model.Nzbget
+{
+ public class ErrorModel
+ {
+ public String Name { get; set; }
+ public Int32 Code { get; set; }
+ public String Message { get; set; }
+
+ public override string ToString()
+ {
+ return String.Format("Name: {0}, Code: {1}, Message: {2}", Name, Code, Message);
+ }
+ }
+}
diff --git a/NzbDrone.Core/Model/Nzbget/JsonError.cs b/NzbDrone.Core/Model/Nzbget/JsonError.cs
new file mode 100644
index 000000000..7389efece
--- /dev/null
+++ b/NzbDrone.Core/Model/Nzbget/JsonError.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace NzbDrone.Core.Model.Nzbget
+{
+ public class JsonError
+ {
+ public String Version { get; set; }
+ public ErrorModel Error { get; set; }
+ }
+}
diff --git a/NzbDrone.Core/Model/Nzbget/JsonRequest.cs b/NzbDrone.Core/Model/Nzbget/JsonRequest.cs
new file mode 100644
index 000000000..3d3f812b1
--- /dev/null
+++ b/NzbDrone.Core/Model/Nzbget/JsonRequest.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace NzbDrone.Core.Model.Nzbget
+{
+ public class JsonRequest
+ {
+ [JsonProperty(PropertyName = "method")]
+ public String Method { get; set; }
+
+ [JsonProperty(PropertyName = "params")]
+ public object[] Params { get; set; }
+ }
+}
diff --git a/NzbDrone.Core/Model/Nzbget/PriorityType.cs b/NzbDrone.Core/Model/Nzbget/PriorityType.cs
new file mode 100644
index 000000000..43be8b196
--- /dev/null
+++ b/NzbDrone.Core/Model/Nzbget/PriorityType.cs
@@ -0,0 +1,11 @@
+namespace NzbDrone.Core.Model.Nzbget
+{
+ public enum PriorityType
+ {
+ VeryLow = -100,
+ Low = -50,
+ Normal = 0,
+ High = 50,
+ VeryHigh = 100
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/Model/Nzbget/Queue.cs b/NzbDrone.Core/Model/Nzbget/Queue.cs
new file mode 100644
index 000000000..831608f60
--- /dev/null
+++ b/NzbDrone.Core/Model/Nzbget/Queue.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace NzbDrone.Core.Model.Nzbget
+{
+ public class Queue
+ {
+ public String Version { get; set; }
+
+ [JsonProperty(PropertyName = "result")]
+ public List QueueItems { get; set; }
+ }
+}
diff --git a/NzbDrone.Core/Model/Nzbget/QueueItem.cs b/NzbDrone.Core/Model/Nzbget/QueueItem.cs
new file mode 100644
index 000000000..82257a213
--- /dev/null
+++ b/NzbDrone.Core/Model/Nzbget/QueueItem.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace NzbDrone.Core.Model.Nzbget
+{
+ public class QueueItem
+ {
+ private string _title;
+
+ public Int32 NzbId { get; set; }
+
+ [JsonProperty(PropertyName = "NzbName")]
+ public string Title
+ {
+ get { return _title; }
+ set
+ {
+ _title = value;
+ ParseResult = Parser.ParseTitle(value.Replace("DUPLICATE / ", String.Empty));
+ }
+ }
+
+ public String Category { get; set; }
+ public Int32 FileSizeMb { get; set; }
+ public Int32 RemainingSizeMb { get; set; }
+
+ public EpisodeParseResult ParseResult { private set; get; }
+ }
+}
diff --git a/NzbDrone.Core/Model/Nzbget/VersionModel.cs b/NzbDrone.Core/Model/Nzbget/VersionModel.cs
new file mode 100644
index 000000000..fdbbec462
--- /dev/null
+++ b/NzbDrone.Core/Model/Nzbget/VersionModel.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace NzbDrone.Core.Model.Nzbget
+{
+ public class VersionModel
+ {
+ public String Version { get; set; }
+ public String Result { get; set; }
+ }
+}
diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj
index 44f7b2664..ea837fe2e 100644
--- a/NzbDrone.Core/NzbDrone.Core.csproj
+++ b/NzbDrone.Core/NzbDrone.Core.csproj
@@ -281,6 +281,14 @@
+
+
+
+
+
+
+
+
@@ -318,6 +326,7 @@
+
diff --git a/NzbDrone.Core/Providers/Core/ConfigProvider.cs b/NzbDrone.Core/Providers/Core/ConfigProvider.cs
index 2ed3a2833..a917eb20d 100644
--- a/NzbDrone.Core/Providers/Core/ConfigProvider.cs
+++ b/NzbDrone.Core/Providers/Core/ConfigProvider.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Model;
+using NzbDrone.Core.Model.Nzbget;
using NzbDrone.Core.Model.Sabnzbd;
using NzbDrone.Core.Repository;
using PetaPoco;
@@ -541,6 +542,62 @@ namespace NzbDrone.Core.Providers.Core
set { SetValue("DownloadClientUseSceneName", value); }
}
+ public virtual String NzbgetUsername
+ {
+ get { return GetValue("NzbgetUsername", "nzbget"); }
+
+ set { SetValue("NzbgetUsername", value); }
+ }
+
+ public virtual String NzbgetPassword
+ {
+ get { return GetValue("NzbgetPassword", ""); }
+
+ set { SetValue("NzbgetPassword", value); }
+ }
+
+ public virtual String NzbgetHost
+ {
+ get { return GetValue("NzbgetHost", "nzbget"); }
+
+ set { SetValue("NzbgetHost", value); }
+ }
+
+ public virtual Int32 NzbgetPort
+ {
+ get { return GetValueInt("NzbgetPort", 6789); }
+
+ set { SetValue("NzbgetPort", value); }
+ }
+
+ public virtual String NzbgetTvCategory
+ {
+ get { return GetValue("NzbgetTvCategory", "nzbget"); }
+
+ set { SetValue("NzbgetTvCategory", value); }
+ }
+
+ public virtual Int32 NzbgetPriority
+ {
+ get { return GetValueInt("NzbgetPriority", 0); }
+
+ set { SetValue("NzbgetPriority", value); }
+ }
+
+ public virtual PriorityType NzbgetBacklogTvPriority
+ {
+ get { return (PriorityType)GetValueInt("NzbgetBacklogTvPriority"); }
+
+ set { SetValue("NzbgetBacklogTvPriority", (int)value); }
+ }
+
+ public virtual PriorityType NzbgetRecentTvPriority
+ {
+ get { return (PriorityType)GetValueInt("NzbgetRecentTvPriority"); }
+
+ set { SetValue("NzbgetRecentTvPriority", (int)value); }
+ }
+
private string GetValue(string key)
{
return GetValue(key, String.Empty);
diff --git a/NzbDrone.Core/Providers/DownloadClients/NzbgetProvider.cs b/NzbDrone.Core/Providers/DownloadClients/NzbgetProvider.cs
new file mode 100644
index 000000000..43a4bb7dc
--- /dev/null
+++ b/NzbDrone.Core/Providers/DownloadClients/NzbgetProvider.cs
@@ -0,0 +1,174 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text.RegularExpressions;
+using System.Web;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using NLog;
+using NzbDrone.Common;
+using NzbDrone.Core.Model;
+using NzbDrone.Core.Model.Nzbget;
+using NzbDrone.Core.Providers.Core;
+
+namespace NzbDrone.Core.Providers.DownloadClients
+{
+ public class NzbgetProvider : IDownloadClient
+ {
+ private static readonly Logger logger = LogManager.GetCurrentClassLogger();
+ private readonly ConfigProvider _configProvider;
+ private readonly HttpProvider _httpProvider;
+
+ public NzbgetProvider(ConfigProvider configProvider, HttpProvider httpProvider)
+ {
+ _configProvider = configProvider;
+ _httpProvider = httpProvider;
+ }
+
+ public NzbgetProvider()
+ {
+ }
+
+ public virtual bool IsInQueue(EpisodeParseResult newParseResult)
+ {
+ try
+ {
+ var queue = GetQueue().Where(c => c.ParseResult != null);
+
+ var matchigTitle = queue.Where(q => String.Equals(q.ParseResult.CleanTitle, newParseResult.Series.CleanTitle, StringComparison.InvariantCultureIgnoreCase));
+
+ var matchingTitleWithQuality = matchigTitle.Where(q => q.ParseResult.Quality >= newParseResult.Quality);
+
+
+ if (newParseResult.Series.IsDaily)
+ {
+ return matchingTitleWithQuality.Any(q => q.ParseResult.AirDate.Value.Date == newParseResult.AirDate.Value.Date);
+ }
+
+ var matchingSeason = matchingTitleWithQuality.Where(q => q.ParseResult.SeasonNumber == newParseResult.SeasonNumber);
+
+ if (newParseResult.FullSeason)
+ {
+ return matchingSeason.Any();
+ }
+
+ return matchingSeason.Any(q => q.ParseResult.EpisodeNumbers != null && q.ParseResult.EpisodeNumbers.Any(e => newParseResult.EpisodeNumbers.Contains(e)));
+ }
+
+ catch (Exception ex)
+ {
+ logger.WarnException("Unable to connect to Nzbget to check queue.", ex);
+ return false;
+ }
+ }
+
+ public virtual bool DownloadNzb(string url, string title, bool recentlyAired)
+ {
+ try
+ {
+ string cat = _configProvider.NzbgetTvCategory;
+ int priority = recentlyAired ? (int)_configProvider.NzbgetRecentTvPriority : (int)_configProvider.NzbgetBacklogTvPriority;
+
+ var command = new JsonRequest
+ {
+ Method = "appendurl",
+ Params = new object[]{ title, cat, priority, false, url }
+ };
+
+ logger.Info("Adding report [{0}] to the queue.", title);
+ var response = PostCommand(JsonConvert.SerializeObject(command));
+
+ CheckForError(response);
+
+ var success = JsonConvert.DeserializeObject(response).Result;
+ logger.Debug("Queue Response: [{0}]", success);
+
+ return true;
+ }
+
+ catch (WebException ex)
+ {
+ logger.Error("Error communicating with Nzbget: " + ex.Message);
+ }
+
+ return false;
+ }
+
+ public virtual List GetQueue()
+ {
+ var command = new JsonRequest
+ {
+ Method = "listgroups",
+ Params = null
+ };
+
+ var response = PostCommand(JsonConvert.SerializeObject(command));
+
+ CheckForError(response);
+
+ return JsonConvert.DeserializeObject(response).QueueItems;
+ }
+
+ public virtual VersionModel GetVersion(string host = null, int port = 0, string username = null, string password = null)
+ {
+ //Get saved values if any of these are defaults
+ if (host == null)
+ host = _configProvider.NzbgetHost;
+
+ if (port == 0)
+ port = _configProvider.NzbgetPort;
+
+ if (username == null)
+ username = _configProvider.NzbgetUsername;
+
+ if (password == null)
+ password = _configProvider.NzbgetPassword;
+
+ var command = new JsonRequest
+ {
+ Method = "version",
+ Params = null
+ };
+
+ var url = String.Format(@"http://{0}:{1}/jsonrpc", host, port);
+ var response = _httpProvider.PostCommand(url, username, password, JsonConvert.SerializeObject(command));
+
+ CheckForError(response);
+
+ return JsonConvert.DeserializeObject(response);
+ }
+
+ public virtual string Test(string host, int port, string apiKey, 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;
+ }
+
+ private string PostCommand(string command)
+ {
+ var url = String.Format(@"http://{0}:{1}/jsonrpc",
+ _configProvider.NzbgetHost,
+ _configProvider.NzbgetPort);
+
+ return _httpProvider.PostCommand(url, _configProvider.NzbgetUsername, _configProvider.NzbgetPassword, command);
+ }
+
+ private void CheckForError(string response)
+ {
+ var result = JsonConvert.DeserializeObject(response);
+
+ if (result.Error != null)
+ throw new ApplicationException(result.Error.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Core/Providers/SceneMappingProvider.cs b/NzbDrone.Core/Providers/SceneMappingProvider.cs
index d4f119d80..e45282a52 100644
--- a/NzbDrone.Core/Providers/SceneMappingProvider.cs
+++ b/NzbDrone.Core/Providers/SceneMappingProvider.cs
@@ -51,11 +51,11 @@ namespace NzbDrone.Core.Providers
return true;
}
- public virtual string GetSceneName(int seriesId)
+ public virtual string GetSceneName(int seriesId, int seasonNumber = -1)
{
UpdateIfEmpty();
- var item = _database.FirstOrDefault("WHERE SeriesId = @0", seriesId);
+ var item = _database.FirstOrDefault("WHERE SeriesId = @0 AND SeasonNumber = @1", seriesId, seasonNumber);
if (item == null)
return null;
diff --git a/NzbDrone.Core/Providers/Search/SearchBase.cs b/NzbDrone.Core/Providers/Search/SearchBase.cs
index c97988895..9c56116ed 100644
--- a/NzbDrone.Core/Providers/Search/SearchBase.cs
+++ b/NzbDrone.Core/Providers/Search/SearchBase.cs
@@ -57,7 +57,8 @@ namespace NzbDrone.Core.Providers.Search
{
SearchTime = DateTime.Now,
SeriesId = series.SeriesId,
- EpisodeId = options.GetType().GetProperty("Episode") != null ? options.Episode.EpisodeId : null
+ EpisodeId = options.GetType().GetProperty("Episode") != null ? options.Episode.EpisodeId : null,
+ SeasonNumber = options.GetType().GetProperty("SeasonNumber") != null ? options.SeasonNumber : null
};
List reports = PerformSearch(series, options, notification);
@@ -166,9 +167,12 @@ namespace NzbDrone.Core.Providers.Search
}
public virtual string GetSearchTitle(Series series, int seasonNumber = -1)
- {
- //Todo: Add support for per season lookup (used for anime)
- //Todo: Add support for multiple names
+ {
+ var seasonTitle = _sceneMappingProvider.GetSceneName(series.SeriesId, seasonNumber);
+
+ if(!String.IsNullOrWhiteSpace(seasonTitle))
+ return seasonTitle;
+
var title = _sceneMappingProvider.GetSceneName(series.SeriesId);
if (String.IsNullOrWhiteSpace(title))