1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-12-12 11:15:43 +02:00

Translate Indexers on the backend

This commit is contained in:
Stevie Robinson 2023-11-17 01:30:22 +01:00 committed by GitHub
parent e68b13940d
commit f205cfabab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 160 additions and 89 deletions

View File

@ -11,6 +11,7 @@
using NzbDrone.Core.Download; using NzbDrone.Core.Download;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.RemotePathMappings; using NzbDrone.Core.RemotePathMappings;
@ -70,7 +71,8 @@ protected virtual IIndexer CreateIndexer()
Mocker.Resolve<IIndexerStatusService>(), Mocker.Resolve<IIndexerStatusService>(),
Mocker.Resolve<IConfigService>(), Mocker.Resolve<IConfigService>(),
Mocker.Resolve<IParsingService>(), Mocker.Resolve<IParsingService>(),
Mocker.Resolve<Logger>()); Mocker.Resolve<Logger>(),
Mocker.Resolve<ILocalizationService>());
} }
protected void VerifyIdentifiable(DownloadClientItem downloadClientItem) protected void VerifyIdentifiable(DownloadClientItem downloadClientItem)

View File

@ -11,6 +11,7 @@
using NzbDrone.Core.Download; using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Pneumatic; using NzbDrone.Core.Download.Clients.Pneumatic;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
@ -51,7 +52,8 @@ public void Setup()
Mocker.Resolve<IIndexerStatusService>(), Mocker.Resolve<IIndexerStatusService>(),
Mocker.Resolve<IConfigService>(), Mocker.Resolve<IConfigService>(),
Mocker.Resolve<IParsingService>(), Mocker.Resolve<IParsingService>(),
Mocker.Resolve<Logger>()); Mocker.Resolve<Logger>(),
Mocker.Resolve<ILocalizationService>());
_downloadClientItem = Builder<DownloadClientItem> _downloadClientItem = Builder<DownloadClientItem>
.CreateNew().With(d => d.DownloadId = "_Droned.S01E01.Pilot.1080p.WEB-DL-DRONE_0") .CreateNew().With(d => d.DownloadId = "_Droned.S01E01.Pilot.1080p.WEB-DL-DRONE_0")

View File

@ -2,6 +2,7 @@
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Test.IndexerTests namespace NzbDrone.Core.Test.IndexerTests
@ -15,8 +16,8 @@ public class TestIndexer : HttpIndexerBase<TestIndexerSettings>
public int _supportedPageSize; public int _supportedPageSize;
public override int PageSize => _supportedPageSize; public override int PageSize => _supportedPageSize;
public TestIndexer(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public TestIndexer(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(httpClient, indexerStatusService, configService, parsingService, logger) : base(httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
} }

View File

@ -7,14 +7,15 @@
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.TorrentRss; using NzbDrone.Core.Indexers.TorrentRss;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
{ {
public class TestTorrentRssIndexer : TorrentRssIndexer public class TestTorrentRssIndexer : TorrentRssIndexer
{ {
public TestTorrentRssIndexer(ITorrentRssParserFactory torrentRssParserFactory, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public TestTorrentRssIndexer(ITorrentRssParserFactory torrentRssParserFactory, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(torrentRssParserFactory, httpClient, indexerStatusService, configService, parsingService, logger) : base(torrentRssParserFactory, httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
} }

View File

@ -1,6 +1,7 @@
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.BroadcastheNet namespace NzbDrone.Core.Indexers.BroadcastheNet
@ -14,8 +15,8 @@ public class BroadcastheNet : HttpIndexerBase<BroadcastheNetSettings>
public override bool SupportsSearch => true; public override bool SupportsSearch => true;
public override int PageSize => 100; public override int PageSize => 100;
public BroadcastheNet(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public BroadcastheNet(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(httpClient, indexerStatusService, configService, parsingService, logger) : base(httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
} }

View File

@ -25,13 +25,13 @@ public BroadcastheNetSettings()
MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS; MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS;
} }
[FieldDefinition(0, Label = "API URL", Advanced = true, HelpText = "Do not change this unless you know what you're doing. Since your API key will be sent to that host.")] [FieldDefinition(0, Label = "IndexerSettingsApiUrl", Advanced = true, HelpText = "IndexerSettingsApiUrlHelpText")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "API Key", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(1, Label = "ApiKey", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(2, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] [FieldDefinition(2, Type = FieldType.Number, Label = "IndexerSettingsMinimumSeeders", HelpText = "IndexerSettingsMinimumSeedersHelpText", Advanced = true)]
public int MinimumSeeders { get; set; } public int MinimumSeeders { get; set; }
[FieldDefinition(3)] [FieldDefinition(3)]

View File

@ -1,6 +1,7 @@
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.Fanzub namespace NzbDrone.Core.Indexers.Fanzub
@ -11,8 +12,8 @@ public class Fanzub : HttpIndexerBase<FanzubSettings>
public override DownloadProtocol Protocol => DownloadProtocol.Usenet; public override DownloadProtocol Protocol => DownloadProtocol.Usenet;
public Fanzub(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public Fanzub(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(httpClient, indexerStatusService, configService, parsingService, logger) : base(httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
} }

View File

@ -21,10 +21,11 @@ public FanzubSettings()
BaseUrl = "http://fanzub.com/rss/"; BaseUrl = "http://fanzub.com/rss/";
} }
[FieldDefinition(0, Label = "Rss URL", HelpText = "Enter to URL to an Fanzub compatible RSS feed")] [FieldDefinition(0, Label = "IndexerSettingsRssUrl", HelpText = "IndexerSettingsRssUrlHelpText")]
[FieldToken(TokenField.HelpText, "IndexerSettingsRssUrl", "indexer", "Fanzub")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "Anime Standard Format Search", Type = FieldType.Checkbox, HelpText = "Also search for anime using the standard numbering")] [FieldDefinition(1, Label = "IndexerSettingsAnimeStandardFormatSearch", Type = FieldType.Checkbox, HelpText = "IndexerSettingsAnimeStandardFormatSearchHelpText")]
public bool AnimeStandardFormatSearch { get; set; } public bool AnimeStandardFormatSearch { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()

View File

@ -1,6 +1,7 @@
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.FileList namespace NzbDrone.Core.Indexers.FileList
@ -12,8 +13,8 @@ public class FileList : HttpIndexerBase<FileListSettings>
public override bool SupportsRss => true; public override bool SupportsRss => true;
public override bool SupportsSearch => true; public override bool SupportsSearch => true;
public FileList(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public FileList(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(httpClient, indexerStatusService, configService, parsingService, logger) : base(httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
} }

View File

@ -40,19 +40,19 @@ public FileListSettings()
[FieldDefinition(0, Label = "Username", Privacy = PrivacyLevel.UserName)] [FieldDefinition(0, Label = "Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(1, Label = "Passkey", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(1, Label = "IndexerSettingsPasskey", Privacy = PrivacyLevel.ApiKey)]
public string Passkey { get; set; } public string Passkey { get; set; }
[FieldDefinition(3, Label = "API URL", Advanced = true, HelpText = "Do not change this unless you know what you're doing. Since your API key will be sent to that host.")] [FieldDefinition(3, Label = "IndexerSettingsApiUrl", Advanced = true, HelpText = "IndexerSettingsApiUrlHelpText")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(4, Label = "Categories", Type = FieldType.Select, SelectOptions = typeof(FileListCategories), HelpText = "Categories for use in search and feeds, leave blank to disable standard/daily shows")] [FieldDefinition(4, Label = "IndexerSettingsCategories", Type = FieldType.Select, SelectOptions = typeof(FileListCategories), HelpText = "IndexerSettingsCategoriesHelpText")]
public IEnumerable<int> Categories { get; set; } public IEnumerable<int> Categories { get; set; }
[FieldDefinition(5, Label = "Anime Categories", Type = FieldType.Select, SelectOptions = typeof(FileListCategories), HelpText = "Categories for use in search and feeds, leave blank to disable anime")] [FieldDefinition(5, Label = "IndexerSettingsAnimeCategories", Type = FieldType.Select, SelectOptions = typeof(FileListCategories), HelpText = "IndexerSettingsAnimeCategoriesHelpText")]
public IEnumerable<int> AnimeCategories { get; set; } public IEnumerable<int> AnimeCategories { get; set; }
[FieldDefinition(6, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] [FieldDefinition(6, Type = FieldType.Number, Label = "IndexerSettingsMinimumSeeders", HelpText = "IndexerSettingsMinimumSeedersHelpText", Advanced = true)]
public int MinimumSeeders { get; set; } public int MinimumSeeders { get; set; }
[FieldDefinition(7)] [FieldDefinition(7)]

View File

@ -1,6 +1,7 @@
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.HDBits namespace NzbDrone.Core.Indexers.HDBits
@ -13,8 +14,8 @@ public class HDBits : HttpIndexerBase<HDBitsSettings>
public override bool SupportsSearch => true; public override bool SupportsSearch => true;
public override int PageSize => 30; public override int PageSize => 30;
public HDBits(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public HDBits(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(httpClient, indexerStatusService, configService, parsingService, logger) : base(httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
} }

View File

@ -28,13 +28,13 @@ public HDBitsSettings()
[FieldDefinition(0, Label = "Username", Privacy = PrivacyLevel.UserName)] [FieldDefinition(0, Label = "Username", Privacy = PrivacyLevel.UserName)]
public string Username { get; set; } public string Username { get; set; }
[FieldDefinition(1, Label = "API Key", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(1, Label = "ApiKey", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(2, Label = "API URL", Advanced = true, HelpText = "Do not change this unless you know what you're doing. Since your API key will be sent to that host.")] [FieldDefinition(2, Label = "IndexerSettingsApiUrl", Advanced = true, HelpText = "IndexerSettingsApiUrlHelpText")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(3, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] [FieldDefinition(3, Type = FieldType.Number, Label = "IndexerSettingsMinimumSeeders", HelpText = "IndexerSettingsMinimumSeedersHelpText", Advanced = true)]
public int MinimumSeeders { get; set; } public int MinimumSeeders { get; set; }
[FieldDefinition(4)] [FieldDefinition(4)]

View File

@ -12,6 +12,7 @@
using NzbDrone.Core.Http.CloudFlare; using NzbDrone.Core.Http.CloudFlare;
using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
@ -34,8 +35,8 @@ public abstract class HttpIndexerBase<TSettings> : IndexerBase<TSettings>
public abstract IIndexerRequestGenerator GetRequestGenerator(); public abstract IIndexerRequestGenerator GetRequestGenerator();
public abstract IParseIndexerResponse GetParser(); public abstract IParseIndexerResponse GetParser();
public HttpIndexerBase(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public HttpIndexerBase(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(indexerStatusService, configService, parsingService, logger) : base(indexerStatusService, configService, parsingService, logger, localizationService)
{ {
_httpClient = httpClient; _httpClient = httpClient;
} }
@ -376,50 +377,50 @@ protected virtual async Task<ValidationFailure> TestConnection()
if (firstRequest == null) if (firstRequest == null)
{ {
return new ValidationFailure(string.Empty, "No rss feed query available. This may be an issue with the indexer or your indexer category settings."); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationJackettNoRssFeedQueryAvailable"));
} }
var releases = await FetchPage(firstRequest, parser); var releases = await FetchPage(firstRequest, parser);
if (releases.Empty()) if (releases.Empty())
{ {
return new ValidationFailure(string.Empty, "Query successful, but no results in the configured categories were returned from your indexer. This may be an issue with the indexer or your indexer category settings."); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationJackettNoResultsInConfiguredCategories"));
} }
} }
catch (ApiKeyException ex) catch (ApiKeyException ex)
{ {
_logger.Warn("Indexer returned result for RSS URL, API Key appears to be invalid: " + ex.Message); _logger.Warn("Indexer returned result for RSS URL, API Key appears to be invalid: " + ex.Message);
return new ValidationFailure("ApiKey", "Invalid API Key"); return new ValidationFailure("ApiKey", _localizationService.GetLocalizedString("IndexerValidationInvalidApiKey"));
} }
catch (RequestLimitReachedException ex) catch (RequestLimitReachedException ex)
{ {
_logger.Warn("Request limit reached: " + ex.Message); _logger.Warn("Request limit reached: " + ex.Message);
return new ValidationFailure(string.Empty, "Request limit reached: " + ex.Message); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationRequestLimitReached", new Dictionary<string, object> { { "exceptionMessage", ex.Message } }));
} }
catch (CloudFlareCaptchaException ex) catch (CloudFlareCaptchaException ex)
{ {
if (ex.IsExpired) if (ex.IsExpired)
{ {
return new ValidationFailure("CaptchaToken", "CloudFlare CAPTCHA token expired, please Refresh."); return new ValidationFailure("CaptchaToken", _localizationService.GetLocalizedString("IndexerValidationCloudFlareCaptchaExpired"));
} }
else else
{ {
return new ValidationFailure("CaptchaToken", "Site protected by CloudFlare CAPTCHA. Valid CAPTCHA token required."); return new ValidationFailure("CaptchaToken", _localizationService.GetLocalizedString("IndexerValidationCloudFlareCaptchaRequired"));
} }
} }
catch (UnsupportedFeedException ex) catch (UnsupportedFeedException ex)
{ {
_logger.Warn(ex, "Indexer feed is not supported"); _logger.Warn(ex, "Indexer feed is not supported");
return new ValidationFailure(string.Empty, "Indexer feed is not supported: " + ex.Message); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationFeedNotSupported", new Dictionary<string, object> { { "exceptionMessage", ex.Message } }));
} }
catch (IndexerException ex) catch (IndexerException ex)
{ {
_logger.Warn(ex, "Unable to connect to indexer"); _logger.Warn(ex, "Unable to connect to indexer");
return new ValidationFailure(string.Empty, "Unable to connect to indexer. " + ex.Message); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationUnableToConnect", new Dictionary<string, object> { { "exceptionMessage", ex.Message } }));
} }
catch (HttpException ex) catch (HttpException ex)
{ {
@ -427,33 +428,33 @@ protected virtual async Task<ValidationFailure> TestConnection()
ex.Response.Content.Contains("not support the requested query")) ex.Response.Content.Contains("not support the requested query"))
{ {
_logger.Warn(ex, "Indexer does not support the query"); _logger.Warn(ex, "Indexer does not support the query");
return new ValidationFailure(string.Empty, "Indexer does not support the current query. Check if the categories and or searching for seasons/episodes are supported. Check the log for more details."); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationQueryNotSupported"));
} }
_logger.Warn(ex, "Unable to connect to indexer"); _logger.Warn(ex, "Unable to connect to indexer");
if (ex.Response.HasHttpServerError) if (ex.Response.HasHttpServerError)
{ {
return new ValidationFailure(string.Empty, "Unable to connect to indexer, indexer's server is unavailable. Try again later. " + ex.Message); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationUnableToConnectServerUnavailable", new Dictionary<string, object> { { "exceptionMessage", ex.Message } }));
} }
if (ex.Response.StatusCode is HttpStatusCode.Forbidden or HttpStatusCode.Unauthorized) if (ex.Response.StatusCode is HttpStatusCode.Forbidden or HttpStatusCode.Unauthorized)
{ {
return new ValidationFailure(string.Empty, "Unable to connect to indexer, invalid credentials. " + ex.Message); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationUnableToConnectInvalidCredentials", new Dictionary<string, object> { { "exceptionMessage", ex.Message } }));
} }
return new ValidationFailure(string.Empty, "Unable to connect to indexer, check the log above the ValidationFailure for more details. " + ex.Message); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationUnableToConnect", new Dictionary<string, object> { { "exceptionMessage", ex.Message } }));
} }
catch (HttpRequestException ex) catch (HttpRequestException ex)
{ {
_logger.Warn(ex, "Unable to connect to indexer"); _logger.Warn(ex, "Unable to connect to indexer");
return new ValidationFailure(string.Empty, "Unable to connect to indexer, please check your DNS settings and ensure IPv6 is working or disabled. " + ex.Message); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationUnableToConnectHttpError", new Dictionary<string, object> { { "exceptionMessage", ex.Message } }));
} }
catch (TaskCanceledException ex) catch (TaskCanceledException ex)
{ {
_logger.Warn(ex, "Unable to connect to indexer"); _logger.Warn(ex, "Unable to connect to indexer");
return new ValidationFailure(string.Empty, "Unable to connect to indexer, possibly due to a timeout. Try again or check your network settings. " + ex.Message); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationUnableToConnectTimeout", new Dictionary<string, object> { { "exceptionMessage", ex.Message } }));
} }
catch (WebException webException) catch (WebException webException)
{ {
@ -461,20 +462,20 @@ protected virtual async Task<ValidationFailure> TestConnection()
if (webException.Status is WebExceptionStatus.NameResolutionFailure or WebExceptionStatus.ConnectFailure) if (webException.Status is WebExceptionStatus.NameResolutionFailure or WebExceptionStatus.ConnectFailure)
{ {
return new ValidationFailure(string.Empty, "Unable to connect to indexer connection failure. Check your connection to the indexer's server and DNS." + webException.Message); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationUnableToConnectResolutionFailure", new Dictionary<string, object> { { "exceptionMessage", webException.Message } }));
} }
if (webException.Message.Contains("502") || webException.Message.Contains("503") || if (webException.Message.Contains("502") || webException.Message.Contains("503") ||
webException.Message.Contains("504") || webException.Message.Contains("timed out")) webException.Message.Contains("504") || webException.Message.Contains("timed out"))
{ {
return new ValidationFailure(string.Empty, "Unable to connect to indexer, indexer's server is unavailable. Try again later. " + webException.Message); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationUnableToConnectServerUnavailable", new Dictionary<string, object> { { "exceptionMessage", webException.Message } }));
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.Warn(ex, "Unable to connect to indexer"); _logger.Warn(ex, "Unable to connect to indexer");
return new ValidationFailure(string.Empty, $"Unable to connect to indexer: {ex.Message}. Check the log surrounding this error for details"); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationUnableToConnect", new Dictionary<string, object> { { "exceptionMessage", ex.Message } }));
} }
return null; return null;

View File

@ -1,6 +1,7 @@
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.IPTorrents namespace NzbDrone.Core.Indexers.IPTorrents
@ -13,8 +14,8 @@ public class IPTorrents : HttpIndexerBase<IPTorrentsSettings>
public override bool SupportsSearch => false; public override bool SupportsSearch => false;
public override int PageSize => 0; public override int PageSize => 0;
public IPTorrents(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public IPTorrents(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(httpClient, indexerStatusService, configService, parsingService, logger) : base(httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
} }

View File

@ -31,10 +31,10 @@ public IPTorrentsSettings()
MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS; MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS;
} }
[FieldDefinition(0, Label = "Feed URL", HelpText = "The full RSS feed url generated by IPTorrents, using only the categories you selected (HD, SD, x264, etc ...)")] [FieldDefinition(0, Label = "IndexerIPTorrentsSettingsFeedUrl", HelpText = "IndexerIPTorrentsSettingsFeedUrlHelpText")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(1, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] [FieldDefinition(1, Type = FieldType.Number, Label = "IndexerSettingsMinimumSeeders", HelpText = "IndexerSettingsMinimumSeedersHelpText", Advanced = true)]
public int MinimumSeeders { get; set; } public int MinimumSeeders { get; set; }
[FieldDefinition(2)] [FieldDefinition(2)]

View File

@ -7,6 +7,7 @@
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.ThingiProvider;
@ -20,6 +21,7 @@ public abstract class IndexerBase<TSettings> : IIndexer
protected readonly IConfigService _configService; protected readonly IConfigService _configService;
protected readonly IParsingService _parsingService; protected readonly IParsingService _parsingService;
protected readonly Logger _logger; protected readonly Logger _logger;
protected readonly ILocalizationService _localizationService;
public abstract string Name { get; } public abstract string Name { get; }
public abstract DownloadProtocol Protocol { get; } public abstract DownloadProtocol Protocol { get; }
@ -29,12 +31,13 @@ public abstract class IndexerBase<TSettings> : IIndexer
public abstract bool SupportsRss { get; } public abstract bool SupportsRss { get; }
public abstract bool SupportsSearch { get; } public abstract bool SupportsSearch { get; }
public IndexerBase(IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public IndexerBase(IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
{ {
_indexerStatusService = indexerStatusService; _indexerStatusService = indexerStatusService;
_configService = configService; _configService = configService;
_parsingService = parsingService; _parsingService = parsingService;
_logger = logger; _logger = logger;
_localizationService = localizationService;
} }
public Type ConfigContract => typeof(TSettings); public Type ConfigContract => typeof(TSettings);
@ -105,7 +108,7 @@ public ValidationResult Test()
catch (Exception ex) catch (Exception ex)
{ {
_logger.Error(ex, "Test aborted due to exception"); _logger.Error(ex, "Test aborted due to exception");
failures.Add(new ValidationFailure(string.Empty, "Test was aborted due to an error: " + ex.Message)); failures.Add(new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationTestAbortedDueToError", new Dictionary<string, object> { { "exceptionMessage", ex.Message } })));
} }
return new ValidationResult(failures); return new ValidationResult(failures);

View File

@ -7,6 +7,7 @@
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
@ -22,8 +23,8 @@ public class Newznab : HttpIndexerBase<NewznabSettings>
public override DownloadProtocol Protocol => DownloadProtocol.Usenet; public override DownloadProtocol Protocol => DownloadProtocol.Usenet;
public override int PageSize => GetProviderPageSize(); public override int PageSize => GetProviderPageSize();
public Newznab(INewznabCapabilitiesProvider capabilitiesProvider, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public Newznab(INewznabCapabilitiesProvider capabilitiesProvider, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(httpClient, indexerStatusService, configService, parsingService, logger) : base(httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
_capabilitiesProvider = capabilitiesProvider; _capabilitiesProvider = capabilitiesProvider;
} }
@ -129,13 +130,13 @@ protected virtual ValidationFailure TestCapabilities()
return null; return null;
} }
return new ValidationFailure(string.Empty, "Indexer does not support required search parameters"); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationSearchParametersNotSupported"));
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.Warn(ex, "Unable to connect to indexer: " + ex.Message); _logger.Warn(ex, "Unable to connect to indexer: " + ex.Message);
return new ValidationFailure(string.Empty, $"Unable to connect to indexer: {ex.Message}. Check the log surrounding this error for details"); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationUnableToConnect", new Dictionary<string, object> { { "exceptionMessage", ex.Message } }));
} }
} }

View File

@ -60,22 +60,23 @@ public NewznabSettings()
[FieldDefinition(0, Label = "URL")] [FieldDefinition(0, Label = "URL")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "API Path", HelpText = "Path to the api, usually /api", Advanced = true)] [FieldDefinition(1, Label = "IndexerSettingsApiPath", HelpText = "IndexerSettingsApiPathHelpText", Advanced = true)]
[FieldToken(TokenField.HelpText, "IndexerSettingsApiPath", "url", "/api")]
public string ApiPath { get; set; } public string ApiPath { get; set; }
[FieldDefinition(2, Label = "API Key", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(2, Label = "ApiKey", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(3, Label = "Categories", Type = FieldType.Select, SelectOptionsProviderAction = "newznabCategories", HelpText = "Drop down list, leave blank to disable standard/daily shows")] [FieldDefinition(3, Label = "IndexerSettingsCategories", Type = FieldType.Select, SelectOptionsProviderAction = "newznabCategories", HelpText = "IndexerSettingsCategoriesHelpText")]
public IEnumerable<int> Categories { get; set; } public IEnumerable<int> Categories { get; set; }
[FieldDefinition(4, Label = "Anime Categories", Type = FieldType.Select, SelectOptionsProviderAction = "newznabCategories", HelpText = "Drop down list, leave blank to disable anime")] [FieldDefinition(4, Label = "IndexerSettingsAnimeCategories", Type = FieldType.Select, SelectOptionsProviderAction = "newznabCategories", HelpText = "IndexerSettingsAnimeCategoriesHelpText")]
public IEnumerable<int> AnimeCategories { get; set; } public IEnumerable<int> AnimeCategories { get; set; }
[FieldDefinition(5, Label = "Anime Standard Format Search", Type = FieldType.Checkbox, HelpText = "Also search for anime using the standard numbering")] [FieldDefinition(5, Label = "IndexerSettingsAnimeStandardFormatSearch", Type = FieldType.Checkbox, HelpText = "IndexerSettingsAnimeStandardFormatSearchHelpText")]
public bool AnimeStandardFormatSearch { get; set; } public bool AnimeStandardFormatSearch { get; set; }
[FieldDefinition(6, Label = "Additional Parameters", HelpText = "Additional Newznab parameters", Advanced = true)] [FieldDefinition(6, Label = "IndexerSettingsAdditionalParameters", HelpText = "IndexerSettingsAdditionalNewznabParametersHelpText", Advanced = true)]
public string AdditionalParameters { get; set; } public string AdditionalParameters { get; set; }
// Field 7 is used by TorznabSettings MinimumSeeders // Field 7 is used by TorznabSettings MinimumSeeders

View File

@ -1,6 +1,7 @@
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.Nyaa namespace NzbDrone.Core.Indexers.Nyaa
@ -12,8 +13,8 @@ public class Nyaa : HttpIndexerBase<NyaaSettings>
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override int PageSize => 100; public override int PageSize => 100;
public Nyaa(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public Nyaa(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(httpClient, indexerStatusService, configService, parsingService, logger) : base(httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
} }

View File

@ -27,16 +27,16 @@ public NyaaSettings()
MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS; MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS;
} }
[FieldDefinition(0, Label = "Website URL")] [FieldDefinition(0, Label = "IndexerSettingsWebsiteUrl")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "Anime Standard Format Search", Type = FieldType.Checkbox, HelpText = "Also search for anime using the standard numbering")] [FieldDefinition(1, Label = "IndexerSettingsAnimeStandardFormatSearch", Type = FieldType.Checkbox, HelpText = "IndexerSettingsAnimeStandardFormatSearchHelpText")]
public bool AnimeStandardFormatSearch { get; set; } public bool AnimeStandardFormatSearch { get; set; }
[FieldDefinition(2, Label = "Additional Parameters", Advanced = true, HelpText = "Please note if you change the category you will have to add required/restricted rules about the subgroups to avoid foreign language releases.")] [FieldDefinition(2, Label = "IndexerSettingsAdditionalParameters", Advanced = true, HelpText = "IndexerSettingsAdditionalNewznabParametersHelpText")]
public string AdditionalParameters { get; set; } public string AdditionalParameters { get; set; }
[FieldDefinition(3, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] [FieldDefinition(3, Type = FieldType.Number, Label = "IndexerSettingsMinimumSeeders", HelpText = "IndexerSettingsMinimumSeedersHelpText", Advanced = true)]
public int MinimumSeeders { get; set; } public int MinimumSeeders { get; set; }
[FieldDefinition(4)] [FieldDefinition(4)]

View File

@ -48,13 +48,13 @@ public SeedCriteriaSettingsValidator(double seedRatioMinimum = 0.0, int seedTime
public class SeedCriteriaSettings public class SeedCriteriaSettings
{ {
[FieldDefinition(0, Type = FieldType.Textbox, Label = "Seed Ratio", HelpText = "The ratio a torrent should reach before stopping, empty is download client's default. Ratio should be at least 1.0 and follow the indexers rules")] [FieldDefinition(0, Type = FieldType.Textbox, Label = "IndexerSettingsSeedRatio", HelpText = "IndexerSettingsSeedRatioHelpText")]
public double? SeedRatio { get; set; } public double? SeedRatio { get; set; }
[FieldDefinition(1, Type = FieldType.Number, Label = "Seed Time", Unit = "minutes", HelpText = "The time a torrent should be seeded before stopping, empty is download client's default", Advanced = true)] [FieldDefinition(1, Type = FieldType.Number, Label = "IndexerSettingsSeedTime", Unit = "minutes", HelpText = "IndexerSettingsSeedTimeHelpText", Advanced = true)]
public int? SeedTime { get; set; } public int? SeedTime { get; set; }
[FieldDefinition(2, Type = FieldType.Number, Label = "Season-Pack Seed Time", Unit = "minutes", HelpText = "The time a torrent should be seeded before stopping, empty is download client's default", Advanced = true)] [FieldDefinition(2, Type = FieldType.Number, Label = "Season-Pack Seed Time", Unit = "minutes", HelpText = "IndexerSettingsSeasonPackSeedTimeHelpText", Advanced = true)]
public int? SeasonPackSeedTime { get; set; } public int? SeasonPackSeedTime { get; set; }
} }
} }

View File

@ -1,6 +1,7 @@
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.TorrentRss namespace NzbDrone.Core.Indexers.TorrentRss
@ -15,8 +16,8 @@ public class TorrentRssIndexer : HttpIndexerBase<TorrentRssIndexerSettings>
private readonly ITorrentRssParserFactory _torrentRssParserFactory; private readonly ITorrentRssParserFactory _torrentRssParserFactory;
public TorrentRssIndexer(ITorrentRssParserFactory torrentRssParserFactory, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public TorrentRssIndexer(ITorrentRssParserFactory torrentRssParserFactory, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(httpClient, indexerStatusService, configService, parsingService, logger) : base(httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
_torrentRssParserFactory = torrentRssParserFactory; _torrentRssParserFactory = torrentRssParserFactory;
} }

View File

@ -25,16 +25,16 @@ public TorrentRssIndexerSettings()
MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS; MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS;
} }
[FieldDefinition(0, Label = "Full RSS Feed URL")] [FieldDefinition(0, Label = "IndexerSettingsRssUrl")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "Cookie", HelpText = "If you site requires a login cookie to access the rss, you'll have to retrieve it via a browser.")] [FieldDefinition(1, Label = "IndexerSettingsCookie", HelpText = "IndexerSettingsCookieHelpText")]
public string Cookie { get; set; } public string Cookie { get; set; }
[FieldDefinition(2, Type = FieldType.Checkbox, Label = "Allow Zero Size", HelpText="Enabling this will allow you to use feeds that don't specify release size, but be careful, size related checks will not be performed.")] [FieldDefinition(2, Type = FieldType.Checkbox, Label = "Allow Zero Size", HelpText="IndexerSettingsAllowZeroSizeHelpText")]
public bool AllowZeroSize { get; set; } public bool AllowZeroSize { get; set; }
[FieldDefinition(3, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] [FieldDefinition(3, Type = FieldType.Number, Label = "IndexerSettingsMinimumSeeders", HelpText = "IndexerSettingsMinimumSeedersHelpText", Advanced = true)]
public int MinimumSeeders { get; set; } public int MinimumSeeders { get; set; }
[FieldDefinition(4)] [FieldDefinition(4)]

View File

@ -1,6 +1,7 @@
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.Torrentleech namespace NzbDrone.Core.Indexers.Torrentleech
@ -13,8 +14,8 @@ public class Torrentleech : HttpIndexerBase<TorrentleechSettings>
public override bool SupportsSearch => false; public override bool SupportsSearch => false;
public override int PageSize => 0; public override int PageSize => 0;
public Torrentleech(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public Torrentleech(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(httpClient, indexerStatusService, configService, parsingService, logger) : base(httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
} }

View File

@ -25,13 +25,13 @@ public TorrentleechSettings()
MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS; MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS;
} }
[FieldDefinition(0, Label = "Website URL")] [FieldDefinition(0, Label = "IndexerSettingsWebsiteUrl")]
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "API Key", Privacy = PrivacyLevel.ApiKey)] [FieldDefinition(1, Label = "ApiKey", Privacy = PrivacyLevel.ApiKey)]
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(2, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] [FieldDefinition(2, Type = FieldType.Number, Label = "IndexerSettingsMinimumSeeders", HelpText = "IndexerSettingsMinimumSeedersHelpText", Advanced = true)]
public int MinimumSeeders { get; set; } public int MinimumSeeders { get; set; }
[FieldDefinition(3)] [FieldDefinition(3)]

View File

@ -8,6 +8,7 @@
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Indexers.Newznab; using NzbDrone.Core.Indexers.Newznab;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
@ -23,8 +24,8 @@ public class Torznab : HttpIndexerBase<TorznabSettings>
public override DownloadProtocol Protocol => DownloadProtocol.Torrent; public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override int PageSize => GetProviderPageSize(); public override int PageSize => GetProviderPageSize();
public Torznab(INewznabCapabilitiesProvider capabilitiesProvider, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) public Torznab(INewznabCapabilitiesProvider capabilitiesProvider, IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger, ILocalizationService localizationService)
: base(httpClient, indexerStatusService, configService, parsingService, logger) : base(httpClient, indexerStatusService, configService, parsingService, logger, localizationService)
{ {
_capabilitiesProvider = capabilitiesProvider; _capabilitiesProvider = capabilitiesProvider;
} }
@ -123,13 +124,13 @@ protected virtual ValidationFailure TestCapabilities()
return null; return null;
} }
return new ValidationFailure(string.Empty, "Indexer does not support required search parameters"); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationSearchParametersNotSupported"));
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.Warn(ex, "Unable to connect to indexer: " + ex.Message); _logger.Warn(ex, "Unable to connect to indexer: " + ex.Message);
return new ValidationFailure(string.Empty, $"Unable to connect to indexer: {ex.Message}. Check the log surrounding this error for details"); return new ValidationFailure(string.Empty, _localizationService.GetLocalizedString("IndexerValidationUnableToConnect", new Dictionary<string, object> { { "exceptionMessage", ex.Message } }));
} }
} }
@ -140,10 +141,10 @@ protected virtual ValidationFailure JackettAll()
Settings.BaseUrl.Contains("/torznab/all") || Settings.BaseUrl.Contains("/torznab/all") ||
Settings.BaseUrl.Contains("/api/v2.0/indexers/all/results/torznab")) Settings.BaseUrl.Contains("/api/v2.0/indexers/all/results/torznab"))
{ {
return new NzbDroneValidationFailure("ApiPath", "Jackett's all endpoint is not supported, please add indexers individually") return new NzbDroneValidationFailure("ApiPath", _localizationService.GetLocalizedString("IndexerValidationJackettAllNotSupported"))
{ {
IsWarning = true, IsWarning = true,
DetailedDescription = "Jackett's all endpoint is not supported, please add indexers individually" DetailedDescription = _localizationService.GetLocalizedString("IndexerValidationJackettAllNotSupportedHelpText")
}; };
} }

View File

@ -51,7 +51,7 @@ public TorznabSettings()
MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS; MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS;
} }
[FieldDefinition(7, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] [FieldDefinition(7, Type = FieldType.Number, Label = "IndexerSettingsMinimumSeeders", HelpText = "IndexerSettingsMinimumSeedersHelpText", Advanced = true)]
public int MinimumSeeders { get; set; } public int MinimumSeeders { get; set; }
[FieldDefinition(8)] [FieldDefinition(8)]

View File

@ -770,6 +770,8 @@
"Indexer": "Indexer", "Indexer": "Indexer",
"IndexerDownloadClientHealthCheckMessage": "Indexers with invalid download clients: {indexerNames}.", "IndexerDownloadClientHealthCheckMessage": "Indexers with invalid download clients: {indexerNames}.",
"IndexerDownloadClientHelpText": "Specify which download client is used for grabs from this indexer", "IndexerDownloadClientHelpText": "Specify which download client is used for grabs from this indexer",
"IndexerIPTorrentsSettingsFeedUrl": "Feed URL",
"IndexerIPTorrentsSettingsFeedUrlHelpText": "The full RSS feed url generated by IPTorrents, using only the categories you selected (HD, SD, x264, etc ...)",
"IndexerJackettAllHealthCheckMessage": "Indexers using the unsupported Jackett 'all' endpoint: {indexerNames}", "IndexerJackettAllHealthCheckMessage": "Indexers using the unsupported Jackett 'all' endpoint: {indexerNames}",
"IndexerLongTermStatusAllUnavailableHealthCheckMessage": "All indexers are unavailable due to failures for more than 6 hours", "IndexerLongTermStatusAllUnavailableHealthCheckMessage": "All indexers are unavailable due to failures for more than 6 hours",
"IndexerLongTermStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures for more than 6 hours: {indexerNames}", "IndexerLongTermStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures for more than 6 hours: {indexerNames}",
@ -782,9 +784,56 @@
"IndexerSearchNoAvailableIndexersHealthCheckMessage": "All search-capable indexers are temporarily unavailable due to recent indexer errors", "IndexerSearchNoAvailableIndexersHealthCheckMessage": "All search-capable indexers are temporarily unavailable due to recent indexer errors",
"IndexerSearchNoInteractiveHealthCheckMessage": "No indexers available with Interactive Search enabled, {appName} will not provide any interactive search results", "IndexerSearchNoInteractiveHealthCheckMessage": "No indexers available with Interactive Search enabled, {appName} will not provide any interactive search results",
"IndexerSettings": "Indexer Settings", "IndexerSettings": "Indexer Settings",
"IndexerSettingsAdditionalNewznabParametersHelpText": "Please note if you change the category you will have to add required/restricted rules about the subgroups to avoid foreign language releases.",
"IndexerSettingsAdditionalParameters": "Additional Parameters",
"IndexerSettingsAdditionalParametersNyaa": "Additional Parameters",
"IndexerSettingsAllowZeroSize": "Allow Zero Size",
"IndexerSettingsAllowZeroSizeHelpText": "Enabling this will allow you to use feeds that don't specify release size, but be careful, size related checks will not be performed.",
"IndexerSettingsAnimeCategories": "Anime Categories",
"IndexerSettingsAnimeCategoriesHelpText": "Drop down list, leave blank to disable anime",
"IndexerSettingsAnimeStandardFormatSearch": "Anime Standard Format Search",
"IndexerSettingsAnimeStandardFormatSearchHelpText": "Also search for anime using the standard numbering",
"IndexerSettingsApiPath": "API Path",
"IndexerSettingsApiPathHelpText": "Path to the api, usually {url}",
"IndexerSettingsApiUrl": "API URL",
"IndexerSettingsApiUrlHelpText": "Do not change this unless you know what you're doing. Since your API key will be sent to that host.",
"IndexerSettingsCategories": "Categories",
"IndexerSettingsCategoriesHelpText": "Drop down list, leave blank to disable standard/daily shows",
"IndexerSettingsCookie": "Cookie",
"IndexerSettingsCookieHelpText": "If your site requires a login cookie to access the rss, you'll have to retrieve it via a browser.",
"IndexerSettingsMinimumSeeders": "Minimum Seeders",
"IndexerSettingsMinimumSeedersHelpText": "Minimum number of seeders required.",
"IndexerSettingsPasskey": "Passkey",
"IndexerSettingsRssUrl": "RSS URL",
"IndexerSettingsRssUrlHelpText": "Enter to URL to an {indexer} compatible RSS feed",
"IndexerSettingsSeasonPackSeedTime": "Season-Pack Seed Time",
"IndexerSettingsSeasonPackSeedTimeHelpText": "The time a season-pack torrent should be seeded before stopping, empty uses the download client's default",
"IndexerSettingsSeedRatio": "Seed Ratio",
"IndexerSettingsSeedRatioHelpText": "The ratio a torrent should reach before stopping, empty uses the download client's default. Ratio should be at least 1.0 and follow the indexers rules",
"IndexerSettingsSeedTime": "Seed Time",
"IndexerSettingsSeedTimeHelpText": "The time a torrent should be seeded before stopping, empty uses the download client's default",
"IndexerSettingsWebsiteUrl": "Website URL",
"IndexerStatusAllUnavailableHealthCheckMessage": "All indexers are unavailable due to failures", "IndexerStatusAllUnavailableHealthCheckMessage": "All indexers are unavailable due to failures",
"IndexerStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures: {indexerNames}", "IndexerStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures: {indexerNames}",
"IndexerTagHelpText": "Only use this indexer for series with at least one matching tag. Leave blank to use with all series.", "IndexerTagHelpText": "Only use this indexer for series with at least one matching tag. Leave blank to use with all series.",
"IndexerValidationCloudFlareCaptchaExpired": "CloudFlare CAPTCHA token expired, please refresh it.",
"IndexerValidationCloudFlareCaptchaRequired": "Site protected by CloudFlare CAPTCHA. Valid CAPTCHA token required.",
"IndexerValidationFeedNotSupported": "Indexer feed is not supported: {exceptionMessage}",
"IndexerValidationInvalidApiKey": "Invalid API Key",
"IndexerValidationJackettAllNotSupported": "Jackett's all endpoint is not supported, please add indexers individually",
"IndexerValidationJackettAllNotSupportedHelpText": "Jackett's all endpoint is not supported, please add indexers individually",
"IndexerValidationJackettNoResultsInConfiguredCategories": "Query successful, but no results in the configured categories were returned from your indexer. This may be an issue with the indexer or your indexer category settings.",
"IndexerValidationJackettNoRssFeedQueryAvailable": "No RSS feed query available. This may be an issue with the indexer or your indexer category settings.",
"IndexerValidationQueryNotSupported": "Indexer does not support the current query. Check if the categories and or searching for seasons/episodes are supported. Check the log for more details.",
"IndexerValidationRequestLimitReached": "Request limit reached: {exceptionMessage}",
"IndexerValidationSearchParametersNotSupported": "Indexer does not support required search parameters",
"IndexerValidationTestAbortedDueToError": "Test was aborted due to an error: {exceptionMessage}",
"IndexerValidationUnableToConnect": "Unable to connect to indexer: {exceptionMessage}. Check the log surrounding this error for details",
"IndexerValidationUnableToConnectHttpError": "Unable to connect to indexer, please check your DNS settings and ensure that IPv6 is working or disabled. {exceptionMessage}.",
"IndexerValidationUnableToConnectInvalidCredentials": "Unable to connect to indexer, invalid credentials. {exceptionMessage}.",
"IndexerValidationUnableToConnectResolutionFailure": "Unable to connect to indexer connection failure. Check your connection to the indexer's server and DNS. {exceptionMessage}.",
"IndexerValidationUnableToConnectServerUnavailable": "Unable to connect to indexer, indexer's server is unavailable. Try again later. {exceptionMessage}.",
"IndexerValidationUnableToConnectTimeout": "Unable to connect to indexer, possibly due to a timeout. Try again or check your network settings. {exceptionMessage}.",
"Indexers": "Indexers", "Indexers": "Indexers",
"IndexersLoadError": "Unable to load Indexers", "IndexersLoadError": "Unable to load Indexers",
"IndexersSettingsSummary": "Indexers and indexer options", "IndexersSettingsSummary": "Indexers and indexer options",