New: Failed download handling for Nzbget

pull/6/head
Mark McDowall 11 years ago
parent b60633882e
commit bac75ac6d9

@ -0,0 +1,21 @@
using System.IO;
namespace NzbDrone.Common.Extensions
{
public static class StreamExtensions
{
public static byte[] ToBytes(this Stream input)
{
var buffer = new byte[16 * 1024];
using (var ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
}
}

@ -107,6 +107,7 @@
<Compile Include="Processes\ProcessOutput.cs" /> <Compile Include="Processes\ProcessOutput.cs" />
<Compile Include="Serializer\IntConverter.cs" /> <Compile Include="Serializer\IntConverter.cs" />
<Compile Include="Services.cs" /> <Compile Include="Services.cs" />
<Compile Include="Extensions\StreamExtensions.cs" />
<Compile Include="TPL\LimitedConcurrencyLevelTaskScheduler.cs" /> <Compile Include="TPL\LimitedConcurrencyLevelTaskScheduler.cs" />
<Compile Include="Security\IgnoreCertErrorPolicy.cs" /> <Compile Include="Security\IgnoreCertErrorPolicy.cs" />
<Compile Include="StringExtensions.cs" /> <Compile Include="StringExtensions.cs" />

@ -27,6 +27,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("86420f8ee425340d8894bf3bc636b66404b95f18")] [TestCase("86420f8ee425340d8894bf3bc636b66404b95f18")]
[TestCase("ce39afb7da6cf7c04eba3090f0a309f609883862")] [TestCase("ce39afb7da6cf7c04eba3090f0a309f609883862")]
[TestCase("THIS SHOULD NEVER PARSE")] [TestCase("THIS SHOULD NEVER PARSE")]
[TestCase("Vh1FvU3bJXw6zs8EEUX4bMo5vbbMdHghxHirc.mkv")]
public void should_not_parse_crap(string title) public void should_not_parse_crap(string title)
{ {
Parser.Parser.ParseTitle(title).Should().BeNull(); Parser.Parser.ParseTitle(title).Should().BeNull();

@ -31,6 +31,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase(@"C:\Test\Unsorted\The.Big.Bang.Theory.S01E01.720p.HDTV\tbbt101.avi", 1, 1)] [TestCase(@"C:\Test\Unsorted\The.Big.Bang.Theory.S01E01.720p.HDTV\tbbt101.avi", 1, 1)]
[TestCase(@"C:\Test\Unsorted\Terminator.The.Sarah.Connor.Chronicles.S02E19.720p.BluRay.x264-SiNNERS-RP\ba27283b17c00d01193eacc02a8ba98eeb523a76.mkv", 2, 19)] [TestCase(@"C:\Test\Unsorted\Terminator.The.Sarah.Connor.Chronicles.S02E19.720p.BluRay.x264-SiNNERS-RP\ba27283b17c00d01193eacc02a8ba98eeb523a76.mkv", 2, 19)]
[TestCase(@"C:\Test\Unsorted\Terminator.The.Sarah.Connor.Chronicles.S02E18.720p.BluRay.x264-SiNNERS-RP\45a55debe3856da318cc35882ad07e43cd32fd15.mkv", 2, 18)] [TestCase(@"C:\Test\Unsorted\Terminator.The.Sarah.Connor.Chronicles.S02E18.720p.BluRay.x264-SiNNERS-RP\45a55debe3856da318cc35882ad07e43cd32fd15.mkv", 2, 18)]
[TestCase(@"C:\Test\The.Blacklist.S01E16.720p.HDTV.X264-DIMENSION\XRmZciqkBopq4851Ddbipe\Vh1FvU3bJXw6zs8EEUX4bMo5vbbMdHghxHirc.mkv", 1, 16)]
public void should_parse_from_path(string path, int season, int episode) public void should_parse_from_path(string path, int season, int episode)
{ {
var result = Parser.Parser.ParsePath(path); var result = Parser.Parser.ParsePath(path);

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
namespace NzbDrone.Core.Download.Clients.Nzbget namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
@ -6,10 +7,13 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
private string _nzbName; private string _nzbName;
public Int32 NzbId { get; set; } public Int32 NzbId { get; set; }
public Int32 FirstId { get; set; }
public Int32 LastId { get; set; }
public string NzbName { get; set; } public string NzbName { get; set; }
public String Category { get; set; } public String Category { get; set; }
public Int32 FileSizeMb { get; set; } public Int32 FileSizeMb { get; set; }
public Int32 RemainingSizeMb { get; set; } public Int32 RemainingSizeMb { get; set; }
public Int32 PausedSizeMb { get; set; } public Int32 PausedSizeMb { get; set; }
public List<NzbgetParameter> Parameters { get; set; }
} }
} }

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
@ -13,14 +14,17 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
private readonly INzbgetProxy _proxy; private readonly INzbgetProxy _proxy;
private readonly IParsingService _parsingService; private readonly IParsingService _parsingService;
private readonly IHttpProvider _httpProvider;
private readonly Logger _logger; private readonly Logger _logger;
public Nzbget(INzbgetProxy proxy, public Nzbget(INzbgetProxy proxy,
IParsingService parsingService, IParsingService parsingService,
IHttpProvider httpProvider,
Logger logger) Logger logger)
{ {
_proxy = proxy; _proxy = proxy;
_parsingService = parsingService; _parsingService = parsingService;
_httpProvider = httpProvider;
_logger = logger; _logger = logger;
} }
@ -29,16 +33,18 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
var url = remoteEpisode.Release.DownloadUrl; var url = remoteEpisode.Release.DownloadUrl;
var title = remoteEpisode.Release.Title + ".nzb"; var title = remoteEpisode.Release.Title + ".nzb";
string cat = Settings.TvCategory; string category = Settings.TvCategory;
int priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority; int priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority;
_logger.Info("Adding report [{0}] to the queue.", title); _logger.Info("Adding report [{0}] to the queue.", title);
var success = _proxy.AddNzb(Settings, title, cat, priority, false, url); using (var nzb = _httpProvider.DownloadStream(url))
{
_logger.Debug("Queue Response: [{0}]", success); _logger.Info("Adding report [{0}] to the queue.", title);
var response = _proxy.DownloadNzb(nzb, title, category, priority, Settings);
return null; return response;
}
} }
public override IEnumerable<QueueItem> GetQueue() public override IEnumerable<QueueItem> GetQueue()
@ -57,14 +63,16 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
var queueItems = new List<QueueItem>(); var queueItems = new List<QueueItem>();
foreach (var nzbGetQueueItem in queue) foreach (var item in queue)
{ {
var droneParameter = item.Parameters.SingleOrDefault(p => p.Name == "drone");
var queueItem = new QueueItem(); var queueItem = new QueueItem();
queueItem.Id = nzbGetQueueItem.NzbId.ToString(); queueItem.Id = droneParameter == null ? item.NzbId.ToString() : droneParameter.Value.ToString();
queueItem.Title = nzbGetQueueItem.NzbName; queueItem.Title = item.NzbName;
queueItem.Size = nzbGetQueueItem.FileSizeMb; queueItem.Size = item.FileSizeMb;
queueItem.Sizeleft = nzbGetQueueItem.RemainingSizeMb; queueItem.Sizeleft = item.RemainingSizeMb;
queueItem.Status = nzbGetQueueItem.FileSizeMb == nzbGetQueueItem.PausedSizeMb ? "paused" : "queued"; queueItem.Status = item.FileSizeMb == item.PausedSizeMb ? "paused" : "queued";
var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title); var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title);
if (parsedEpisodeInfo == null) continue; if (parsedEpisodeInfo == null) continue;
@ -81,7 +89,43 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10) public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10)
{ {
return new HistoryItem[0]; List<NzbgetHistoryItem> history;
try
{
history = _proxy.GetHistory(Settings);
}
catch (DownloadClientException ex)
{
_logger.ErrorException(ex.Message, ex);
return Enumerable.Empty<HistoryItem>();
}
var historyItems = new List<HistoryItem>();
var successStatues = new[] {"SUCCESS", "NONE"};
foreach (var item in history)
{
var droneParameter = item.Parameters.SingleOrDefault(p => p.Name == "drone");
var status = successStatues.Contains(item.ParStatus) &&
successStatues.Contains(item.ScriptStatus)
? HistoryStatus.Completed
: HistoryStatus.Failed;
var historyItem = new HistoryItem();
historyItem.Id = droneParameter == null ? item.Id.ToString() : droneParameter.Value.ToString();
historyItem.Title = item.Name;
historyItem.Size = item.FileSizeMb.ToString(); //Why is this a string?
historyItem.DownloadTime = 0;
historyItem.Storage = item.DestDir;
historyItem.Category = item.Category;
historyItem.Message = String.Format("PAR Status: {0} - Script Status: {1}", item.ParStatus, item.ScriptStatus);
historyItem.Status = status;
historyItems.Add(historyItem);
}
return historyItems;
} }
public override void RemoveFromQueue(string id) public override void RemoveFromQueue(string id)
@ -91,7 +135,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
public override void RemoveFromHistory(string id) public override void RemoveFromHistory(string id)
{ {
throw new NotImplementedException(); _proxy.RemoveFromHistory(id, Settings);
} }
public override void Test() public override void Test()

@ -2,7 +2,7 @@
namespace NzbDrone.Core.Download.Clients.Nzbget namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
public class EnqueueResponse public class NzbgetBooleanResponse
{ {
public String Version { get; set; } public String Version { get; set; }
public Boolean Result { get; set; } public Boolean Result { get; set; }

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
namespace NzbDrone.Core.Download.Clients.Nzbget
{
public class NzbgetHistoryItem
{
private string _nzbName;
public Int32 Id { get; set; }
public String Name { get; set; }
public String Category { get; set; }
public Int32 FileSizeMb { get; set; }
public String ParStatus { get; set; }
public String ScriptStatus { get; set; }
public String DestDir { get; set; }
public List<NzbgetParameter> Parameters { get; set; }
}
}

@ -4,11 +4,11 @@ using Newtonsoft.Json;
namespace NzbDrone.Core.Download.Clients.Nzbget namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
public class NzbgetQueue public class NzbgetListResponse<T>
{ {
public String Version { get; set; } public String Version { get; set; }
[JsonProperty(PropertyName = "result")] [JsonProperty(PropertyName = "result")]
public List<NzbgetQueueItem> QueueItems { get; set; } public List<T> QueueItems { get; set; }
} }
} }

@ -0,0 +1,9 @@
using System;
namespace NzbDrone.Core.Download.Clients.Nzbget
{
public class NzbgetParameter
{
public String Name { get; set; }
public object Value { get; set; }
}
}

@ -1,6 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Rest; using NzbDrone.Core.Rest;
using RestSharp; using RestSharp;
@ -9,9 +12,11 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
public interface INzbgetProxy public interface INzbgetProxy
{ {
bool AddNzb(NzbgetSettings settings, params object[] parameters); string DownloadNzb(Stream nzb, string title, string category, int priority, NzbgetSettings settings);
List<NzbgetQueueItem> GetQueue(NzbgetSettings settings); List<NzbgetQueueItem> GetQueue(NzbgetSettings settings);
List<NzbgetHistoryItem> GetHistory(NzbgetSettings settings);
VersionResponse GetVersion(NzbgetSettings settings); VersionResponse GetVersion(NzbgetSettings settings);
void RemoveFromHistory(string id, NzbgetSettings settings);
} }
public class NzbgetProxy : INzbgetProxy public class NzbgetProxy : INzbgetProxy
@ -23,18 +28,50 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
_logger = logger; _logger = logger;
} }
public bool AddNzb(NzbgetSettings settings, params object[] parameters) public string DownloadNzb(Stream nzb, string title, string category, int priority, NzbgetSettings settings)
{ {
var request = BuildRequest(new JsonRequest("appendurl", parameters)); var parameters = new object[] { title, category, priority, false, Convert.ToBase64String(nzb.ToBytes()) };
var request = BuildRequest(new JsonRequest("append", parameters));
return Json.Deserialize<EnqueueResponse>(ProcessRequest(request, settings)).Result; var response = Json.Deserialize<NzbgetBooleanResponse>(ProcessRequest(request, settings));
_logger.Debug("Queue Response: [{0}]", response.Result);
if (!response.Result)
{
return null;
}
var queue = GetQueue(settings);
var item = queue.FirstOrDefault(q => q.NzbName == title.Substring(0, title.Length - 4));
if (item == null)
{
return null;
}
var droneId = Guid.NewGuid().ToString().Replace("-", "");
var editResult = EditQueue("GroupSetParameter", 0, "drone=" + droneId, item.LastId, settings);
if (editResult)
{
_logger.Debug("Nzbget download drone parameter set to: {0}", droneId);
}
return droneId;
} }
public List<NzbgetQueueItem> GetQueue(NzbgetSettings settings) public List<NzbgetQueueItem> GetQueue(NzbgetSettings settings)
{ {
var request = BuildRequest(new JsonRequest("listgroups")); var request = BuildRequest(new JsonRequest("listgroups"));
return Json.Deserialize<NzbgetQueue>(ProcessRequest(request, settings)).QueueItems; return Json.Deserialize<NzbgetListResponse<NzbgetQueueItem>>(ProcessRequest(request, settings)).QueueItems;
}
public List<NzbgetHistoryItem> GetHistory(NzbgetSettings settings)
{
var request = BuildRequest(new JsonRequest("history"));
return Json.Deserialize<NzbgetListResponse<NzbgetHistoryItem>>(ProcessRequest(request, settings)).QueueItems;
} }
public VersionResponse GetVersion(NzbgetSettings settings) public VersionResponse GetVersion(NzbgetSettings settings)
@ -44,6 +81,32 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
return Json.Deserialize<VersionResponse>(ProcessRequest(request, settings)); return Json.Deserialize<VersionResponse>(ProcessRequest(request, settings));
} }
public void RemoveFromHistory(string id, NzbgetSettings settings)
{
var history = GetHistory(settings);
var item = history.SingleOrDefault(h => h.Parameters.SingleOrDefault(p => p.Name == "drone") != null);
if (item == null)
{
_logger.Warn("Unable to remove item from nzbget's history, Unknown ID: {0}", id);
return;
}
if (!EditQueue("HistoryDelete", 0, "", item.Id, settings))
{
_logger.Warn("Failed to remove item from nzbget history, {0} [{1}]", item.Name, item.Id);
}
}
private bool EditQueue(string command, int offset, string editText, int id, NzbgetSettings settings)
{
var parameters = new object[] { command, offset, editText, id };
var request = BuildRequest(new JsonRequest("editqueue", parameters));
var response = Json.Deserialize<NzbgetBooleanResponse>(ProcessRequest(request, settings));
return response.Result;
}
private string ProcessRequest(IRestRequest restRequest, NzbgetSettings settings) private string ProcessRequest(IRestRequest restRequest, NzbgetSettings settings)
{ {
var client = BuildClient(settings); var client = BuildClient(settings);

@ -3,6 +3,7 @@ using System.IO;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using NLog; using NLog;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download.Clients.Sabnzbd.Responses; using NzbDrone.Core.Download.Clients.Sabnzbd.Responses;
using NzbDrone.Core.Instrumentation.Extensions; using NzbDrone.Core.Instrumentation.Extensions;
@ -35,7 +36,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
var request = new RestRequest(Method.POST); var request = new RestRequest(Method.POST);
var action = String.Format("mode=addfile&cat={0}&priority={1}", category, priority); var action = String.Format("mode=addfile&cat={0}&priority={1}", category, priority);
request.AddFile("name", ReadFully(nzb), title, "application/x-nzb"); request.AddFile("name", nzb.ToBytes(), title, "application/x-nzb");
SabnzbdAddResponse response; SabnzbdAddResponse response;
@ -161,20 +162,5 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
if (result.Failed) if (result.Failed)
throw new DownloadClientException("Error response received from SABnzbd: {0}", result.Error); throw new DownloadClientException("Error response received from SABnzbd: {0}", 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,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NLog;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.ThingiProvider;

@ -236,6 +236,8 @@
<Compile Include="Download\Clients\Blackhole\TestBlackholeCommand.cs" /> <Compile Include="Download\Clients\Blackhole\TestBlackholeCommand.cs" />
<Compile Include="Download\Clients\DownloadClientException.cs" /> <Compile Include="Download\Clients\DownloadClientException.cs" />
<Compile Include="Download\Clients\FolderSettings.cs" /> <Compile Include="Download\Clients\FolderSettings.cs" />
<Compile Include="Download\Clients\Nzbget\NzbgetHistoryItem.cs" />
<Compile Include="Download\Clients\Nzbget\NzbgetParameter.cs" />
<Compile Include="Download\Clients\Nzbget\NzbgetSettings.cs" /> <Compile Include="Download\Clients\Nzbget\NzbgetSettings.cs" />
<Compile Include="Download\Clients\Nzbget\TestNzbgetCommand.cs" /> <Compile Include="Download\Clients\Nzbget\TestNzbgetCommand.cs" />
<Compile Include="Download\Clients\Pneumatic\Pneumatic.cs" /> <Compile Include="Download\Clients\Pneumatic\Pneumatic.cs" />
@ -500,10 +502,10 @@
<Compile Include="Instrumentation\LogService.cs" /> <Compile Include="Instrumentation\LogService.cs" />
<Compile Include="Instrumentation\DatabaseTarget.cs" /> <Compile Include="Instrumentation\DatabaseTarget.cs" />
<Compile Include="MediaFiles\MediaInfo\MediaInfoModel.cs" /> <Compile Include="MediaFiles\MediaInfo\MediaInfoModel.cs" />
<Compile Include="Download\Clients\Nzbget\EnqueueResponse.cs" /> <Compile Include="Download\Clients\Nzbget\NzbgetBooleanResponse.cs" />
<Compile Include="Download\Clients\Nzbget\ErrorModel.cs" /> <Compile Include="Download\Clients\Nzbget\ErrorModel.cs" />
<Compile Include="Download\Clients\Nzbget\JsonError.cs" /> <Compile Include="Download\Clients\Nzbget\JsonError.cs" />
<Compile Include="Download\Clients\Nzbget\NzbgetQueue.cs" /> <Compile Include="Download\Clients\Nzbget\NzbgetListResponse.cs" />
<Compile Include="Download\Clients\Nzbget\NzbgetQueueItem.cs" /> <Compile Include="Download\Clients\Nzbget\NzbgetQueueItem.cs" />
<Compile Include="Download\Clients\Nzbget\NzbgetPriority.cs" /> <Compile Include="Download\Clients\Nzbget\NzbgetPriority.cs" />
<Compile Include="Download\Clients\Nzbget\VersionResponse.cs" /> <Compile Include="Download\Clients\Nzbget\VersionResponse.cs" />

Loading…
Cancel
Save