Fixed: Qbittorrent api errors when only one of two seed criteria was configured
closes #4393
This commit is contained in:
parent
5a69801877
commit
652d44722b
|
@ -179,6 +179,38 @@ namespace NzbDrone.Common.Test.Http
|
||||||
ExceptionVerification.IgnoreWarns();
|
ExceptionVerification.IgnoreWarns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_throw_on_suppressed_status_codes()
|
||||||
|
{
|
||||||
|
var request = new HttpRequest($"http://{_httpBinHost}/status/{HttpStatusCode.NotFound}");
|
||||||
|
request.SuppressHttpErrorStatusCodes = new[] { HttpStatusCode.NotFound };
|
||||||
|
|
||||||
|
var exception = Assert.Throws<HttpException>(() => Subject.Get<HttpBinResource>(request));
|
||||||
|
|
||||||
|
ExceptionVerification.IgnoreWarns();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_log_unsuccessful_status_codes()
|
||||||
|
{
|
||||||
|
var request = new HttpRequest($"http://{_httpBinHost}/status/{HttpStatusCode.NotFound}");
|
||||||
|
|
||||||
|
var exception = Assert.Throws<HttpException>(() => Subject.Get<HttpBinResource>(request));
|
||||||
|
|
||||||
|
ExceptionVerification.ExpectedWarns(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_log_unsuccessful_status_codes()
|
||||||
|
{
|
||||||
|
var request = new HttpRequest($"http://{_httpBinHost}/status/{HttpStatusCode.NotFound}");
|
||||||
|
request.LogHttpError = false;
|
||||||
|
|
||||||
|
var exception = Assert.Throws<HttpException>(() => Subject.Get<HttpBinResource>(request));
|
||||||
|
|
||||||
|
ExceptionVerification.ExpectedWarns(0);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_not_follow_redirects_when_not_in_production()
|
public void should_not_follow_redirects_when_not_in_production()
|
||||||
{
|
{
|
||||||
|
|
|
@ -85,9 +85,12 @@ namespace NzbDrone.Common.Http
|
||||||
_logger.Error("Server requested a redirect to [{0}] while in developer mode. Update the request URL to avoid this redirect.", response.Headers["Location"]);
|
_logger.Error("Server requested a redirect to [{0}] while in developer mode. Update the request URL to avoid this redirect.", response.Headers["Location"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!request.SuppressHttpError && response.HasHttpError)
|
if (!request.SuppressHttpError && response.HasHttpError && (request.SuppressHttpErrorStatusCodes == null || !request.SuppressHttpErrorStatusCodes.Contains(response.StatusCode)))
|
||||||
|
{
|
||||||
|
if (request.LogHttpError)
|
||||||
{
|
{
|
||||||
_logger.Warn("HTTP Error - {0}", response);
|
_logger.Warn("HTTP Error - {0}", response);
|
||||||
|
}
|
||||||
|
|
||||||
if ((int)response.StatusCode == 429)
|
if ((int)response.StatusCode == 429)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
@ -15,6 +16,7 @@ namespace NzbDrone.Common.Http
|
||||||
Headers = new HttpHeader();
|
Headers = new HttpHeader();
|
||||||
AllowAutoRedirect = true;
|
AllowAutoRedirect = true;
|
||||||
StoreRequestCookie = true;
|
StoreRequestCookie = true;
|
||||||
|
LogHttpError = true;
|
||||||
Cookies = new Dictionary<string, string>();
|
Cookies = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,10 +37,12 @@ namespace NzbDrone.Common.Http
|
||||||
public byte[] ContentData { get; set; }
|
public byte[] ContentData { get; set; }
|
||||||
public string ContentSummary { get; set; }
|
public string ContentSummary { get; set; }
|
||||||
public bool SuppressHttpError { get; set; }
|
public bool SuppressHttpError { get; set; }
|
||||||
|
public IEnumerable<HttpStatusCode> SuppressHttpErrorStatusCodes { get; set; }
|
||||||
public bool UseSimplifiedUserAgent { get; set; }
|
public bool UseSimplifiedUserAgent { get; set; }
|
||||||
public bool AllowAutoRedirect { get; set; }
|
public bool AllowAutoRedirect { get; set; }
|
||||||
public bool ConnectionKeepAlive { get; set; }
|
public bool ConnectionKeepAlive { get; set; }
|
||||||
public bool LogResponseContent { get; set; }
|
public bool LogResponseContent { get; set; }
|
||||||
|
public bool LogHttpError { get; set; }
|
||||||
public Dictionary<string, string> Cookies { get; private set; }
|
public Dictionary<string, string> Cookies { get; private set; }
|
||||||
public bool StoreRequestCookie { get; set; }
|
public bool StoreRequestCookie { get; set; }
|
||||||
public bool StoreResponseCookie { get; set; }
|
public bool StoreResponseCookie { get; set; }
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace NzbDrone.Common.Http
|
||||||
public Dictionary<string, string> Segments { get; private set; }
|
public Dictionary<string, string> Segments { get; private set; }
|
||||||
public HttpHeader Headers { get; private set; }
|
public HttpHeader Headers { get; private set; }
|
||||||
public bool SuppressHttpError { get; set; }
|
public bool SuppressHttpError { get; set; }
|
||||||
|
public bool LogHttpError { get; set; }
|
||||||
public bool UseSimplifiedUserAgent { get; set; }
|
public bool UseSimplifiedUserAgent { get; set; }
|
||||||
public bool AllowAutoRedirect { get; set; }
|
public bool AllowAutoRedirect { get; set; }
|
||||||
public bool ConnectionKeepAlive { get; set; }
|
public bool ConnectionKeepAlive { get; set; }
|
||||||
|
@ -41,6 +42,7 @@ namespace NzbDrone.Common.Http
|
||||||
Headers = new HttpHeader();
|
Headers = new HttpHeader();
|
||||||
Cookies = new Dictionary<string, string>();
|
Cookies = new Dictionary<string, string>();
|
||||||
FormData = new List<HttpFormData>();
|
FormData = new List<HttpFormData>();
|
||||||
|
LogHttpError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpRequestBuilder(bool useHttps, string host, int port, string urlBase = null)
|
public HttpRequestBuilder(bool useHttps, string host, int port, string urlBase = null)
|
||||||
|
@ -101,6 +103,7 @@ namespace NzbDrone.Common.Http
|
||||||
{
|
{
|
||||||
request.Method = Method;
|
request.Method = Method;
|
||||||
request.SuppressHttpError = SuppressHttpError;
|
request.SuppressHttpError = SuppressHttpError;
|
||||||
|
request.LogHttpError = LogHttpError;
|
||||||
request.UseSimplifiedUserAgent = UseSimplifiedUserAgent;
|
request.UseSimplifiedUserAgent = UseSimplifiedUserAgent;
|
||||||
request.AllowAutoRedirect = AllowAutoRedirect;
|
request.AllowAutoRedirect = AllowAutoRedirect;
|
||||||
request.ConnectionKeepAlive = ConnectionKeepAlive;
|
request.ConnectionKeepAlive = ConnectionKeepAlive;
|
||||||
|
|
|
@ -87,9 +87,16 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!addHasSetShareLimits && setShareLimits)
|
if (!addHasSetShareLimits && setShareLimits)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteEpisode.SeedConfiguration, Settings);
|
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteEpisode.SeedConfiguration, Settings);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Warn(ex, "Failed to set the torrent seed criteria for {0}.", hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (moveToTop)
|
if (moveToTop)
|
||||||
{
|
{
|
||||||
|
@ -138,9 +145,16 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!addHasSetShareLimits && setShareLimits)
|
if (!addHasSetShareLimits && setShareLimits)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteEpisode.SeedConfiguration, Settings);
|
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteEpisode.SeedConfiguration, Settings);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Warn(ex, "Failed to set the torrent seed criteria for {0}.", hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (moveToTop)
|
if (moveToTop)
|
||||||
{
|
{
|
||||||
|
@ -172,15 +186,17 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
|
|
||||||
protected bool WaitForTorrent(string hash)
|
protected bool WaitForTorrent(string hash)
|
||||||
{
|
{
|
||||||
var count = 5;
|
var count = 10;
|
||||||
|
|
||||||
while (count != 0)
|
while (count != 0)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Proxy.GetTorrentProperties(hash.ToLower(), Settings);
|
if (Proxy.IsTorrentLoaded(hash.ToLower(), Settings))
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
string GetVersion(QBittorrentSettings settings);
|
string GetVersion(QBittorrentSettings settings);
|
||||||
QBittorrentPreferences GetConfig(QBittorrentSettings settings);
|
QBittorrentPreferences GetConfig(QBittorrentSettings settings);
|
||||||
List<QBittorrentTorrent> GetTorrents(QBittorrentSettings settings);
|
List<QBittorrentTorrent> GetTorrents(QBittorrentSettings settings);
|
||||||
|
bool IsTorrentLoaded(string hash, QBittorrentSettings settings);
|
||||||
QBittorrentTorrentProperties GetTorrentProperties(string hash, QBittorrentSettings settings);
|
QBittorrentTorrentProperties GetTorrentProperties(string hash, QBittorrentSettings settings);
|
||||||
List<QBittorrentTorrentFile> GetTorrentFiles(string hash, QBittorrentSettings settings);
|
List<QBittorrentTorrentFile> GetTorrentFiles(string hash, QBittorrentSettings settings);
|
||||||
|
|
||||||
|
@ -41,7 +42,6 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
|
|
||||||
public class QBittorrentProxySelector : IQBittorrentProxySelector
|
public class QBittorrentProxySelector : IQBittorrentProxySelector
|
||||||
{
|
{
|
||||||
private readonly IHttpClient _httpClient;
|
|
||||||
private readonly ICached<Tuple<IQBittorrentProxy, Version>> _proxyCache;
|
private readonly ICached<Tuple<IQBittorrentProxy, Version>> _proxyCache;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
@ -50,11 +50,9 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
|
|
||||||
public QBittorrentProxySelector(QBittorrentProxyV1 proxyV1,
|
public QBittorrentProxySelector(QBittorrentProxyV1 proxyV1,
|
||||||
QBittorrentProxyV2 proxyV2,
|
QBittorrentProxyV2 proxyV2,
|
||||||
IHttpClient httpClient,
|
|
||||||
ICacheManager cacheManager,
|
ICacheManager cacheManager,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
|
||||||
_proxyCache = cacheManager.GetCache<Tuple<IQBittorrentProxy, Version>>(GetType());
|
_proxyCache = cacheManager.GetCache<Tuple<IQBittorrentProxy, Version>>(GetType());
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,23 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsTorrentLoaded(string hash, QBittorrentSettings settings)
|
||||||
|
{
|
||||||
|
var request = BuildRequest(settings).Resource($"/query/propertiesGeneral/{hash}");
|
||||||
|
request.LogHttpError = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProcessRequest(request, settings);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public QBittorrentTorrentProperties GetTorrentProperties(string hash, QBittorrentSettings settings)
|
public QBittorrentTorrentProperties GetTorrentProperties(string hash, QBittorrentSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings).Resource($"/query/propertiesGeneral/{hash}");
|
var request = BuildRequest(settings).Resource($"/query/propertiesGeneral/{hash}");
|
||||||
|
@ -297,15 +314,14 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
|
|
||||||
var request = requestBuilder.Build();
|
var request = requestBuilder.Build();
|
||||||
request.LogResponseContent = true;
|
request.LogResponseContent = true;
|
||||||
|
request.SuppressHttpErrorStatusCodes = new[] { HttpStatusCode.Forbidden };
|
||||||
|
|
||||||
HttpResponse response;
|
HttpResponse response;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
response = _httpClient.Execute(request);
|
response = _httpClient.Execute(request);
|
||||||
}
|
|
||||||
catch (HttpException ex)
|
if (response.StatusCode == HttpStatusCode.Forbidden)
|
||||||
{
|
|
||||||
if (ex.Response.StatusCode == HttpStatusCode.Forbidden)
|
|
||||||
{
|
{
|
||||||
_logger.Debug("Authentication required, logging in.");
|
_logger.Debug("Authentication required, logging in.");
|
||||||
|
|
||||||
|
@ -315,11 +331,11 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
|
|
||||||
response = _httpClient.Execute(request);
|
response = _httpClient.Execute(request);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
catch (HttpException ex)
|
||||||
{
|
{
|
||||||
throw new DownloadClientException("Failed to connect to qBittorrent, check your settings.", ex);
|
throw new DownloadClientException("Failed to connect to qBittorrent, check your settings.", ex);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (WebException ex)
|
catch (WebException ex)
|
||||||
{
|
{
|
||||||
throw new DownloadClientException("Failed to connect to qBittorrent, please check your settings.", ex);
|
throw new DownloadClientException("Failed to connect to qBittorrent, please check your settings.", ex);
|
||||||
|
|
|
@ -101,6 +101,24 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsTorrentLoaded(string hash, QBittorrentSettings settings)
|
||||||
|
{
|
||||||
|
var request = BuildRequest(settings).Resource("/api/v2/torrents/properties")
|
||||||
|
.AddQueryParam("hash", hash);
|
||||||
|
request.LogHttpError = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProcessRequest(request, settings);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public QBittorrentTorrentProperties GetTorrentProperties(string hash, QBittorrentSettings settings)
|
public QBittorrentTorrentProperties GetTorrentProperties(string hash, QBittorrentSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings).Resource("/api/v2/torrents/properties")
|
var request = BuildRequest(settings).Resource("/api/v2/torrents/properties")
|
||||||
|
@ -142,7 +160,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
|
|
||||||
if (seedConfiguration != null)
|
if (seedConfiguration != null)
|
||||||
{
|
{
|
||||||
AddTorrentSeedingFormParameters(request, seedConfiguration, settings);
|
AddTorrentSeedingFormParameters(request, seedConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = ProcessRequest(request, settings);
|
var result = ProcessRequest(request, settings);
|
||||||
|
@ -177,7 +195,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
|
|
||||||
if (seedConfiguration != null)
|
if (seedConfiguration != null)
|
||||||
{
|
{
|
||||||
AddTorrentSeedingFormParameters(request, seedConfiguration, settings);
|
AddTorrentSeedingFormParameters(request, seedConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = ProcessRequest(request, settings);
|
var result = ProcessRequest(request, settings);
|
||||||
|
@ -226,17 +244,17 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
return Json.Deserialize<Dictionary<string, QBittorrentLabel>>(ProcessRequest(request, settings));
|
return Json.Deserialize<Dictionary<string, QBittorrentLabel>>(ProcessRequest(request, settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddTorrentSeedingFormParameters(HttpRequestBuilder request, TorrentSeedConfiguration seedConfiguration, QBittorrentSettings settings)
|
private void AddTorrentSeedingFormParameters(HttpRequestBuilder request, TorrentSeedConfiguration seedConfiguration, bool always = false)
|
||||||
{
|
{
|
||||||
var ratioLimit = seedConfiguration.Ratio.HasValue ? seedConfiguration.Ratio : -2;
|
var ratioLimit = seedConfiguration.Ratio.HasValue ? seedConfiguration.Ratio : -2;
|
||||||
var seedingTimeLimit = seedConfiguration.SeedTime.HasValue ? (long)seedConfiguration.SeedTime.Value.TotalMinutes : -2;
|
var seedingTimeLimit = seedConfiguration.SeedTime.HasValue ? (long)seedConfiguration.SeedTime.Value.TotalMinutes : -2;
|
||||||
|
|
||||||
if (ratioLimit != -2)
|
if (ratioLimit != -2 || always)
|
||||||
{
|
{
|
||||||
request.AddFormParameter("ratioLimit", ratioLimit);
|
request.AddFormParameter("ratioLimit", ratioLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seedingTimeLimit != -2)
|
if (seedingTimeLimit != -2 || always)
|
||||||
{
|
{
|
||||||
request.AddFormParameter("seedingTimeLimit", seedingTimeLimit);
|
request.AddFormParameter("seedingTimeLimit", seedingTimeLimit);
|
||||||
}
|
}
|
||||||
|
@ -248,7 +266,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
.Post()
|
.Post()
|
||||||
.AddFormParameter("hashes", hash);
|
.AddFormParameter("hashes", hash);
|
||||||
|
|
||||||
AddTorrentSeedingFormParameters(request, seedConfiguration, settings);
|
AddTorrentSeedingFormParameters(request, seedConfiguration, true);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -338,15 +356,14 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
|
|
||||||
var request = requestBuilder.Build();
|
var request = requestBuilder.Build();
|
||||||
request.LogResponseContent = true;
|
request.LogResponseContent = true;
|
||||||
|
request.SuppressHttpErrorStatusCodes = new[] { HttpStatusCode.Forbidden };
|
||||||
|
|
||||||
HttpResponse response;
|
HttpResponse response;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
response = _httpClient.Execute(request);
|
response = _httpClient.Execute(request);
|
||||||
}
|
|
||||||
catch (HttpException ex)
|
if (response.StatusCode == HttpStatusCode.Forbidden)
|
||||||
{
|
|
||||||
if (ex.Response.StatusCode == HttpStatusCode.Forbidden)
|
|
||||||
{
|
{
|
||||||
_logger.Debug("Authentication required, logging in.");
|
_logger.Debug("Authentication required, logging in.");
|
||||||
|
|
||||||
|
@ -356,11 +373,11 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
|
|
||||||
response = _httpClient.Execute(request);
|
response = _httpClient.Execute(request);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
catch (HttpException ex)
|
||||||
{
|
{
|
||||||
throw new DownloadClientException("Failed to connect to qBittorrent, check your settings.", ex);
|
throw new DownloadClientException("Failed to connect to qBittorrent, check your settings.", ex);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (WebException ex)
|
catch (WebException ex)
|
||||||
{
|
{
|
||||||
throw new DownloadClientException("Failed to connect to qBittorrent, please check your settings.", ex);
|
throw new DownloadClientException("Failed to connect to qBittorrent, please check your settings.", ex);
|
||||||
|
|
Loading…
Reference in New Issue