mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-26 22:56:23 -04:00
@@ -504,7 +504,8 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
catch (DownloadClientAuthenticationException ex)
|
catch (DownloadClientAuthenticationException ex)
|
||||||
{
|
{
|
||||||
_logger.Error(ex, ex.Message);
|
_logger.Error(ex, ex.Message);
|
||||||
return new NzbDroneValidationFailure("Username", _localizationService.GetLocalizedString("DownloadClientValidationAuthenticationFailure"))
|
|
||||||
|
return new NzbDroneValidationFailure(Settings.ApiKey.IsNotNullOrWhiteSpace() ? "ApiKey" : "Username", _localizationService.GetLocalizedString("DownloadClientValidationAuthenticationFailure"))
|
||||||
{
|
{
|
||||||
DetailedDescription = _localizationService.GetLocalizedString("DownloadClientValidationAuthenticationFailureDetail", new Dictionary<string, object> { { "clientName", Name } })
|
DetailedDescription = _localizationService.GetLocalizedString("DownloadClientValidationAuthenticationFailureDetail", new Dictionary<string, object> { { "clientName", Name } })
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -347,13 +347,19 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
ProcessRequest(request, settings);
|
ProcessRequest(request, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpRequestBuilder BuildRequest(QBittorrentSettings settings)
|
private static HttpRequestBuilder BuildRequest(QBittorrentSettings settings)
|
||||||
{
|
{
|
||||||
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port, settings.UrlBase)
|
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port, settings.UrlBase)
|
||||||
{
|
{
|
||||||
LogResponseContent = true,
|
LogResponseContent = true,
|
||||||
StoreRequestCookie = false
|
StoreRequestCookie = false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (settings.ApiKey.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
requestBuilder.Headers["Authorization"] = $"Bearer {settings.ApiKey}";
|
||||||
|
}
|
||||||
|
|
||||||
return requestBuilder;
|
return requestBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,16 +373,39 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
|
|
||||||
private string ProcessRequest(HttpRequestBuilder requestBuilder, QBittorrentSettings settings)
|
private string ProcessRequest(HttpRequestBuilder requestBuilder, QBittorrentSettings settings)
|
||||||
{
|
{
|
||||||
AuthenticateClient(requestBuilder, settings);
|
|
||||||
|
|
||||||
var request = requestBuilder.Build();
|
var request = requestBuilder.Build();
|
||||||
request.LogResponseContent = true;
|
request.LogResponseContent = true;
|
||||||
request.SuppressHttpErrorStatusCodes = new[] { HttpStatusCode.Forbidden };
|
|
||||||
|
|
||||||
HttpResponse response;
|
if (settings.ApiKey.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _httpClient.Execute(request).Content;
|
||||||
|
}
|
||||||
|
catch (HttpException ex)
|
||||||
|
{
|
||||||
|
if (ex.Response.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden)
|
||||||
|
{
|
||||||
|
_logger.Debug(ex, "qbitTorrent authentication failed.");
|
||||||
|
|
||||||
|
throw new DownloadClientAuthenticationException("Failed to authenticate with qBittorrent.", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new DownloadClientException("Failed to connect to qBittorrent, check your settings.", ex);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new DownloadClientException("Failed to connect to qBittorrent, please check your settings.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthenticateClient(requestBuilder, settings);
|
||||||
|
|
||||||
|
request.SuppressHttpErrorStatusCodes = [HttpStatusCode.Forbidden];
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
response = _httpClient.Execute(request);
|
var response = _httpClient.Execute(request);
|
||||||
|
|
||||||
if (response.StatusCode == HttpStatusCode.Forbidden)
|
if (response.StatusCode == HttpStatusCode.Forbidden)
|
||||||
{
|
{
|
||||||
@@ -388,17 +417,17 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
|
|
||||||
response = _httpClient.Execute(request);
|
response = _httpClient.Execute(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return response.Content;
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
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 (Exception 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.Content;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AuthenticateClient(HttpRequestBuilder requestBuilder, QBittorrentSettings settings, bool reauthenticate = false)
|
private void AuthenticateClient(HttpRequestBuilder requestBuilder, QBittorrentSettings settings, bool reauthenticate = false)
|
||||||
|
|||||||
@@ -13,6 +13,13 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
RuleFor(c => c.Port).InclusiveBetween(1, 65535);
|
RuleFor(c => c.Port).InclusiveBetween(1, 65535);
|
||||||
RuleFor(c => c.UrlBase).ValidUrlBase().When(c => c.UrlBase.IsNotNullOrWhiteSpace());
|
RuleFor(c => c.UrlBase).ValidUrlBase().When(c => c.UrlBase.IsNotNullOrWhiteSpace());
|
||||||
|
|
||||||
|
RuleFor(c => c.Username).Empty()
|
||||||
|
.WithMessage("Username must be empty when using API Key.")
|
||||||
|
.When(c => c.ApiKey.IsNotNullOrWhiteSpace());
|
||||||
|
RuleFor(c => c.Password).Empty()
|
||||||
|
.WithMessage("Password must be empty when using API Key.")
|
||||||
|
.When(c => c.ApiKey.IsNotNullOrWhiteSpace());
|
||||||
|
|
||||||
RuleFor(c => c.TvCategory).Matches(@"^([^\\\/](\/?[^\\\/])*)?$").WithMessage(@"Can not contain '\', '//', or start/end with '/'");
|
RuleFor(c => c.TvCategory).Matches(@"^([^\\\/](\/?[^\\\/])*)?$").WithMessage(@"Can not contain '\', '//', or start/end with '/'");
|
||||||
RuleFor(c => c.TvImportedCategory).Matches(@"^([^\\\/](\/?[^\\\/])*)?$").WithMessage(@"Can not contain '\', '//', or start/end with '/'");
|
RuleFor(c => c.TvImportedCategory).Matches(@"^([^\\\/](\/?[^\\\/])*)?$").WithMessage(@"Can not contain '\', '//', or start/end with '/'");
|
||||||
}
|
}
|
||||||
@@ -43,37 +50,40 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
[FieldToken(TokenField.HelpText, "UrlBase", "url", "http://[host]:[port]/[urlBase]/api")]
|
[FieldToken(TokenField.HelpText, "UrlBase", "url", "http://[host]:[port]/[urlBase]/api")]
|
||||||
public string UrlBase { get; set; }
|
public string UrlBase { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(4, Label = "Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)]
|
[FieldDefinition(4, Label = "ApiKey", Type = FieldType.Textbox, Privacy = PrivacyLevel.ApiKey)]
|
||||||
|
public string ApiKey { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(5, Label = "Username", Type = FieldType.Textbox, Privacy = PrivacyLevel.UserName)]
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(5, Label = "Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)]
|
[FieldDefinition(6, Label = "Password", Type = FieldType.Password, Privacy = PrivacyLevel.Password)]
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(6, Label = "Category", Type = FieldType.Textbox, HelpText = "DownloadClientSettingsCategoryHelpText")]
|
[FieldDefinition(7, Label = "Category", Type = FieldType.Textbox, HelpText = "DownloadClientSettingsCategoryHelpText")]
|
||||||
public string TvCategory { get; set; }
|
public string TvCategory { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(7, Label = "PostImportCategory", Type = FieldType.Textbox, Advanced = true, HelpText = "DownloadClientSettingsPostImportCategoryHelpText")]
|
[FieldDefinition(8, Label = "PostImportCategory", Type = FieldType.Textbox, Advanced = true, HelpText = "DownloadClientSettingsPostImportCategoryHelpText")]
|
||||||
public string TvImportedCategory { get; set; }
|
public string TvImportedCategory { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(8, Label = "DownloadClientSettingsRecentPriority", Type = FieldType.Select, SelectOptions = typeof(QBittorrentPriority), HelpText = "DownloadClientSettingsRecentPriorityEpisodeHelpText")]
|
[FieldDefinition(9, Label = "DownloadClientSettingsRecentPriority", Type = FieldType.Select, SelectOptions = typeof(QBittorrentPriority), HelpText = "DownloadClientSettingsRecentPriorityEpisodeHelpText")]
|
||||||
public int RecentTvPriority { get; set; }
|
public int RecentTvPriority { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(9, Label = "DownloadClientSettingsOlderPriority", Type = FieldType.Select, SelectOptions = typeof(QBittorrentPriority), HelpText = "DownloadClientSettingsOlderPriorityEpisodeHelpText")]
|
[FieldDefinition(10, Label = "DownloadClientSettingsOlderPriority", Type = FieldType.Select, SelectOptions = typeof(QBittorrentPriority), HelpText = "DownloadClientSettingsOlderPriorityEpisodeHelpText")]
|
||||||
public int OlderTvPriority { get; set; }
|
public int OlderTvPriority { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(10, Label = "DownloadClientSettingsInitialState", Type = FieldType.Select, SelectOptions = typeof(QBittorrentState), HelpText = "DownloadClientQbittorrentSettingsInitialStateHelpText")]
|
[FieldDefinition(11, Label = "DownloadClientSettingsInitialState", Type = FieldType.Select, SelectOptions = typeof(QBittorrentState), HelpText = "DownloadClientQbittorrentSettingsInitialStateHelpText")]
|
||||||
public int InitialState { get; set; }
|
public int InitialState { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(11, Label = "DownloadClientQbittorrentSettingsSequentialOrder", Type = FieldType.Checkbox, HelpText = "DownloadClientQbittorrentSettingsSequentialOrderHelpText")]
|
[FieldDefinition(12, Label = "DownloadClientQbittorrentSettingsSequentialOrder", Type = FieldType.Checkbox, HelpText = "DownloadClientQbittorrentSettingsSequentialOrderHelpText")]
|
||||||
public bool SequentialOrder { get; set; }
|
public bool SequentialOrder { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(12, Label = "DownloadClientQbittorrentSettingsFirstAndLastFirst", Type = FieldType.Checkbox, HelpText = "DownloadClientQbittorrentSettingsFirstAndLastFirstHelpText")]
|
[FieldDefinition(13, Label = "DownloadClientQbittorrentSettingsFirstAndLastFirst", Type = FieldType.Checkbox, HelpText = "DownloadClientQbittorrentSettingsFirstAndLastFirstHelpText")]
|
||||||
public bool FirstAndLast { get; set; }
|
public bool FirstAndLast { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(13, Label = "DownloadClientQbittorrentSettingsContentLayout", Type = FieldType.Select, SelectOptions = typeof(QBittorrentContentLayout), HelpText = "DownloadClientQbittorrentSettingsContentLayoutHelpText")]
|
[FieldDefinition(14, Label = "DownloadClientQbittorrentSettingsContentLayout", Type = FieldType.Select, SelectOptions = typeof(QBittorrentContentLayout), HelpText = "DownloadClientQbittorrentSettingsContentLayoutHelpText")]
|
||||||
public int ContentLayout { get; set; }
|
public int ContentLayout { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(14, Label = "DownloadClientQbittorrentSettingsAddSeriesTags", Type = FieldType.Checkbox, HelpText = "DownloadClientQbittorrentSettingsAddSeriesTagsHelpText")]
|
[FieldDefinition(15, Label = "DownloadClientQbittorrentSettingsAddSeriesTags", Type = FieldType.Checkbox, HelpText = "DownloadClientQbittorrentSettingsAddSeriesTagsHelpText")]
|
||||||
public bool AddSeriesTags { get; set; }
|
public bool AddSeriesTags { get; set; }
|
||||||
|
|
||||||
public override NzbDroneValidationResult Validate()
|
public override NzbDroneValidationResult Validate()
|
||||||
|
|||||||
@@ -562,7 +562,7 @@
|
|||||||
"DownloadClientValidationApiKeyIncorrect": "API Key Incorrect",
|
"DownloadClientValidationApiKeyIncorrect": "API Key Incorrect",
|
||||||
"DownloadClientValidationApiKeyRequired": "API Key Required",
|
"DownloadClientValidationApiKeyRequired": "API Key Required",
|
||||||
"DownloadClientValidationAuthenticationFailure": "Authentication Failure",
|
"DownloadClientValidationAuthenticationFailure": "Authentication Failure",
|
||||||
"DownloadClientValidationAuthenticationFailureDetail": "Please verify your username and password. Also verify if the host running {appName} isn't blocked from accessing {clientName} by WhiteList limitations in the {clientName} configuration.",
|
"DownloadClientValidationAuthenticationFailureDetail": "Please verify your credentials. Also verify if the host running {appName} isn't blocked from accessing {clientName} by WhiteList limitations in the {clientName} configuration.",
|
||||||
"DownloadClientValidationCategoryMissing": "Category does not exist",
|
"DownloadClientValidationCategoryMissing": "Category does not exist",
|
||||||
"DownloadClientValidationCategoryMissingDetail": "The category you entered doesn't exist in {clientName}. Create it in {clientName} first.",
|
"DownloadClientValidationCategoryMissingDetail": "The category you entered doesn't exist in {clientName}. Create it in {clientName} first.",
|
||||||
"DownloadClientValidationErrorVersion": "{clientName} version should be at least {requiredVersion}. Version reported is {reportedVersion}",
|
"DownloadClientValidationErrorVersion": "{clientName} version should be at least {requiredVersion}. Version reported is {reportedVersion}",
|
||||||
|
|||||||
Reference in New Issue
Block a user