Fixed: DownloadStation api client for DSM 5.x.

pull/6/head
margaale 7 years ago committed by Taloth
parent 29419d6575
commit 5033886b90

@ -275,7 +275,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
{ "default_destination", _defaultDestination }, { "default_destination", _defaultDestination },
}; };
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationInfoProxy>()
.Setup(v => v.GetConfig(It.IsAny<DownloadStationSettings>())) .Setup(v => v.GetConfig(It.IsAny<DownloadStationSettings>()))
.Returns(_downloadStationConfigItems); .Returns(_downloadStationConfigItems);
} }
@ -311,7 +311,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
torrents = new List<DownloadStationTask>(); torrents = new List<DownloadStationTask>();
} }
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Setup(s => s.GetTasks(It.IsAny<DownloadStationSettings>())) .Setup(s => s.GetTasks(It.IsAny<DownloadStationSettings>()))
.Returns(torrents); .Returns(torrents);
} }
@ -330,11 +330,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
.Setup(s => s.Get(It.IsAny<HttpRequest>())) .Setup(s => s.Get(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[1000])); .Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[1000]));
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Setup(s => s.AddTaskFromUrl(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>())) .Setup(s => s.AddTaskFromUrl(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
.Callback(PrepareClientToReturnQueuedItem); .Callback(PrepareClientToReturnQueuedItem);
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Setup(s => s.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>())) .Setup(s => s.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
.Callback(PrepareClientToReturnQueuedItem); .Callback(PrepareClientToReturnQueuedItem);
} }
@ -352,7 +352,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
{ {
var tasks = new List<DownloadStationTask>() { _queued, _completed, _failed, _downloading, _seeding }; var tasks = new List<DownloadStationTask>() { _queued, _completed, _failed, _downloading, _seeding };
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Setup(d => d.GetTasks(_settings)) .Setup(d => d.GetTasks(_settings))
.Returns(tasks); .Returns(tasks);
@ -372,7 +372,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
id.Should().NotBeNullOrEmpty(); id.Should().NotBeNullOrEmpty();
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once()); .Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
} }
@ -389,7 +389,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
id.Should().NotBeNullOrEmpty(); id.Should().NotBeNullOrEmpty();
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), $"{_defaultDestination}/{_category}", It.IsAny<DownloadStationSettings>()), Times.Once()); .Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), $"{_defaultDestination}/{_category}", It.IsAny<DownloadStationSettings>()), Times.Once());
} }
@ -405,7 +405,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
id.Should().NotBeNullOrEmpty(); id.Should().NotBeNullOrEmpty();
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, It.IsAny<DownloadStationSettings>()), Times.Once()); .Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, It.IsAny<DownloadStationSettings>()), Times.Once());
} }
@ -482,7 +482,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.Download(remoteEpisode)); Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.Download(remoteEpisode));
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, _settings), Times.Never()); .Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, _settings), Times.Never());
} }

@ -177,7 +177,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
{ "default_destination", _defaultDestination }, { "default_destination", _defaultDestination },
}; };
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationInfoProxy>()
.Setup(v => v.GetConfig(It.IsAny<DownloadStationSettings>())) .Setup(v => v.GetConfig(It.IsAny<DownloadStationSettings>()))
.Returns(_downloadStationConfigItems); .Returns(_downloadStationConfigItems);
} }
@ -213,7 +213,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
nzbs = new List<DownloadStationTask>(); nzbs = new List<DownloadStationTask>();
} }
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Setup(s => s.GetTasks(It.IsAny<DownloadStationSettings>())) .Setup(s => s.GetTasks(It.IsAny<DownloadStationSettings>()))
.Returns(nzbs); .Returns(nzbs);
} }
@ -233,7 +233,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[1000])); .Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[1000]));
*/ */
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Setup(s => s.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>())) .Setup(s => s.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
.Callback(PrepareClientToReturnQueuedItem); .Callback(PrepareClientToReturnQueuedItem);
} }
@ -242,7 +242,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
{ {
var tasks = new List<DownloadStationTask>() { _queued, _completed, _failed, _downloading, _seeding }; var tasks = new List<DownloadStationTask>() { _queued, _completed, _failed, _downloading, _seeding };
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Setup(d => d.GetTasks(_settings)) .Setup(d => d.GetTasks(_settings))
.Returns(tasks); .Returns(tasks);
} }
@ -260,7 +260,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
id.Should().NotBeNullOrEmpty(); id.Should().NotBeNullOrEmpty();
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once()); .Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
} }
@ -277,7 +277,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
id.Should().NotBeNullOrEmpty(); id.Should().NotBeNullOrEmpty();
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), $"{_defaultDestination}/{_category}", It.IsAny<DownloadStationSettings>()), Times.Once()); .Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), $"{_defaultDestination}/{_category}", It.IsAny<DownloadStationSettings>()), Times.Once());
} }
@ -293,7 +293,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
id.Should().NotBeNullOrEmpty(); id.Should().NotBeNullOrEmpty();
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), null, It.IsAny<DownloadStationSettings>()), Times.Once()); .Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), null, It.IsAny<DownloadStationSettings>()), Times.Once());
} }
@ -370,7 +370,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.Download(remoteEpisode)); Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.Download(remoteEpisode));
Mocker.GetMock<IDownloadStationProxy>() Mocker.GetMock<IDownloadStationTaskProxy>()
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, _settings), Times.Never()); .Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, _settings), Times.Never());
} }

@ -1,13 +1,19 @@
namespace NzbDrone.Core.Download.Clients.DownloadStation namespace NzbDrone.Core.Download.Clients.DownloadStation
{ {
public class DiskStationApiInfo public class DiskStationApiInfo
{ {
private string _path; private string _path;
public int MaxVersion { get; set; } public int MaxVersion { get; set; }
public int MinVersion { get; set; } public int MinVersion { get; set; }
public DiskStationApi Type { get; set; }
public string Name { get; set; }
public bool NeedsAuthentication { get; set; }
public string Path public string Path
{ {
get { return _path; } get { return _path; }

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NLog; using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Download.Clients.DownloadStation.Responses; using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
@ -13,20 +14,19 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
public class DSMInfoProxy : DiskStationProxyBase, IDSMInfoProxy public class DSMInfoProxy : DiskStationProxyBase, IDSMInfoProxy
{ {
public DSMInfoProxy(IHttpClient httpClient, Logger logger) : public DSMInfoProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger) :
base(httpClient, logger) base(DiskStationApi.DSMInfo, "SYNO.DSM.Info", httpClient, cacheManager, logger)
{ {
} }
public string GetSerialNumber(DownloadStationSettings settings) public string GetSerialNumber(DownloadStationSettings settings)
{ {
var arguments = new Dictionary<string, object>() { var info = GetApiInfo(settings);
{ "api", "SYNO.DSM.Info" },
{ "version", "2" }, var requestBuilder = BuildRequest(settings, "getinfo", info.MinVersion);
{ "method", "getinfo" }
}; var response = ProcessRequest<DSMInfoResponse>(requestBuilder, "get serial number", settings);
var response = ProcessRequest<DSMInfoResponse>(DiskStationApi.DSMInfo, arguments, settings, "get serial number");
return response.Data.SerialNumber; return response.Data.SerialNumber;
} }
} }

@ -1,63 +1,77 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using NLog; using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download.Clients.DownloadStation.Responses; using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
{ {
public abstract class DiskStationProxyBase public interface IDiskStationProxy
{ {
private static readonly Dictionary<DiskStationApi, string> Resources; DiskStationApiInfo GetApiInfo(DownloadStationSettings settings);
}
private readonly IHttpClient _httpClient; public abstract class DiskStationProxyBase : IDiskStationProxy
{
protected readonly Logger _logger; protected readonly Logger _logger;
private bool _authenticated;
private readonly IHttpClient _httpClient;
private readonly ICached<DiskStationApiInfo> _infoCache;
private readonly ICached<string> _sessionCache;
private readonly DiskStationApi _apiType;
private readonly string _apiName;
private static readonly DiskStationApiInfo _apiInfo;
static DiskStationProxyBase() static DiskStationProxyBase()
{ {
Resources = new Dictionary<DiskStationApi, string> _apiInfo = new DiskStationApiInfo()
{ {
{ DiskStationApi.Info, "query.cgi" } Type = DiskStationApi.Info,
Name = "SYNO.API.Info",
Path = "query.cgi",
MaxVersion = 1,
MinVersion = 1,
NeedsAuthentication = false
}; };
} }
public DiskStationProxyBase(IHttpClient httpClient, Logger logger) public DiskStationProxyBase(DiskStationApi apiType,
string apiName,
IHttpClient httpClient,
ICacheManager cacheManager,
Logger logger)
{ {
_httpClient = httpClient; _httpClient = httpClient;
_logger = logger; _logger = logger;
_infoCache = cacheManager.GetCache<DiskStationApiInfo>(typeof(DiskStationProxyBase), "apiInfo");
_sessionCache = cacheManager.GetCache<string>(typeof(DiskStationProxyBase), "sessions");
_apiType = apiType;
_apiName = apiName;
} }
private string GenerateSessionCacheKey(DownloadStationSettings settings)
protected DiskStationResponse<object> ProcessRequest(DiskStationApi api,
Dictionary<string, object> arguments,
DownloadStationSettings settings,
string operation,
HttpMethod method = HttpMethod.GET)
{ {
return ProcessRequest<object>(api, arguments, settings, operation, method); return $"{settings.Username}@{settings.Host}:{settings.Port}";
} }
protected DiskStationResponse<T> ProcessRequest<T>(DiskStationApi api, protected DiskStationResponse<T> ProcessRequest<T>(HttpRequestBuilder requestBuilder,
Dictionary<string, object> arguments, string operation,
DownloadStationSettings settings, DownloadStationSettings settings) where T : new()
string operation,
HttpMethod method = HttpMethod.GET,
int retries = 0) where T : new()
{ {
if (retries == 5) return ProcessRequest<T>(requestBuilder, operation, _apiType, settings);
{ }
throw new DownloadClientException("Try to process request to {0} with {1} more than 5 times", api, arguments.ToJson().ToString());
}
if (!_authenticated && api != DiskStationApi.Info && api != DiskStationApi.DSMInfo)
{
AuthenticateClient(settings);
}
var request = BuildRequest(settings, api, arguments, method); private DiskStationResponse<T> ProcessRequest<T>(HttpRequestBuilder requestBuilder,
string operation,
DiskStationApi api,
DownloadStationSettings settings) where T : new()
{
var request = requestBuilder.Build();
var response = _httpClient.Execute(request); var response = _httpClient.Execute(request);
_logger.Debug("Trying to {0}", operation); _logger.Debug("Trying to {0}", operation);
@ -77,16 +91,14 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
if (responseContent.Error.SessionError) if (responseContent.Error.SessionError)
{ {
_authenticated = false; _sessionCache.Remove(GenerateSessionCacheKey(settings));
if (responseContent.Error.Code == 105) if (responseContent.Error.Code == 105)
{ {
throw new DownloadClientAuthenticationException(msg); throw new DownloadClientAuthenticationException(msg);
} }
return ProcessRequest<T>(api, arguments, settings, operation, method, ++retries);
} }
throw new DownloadClientException(msg); throw new DownloadClientException(msg);
} }
} }
@ -96,124 +108,126 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
} }
} }
private void AuthenticateClient(DownloadStationSettings settings) private string AuthenticateClient(DownloadStationSettings settings)
{ {
var arguments = new Dictionary<string, object> var authInfo = GetApiInfo(DiskStationApi.Auth, settings);
{
{ "api", "SYNO.API.Auth" },
{ "version", "1" },
{ "method", "login" },
{ "account", settings.Username },
{ "passwd", settings.Password },
{ "format", "cookie" },
{ "session", "DownloadStation" },
};
var authLoginRequest = BuildRequest(settings, DiskStationApi.Auth, arguments, HttpMethod.GET);
authLoginRequest.StoreResponseCookie = true;
var response = _httpClient.Execute(authLoginRequest); var requestBuilder = BuildRequest(settings, authInfo, "login", 2);
requestBuilder.AddQueryParam("account", settings.Username);
requestBuilder.AddQueryParam("passwd", settings.Password);
requestBuilder.AddQueryParam("format", "sid");
requestBuilder.AddQueryParam("session", Guid.NewGuid().ToString());
var downloadStationResponse = Json.Deserialize<DiskStationResponse<DiskStationAuthResponse>>(response.Content); var authResponse = ProcessRequest<DiskStationAuthResponse>(requestBuilder, "login", DiskStationApi.Auth, settings);
var authResponse = Json.Deserialize<DiskStationResponse<DiskStationAuthResponse>>(response.Content); return authResponse.Data.SId;
}
_authenticated = authResponse.Success; protected HttpRequestBuilder BuildRequest(DownloadStationSettings settings, string methodName, int apiVersion, HttpMethod httpVerb = HttpMethod.GET)
{
var info = GetApiInfo(_apiType, settings);
if (!_authenticated) return BuildRequest(settings, info, methodName, apiVersion, httpVerb);
{
throw new DownloadClientAuthenticationException(downloadStationResponse.Error.GetMessage(DiskStationApi.Auth));
}
} }
private HttpRequest BuildRequest(DownloadStationSettings settings, DiskStationApi api, Dictionary<string, object> arguments, HttpMethod method) private HttpRequestBuilder BuildRequest(DownloadStationSettings settings, DiskStationApiInfo apiInfo, string methodName, int apiVersion, HttpMethod httpVerb = HttpMethod.GET)
{ {
if (!Resources.ContainsKey(api)) var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port).Resource($"webapi/{apiInfo.Path}");
{ requestBuilder.Method = httpVerb;
GetApiVersion(settings, api);
}
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port).Resource($"webapi/{Resources[api]}");
requestBuilder.Method = method;
requestBuilder.LogResponseContent = true; requestBuilder.LogResponseContent = true;
requestBuilder.SuppressHttpError = true; requestBuilder.SuppressHttpError = true;
requestBuilder.AllowAutoRedirect = false; requestBuilder.AllowAutoRedirect = false;
requestBuilder.Headers.ContentType = "application/json";
if (requestBuilder.Method == HttpMethod.POST) if (apiVersion < apiInfo.MinVersion || apiVersion > apiInfo.MaxVersion)
{ {
if (api == DiskStationApi.DownloadStationTask && arguments.ContainsKey("file")) throw new ArgumentOutOfRangeException(nameof(apiVersion));
{ }
requestBuilder.Headers.ContentType = "multipart/form-data";
foreach (var arg in arguments) if (httpVerb == HttpMethod.POST)
{ {
if (arg.Key == "file") if (apiInfo.NeedsAuthentication)
{
Dictionary<string, object> file = (Dictionary<string, object>)arg.Value;
requestBuilder.AddFormUpload(arg.Key, file["name"].ToString(), (byte[])file["data"]);
}
else
{
requestBuilder.AddFormParameter(arg.Key, arg.Value);
}
}
}
else
{ {
requestBuilder.Headers.ContentType = "application/json"; requestBuilder.AddFormParameter("_sid", _sessionCache.Get(GenerateSessionCacheKey(settings), () => AuthenticateClient(settings), TimeSpan.FromHours(6)));
} }
requestBuilder.AddFormParameter("api", apiInfo.Name);
requestBuilder.AddFormParameter("version", apiVersion);
requestBuilder.AddFormParameter("method", methodName);
} }
else else
{ {
foreach (var arg in arguments) if (apiInfo.NeedsAuthentication)
{ {
requestBuilder.AddQueryParam(arg.Key, arg.Value); requestBuilder.AddQueryParam("_sid", _sessionCache.Get(GenerateSessionCacheKey(settings), () => AuthenticateClient(settings), TimeSpan.FromHours(6)));
} }
requestBuilder.AddQueryParam("api", apiInfo.Name);
requestBuilder.AddQueryParam("version", apiVersion);
requestBuilder.AddQueryParam("method", methodName);
} }
return requestBuilder.Build(); return requestBuilder;
}
private string GenerateInfoCacheKey(DownloadStationSettings settings, DiskStationApi api)
{
return $"{settings.Host}:{settings.Port}->{api}";
}
private void UpdateApiInfo(DownloadStationSettings settings)
{
var apis = new Dictionary<string, DiskStationApi>()
{
{ "SYNO.API.Auth", DiskStationApi.Auth },
{ _apiName, _apiType }
};
var requestBuilder = BuildRequest(settings, _apiInfo, "query", _apiInfo.MinVersion);
requestBuilder.AddQueryParam("query", string.Join(",", apis.Keys));
var infoResponse = ProcessRequest<DiskStationApiInfoResponse>(requestBuilder, "get api info", _apiInfo.Type, settings);
foreach (var data in infoResponse.Data)
{
if (apis.ContainsKey(data.Key))
{
data.Value.Name = data.Key;
data.Value.Type = apis[data.Key];
data.Value.NeedsAuthentication = apis[data.Key] != DiskStationApi.Auth;
_infoCache.Set(GenerateInfoCacheKey(settings, apis[data.Key]), data.Value, TimeSpan.FromHours(1));
}
}
} }
protected IEnumerable<int> GetApiVersion(DownloadStationSettings settings, DiskStationApi api) private DiskStationApiInfo GetApiInfo(DiskStationApi api, DownloadStationSettings settings)
{ {
var arguments = new Dictionary<string, object> if (api == DiskStationApi.Info)
{ {
{ "api", "SYNO.API.Info" }, return _apiInfo;
{ "version", "1" }, }
{ "method", "query" },
{ "query", "SYNO.API.Auth, SYNO.DownloadStation.Info, SYNO.DownloadStation.Task, SYNO.FileStation.List, SYNO.DSM.Info" }, var key = GenerateInfoCacheKey(settings, api);
}; var info = _infoCache.Find(key);
var infoResponse = ProcessRequest<DiskStationApiInfoResponse>(DiskStationApi.Info, arguments, settings, "Get api version"); if (info == null)
//TODO: Refactor this into more elegant code
var infoResponeDSAuth = infoResponse.Data["SYNO.API.Auth"];
var infoResponeDSInfo = infoResponse.Data["SYNO.DownloadStation.Info"];
var infoResponeDSTask = infoResponse.Data["SYNO.DownloadStation.Task"];
var infoResponseFSList = infoResponse.Data["SYNO.FileStation.List"];
var infoResponseDSMInfo = infoResponse.Data["SYNO.DSM.Info"];
Resources[DiskStationApi.Auth] = infoResponeDSAuth.Path;
Resources[DiskStationApi.DownloadStationInfo] = infoResponeDSInfo.Path;
Resources[DiskStationApi.DownloadStationTask] = infoResponeDSTask.Path;
Resources[DiskStationApi.FileStationList] = infoResponseFSList.Path;
Resources[DiskStationApi.DSMInfo] = infoResponseDSMInfo.Path;
switch (api)
{ {
case DiskStationApi.Auth: UpdateApiInfo(settings);
return Enumerable.Range(infoResponeDSAuth.MinVersion, infoResponeDSAuth.MaxVersion - infoResponeDSAuth.MinVersion + 1); info = _infoCache.Find(key);
case DiskStationApi.DownloadStationInfo:
return Enumerable.Range(infoResponeDSInfo.MinVersion, infoResponeDSInfo.MaxVersion - infoResponeDSInfo.MinVersion + 1); if (info == null)
case DiskStationApi.DownloadStationTask: {
return Enumerable.Range(infoResponeDSTask.MinVersion, infoResponeDSTask.MaxVersion - infoResponeDSTask.MinVersion + 1); throw new DownloadClientException("Info of {0} not found on {1}:{2}", api, settings.Host, settings.Port);
case DiskStationApi.FileStationList: }
return Enumerable.Range(infoResponseFSList.MinVersion, infoResponseFSList.MaxVersion - infoResponseFSList.MinVersion + 1);
case DiskStationApi.DSMInfo:
return Enumerable.Range(infoResponseDSMInfo.MinVersion, infoResponseDSMInfo.MaxVersion - infoResponseDSMInfo.MinVersion + 1);
default:
throw new DownloadClientException("Api not implemented");
} }
return info;
}
public DiskStationApiInfo GetApiInfo(DownloadStationSettings settings)
{
return GetApiInfo(_apiType, settings);
} }
} }
} }

@ -0,0 +1,29 @@
using NLog;
using NzbDrone.Common.Http;
using System.Collections.Generic;
using NzbDrone.Common.Cache;
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
{
public interface IDownloadStationInfoProxy : IDiskStationProxy
{
Dictionary<string, object> GetConfig(DownloadStationSettings settings);
}
public class DownloadStationInfoProxy : DiskStationProxyBase, IDownloadStationInfoProxy
{
public DownloadStationInfoProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger) :
base(DiskStationApi.DownloadStationInfo, "SYNO.DownloadStation.Info", httpClient, cacheManager, logger)
{
}
public Dictionary<string, object> GetConfig(DownloadStationSettings settings)
{
var requestBuilder = BuildRequest(settings, "getConfig", 1);
var response = ProcessRequest<Dictionary<string, object>>(requestBuilder, "get config", settings);
return response.Data;
}
}
}

@ -1,121 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
{
public interface IDownloadStationProxy
{
IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings);
Dictionary<string, object> GetConfig(DownloadStationSettings settings);
void RemoveTask(string downloadId, DownloadStationSettings settings);
void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings);
void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings);
IEnumerable<int> GetApiVersion(DownloadStationSettings settings);
}
public class DownloadStationProxy : DiskStationProxyBase, IDownloadStationProxy
{
public DownloadStationProxy(IHttpClient httpClient, Logger logger)
: base(httpClient, logger)
{
}
public void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings)
{
var arguments = new Dictionary<string, object>
{
{ "api", "SYNO.DownloadStation.Task" },
{ "version", "2" },
{ "method", "create" }
};
if (downloadDirectory.IsNotNullOrWhiteSpace())
{
arguments.Add("destination", downloadDirectory);
}
arguments.Add("file", new Dictionary<string, object>() { { "name", filename }, { "data", data } });
var response = ProcessRequest(DiskStationApi.DownloadStationTask, arguments, settings, $"add task from data {filename}", HttpMethod.POST);
}
public void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings)
{
var arguments = new Dictionary<string, object>
{
{ "api", "SYNO.DownloadStation.Task" },
{ "version", "3" },
{ "method", "create" },
{ "uri", url }
};
if (downloadDirectory.IsNotNullOrWhiteSpace())
{
arguments.Add("destination", downloadDirectory);
}
var response = ProcessRequest(DiskStationApi.DownloadStationTask, arguments, settings, $"add task from url {url}");
}
public IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings)
{
var arguments = new Dictionary<string, object>
{
{ "api", "SYNO.DownloadStation.Task" },
{ "version", "1" },
{ "method", "list" },
{ "additional", "detail,transfer" }
};
try
{
var response = ProcessRequest<DownloadStationTaskInfoResponse>(DiskStationApi.DownloadStationTask, arguments, settings, "get tasks");
return response.Data.Tasks;
}
catch (DownloadClientException e)
{
_logger.Error(e);
return new List<DownloadStationTask>();
}
}
public Dictionary<string, object> GetConfig(DownloadStationSettings settings)
{
var arguments = new Dictionary<string, object>
{
{ "api", "SYNO.DownloadStation.Info" },
{ "version", "1" },
{ "method", "getconfig" }
};
var response = ProcessRequest<Dictionary<string, object>>(DiskStationApi.DownloadStationInfo, arguments, settings, "get config");
return response.Data;
}
public void RemoveTask(string downloadId, DownloadStationSettings settings)
{
var arguments = new Dictionary<string, object>
{
{ "api", "SYNO.DownloadStation.Task" },
{ "version", "1" },
{ "method", "delete" },
{ "id", downloadId },
{ "force_complete", false }
};
var response = ProcessRequest(DiskStationApi.DownloadStationTask, arguments, settings, $"remove item {downloadId}");
}
public IEnumerable<int> GetApiVersion(DownloadStationSettings settings)
{
return base.GetApiVersion(settings, DiskStationApi.DownloadStationInfo);
}
}
}

@ -0,0 +1,79 @@
using System.Collections.Generic;
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
{
public interface IDownloadStationTaskProxy : IDiskStationProxy
{
IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings);
void RemoveTask(string downloadId, DownloadStationSettings settings);
void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings);
void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings);
}
public class DownloadStationTaskProxy : DiskStationProxyBase, IDownloadStationTaskProxy
{
public DownloadStationTaskProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger)
: base(DiskStationApi.DownloadStationTask, "SYNO.DownloadStation.Task", httpClient, cacheManager, logger)
{
}
public void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings)
{
var requestBuilder = BuildRequest(settings, "create", 2, HttpMethod.POST);
if (downloadDirectory.IsNotNullOrWhiteSpace())
{
requestBuilder.AddFormParameter("destination", downloadDirectory);
}
requestBuilder.AddFormUpload("file", filename, data);
var response = ProcessRequest<object>(requestBuilder, $"add task from data {filename}", settings);
}
public void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings)
{
var requestBuilder = BuildRequest(settings, "create", 3);
requestBuilder.AddQueryParam("uri", url);
if (downloadDirectory.IsNotNullOrWhiteSpace())
{
requestBuilder.AddQueryParam("destination", downloadDirectory);
}
var response = ProcessRequest<object>(requestBuilder, $"add task from url {url}", settings);
}
public IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings)
{
try
{
var requestBuilder = BuildRequest(settings, "list", 1);
requestBuilder.AddQueryParam("additional", "detail,transfer");
var response = ProcessRequest<DownloadStationTaskInfoResponse>(requestBuilder, "get tasks", settings);
return response.Data.Tasks;
}
catch (DownloadClientException e)
{
_logger.Error(e);
return new List<DownloadStationTask>();
}
}
public void RemoveTask(string downloadId, DownloadStationSettings settings)
{
var requestBuilder = BuildRequest(settings, "delete", 1);
requestBuilder.AddQueryParam("id", downloadId);
requestBuilder.AddQueryParam("force_complete", false);
var response = ProcessRequest<object>(requestBuilder, $"remove item {downloadId}", settings);
}
}
}

@ -2,31 +2,27 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download.Clients.DownloadStation.Responses; using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
{ {
public interface IFileStationProxy public interface IFileStationProxy : IDiskStationProxy
{ {
SharedFolderMapping GetSharedFolderMapping(string sharedFolder, DownloadStationSettings settings); SharedFolderMapping GetSharedFolderMapping(string sharedFolder, DownloadStationSettings settings);
IEnumerable<int> GetApiVersion(DownloadStationSettings settings);
FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings); FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings);
} }
public class FileStationProxy : DiskStationProxyBase, IFileStationProxy public class FileStationProxy : DiskStationProxyBase, IFileStationProxy
{ {
public FileStationProxy(IHttpClient httpClient, Logger logger) public FileStationProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger)
: base(httpClient, logger) : base(DiskStationApi.FileStationList, "SYNO.FileStation.List", httpClient, cacheManager, logger)
{
}
public IEnumerable<int> GetApiVersion(DownloadStationSettings settings)
{ {
return base.GetApiVersion(settings, DiskStationApi.FileStationList);
} }
public SharedFolderMapping GetSharedFolderMapping(string sharedFolder, DownloadStationSettings settings) public SharedFolderMapping GetSharedFolderMapping(string sharedFolder, DownloadStationSettings settings)
{ {
var info = GetInfoFileOrDirectory(sharedFolder, settings); var info = GetInfoFileOrDirectory(sharedFolder, settings);
@ -38,16 +34,11 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
public FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings) public FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings)
{ {
var arguments = new Dictionary<string, object> var requestBuilder = BuildRequest(settings, "getinfo", 2);
{ requestBuilder.AddQueryParam("path", new[] { path }.ToJson());
{ "api", "SYNO.FileStation.List" }, requestBuilder.AddQueryParam("additional", "[\"real_path\"]");
{ "version", "2" },
{ "method", "getinfo" }, var response = ProcessRequest<FileStationListResponse>(requestBuilder, $"get info of {path}", settings);
{ "path", new [] { path }.ToJson() },
{ "additional", $"[\"real_path\"]" }
};
var response = ProcessRequest<FileStationListResponse>(DiskStationApi.FileStationList, arguments, settings, $"get info of {path}");
return response.Data.Files.First(); return response.Data.Files.First();
} }

@ -5,7 +5,6 @@ using System.Linq;
using System.Net; using System.Net;
using FluentValidation.Results; using FluentValidation.Results;
using NLog; using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
@ -20,7 +19,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
{ {
public class TorrentDownloadStation : TorrentClientBase<DownloadStationSettings> public class TorrentDownloadStation : TorrentClientBase<DownloadStationSettings>
{ {
protected readonly IDownloadStationProxy _proxy; protected readonly IDownloadStationInfoProxy _dsInfoProxy;
protected readonly IDownloadStationTaskProxy _dsTaskProxy;
protected readonly ISharedFolderResolver _sharedFolderResolver; protected readonly ISharedFolderResolver _sharedFolderResolver;
protected readonly ISerialNumberProvider _serialNumberProvider; protected readonly ISerialNumberProvider _serialNumberProvider;
protected readonly IFileStationProxy _fileStationProxy; protected readonly IFileStationProxy _fileStationProxy;
@ -28,7 +28,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
public TorrentDownloadStation(ISharedFolderResolver sharedFolderResolver, public TorrentDownloadStation(ISharedFolderResolver sharedFolderResolver,
ISerialNumberProvider serialNumberProvider, ISerialNumberProvider serialNumberProvider,
IFileStationProxy fileStationProxy, IFileStationProxy fileStationProxy,
IDownloadStationProxy proxy, IDownloadStationInfoProxy dsInfoProxy,
IDownloadStationTaskProxy dsTaskProxy,
ITorrentFileInfoReader torrentFileInfoReader, ITorrentFileInfoReader torrentFileInfoReader,
IHttpClient httpClient, IHttpClient httpClient,
IConfigService configService, IConfigService configService,
@ -37,7 +38,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
Logger logger) Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger)
{ {
_proxy = proxy; _dsInfoProxy = dsInfoProxy;
_dsTaskProxy = dsTaskProxy;
_fileStationProxy = fileStationProxy; _fileStationProxy = fileStationProxy;
_sharedFolderResolver = sharedFolderResolver; _sharedFolderResolver = sharedFolderResolver;
_serialNumberProvider = serialNumberProvider; _serialNumberProvider = serialNumberProvider;
@ -47,7 +49,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
protected IEnumerable<DownloadStationTask> GetTasks() protected IEnumerable<DownloadStationTask> GetTasks()
{ {
return _proxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.BT.ToString().ToLower()); return _dsTaskProxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.BT.ToString().ToLower());
} }
public override IEnumerable<DownloadClientItem> GetItems() public override IEnumerable<DownloadClientItem> GetItems()
@ -129,7 +131,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
DeleteItemData(downloadId); DeleteItemData(downloadId);
} }
_proxy.RemoveTask(ParseDownloadId(downloadId), Settings); _dsTaskProxy.RemoveTask(ParseDownloadId(downloadId), Settings);
_logger.Debug("{0} removed correctly", downloadId); _logger.Debug("{0} removed correctly", downloadId);
} }
@ -148,7 +150,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
{ {
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings); var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
_proxy.AddTaskFromUrl(magnetLink, GetDownloadDirectory(), Settings); _dsTaskProxy.AddTaskFromUrl(magnetLink, GetDownloadDirectory(), Settings);
var item = GetTasks().SingleOrDefault(t => t.Additional.Detail["uri"] == magnetLink); var item = GetTasks().SingleOrDefault(t => t.Additional.Detail["uri"] == magnetLink);
@ -167,7 +169,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
{ {
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings); var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
_proxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings); _dsTaskProxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings);
var items = GetTasks().Where(t => t.Additional.Detail["uri"] == Path.GetFileNameWithoutExtension(filename)); var items = GetTasks().Where(t => t.Additional.Detail["uri"] == Path.GetFileNameWithoutExtension(filename));
@ -358,13 +360,13 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
protected ValidationFailure ValidateVersion() protected ValidationFailure ValidateVersion()
{ {
var versionRange = _proxy.GetApiVersion(Settings); var info = _dsTaskProxy.GetApiInfo(Settings);
_logger.Debug("Download Station api version information: Min {0} - Max {1}", versionRange.Min(), versionRange.Max()); _logger.Debug("Download Station api version information: Min {0} - Max {1}", info.MinVersion, info.MaxVersion);
if (!versionRange.Contains(2)) if (info.MinVersion > 2 || info.MaxVersion < 2)
{ {
return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {versionRange.Min()} to {versionRange.Max()}"); return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {info.MinVersion} to {info.MaxVersion}");
} }
return null; return null;
@ -395,7 +397,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
protected string GetDefaultDir() protected string GetDefaultDir()
{ {
var config = _proxy.GetConfig(Settings); var config = _dsInfoProxy.GetConfig(Settings);
var path = config["default_destination"] as string; var path = config["default_destination"] as string;

@ -17,7 +17,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
{ {
public class UsenetDownloadStation : UsenetClientBase<DownloadStationSettings> public class UsenetDownloadStation : UsenetClientBase<DownloadStationSettings>
{ {
protected readonly IDownloadStationProxy _proxy; protected readonly IDownloadStationInfoProxy _dsInfoProxy;
protected readonly IDownloadStationTaskProxy _dsTaskProxy;
protected readonly ISharedFolderResolver _sharedFolderResolver; protected readonly ISharedFolderResolver _sharedFolderResolver;
protected readonly ISerialNumberProvider _serialNumberProvider; protected readonly ISerialNumberProvider _serialNumberProvider;
protected readonly IFileStationProxy _fileStationProxy; protected readonly IFileStationProxy _fileStationProxy;
@ -25,7 +26,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
public UsenetDownloadStation(ISharedFolderResolver sharedFolderResolver, public UsenetDownloadStation(ISharedFolderResolver sharedFolderResolver,
ISerialNumberProvider serialNumberProvider, ISerialNumberProvider serialNumberProvider,
IFileStationProxy fileStationProxy, IFileStationProxy fileStationProxy,
IDownloadStationProxy proxy, IDownloadStationInfoProxy dsInfoProxy,
IDownloadStationTaskProxy dsTaskProxy,
IHttpClient httpClient, IHttpClient httpClient,
IConfigService configService, IConfigService configService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
@ -34,7 +36,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
) )
: base(httpClient, configService, diskProvider, remotePathMappingService, logger) : base(httpClient, configService, diskProvider, remotePathMappingService, logger)
{ {
_proxy = proxy; _dsInfoProxy = dsInfoProxy;
_dsTaskProxy = dsTaskProxy;
_fileStationProxy = fileStationProxy; _fileStationProxy = fileStationProxy;
_sharedFolderResolver = sharedFolderResolver; _sharedFolderResolver = sharedFolderResolver;
_serialNumberProvider = serialNumberProvider; _serialNumberProvider = serialNumberProvider;
@ -44,7 +47,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
protected IEnumerable<DownloadStationTask> GetTasks() protected IEnumerable<DownloadStationTask> GetTasks()
{ {
return _proxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.NZB.ToString().ToLower()); return _dsTaskProxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.NZB.ToString().ToLower());
} }
public override IEnumerable<DownloadClientItem> GetItems() public override IEnumerable<DownloadClientItem> GetItems()
@ -153,7 +156,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
DeleteItemData(downloadId); DeleteItemData(downloadId);
} }
_proxy.RemoveTask(ParseDownloadId(downloadId), Settings); _dsTaskProxy.RemoveTask(ParseDownloadId(downloadId), Settings);
_logger.Debug("{0} removed correctly", downloadId); _logger.Debug("{0} removed correctly", downloadId);
} }
@ -161,7 +164,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
{ {
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings); var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
_proxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings); _dsTaskProxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings);
var items = GetTasks().Where(t => t.Additional.Detail["uri"] == filename); var items = GetTasks().Where(t => t.Additional.Detail["uri"] == filename);
@ -276,13 +279,13 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
protected ValidationFailure ValidateVersion() protected ValidationFailure ValidateVersion()
{ {
var versionRange = _proxy.GetApiVersion(Settings); var info = _dsTaskProxy.GetApiInfo(Settings);
_logger.Debug("Download Station api version information: Min {0} - Max {1}", versionRange.Min(), versionRange.Max()); _logger.Debug("Download Station api version information: Min {0} - Max {1}", info.MinVersion, info.MaxVersion);
if (!versionRange.Contains(2)) if (info.MinVersion > 2 || info.MaxVersion < 2)
{ {
return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {versionRange.Min()} to {versionRange.Max()}"); return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {info.MinVersion} to {info.MaxVersion}");
} }
return null; return null;
@ -394,7 +397,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
protected string GetDefaultDir() protected string GetDefaultDir()
{ {
var config = _proxy.GetConfig(Settings); var config = _dsInfoProxy.GetConfig(Settings);
var path = config["default_destination"] as string; var path = config["default_destination"] as string;

@ -355,8 +355,9 @@
<Compile Include="Download\Clients\Deluge\DelugeUpdateUIResult.cs" /> <Compile Include="Download\Clients\Deluge\DelugeUpdateUIResult.cs" />
<Compile Include="Download\Clients\DownloadClientAuthenticationException.cs" /> <Compile Include="Download\Clients\DownloadClientAuthenticationException.cs" />
<Compile Include="Download\Clients\DownloadClientException.cs" /> <Compile Include="Download\Clients\DownloadClientException.cs" />
<Compile Include="Download\Clients\DownloadStation\Proxies\DownloadStationInfoProxy.cs" />
<Compile Include="Download\Clients\DownloadStation\TorrentDownloadStation.cs" /> <Compile Include="Download\Clients\DownloadStation\TorrentDownloadStation.cs" />
<Compile Include="Download\Clients\DownloadStation\Proxies\DownloadStationProxy.cs" /> <Compile Include="Download\Clients\DownloadStation\Proxies\DownloadStationTaskProxy.cs" />
<Compile Include="Download\Clients\DownloadStation\DownloadStationSettings.cs" /> <Compile Include="Download\Clients\DownloadStation\DownloadStationSettings.cs" />
<Compile Include="Download\Clients\DownloadStation\DownloadStationTask.cs" /> <Compile Include="Download\Clients\DownloadStation\DownloadStationTask.cs" />
<Compile Include="Download\Clients\DownloadStation\DownloadStationTaskAdditional.cs" /> <Compile Include="Download\Clients\DownloadStation\DownloadStationTaskAdditional.cs" />

Loading…
Cancel
Save