1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-12-16 11:37:58 +02:00

New: Failed download handling for Nzbget

This commit is contained in:
Mark McDowall 2014-03-20 00:08:15 -07:00
parent b60633882e
commit bac75ac6d9
14 changed files with 189 additions and 40 deletions

View File

@ -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();
}
}
}
}

View File

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

View File

@ -27,6 +27,7 @@ public class CrapParserFixture : CoreTest
[TestCase("86420f8ee425340d8894bf3bc636b66404b95f18")]
[TestCase("ce39afb7da6cf7c04eba3090f0a309f609883862")]
[TestCase("THIS SHOULD NEVER PARSE")]
[TestCase("Vh1FvU3bJXw6zs8EEUX4bMo5vbbMdHghxHirc.mkv")]
public void should_not_parse_crap(string title)
{
Parser.Parser.ParseTitle(title).Should().BeNull();

View File

@ -31,6 +31,7 @@ public class PathParserFixture : CoreTest
[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.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)
{
var result = Parser.Parser.ParsePath(path);

View File

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

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
@ -13,14 +14,17 @@ public class Nzbget : DownloadClientBase<NzbgetSettings>, IExecute<TestNzbgetCom
{
private readonly INzbgetProxy _proxy;
private readonly IParsingService _parsingService;
private readonly IHttpProvider _httpProvider;
private readonly Logger _logger;
public Nzbget(INzbgetProxy proxy,
IParsingService parsingService,
IHttpProvider httpProvider,
Logger logger)
{
_proxy = proxy;
_parsingService = parsingService;
_httpProvider = httpProvider;
_logger = logger;
}
@ -29,16 +33,18 @@ public override string DownloadNzb(RemoteEpisode remoteEpisode)
var url = remoteEpisode.Release.DownloadUrl;
var title = remoteEpisode.Release.Title + ".nzb";
string cat = Settings.TvCategory;
string category = 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);
using (var nzb = _httpProvider.DownloadStream(url))
{
_logger.Info("Adding report [{0}] to the queue.", title);
var response = _proxy.DownloadNzb(nzb, title, category, priority, Settings);
_logger.Debug("Queue Response: [{0}]", success);
return null;
return response;
}
}
public override IEnumerable<QueueItem> GetQueue()
@ -57,14 +63,16 @@ public override IEnumerable<QueueItem> GetQueue()
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();
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";
queueItem.Id = droneParameter == null ? item.NzbId.ToString() : droneParameter.Value.ToString();
queueItem.Title = item.NzbName;
queueItem.Size = item.FileSizeMb;
queueItem.Sizeleft = item.RemainingSizeMb;
queueItem.Status = item.FileSizeMb == item.PausedSizeMb ? "paused" : "queued";
var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title);
if (parsedEpisodeInfo == null) continue;
@ -81,7 +89,43 @@ public override IEnumerable<QueueItem> GetQueue()
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)
@ -91,7 +135,7 @@ public override void RemoveFromQueue(string id)
public override void RemoveFromHistory(string id)
{
throw new NotImplementedException();
_proxy.RemoveFromHistory(id, Settings);
}
public override void Test()

View File

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

View File

@ -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; }
}
}

View File

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

View File

@ -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; }
}
}

View File

@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Rest;
using RestSharp;
@ -9,9 +12,11 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
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<NzbgetHistoryItem> GetHistory(NzbgetSettings settings);
VersionResponse GetVersion(NzbgetSettings settings);
void RemoveFromHistory(string id, NzbgetSettings settings);
}
public class NzbgetProxy : INzbgetProxy
@ -23,18 +28,50 @@ public NzbgetProxy(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)
{
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)
@ -44,6 +81,32 @@ public VersionResponse GetVersion(NzbgetSettings 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)
{
var client = BuildClient(settings);

View File

@ -3,6 +3,7 @@
using Newtonsoft.Json.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download.Clients.Sabnzbd.Responses;
using NzbDrone.Core.Instrumentation.Extensions;
@ -35,7 +36,7 @@ public SabnzbdAddResponse DownloadNzb(Stream nzb, string title, string category,
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");
request.AddFile("name", nzb.ToBytes(), title, "application/x-nzb");
SabnzbdAddResponse response;
@ -161,20 +162,5 @@ private void CheckForError(IRestResponse response)
if (result.Failed)
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();
}
}
}
}

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using NLog;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider;

View File

@ -236,6 +236,8 @@
<Compile Include="Download\Clients\Blackhole\TestBlackholeCommand.cs" />
<Compile Include="Download\Clients\DownloadClientException.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\TestNzbgetCommand.cs" />
<Compile Include="Download\Clients\Pneumatic\Pneumatic.cs" />
@ -500,10 +502,10 @@
<Compile Include="Instrumentation\LogService.cs" />
<Compile Include="Instrumentation\DatabaseTarget.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\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\NzbgetPriority.cs" />
<Compile Include="Download\Clients\Nzbget\VersionResponse.cs" />