mirror of https://github.com/lidarr/Lidarr
219 lines
7.4 KiB
C#
219 lines
7.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Xml.Linq;
|
|
using System.Xml.XPath;
|
|
using NzbDrone.Common.Extensions;
|
|
using NzbDrone.Common.Http;
|
|
using NzbDrone.Core.Download.Extensions;
|
|
|
|
namespace NzbDrone.Core.Download.Clients.RTorrent
|
|
{
|
|
public interface IRTorrentProxy
|
|
{
|
|
string GetVersion(RTorrentSettings settings);
|
|
List<RTorrentTorrent> GetTorrents(RTorrentSettings settings);
|
|
|
|
void AddTorrentFromUrl(string torrentUrl, string label, RTorrentPriority priority, string directory, RTorrentSettings settings);
|
|
void AddTorrentFromFile(string fileName, byte[] fileContent, string label, RTorrentPriority priority, string directory, RTorrentSettings settings);
|
|
void RemoveTorrent(string hash, RTorrentSettings settings);
|
|
void SetTorrentLabel(string hash, string label, RTorrentSettings settings);
|
|
bool HasHashTorrent(string hash, RTorrentSettings settings);
|
|
void PushTorrentUniqueView(string hash, string view, RTorrentSettings settings);
|
|
}
|
|
|
|
public class RTorrentProxy : IRTorrentProxy
|
|
{
|
|
private readonly IHttpClient _httpClient;
|
|
|
|
public RTorrentProxy(IHttpClient httpClient)
|
|
{
|
|
_httpClient = httpClient;
|
|
}
|
|
|
|
public string GetVersion(RTorrentSettings settings)
|
|
{
|
|
var document = ExecuteRequest(settings, "system.client_version");
|
|
|
|
return document.Descendants("string").FirstOrDefault()?.Value ?? "0.0.0";
|
|
}
|
|
|
|
public List<RTorrentTorrent> GetTorrents(RTorrentSettings settings)
|
|
{
|
|
var document = ExecuteRequest(settings,
|
|
"d.multicall2",
|
|
"",
|
|
"",
|
|
"d.name=", // string
|
|
"d.hash=", // string
|
|
"d.base_path=", // string
|
|
"d.custom1=", // string (label)
|
|
"d.size_bytes=", // long
|
|
"d.left_bytes=", // long
|
|
"d.down.rate=", // long (in bytes / s)
|
|
"d.ratio=", // long
|
|
"d.is_open=", // long
|
|
"d.is_active=", // long
|
|
"d.complete=", // long
|
|
"d.timestamp.finished="); // long (unix timestamp)
|
|
|
|
var torrents = document.XPathSelectElement("./methodResponse/params/param/value/array/data")
|
|
?.Elements()
|
|
.Select(x => new RTorrentTorrent(x))
|
|
.ToList()
|
|
?? new List<RTorrentTorrent>();
|
|
|
|
return torrents;
|
|
}
|
|
|
|
public void AddTorrentFromUrl(string torrentUrl, string label, RTorrentPriority priority, string directory, RTorrentSettings settings)
|
|
{
|
|
var args = new List<object> { "", torrentUrl };
|
|
args.AddRange(GetCommands(label, priority, directory));
|
|
|
|
XDocument response;
|
|
|
|
if (settings.AddStopped)
|
|
{
|
|
response = ExecuteRequest(settings, "load.normal", args.ToArray());
|
|
}
|
|
else
|
|
{
|
|
response = ExecuteRequest(settings, "load.start", args.ToArray());
|
|
}
|
|
|
|
if (response.GetIntResponse() != 0)
|
|
{
|
|
throw new DownloadClientException("Could not add torrent: {0}.", torrentUrl);
|
|
}
|
|
}
|
|
|
|
public void AddTorrentFromFile(string fileName, byte[] fileContent, string label, RTorrentPriority priority, string directory, RTorrentSettings settings)
|
|
{
|
|
var args = new List<object> { "", fileContent };
|
|
args.AddRange(GetCommands(label, priority, directory));
|
|
|
|
XDocument response;
|
|
|
|
if (settings.AddStopped)
|
|
{
|
|
response = ExecuteRequest(settings, "load.raw", args.ToArray());
|
|
}
|
|
else
|
|
{
|
|
response = ExecuteRequest(settings, "load.raw_start", args.ToArray());
|
|
}
|
|
|
|
if (response.GetIntResponse() != 0)
|
|
{
|
|
throw new DownloadClientException("Could not add torrent: {0}.", fileName);
|
|
}
|
|
}
|
|
|
|
public void SetTorrentLabel(string hash, string label, RTorrentSettings settings)
|
|
{
|
|
var response = ExecuteRequest(settings, "d.custom1.set", hash, label);
|
|
|
|
if (response.GetStringResponse() != label)
|
|
{
|
|
throw new DownloadClientException("Could not set label to {1} for torrent: {0}.", hash, label);
|
|
}
|
|
}
|
|
|
|
public void PushTorrentUniqueView(string hash, string view, RTorrentSettings settings)
|
|
{
|
|
var response = ExecuteRequest(settings, "d.views.push_back_unique", hash, view);
|
|
|
|
if (response.GetIntResponse() != 0)
|
|
{
|
|
throw new DownloadClientException("Could not push unique view {0} for torrent: {1}.", view, hash);
|
|
}
|
|
}
|
|
|
|
public void RemoveTorrent(string hash, RTorrentSettings settings)
|
|
{
|
|
var response = ExecuteRequest(settings, "d.erase", hash);
|
|
|
|
if (response.GetIntResponse() != 0)
|
|
{
|
|
throw new DownloadClientException("Could not remove torrent: {0}.", hash);
|
|
}
|
|
}
|
|
|
|
public bool HasHashTorrent(string hash, RTorrentSettings settings)
|
|
{
|
|
try
|
|
{
|
|
var response = ExecuteRequest(settings, "d.name", hash);
|
|
var name = response.GetStringResponse();
|
|
|
|
if (name.IsNullOrWhiteSpace())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var metaTorrent = name == (hash + ".meta");
|
|
|
|
return !metaTorrent;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private string[] GetCommands(string label, RTorrentPriority priority, string directory)
|
|
{
|
|
var result = new List<string>();
|
|
|
|
if (label.IsNotNullOrWhiteSpace())
|
|
{
|
|
result.Add("d.custom1.set=" + label);
|
|
}
|
|
|
|
if (priority != RTorrentPriority.Normal)
|
|
{
|
|
result.Add("d.priority.set=" + (int)priority);
|
|
}
|
|
|
|
if (directory.IsNotNullOrWhiteSpace())
|
|
{
|
|
result.Add("d.directory.set=" + directory);
|
|
}
|
|
|
|
return result.ToArray();
|
|
}
|
|
|
|
private XDocument ExecuteRequest(RTorrentSettings settings, string methodName, params object[] args)
|
|
{
|
|
var requestBuilder = new XmlRpcRequestBuilder(settings.UseSsl, settings.Host, settings.Port, settings.UrlBase)
|
|
{
|
|
LogResponseContent = true,
|
|
};
|
|
|
|
if (!settings.Username.IsNullOrWhiteSpace())
|
|
{
|
|
requestBuilder.NetworkCredential = new NetworkCredential(settings.Username, settings.Password);
|
|
}
|
|
|
|
var request = requestBuilder.Call(methodName, args).Build();
|
|
|
|
var response = _httpClient.Execute(request);
|
|
|
|
var doc = XDocument.Parse(response.Content);
|
|
|
|
var faultElement = doc.XPathSelectElement("./methodResponse/fault");
|
|
|
|
if (faultElement != null)
|
|
{
|
|
var fault = new RTorrentFault(faultElement);
|
|
|
|
throw new DownloadClientException($"rTorrent returned error code {fault.FaultCode}: {fault.FaultString}");
|
|
}
|
|
|
|
return doc;
|
|
}
|
|
}
|
|
}
|