Merge pull request #674 from Sonarr/rtorrent-directory

Choose download folder for rTorrent
This commit is contained in:
Mark McDowall 2015-07-15 22:45:40 -07:00
commit 346d7f3cf4
5 changed files with 152 additions and 41 deletions

View File

@ -10,6 +10,7 @@ using NzbDrone.Core.MediaFiles.TorrentInfo;
using NLog;
using NzbDrone.Core.Validation;
using FluentValidation.Results;
using NzbDrone.Core.Download.Clients.rTorrent;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.RemotePathMappings;
using NzbDrone.Core.ThingiProvider;
@ -19,6 +20,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
public class RTorrent : TorrentClientBase<RTorrentSettings>
{
private readonly IRTorrentProxy _proxy;
private readonly IRTorrentDirectoryValidator _rTorrentDirectoryValidator;
public RTorrent(IRTorrentProxy proxy,
ITorrentFileInfoReader torrentFileInfoReader,
@ -26,10 +28,12 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
IConfigService configService,
IDiskProvider diskProvider,
IRemotePathMappingService remotePathMappingService,
IRTorrentDirectoryValidator rTorrentDirectoryValidator,
Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger)
{
_proxy = proxy;
_rTorrentDirectoryValidator = rTorrentDirectoryValidator;
}
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
@ -40,6 +44,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
var TRIES = 5;
var RETRY_DELAY = 500; //ms
var ready = false;
for (var i = 0; i < TRIES; i++)
{
ready = _proxy.HasHashTorrent(hash, Settings);
@ -55,9 +60,10 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
{
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ?
Settings.RecentTvPriority : Settings.OlderTvPriority);
_proxy.SetTorrentPriority(hash, Settings, priority);
SetPriority(remoteEpisode, hash);
SetDownloadDirectory(hash);
_proxy.StartTorrent(hash, Settings);
return hash;
}
@ -74,12 +80,12 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ?
Settings.RecentTvPriority : Settings.OlderTvPriority);
_proxy.SetTorrentPriority(hash, Settings, priority);
SetPriority(remoteEpisode, hash);
SetDownloadDirectory(hash);
_proxy.StartTorrent(hash, Settings);
return hash;
}
@ -182,6 +188,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
failures.AddIfNotNull(TestConnection());
if (failures.Any()) return;
failures.AddIfNotNull(TestGetTorrents());
failures.AddIfNotNull(TestDirectory());
}
private ValidationFailure TestConnection()
@ -218,5 +225,31 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
return null;
}
private ValidationFailure TestDirectory()
{
var result = _rTorrentDirectoryValidator.Validate(Settings);
if (result.IsValid)
{
return null;
}
return result.Errors.First();
}
private void SetPriority(RemoteEpisode remoteEpisode, string hash)
{
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
_proxy.SetTorrentPriority(hash, priority, Settings);
}
private void SetDownloadDirectory(string hash)
{
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
{
_proxy.SetTorrentDownloadDirectory(hash, Settings.TvDirectory, Settings);
}
}
}
}

View File

@ -0,0 +1,29 @@
using FluentValidation;
using FluentValidation.Results;
using NzbDrone.Core.Download.Clients.RTorrent;
using NzbDrone.Core.Validation.Paths;
namespace NzbDrone.Core.Download.Clients.rTorrent
{
public interface IRTorrentDirectoryValidator
{
ValidationResult Validate(RTorrentSettings instance);
}
public class RTorrentDirectoryValidator : AbstractValidator<RTorrentSettings>, IRTorrentDirectoryValidator
{
public RTorrentDirectoryValidator(RootFolderValidator rootFolderValidator,
PathExistsValidator pathExistsValidator,
DroneFactoryValidator droneFactoryValidator,
MappedNetworkDriveValidator mappedNetworkDriveValidator)
{
RuleFor(c => c.TvDirectory).Cascade(CascadeMode.StopOnFirstFailure)
.IsValidPath()
.SetValidator(rootFolderValidator)
.SetValidator(droneFactoryValidator)
.SetValidator(mappedNetworkDriveValidator)
.SetValidator(pathExistsValidator)
.When(c => c.Host == "localhost" || c.Host == "127.0.0.1");
}
}
}

View File

@ -16,9 +16,11 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
void AddTorrentFromUrl(string torrentUrl, RTorrentSettings settings);
void AddTorrentFromFile(string fileName, byte[] fileContent, RTorrentSettings settings);
void RemoveTorrent(string hash, RTorrentSettings settings);
void SetTorrentPriority(string hash, RTorrentSettings settings, RTorrentPriority priority);
void SetTorrentPriority(string hash, RTorrentPriority priority, RTorrentSettings settings);
void SetTorrentLabel(string hash, string label, RTorrentSettings settings);
void SetTorrentDownloadDirectory(string hash, string directory, RTorrentSettings settings);
bool HasHashTorrent(string hash, RTorrentSettings settings);
void StartTorrent(string hash, RTorrentSettings settings);
}
public interface IRTorrent : IXmlRpcProxy
@ -26,10 +28,10 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
[XmlRpcMethod("d.multicall2")]
object[] TorrentMulticall(params string[] parameters);
[XmlRpcMethod("load.start")]
int LoadURL(string target, string data);
[XmlRpcMethod("load.normal")]
int LoadUrl(string target, string data);
[XmlRpcMethod("load.raw_start")]
[XmlRpcMethod("load.raw")]
int LoadBinary(string target, byte[] data);
[XmlRpcMethod("d.erase")]
@ -41,11 +43,17 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
[XmlRpcMethod("d.priority.set")]
int SetPriority(string hash, long priority);
[XmlRpcMethod("d.directory.set")]
int SetDirectory(string hash, string directory);
[XmlRpcMethod("d.name")]
string GetName(string hash);
[XmlRpcMethod("system.client_version")]
string GetVersion();
[XmlRpcMethod("system.multicall")]
object[] SystemMulticall(object[] parameters);
}
public class RTorrentProxy : IRTorrentProxy
@ -108,32 +116,13 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
return items;
}
public bool HasHashTorrent(string hash, RTorrentSettings settings)
{
_logger.Debug("Executing remote method: d.name");
var client = BuildClient(settings);
try
{
var name = client.GetName(hash);
if (name.IsNullOrWhiteSpace()) return false;
bool metaTorrent = name == (hash + ".meta");
return !metaTorrent;
}
catch (Exception)
{
return false;
}
}
public void AddTorrentFromUrl(string torrentUrl, RTorrentSettings settings)
{
_logger.Debug("Executing remote method: load.start");
_logger.Debug("Executing remote method: load.normal");
var client = BuildClient(settings);
var response = client.LoadURL("", torrentUrl);
var response = client.LoadUrl("", torrentUrl);
if (response != 0)
{
throw new DownloadClientException("Could not add torrent: {0}.", torrentUrl);
@ -142,7 +131,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
public void AddTorrentFromFile(string fileName, Byte[] fileContent, RTorrentSettings settings)
{
_logger.Debug("Executing remote method: load.raw_start");
_logger.Debug("Executing remote method: load.raw");
var client = BuildClient(settings);
@ -166,7 +155,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
}
}
public void SetTorrentPriority(string hash, RTorrentSettings settings, RTorrentPriority priority)
public void SetTorrentPriority(string hash, RTorrentPriority priority, RTorrentSettings settings)
{
_logger.Debug("Executing remote method: d.priority.set");
@ -185,13 +174,71 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
var client = BuildClient(settings);
var satLabel = client.SetLabel(hash, label);
if (satLabel != label)
var setLabel = client.SetLabel(hash, label);
if (setLabel != label)
{
throw new DownloadClientException("Could set label on torrent: {0}.", hash);
}
}
public void SetTorrentDownloadDirectory(string hash, string directory, RTorrentSettings settings)
{
_logger.Debug("Executing remote method: d.directory.set");
var client = BuildClient(settings);
var response = client.SetDirectory(hash, directory);
if (response != 0)
{
throw new DownloadClientException("Could not set directory for torrent: {0}.", hash);
}
}
public bool HasHashTorrent(string hash, RTorrentSettings settings)
{
_logger.Debug("Executing remote method: d.name");
var client = BuildClient(settings);
try
{
var name = client.GetName(hash);
if (name.IsNullOrWhiteSpace()) return false;
bool metaTorrent = name == (hash + ".meta");
return !metaTorrent;
}
catch (Exception)
{
return false;
}
}
public void StartTorrent(string hash, RTorrentSettings settings)
{
_logger.Debug("Executing remote methods: d.open and d.start");
var client = BuildClient(settings);
var multicallResponse = client.SystemMulticall(new[]
{
new
{
methodName = "d.open",
@params = new[] { hash }
},
new
{
methodName = "d.start",
@params = new[] { hash }
},
}).SelectMany(c => ((IEnumerable<int>)c));
if (multicallResponse.Any(r => r != 0))
{
throw new DownloadClientException("Could not start torrent: {0}.", hash);
}
}
private IRTorrent BuildClient(RTorrentSettings settings)
{
var client = XmlRpcProxyGen.Create<IRTorrent>();

View File

@ -1,6 +1,4 @@
using System;
using FluentValidation;
using FluentValidation.Results;
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
@ -52,10 +50,13 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
[FieldDefinition(6, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional.")]
public string TvCategory { get; set; }
[FieldDefinition(7, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
[FieldDefinition(7, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default rTorrent location")]
public string TvDirectory { get; set; }
[FieldDefinition(8, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
public int RecentTvPriority { get; set; }
[FieldDefinition(8, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
[FieldDefinition(9, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
public int OlderTvPriority { get; set; }
public NzbDroneValidationResult Validate()

View File

@ -347,6 +347,7 @@
<Compile Include="Download\Clients\Nzbget\NzbgetSettings.cs" />
<Compile Include="Download\Clients\Pneumatic\Pneumatic.cs" />
<Compile Include="Download\Clients\Pneumatic\PneumaticSettings.cs" />
<Compile Include="Download\Clients\rTorrent\RTorrentDirectoryValidator.cs" />
<Compile Include="Download\Clients\Sabnzbd\JsonConverters\SabnzbdPriorityTypeConverter.cs" />
<Compile Include="Download\Clients\Sabnzbd\JsonConverters\SabnzbdQueueTimeConverter.cs" />
<Compile Include="Download\Clients\Sabnzbd\Responses\SabnzbdRetryResponse.cs" />