Fixed: Qbittorrent api errors when only one of two seed criteria was configured

closes #907

(cherry picked from commit 652d44722b96a7a830ec45fe83260ddcecc525a7)
pull/1112/head
Taloth Saldono 4 years ago committed by Qstick
parent ac36675c6e
commit 916391edc3

@ -185,6 +185,38 @@ namespace NzbDrone.Common.Test.Http
ExceptionVerification.IgnoreWarns(); ExceptionVerification.IgnoreWarns();
} }
[Test]
public void should_not_throw_on_suppressed_status_codes()
{
var request = new HttpRequest($"https://{_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($"https://{_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($"https://{_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()
{ {

@ -83,9 +83,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)))
{ {
_logger.Warn("HTTP Error - {0}", response); if (request.LogHttpError)
{
_logger.Warn("HTTP Error - {0}", response);
}
if ((int)response.StatusCode == 429) if ((int)response.StatusCode == 429)
{ {

@ -16,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>();
if (!RuntimeInfo.IsProduction) if (!RuntimeInfo.IsProduction)
@ -36,10 +37,12 @@ namespace NzbDrone.Common.Http
public string ContentSummary { get; set; } public string ContentSummary { get; set; }
public ICredentials Credentials { get; set; } public ICredentials Credentials { 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; }
@ -40,6 +41,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)
@ -99,6 +101,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;

@ -88,7 +88,14 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
if (!addHasSetShareLimits && setShareLimits) if (!addHasSetShareLimits && setShareLimits)
{ {
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteBook.SeedConfiguration, Settings); try
{
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteBook.SeedConfiguration, Settings);
}
catch (Exception ex)
{
_logger.Warn(ex, "Failed to set the torrent seed criteria for {0}.", hash);
}
} }
if (moveToTop) if (moveToTop)
@ -138,8 +145,15 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
if (!addHasSetShareLimits && setShareLimits) if (!addHasSetShareLimits && setShareLimits)
{ {
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteBook.SeedConfiguration, Settings); try
} {
Proxy.SetTorrentSeedingConfiguration(hash.ToLower(), remoteBook.SeedConfiguration, Settings);
}
catch (Exception ex)
{
_logger.Warn(ex, "Failed to set the torrent seed criteria for {0}.", hash);
}
}
if (moveToTop) if (moveToTop)
{ {
@ -171,14 +185,16 @@ 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
{ {

@ -15,6 +15,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);
@ -40,7 +41,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;
@ -49,11 +49,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;

@ -99,6 +99,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}");
@ -298,15 +315,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.");
@ -316,10 +332,10 @@ 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)
{ {

@ -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")
@ -141,7 +159,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);
@ -176,7 +194,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);
@ -225,17 +243,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);
} }
@ -247,7 +265,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
{ {
@ -336,15 +354,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.");
@ -354,10 +371,10 @@ 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)
{ {

Loading…
Cancel
Save