mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2026-04-17 21:44:48 -04:00
Compare commits
24 Commits
v1.35.0.50
...
v1.36.1.50
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52a49e6a34 | ||
|
|
a7d99f351c | ||
|
|
b0212dd780 | ||
|
|
c8f5099423 | ||
|
|
5cc4c3f302 | ||
|
|
c0d2cb42e9 | ||
|
|
8081f13052 | ||
|
|
84b672e617 | ||
|
|
ed586c2d72 | ||
|
|
233176e321 | ||
|
|
d1e3390bae | ||
|
|
1cd60c7a40 | ||
|
|
c61cfcd312 | ||
|
|
5eb4d112ca | ||
|
|
70f2361d69 | ||
|
|
1d6babaa15 | ||
|
|
0427add8d0 | ||
|
|
010c2b836d | ||
|
|
22c4c1fc9a | ||
|
|
d5f6cc94b8 | ||
|
|
411e96ef2a | ||
|
|
2b0e52ebca | ||
|
|
c6fa26ca7b | ||
|
|
c85f170d41 |
@@ -78,6 +78,6 @@ Thank you to [<img src="https://resources.jetbrains.com/storage/products/company
|
||||
### License
|
||||
|
||||
- [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
|
||||
- Copyright 2010-2024
|
||||
- Copyright 2010-2025
|
||||
|
||||
Icon Credit - [Box vector created by freepik - www.freepik.com](https://www.freepik.com/vectors/box)
|
||||
|
||||
@@ -9,7 +9,7 @@ variables:
|
||||
testsFolder: './_tests'
|
||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||
majorVersion: '1.35.0'
|
||||
majorVersion: '1.36.1'
|
||||
minorVersion: $[counter('minorVersion', 1)]
|
||||
prowlarrVersion: '$(majorVersion).$(minorVersion)'
|
||||
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
|
||||
|
||||
@@ -170,7 +170,7 @@ module.exports = (env) => {
|
||||
loose: true,
|
||||
debug: false,
|
||||
useBuiltIns: 'entry',
|
||||
corejs: '3.39'
|
||||
corejs: '3.41'
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
"babel-loader": "9.2.1",
|
||||
"babel-plugin-inline-classnames": "2.0.1",
|
||||
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
|
||||
"core-js": "3.39.0",
|
||||
"core-js": "3.41.0",
|
||||
"css-loader": "6.7.3",
|
||||
"css-modules-typescript-loader": "4.0.1",
|
||||
"eslint": "8.57.1",
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace NzbDrone.Common.Test.Http
|
||||
[TestCase("Readarr/1.0.0.2300 (ubuntu 20.04)", "Readarr")]
|
||||
[TestCase("Sonarr/3.0.6.9999 (ubuntu 20.04)", "Sonarr")]
|
||||
[TestCase("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36", "Other")]
|
||||
[TestCase("appbrr", "appbrr")]
|
||||
[TestCase(" appbrr ", "appbrr")]
|
||||
public void should_parse_user_agent(string userAgent, string parsedAgent)
|
||||
{
|
||||
UserAgentParser.ParseSource(userAgent).Should().Be(parsedAgent);
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||
}
|
||||
catch (OperationCanceledException ex) when (cts.IsCancellationRequested)
|
||||
{
|
||||
throw new WebException("Http request timed out", ex.InnerException, WebExceptionStatus.Timeout, null);
|
||||
throw new WebException("Http request timed out", ex, WebExceptionStatus.Timeout, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace NzbDrone.Common.Http
|
||||
{
|
||||
public static class UserAgentParser
|
||||
{
|
||||
private static readonly Regex AppSourceRegex = new Regex(@"(?<agent>[a-z0-9]*)\/.*(?:\(.*\))?",
|
||||
private static readonly Regex AppSourceRegex = new (@"^(?<agent>[a-z0-9]+)(?:\/.+(?:\(.*\))?|$)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
public static string SimplifyUserAgent(string userAgent)
|
||||
{
|
||||
if (userAgent == null || userAgent.StartsWith("Mozilla/5.0"))
|
||||
if (userAgent == null || userAgent.StartsWith("Mozilla/5.0", StringComparison.Ordinal))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -19,14 +20,9 @@ namespace NzbDrone.Common.Http
|
||||
|
||||
public static string ParseSource(string userAgent)
|
||||
{
|
||||
var match = AppSourceRegex.Match(SimplifyUserAgent(userAgent) ?? string.Empty);
|
||||
var match = AppSourceRegex.Match(SimplifyUserAgent(userAgent?.Trim()) ?? string.Empty);
|
||||
|
||||
if (match.Groups["agent"].Success)
|
||||
{
|
||||
return match.Groups["agent"].Value;
|
||||
}
|
||||
|
||||
return "Other";
|
||||
return match.Groups["agent"].Success ? match.Groups["agent"].Value : "Other";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,27 +4,27 @@ namespace NzbDrone.Common.Instrumentation.Extensions
|
||||
{
|
||||
public static class LoggerExtensions
|
||||
{
|
||||
[MessageTemplateFormatMethod("message")]
|
||||
public static void ProgressInfo(this Logger logger, string message, params object[] args)
|
||||
{
|
||||
var formattedMessage = string.Format(message, args);
|
||||
LogProgressMessage(logger, LogLevel.Info, formattedMessage);
|
||||
LogProgressMessage(logger, LogLevel.Info, message, args);
|
||||
}
|
||||
|
||||
[MessageTemplateFormatMethod("message")]
|
||||
public static void ProgressDebug(this Logger logger, string message, params object[] args)
|
||||
{
|
||||
var formattedMessage = string.Format(message, args);
|
||||
LogProgressMessage(logger, LogLevel.Debug, formattedMessage);
|
||||
LogProgressMessage(logger, LogLevel.Debug, message, args);
|
||||
}
|
||||
|
||||
[MessageTemplateFormatMethod("message")]
|
||||
public static void ProgressTrace(this Logger logger, string message, params object[] args)
|
||||
{
|
||||
var formattedMessage = string.Format(message, args);
|
||||
LogProgressMessage(logger, LogLevel.Trace, formattedMessage);
|
||||
LogProgressMessage(logger, LogLevel.Trace, message, args);
|
||||
}
|
||||
|
||||
private static void LogProgressMessage(Logger logger, LogLevel level, string message)
|
||||
private static void LogProgressMessage(Logger logger, LogLevel level, string message, object[] parameters)
|
||||
{
|
||||
var logEvent = new LogEventInfo(level, logger.Name, message);
|
||||
var logEvent = new LogEventInfo(level, logger.Name, null, message, parameters);
|
||||
logEvent.Properties.Add("Status", "");
|
||||
|
||||
logger.Log(logEvent);
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -121,9 +121,16 @@ namespace NzbDrone.Core.Applications.Lidarr
|
||||
{
|
||||
var indexerCapabilities = GetIndexerCapabilities(indexer);
|
||||
|
||||
if (!indexerCapabilities.MusicSearchAvailable)
|
||||
{
|
||||
_logger.Debug("Skipping add for indexer {0} [{1}] due to missing music search support by the indexer", indexer.Name, indexer.Id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty())
|
||||
{
|
||||
_logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
|
||||
_logger.Debug("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -178,7 +185,7 @@ namespace NzbDrone.Core.Applications.Lidarr
|
||||
{
|
||||
_logger.Debug("Syncing remote indexer with current settings");
|
||||
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
if (indexerCapabilities.MusicSearchAvailable && indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
{
|
||||
// Retain user fields not-affiliated with Prowlarr
|
||||
lidarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => lidarrIndexer.Fields.All(s => s.Name != f.Name)));
|
||||
@@ -204,7 +211,7 @@ namespace NzbDrone.Core.Applications.Lidarr
|
||||
{
|
||||
_appIndexerMapService.Delete(indexerMapping.Id);
|
||||
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
if (indexerCapabilities.MusicSearchAvailable && indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
{
|
||||
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Lidarr", indexer.Name, indexer.Id);
|
||||
lidarrIndexer.Id = 0;
|
||||
|
||||
@@ -121,9 +121,16 @@ namespace NzbDrone.Core.Applications.Radarr
|
||||
{
|
||||
var indexerCapabilities = GetIndexerCapabilities(indexer);
|
||||
|
||||
if (!indexerCapabilities.MovieSearchAvailable)
|
||||
{
|
||||
_logger.Debug("Skipping add for indexer {0} [{1}] due to missing movie search support by the indexer", indexer.Name, indexer.Id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty())
|
||||
{
|
||||
_logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
|
||||
_logger.Debug("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -176,7 +183,7 @@ namespace NzbDrone.Core.Applications.Radarr
|
||||
|
||||
if (!radarrIndexer.Equals(remoteIndexer) || forceSync)
|
||||
{
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
if (indexerCapabilities.MovieSearchAvailable && indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
{
|
||||
// Retain user fields not-affiliated with Prowlarr
|
||||
radarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => radarrIndexer.Fields.All(s => s.Name != f.Name)));
|
||||
@@ -202,7 +209,7 @@ namespace NzbDrone.Core.Applications.Radarr
|
||||
{
|
||||
_appIndexerMapService.Delete(indexerMapping.Id);
|
||||
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
if (indexerCapabilities.MovieSearchAvailable && indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
{
|
||||
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Radarr", indexer.Name, indexer.Id);
|
||||
radarrIndexer.Id = 0;
|
||||
|
||||
@@ -121,9 +121,16 @@ namespace NzbDrone.Core.Applications.Readarr
|
||||
{
|
||||
var indexerCapabilities = GetIndexerCapabilities(indexer);
|
||||
|
||||
if (!indexerCapabilities.BookSearchAvailable)
|
||||
{
|
||||
_logger.Debug("Skipping add for indexer {0} [{1}] due to missing book search support by the indexer", indexer.Name, indexer.Id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty())
|
||||
{
|
||||
_logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
|
||||
_logger.Debug("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -178,7 +185,7 @@ namespace NzbDrone.Core.Applications.Readarr
|
||||
{
|
||||
_logger.Debug("Syncing remote indexer with current settings");
|
||||
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
if (indexerCapabilities.BookSearchAvailable && indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
{
|
||||
// Retain user fields not-affiliated with Prowlarr
|
||||
readarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => readarrIndexer.Fields.All(s => s.Name != f.Name)));
|
||||
@@ -204,7 +211,7 @@ namespace NzbDrone.Core.Applications.Readarr
|
||||
{
|
||||
_appIndexerMapService.Delete(indexerMapping.Id);
|
||||
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
if (indexerCapabilities.BookSearchAvailable && indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
|
||||
{
|
||||
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Readarr", indexer.Name, indexer.Id);
|
||||
readarrIndexer.Id = 0;
|
||||
|
||||
@@ -125,10 +125,17 @@ namespace NzbDrone.Core.Applications.Sonarr
|
||||
{
|
||||
var indexerCapabilities = GetIndexerCapabilities(indexer);
|
||||
|
||||
if (!indexerCapabilities.TvSearchAvailable)
|
||||
{
|
||||
_logger.Debug("Skipping add for indexer {0} [{1}] due to missing TV search support by the indexer", indexer.Name, indexer.Id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty() &&
|
||||
indexerCapabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Empty())
|
||||
{
|
||||
_logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
|
||||
_logger.Debug("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -183,7 +190,7 @@ namespace NzbDrone.Core.Applications.Sonarr
|
||||
{
|
||||
_logger.Debug("Syncing remote indexer with current settings");
|
||||
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexerCapabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any())
|
||||
if (indexerCapabilities.TvSearchAvailable && (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexerCapabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any()))
|
||||
{
|
||||
// Retain user fields not-affiliated with Prowlarr
|
||||
sonarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => sonarrIndexer.Fields.All(s => s.Name != f.Name)));
|
||||
@@ -210,7 +217,7 @@ namespace NzbDrone.Core.Applications.Sonarr
|
||||
{
|
||||
_appIndexerMapService.Delete(indexerMapping.Id);
|
||||
|
||||
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexerCapabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any())
|
||||
if (indexerCapabilities.TvSearchAvailable && (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexerCapabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any()))
|
||||
{
|
||||
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Sonarr", indexer.Name, indexer.Id);
|
||||
sonarrIndexer.Id = 0;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
@@ -15,39 +16,53 @@ namespace NzbDrone.Core.Download
|
||||
{
|
||||
public void Validate(byte[] fileContent)
|
||||
{
|
||||
var reader = new StreamReader(new MemoryStream(fileContent));
|
||||
|
||||
using (var xmlTextReader = XmlReader.Create(reader, new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, IgnoreComments = true }))
|
||||
try
|
||||
{
|
||||
var xDoc = XDocument.Load(xmlTextReader);
|
||||
var nzb = xDoc.Root;
|
||||
var reader = new StreamReader(new MemoryStream(fileContent));
|
||||
|
||||
if (nzb == null)
|
||||
using (var xmlTextReader = XmlReader.Create(reader,
|
||||
new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, IgnoreComments = true }))
|
||||
{
|
||||
throw new InvalidNzbException("Invalid NZB: No Root element");
|
||||
}
|
||||
var xDoc = XDocument.Load(xmlTextReader);
|
||||
var nzb = xDoc.Root;
|
||||
|
||||
// nZEDb has an bug in their error reporting code spitting out invalid http status codes
|
||||
if (nzb.Name.LocalName.Equals("error") &&
|
||||
nzb.TryGetAttributeValue("code", out var code) &&
|
||||
nzb.TryGetAttributeValue("description", out var description))
|
||||
{
|
||||
throw new InvalidNzbException("Invalid NZB: Contains indexer error: {0} - {1}", code, description);
|
||||
}
|
||||
if (nzb == null)
|
||||
{
|
||||
throw new InvalidNzbException("Invalid NZB: No Root element");
|
||||
}
|
||||
|
||||
if (!nzb.Name.LocalName.Equals("nzb"))
|
||||
{
|
||||
throw new InvalidNzbException("Invalid NZB: Unexpected root element. Expected 'nzb' found '{0}'", nzb.Name.LocalName);
|
||||
}
|
||||
// nZEDb has a bug in their error reporting code spitting out invalid http status codes
|
||||
if (nzb.Name.LocalName.Equals("error") &&
|
||||
nzb.TryGetAttributeValue("code", out var code) &&
|
||||
nzb.TryGetAttributeValue("description", out var description))
|
||||
{
|
||||
throw new InvalidNzbException("Invalid NZB: Contains indexer error: {0} - {1}", code, description);
|
||||
}
|
||||
|
||||
var ns = nzb.Name.Namespace;
|
||||
var files = nzb.Elements(ns + "file").ToList();
|
||||
if (!nzb.Name.LocalName.Equals("nzb"))
|
||||
{
|
||||
throw new InvalidNzbException(
|
||||
"Invalid NZB: Unexpected root element. Expected 'nzb' found '{0}'", nzb.Name.LocalName);
|
||||
}
|
||||
|
||||
if (files.Empty())
|
||||
{
|
||||
throw new InvalidNzbException("Invalid NZB: No files");
|
||||
var ns = nzb.Name.Namespace;
|
||||
var files = nzb.Elements(ns + "file").ToList();
|
||||
|
||||
if (files.Empty())
|
||||
{
|
||||
throw new InvalidNzbException("Invalid NZB: No files");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidNzbException)
|
||||
{
|
||||
// Throw the original exception
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidNzbException("Invalid NZB: Unable to parse", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,6 +255,11 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
throw new IndexerException(indexerResponse, $"Unexpected response status {indexerHttpResponse.StatusCode} code from indexer request");
|
||||
}
|
||||
|
||||
if (indexerHttpResponse.Headers.ContentType.Contains("text/html"))
|
||||
{
|
||||
throw new IndexerException(indexerResponse, $"Indexer responded with HTML content. {(indexerHttpResponse.Content.ContainsIgnoreCase("site maintenance") ? "Site is under maintenance." : "Site is likely blocked or unavailable.")}");
|
||||
}
|
||||
|
||||
if (!indexerHttpResponse.Headers.ContentType.Contains(HttpAccept.Json.Value))
|
||||
{
|
||||
throw new IndexerException(indexerResponse, $"Unexpected response header {indexerHttpResponse.Headers.ContentType} from indexer request, expected {HttpAccept.Json.Value}");
|
||||
|
||||
@@ -227,7 +227,9 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
|
||||
{
|
||||
if (required)
|
||||
{
|
||||
throw new Exception($"Selector \"{selectorSelector}\" didn't match {parentObj.ToString(Formatting.None)}");
|
||||
var jsonContent = parentObj.ToString(Formatting.None);
|
||||
|
||||
throw new Exception($"Selector \"{selectorSelector}\" didn't match JSON content").WithData("JsonContent", jsonContent[..Math.Min(jsonContent.Length, 5 * 1024)]);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -260,7 +262,9 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
|
||||
{
|
||||
if (required)
|
||||
{
|
||||
throw new Exception($"None of the case selectors \"{string.Join(",", selector.Case)}\" matched {parentObj.ToString(Formatting.None)}");
|
||||
var jsonContent = parentObj.ToString(Formatting.None);
|
||||
|
||||
throw new Exception($"None of the case selectors \"{string.Join(",", selector.Case)}\" matched JSON content").WithData("JsonContent", jsonContent[..Math.Min(jsonContent.Length, 5 * 1024)]);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -739,7 +743,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
|
||||
case "hexdump":
|
||||
// this is mainly for debugging invisible special char related issues
|
||||
var hexData = string.Join("", data.Select(c => c + "(" + ((int)c).ToString("X2") + ")"));
|
||||
_logger.Debug(string.Format("CardigannIndexer ({0}): strdump: {1}", _definition.Id, hexData));
|
||||
_logger.Debug("CardigannIndexer ({0}): strdump: {1}", _definition.Id, hexData);
|
||||
break;
|
||||
case "strdump":
|
||||
// for debugging
|
||||
@@ -915,7 +919,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
|
||||
|
||||
break;
|
||||
default:
|
||||
_logger.Error(string.Format("CardigannIndexer ({0}): Unsupported selector: {1}", _definition.Id, rowSelector));
|
||||
_logger.Error("CardigannIndexer ({0}): Unsupported selector: {1}", _definition.Id, rowSelector);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
|
||||
{
|
||||
results = ApplyFilters(results, search.Preprocessingfilters, variables);
|
||||
searchResultDocument = searchResultParser.ParseDocument(results);
|
||||
_logger.Trace(string.Format("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results));
|
||||
_logger.Trace("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results);
|
||||
}
|
||||
|
||||
var rowsSelector = ApplyGoTemplateText(search.Rows.Selector, variables);
|
||||
@@ -241,7 +241,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
|
||||
{
|
||||
results = ApplyFilters(results, search.Preprocessingfilters, variables);
|
||||
searchResultDocument = searchResultParser.ParseDocument(results);
|
||||
_logger.Trace(string.Format("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results));
|
||||
_logger.Trace("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results);
|
||||
}
|
||||
|
||||
var rowsSelector = ApplyGoTemplateText(search.Rows.Selector, variables);
|
||||
|
||||
@@ -148,7 +148,8 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
SupportsSearch = SupportsSearch,
|
||||
SupportsRedirect = SupportsRedirect,
|
||||
SupportsPagination = SupportsPagination,
|
||||
Capabilities = caps
|
||||
Capabilities = caps,
|
||||
Redirect = true
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
|
||||
|
||||
public override IParseIndexerResponse GetParser()
|
||||
{
|
||||
return new PassThePopcornParser(Settings);
|
||||
return new PassThePopcornParser(Settings, Capabilities.Categories);
|
||||
}
|
||||
|
||||
private IndexerCapabilities SetCapabilities()
|
||||
@@ -45,10 +45,6 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
|
||||
{
|
||||
LimitsDefault = PageSize,
|
||||
LimitsMax = PageSize,
|
||||
TvSearchParams = new List<TvSearchParam>
|
||||
{
|
||||
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep, TvSearchParam.ImdbId
|
||||
},
|
||||
MovieSearchParams = new List<MovieSearchParam>
|
||||
{
|
||||
MovieSearchParam.Q, MovieSearchParam.ImdbId
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
|
||||
public class PassThePopcornMovie
|
||||
{
|
||||
public string GroupId { get; set; }
|
||||
public string CategoryId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Year { get; set; }
|
||||
public string Cover { get; set; }
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Common.Serializer;
|
||||
@@ -14,12 +13,12 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
|
||||
public class PassThePopcornParser : IParseIndexerResponse
|
||||
{
|
||||
private readonly PassThePopcornSettings _settings;
|
||||
private readonly IndexerCapabilitiesCategories _categories;
|
||||
|
||||
private static Regex SeasonRegex => new (@"\bS\d{2,3}(E\d{2,3})?\b", RegexOptions.Compiled);
|
||||
|
||||
public PassThePopcornParser(PassThePopcornSettings settings)
|
||||
public PassThePopcornParser(PassThePopcornSettings settings, IndexerCapabilitiesCategories categories)
|
||||
{
|
||||
_settings = settings;
|
||||
_categories = categories;
|
||||
}
|
||||
|
||||
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
@@ -84,13 +83,6 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
|
||||
flags.Add(PassThePopcornFlag.Approved);
|
||||
}
|
||||
|
||||
var categories = new List<IndexerCategory> { NewznabStandardCategory.Movies };
|
||||
|
||||
if (title != null && SeasonRegex.Match(title).Success)
|
||||
{
|
||||
categories.Add(NewznabStandardCategory.TV);
|
||||
}
|
||||
|
||||
var uploadVolumeFactor = torrent.FreeleechType?.ToUpperInvariant() switch
|
||||
{
|
||||
"NEUTRAL LEECH" => 0,
|
||||
@@ -104,7 +96,7 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
|
||||
Year = int.Parse(result.Year),
|
||||
InfoUrl = GetInfoUrl(result.GroupId, id),
|
||||
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
|
||||
Categories = categories,
|
||||
Categories = _categories.MapTrackerCatToNewznab(result.CategoryId),
|
||||
Size = long.Parse(torrent.Size),
|
||||
Grabs = int.Parse(torrent.Snatched),
|
||||
Seeders = int.Parse(torrent.Seeders),
|
||||
|
||||
@@ -78,6 +78,8 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
|
||||
{ "action", "advanced" },
|
||||
{ "json", "noredirect" },
|
||||
{ "grouping", "0" },
|
||||
{ "order_by", "time" },
|
||||
{ "order_way", "desc" },
|
||||
{ "searchstr", searchTerm }
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,12 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
|
||||
{
|
||||
private static readonly PassThePopcornSettingsValidator Validator = new ();
|
||||
|
||||
public PassThePopcornSettings()
|
||||
{
|
||||
BaseSettings.QueryLimit = 150;
|
||||
BaseSettings.LimitsUnit = (int)IndexerLimitsUnit.Hour;
|
||||
}
|
||||
|
||||
[FieldDefinition(2, Label = "IndexerSettingsApiUser", HelpText = "IndexerPassThePopcornSettingsApiUserHelpText", Privacy = PrivacyLevel.UserName)]
|
||||
public string APIUser { get; set; }
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ namespace NzbDrone.Core.Indexers
|
||||
}
|
||||
else if (settings.BaseUrl.IsNotNullOrWhiteSpace() && LegacyUrls.Contains(settings.BaseUrl))
|
||||
{
|
||||
_logger.Debug(string.Format("Changing legacy site link from {0} to {1}", settings.BaseUrl, defaultLink));
|
||||
_logger.Debug("Changing legacy site link from {0} to {1}", settings.BaseUrl, defaultLink);
|
||||
settings.BaseUrl = defaultLink;
|
||||
}
|
||||
|
||||
|
||||
@@ -740,5 +740,72 @@
|
||||
"SelectedCountOfCountReleases": "S'han seleccionat {selectedCount} de les versions {itemCount}",
|
||||
"SettingsLogRotate": "Rotació del registre",
|
||||
"AreYouSureYouWantToDeleteCategory": "Esteu segur que voleu suprimir la categoria assignada?",
|
||||
"Book": "Llibre"
|
||||
"Book": "Llibre",
|
||||
"IndexerSettingsCookie": "Cookie",
|
||||
"DownloadClientFreeboxSettingsAppIdHelpText": "ID d'aplicació indicat en crear accés a l'API de Freebox (ex: 'app_id')",
|
||||
"DownloadClientFreeboxSettingsHostHelpText": "Nom d'amfitrió o adreça IP de l'amfitrió del Freebox, per defecte a '{url}' (només funcionarà si es troba a la mateixa xarxa)",
|
||||
"DownloadClientFreeboxSettingsPortHelpText": "Port utilitzat per accedir a la interfície Freebox, per defecte a '{port}'",
|
||||
"DownloadClientRTorrentSettingsUrlPath": "Camí de l'Url",
|
||||
"IndexerHDBitsSettingsMediumsHelpText": "Si no s'especifica, s'utilitzen totes les opcions.",
|
||||
"NotificationsEmailSettingsUseEncryptionHelpText": "Si s'ha de preferir l'ús de l'encriptatge si es configura al servidor, per utilitzar sempre l'encriptatge mitjançant SSL (només Port 465) o StartTLS (qualsevol altre port) o per no utilitzar mai l'encriptatge",
|
||||
"DownloadClientQbittorrentSettingsFirstAndLastFirst": "Primer i últim",
|
||||
"DownloadClientFloodSettingsTagsHelpText": "Etiquetes inicials d'una baixada. Per ser reconegut, una baixada ha de tenir totes les etiquetes inicials. Això evita conflictes amb baixades no relacionades.",
|
||||
"DownloadClientQbittorrentSettingsSequentialOrder": "Ordre seqüencial",
|
||||
"DownloadClientSettingsUseSslHelpText": "Usa una connexió segura quan es connecti a {clientName}",
|
||||
"InstallMajorVersionUpdate": "Instal·la l'actualització",
|
||||
"InstallMajorVersionUpdateMessageLink": "Si us plau, comproveu [{domain}]({url}) per a més informació.",
|
||||
"OverrideGrabModalTitle": "Sobreescriu i Captura - {title}",
|
||||
"SecretToken": "Testimoni secret",
|
||||
"TorrentBlackholeSaveMagnetFilesExtension": "Desa l'extensió dels fitxers magnètics",
|
||||
"FailedToFetchSettings": "No s'ha pogut recuperar la configuració",
|
||||
"DownloadClientFreeboxSettingsApiUrlHelpText": "Defineix l'URL base de l'API de Freebox amb la versió de l'API, p. ex. '{url}', per defecte a '{defaultApiUrl}'",
|
||||
"IndexerSettingsSeedTime": "Temps de la llavor",
|
||||
"DownloadClientDownloadStationSettingsDirectoryHelpText": "Carpeta compartida opcional per posar les baixades, deixeu en blanc per utilitzar la ubicació predeterminada de l'estació de baixada",
|
||||
"DownloadClientPneumaticSettingsNzbFolderHelpText": "Aquesta carpeta haurà de ser accessible des de XBMC",
|
||||
"DownloadClientPneumaticSettingsStrmFolder": "Carpeta Strm",
|
||||
"DownloadClientSettingsDestinationHelpText": "Especifica manualment la destinació de la baixada, deixeu-ho en blanc per a utilitzar el predeterminat",
|
||||
"DownloadClientTransmissionSettingsUrlBaseHelpText": "Afegeix un prefix a l'URL rpc de {clientName}, ex. {url}, per defecte a ‘{defaultUrl}’",
|
||||
"IndexerSettingsApiPathHelpText": "Camí a l'api, normalment {url}",
|
||||
"LogSizeLimitHelpText": "Mida màxima del fitxer de registre en MB abans d'arxivar. Per defecte és 1MB.",
|
||||
"IndexerNewznabSettingsAdditionalParametersHelpText": "Paràmetres addicionals de Newznab",
|
||||
"InstallMajorVersionUpdateMessage": "Aquesta actualització instal·larà una nova versió principal i pot no ser compatible amb el vostre sistema. Esteu segur que voleu instal·lar aquesta actualització?",
|
||||
"PackageVersionInfo": "{packageVersion} per {packageAuthor}",
|
||||
"UpdaterLogFiles": "Fitxers de registre de l'actualitzador",
|
||||
"NotificationsEmailSettingsUseEncryption": "Utilitza l'encriptatge",
|
||||
"NotificationsTelegramSettingsIncludeAppNameHelpText": "Opcionalment prefixa el títol del missatge amb {appName} per diferenciar les notificacions de diferents aplicacions",
|
||||
"DownloadClientSettingsInitialState": "Estat inicial",
|
||||
"DownloadClientSettingsInitialStateHelpText": "Estat inicial dels torrents afegits a {clientName}",
|
||||
"IndexerPassThePopcornSettingsApiUserHelpText": "Aquests paràmetres es troben a la configuració de seguretat de PassThePopcorn (Edita el perfil > Seguretat).",
|
||||
"DownloadClientRTorrentSettingsUrlPathHelpText": "Camí al extrem XMLRPC, vegeu {url}. Normalment és RPC2 o [camí a ruTorrent]{url2} quan s'utilitza ruTorrent.",
|
||||
"IndexerSettingsApiPath": "Camí de l'API",
|
||||
"IndexerHDBitsSettingsCodecsHelpText": "Si no s'especifica, s'utilitzen totes les opcions.",
|
||||
"IndexerSettingsApiUser": "Usuari de l'API",
|
||||
"IndexerSettingsSeedTimeHelpText": "El temps en què s'ha de sembrar un torrent abans d'aturar-lo, el buit utilitza el valor per defecte del client de baixada",
|
||||
"IndexerSettingsSeedRatio": "Ràtio de la llavor",
|
||||
"IndexerSettingsSeedRatioHelpText": "Ràtio a la qual ha d'arribar un torrent abans d'aturar-se, buit utilitza el valor per defecte del client de baixada. La relació ha de ser com a mínim 1.0 i seguir les regles dels indexadors",
|
||||
"IndexerSettingsAdditionalParameters": "Paràmetres addicionals",
|
||||
"DownloadClientFloodSettingsAdditionalTagsHelpText": "Afegeix les propietats dels suports com a etiquetes. Els consells són exemples.",
|
||||
"DownloadClientFloodSettingsUrlBaseHelpText": "Afegeix un prefix a l'API de Flood, com ara {url}",
|
||||
"DownloadClientFreeboxSettingsAppToken": "Testimoni d'aplicació",
|
||||
"DownloadClientNzbgetSettingsAddPausedHelpText": "Aquesta opció requereix com a mínim la versió 16.0 de NzbGet",
|
||||
"DownloadClientPneumaticSettingsNzbFolder": "Carpeta Nzb",
|
||||
"DownloadClientPneumaticSettingsStrmFolderHelpText": "Els fitxers .strm d'aquesta carpeta s'importaran amb el dron",
|
||||
"DownloadClientQbittorrentSettingsFirstAndLastFirstHelpText": "Baixeu primer i primer les últimes peces (qBittorrent 4.1.0+)",
|
||||
"DownloadClientQbittorrentSettingsSequentialOrderHelpText": "Baixada en ordre seqüencial (qBittorrent 4.1.0+)",
|
||||
"LabelIsRequired": "L'etiqueta és necessària",
|
||||
"NotificationsTelegramSettingsIncludeAppName": "Inclou {appName} al títol",
|
||||
"TorrentBlackholeSaveMagnetFiles": "Desa els fitxers Magnet",
|
||||
"TorrentBlackholeSaveMagnetFilesExtensionHelpText": "Extensió a utilitzar per als enllaços magnet, per defecte és '.magnet'",
|
||||
"TorrentBlackholeSaveMagnetFilesHelpText": "Desa l'enllaç magnet si no hi ha cap fitxer .torrent disponible (només útil si el client de baixada admet magnets desats a un fitxer)",
|
||||
"TorrentBlackholeTorrentFolder": "Carpeta torrent",
|
||||
"UseSsl": "Usa SSL",
|
||||
"UsenetBlackholeNzbFolder": "Carpeta Nzb",
|
||||
"XmlRpcPath": "Camí RPC XML",
|
||||
"DownloadClientRTorrentSettingsAddStopped": "Afegeix aturat",
|
||||
"DownloadClientRTorrentSettingsAddStoppedHelpText": "En activar s'afegiran torrents i imants a rTorrent en un estat aturat. Això pot trencar els fitxers magnet.",
|
||||
"DownloadClientFreeboxSettingsAppTokenHelpText": "S'ha recuperat el testimoni de l'aplicació en crear l'accés a l'API de Freebox (ex: 'app_token')",
|
||||
"DownloadClientUTorrentProviderMessage": "uTorrent té un historial d'inclusió de criptominers, programari maliciós i anuncis, us animem a triar un client diferent.",
|
||||
"DownloadClientQbittorrentSettingsInitialStateHelpText": "Estat inicial dels torrents afegits a qBittorrent. Tingueu en compte que els torrents forçats no compleixen amb les restriccions de llavors",
|
||||
"LogSizeLimit": "Límit de la mida del registre",
|
||||
"SelectDownloadClientModalTitle": "{modalTitle} - Seleccioneu el client de baixada"
|
||||
}
|
||||
|
||||
@@ -724,7 +724,7 @@
|
||||
"TestAllApps": "Test All Apps",
|
||||
"TestAllClients": "Test All Clients",
|
||||
"TestAllIndexers": "Test All Indexers",
|
||||
"TheLogLevelDefault": "The log level defaults to 'Info' and can be changed in [General Settings](/settings/general)",
|
||||
"TheLogLevelDefault": "The log level defaults to 'Debug' and can be changed in [General Settings](/settings/general)",
|
||||
"Theme": "Theme",
|
||||
"ThemeHelpText": "Change Application UI Theme, 'Auto' Theme will use your OS Theme to set Light or Dark mode. Inspired by {inspiredBy}.",
|
||||
"Time": "Time",
|
||||
|
||||
@@ -710,7 +710,7 @@
|
||||
"Logout": "Kirjaudu ulos",
|
||||
"NoEventsFound": "Tapahtumia ei löytynyt",
|
||||
"RestartReloadNote": "Huomioi: {appName} käynnistyy palautusprosessin aikana automaattisesti uudelleen.",
|
||||
"TheLogLevelDefault": "Lokikirjauksen oletusarvoinen laajuus on \"Informatiivinen\". Laajuutta voidaan muuttaa [Yleisistä asetuksista](/settings/general).",
|
||||
"TheLogLevelDefault": "Lokikirjauksen oletusarvoinen laajuus on \"Vianselvitys\". Laajuutta voidaan muuttaa [Yleisistä asetuksista](/settings/general).",
|
||||
"UpdateAppDirectlyLoadError": "{appName}ia ei voida päivittää suoraan,",
|
||||
"UpdaterLogFiles": "Päivittäjän lokitiedostot",
|
||||
"WouldYouLikeToRestoreBackup": "Haluatko palauttaa varmuuskopion \"{name}\"?",
|
||||
@@ -806,5 +806,6 @@
|
||||
"IndexerPassThePopcornSettingsGoldenPopcornOnlyHelpText": "Etsi vain ns. kultaisella pocornilla merkittyjä julkaisuja.",
|
||||
"IndexerSettingsFreeleechOnly": "Vain \"Freeleech\"",
|
||||
"IndexerSettingsCookieHelpText": "Jos sivusto vaatii kirjautumisevästeen, on se noudettava selaimen avulla.",
|
||||
"IndexerAvistazSettingsPasswordHelpText": "Sivuston salasana"
|
||||
"IndexerAvistazSettingsPasswordHelpText": "Sivuston salasana",
|
||||
"DownloadClientUTorrentProviderMessage": "Koska uTorrent on tullut tunnetuksi kryptolouhinnasta sekä haitta- ja mainossisällöstä, suosittelemme valitsemaan jonkin muun työkalun."
|
||||
}
|
||||
|
||||
@@ -161,5 +161,6 @@
|
||||
"Discord": "Discord",
|
||||
"AddCustomFilter": "Legg til eget filter",
|
||||
"Clone": "Lukk",
|
||||
"AddDownloadClientImplementation": "Ny Nedlastingsklient - {implementationName}"
|
||||
"AddDownloadClientImplementation": "Ny Nedlastingsklient - {implementationName}",
|
||||
"History": "Historikk"
|
||||
}
|
||||
|
||||
@@ -503,5 +503,10 @@
|
||||
"UpdateAppDirectlyLoadError": "Não foi possível atualizar o {appName} diretamente,",
|
||||
"InstallLatest": "Instalar o mais recente",
|
||||
"CurrentlyInstalled": "Atualmente instalado",
|
||||
"Mixed": "Corrigido"
|
||||
"Mixed": "Corrigido",
|
||||
"FailedToFetchSettings": "Falha ao obter as definições",
|
||||
"FailedToFetchUpdates": "Falha a obter atualizações",
|
||||
"External": "Externo",
|
||||
"Categories": "Categorias",
|
||||
"days": "dias"
|
||||
}
|
||||
|
||||
@@ -794,7 +794,7 @@
|
||||
"LogFilesLocation": "Os arquivos de log estão localizados em: {location}",
|
||||
"Logout": "Sair",
|
||||
"NoEventsFound": "Nenhum evento encontrado",
|
||||
"TheLogLevelDefault": "O nível de registro é padronizado como 'Info' e pode ser alterado em [Configurações Gerais](/settings/general)",
|
||||
"TheLogLevelDefault": "O nível de log padrão é ' Debug ' e pode ser alterado em [ Configurações gerais](/ configurações/geral)",
|
||||
"UpdateAppDirectlyLoadError": "Incapaz de atualizar o {appName} diretamente,",
|
||||
"UpdaterLogFiles": "Arquivos de log do atualizador",
|
||||
"WouldYouLikeToRestoreBackup": "Gostaria de restaurar o backup '{name}'?",
|
||||
|
||||
@@ -544,7 +544,7 @@
|
||||
"LogFilesLocation": "Log kayıtlarının bulunduğu konum: {location}",
|
||||
"NoEventsFound": "Etkinlik bulunamadı",
|
||||
"RestartReloadNote": "Not: {appName} geri yükleme işlemi sırasında otomatik olarak yeniden başlatılacak ve kullanıcı arayüzünü yeniden yükleyecektir.",
|
||||
"TheLogLevelDefault": "Log seviyesi varsayılan olarak 'Bilgi' şeklindedir ve [Genel Ayarlar](/ayarlar/genel) bölümünden değiştirilebilir",
|
||||
"TheLogLevelDefault": "Günlük düzeyi varsayılan olarak 'Hata Ayıklama'dır ve [Genel Ayarlar](/ayarlar/genel) bölümünden değiştirilebilir",
|
||||
"UpdateAppDirectlyLoadError": "{appName} doğrudan güncellenemiyor,",
|
||||
"DockerUpdater": "Güncellemeyi almak için docker konteynerini güncelleyin",
|
||||
"FailedToFetchUpdates": "Güncellemeler alınamadı",
|
||||
|
||||
@@ -449,5 +449,103 @@
|
||||
"Author": "Автор",
|
||||
"OnHealthRestoredHelpText": "При відновленні стану",
|
||||
"IndexerHDBitsSettingsOriginsHelpText": "Якщо не вказано, використовуються всі параметри.",
|
||||
"days": "дні(в)"
|
||||
"days": "дні(в)",
|
||||
"XmlRpcPath": "Шлях XML RPC",
|
||||
"Directory": "Тека",
|
||||
"DownloadClientFreeboxSettingsAppId": "ID додатку",
|
||||
"DownloadClientQbittorrentSettingsFirstAndLastFirst": "Перше і останнє спочатку",
|
||||
"FailedToFetchUpdates": "Не вдалося завантажити оновлення",
|
||||
"OverrideGrabModalTitle": "Перевизначити та захопити - {title}",
|
||||
"UpdaterLogFiles": "Файли журналу оновлення",
|
||||
"UseSsl": "Використовувати SSL",
|
||||
"WouldYouLikeToRestoreBackup": "Бажаєте відновити резервну копію '{name}'?",
|
||||
"DownloadClientSettingsInitialState": "Початковий стан",
|
||||
"Install": "Встановити",
|
||||
"InstallMajorVersionUpdateMessage": "Це оновлення встановить нову основну версію і може бути несумісним з вашою системою. Ви впевнені, що хочете встановити це оновлення?",
|
||||
"Logout": "Завершити сеанс",
|
||||
"NoDownloadClientsFound": "Клієнти завантаження не знайдено",
|
||||
"PackageVersionInfo": "{packageVersion} створено {packageAuthor}",
|
||||
"SecretToken": "Таємний токен",
|
||||
"DownloadClientFloodSettingsAdditionalTagsHelpText": "Додає властивості мультимедіа у вигляді тегів. Підказки є прикладами.",
|
||||
"DownloadClientRTorrentSettingsUrlPathHelpText": "Шлях до кінцевої точки XMLRPC див. {url}. Зазвичай це RPC2 або [шлях до ruTorrent]{url2}, коли використовується ruTorrent.",
|
||||
"DownloadClientSettingsAddPaused": "Додати призупинені",
|
||||
"FailedToFetchSettings": "Не вдалося отримати налаштування",
|
||||
"IndexerNewznabSettingsAdditionalParametersHelpText": "Додаткові параметри Newznab",
|
||||
"DownloadClientPneumaticSettingsNzbFolderHelpText": "Ця тека повинна бути доступна з XBMC",
|
||||
"DownloadClientPneumaticSettingsStrmFolder": "Тека STRM",
|
||||
"DownloadClientPneumaticSettingsStrmFolderHelpText": "Файли .strm у цій теці будуть імпортовані дроном",
|
||||
"InfoUrl": "URL-адреса інформації",
|
||||
"DownloadClientUTorrentProviderMessage": "uTorrent має історію включення криптомайнерів, шкідливого програмного забезпечення та реклами. Ми наполегливо рекомендуємо вибрати інший клієнт.",
|
||||
"EditSelectedDownloadClients": "Редагувати вибрані клієнти завантаження",
|
||||
"IndexerHDBitsSettingsMediumsHelpText": "Якщо не вказано, використовуються всі параметри.",
|
||||
"IndexerSettingsAdditionalParameters": "Додаткові параметри",
|
||||
"IndexerSettingsCookie": "Cookie",
|
||||
"InstallMajorVersionUpdateMessageLink": "Будь ласка, перевірте [{domain}]({url}) для отримання додаткової інформації.",
|
||||
"InvalidUILanguage": "У вашому інтерфейсі встановлена недопустима мова. Виправте її та збережіть налаштування",
|
||||
"LogFilesLocation": "Файли журналу знаходяться в: {location}",
|
||||
"Menu": "Меню",
|
||||
"OnHealthRestored": "При відновленні стану",
|
||||
"PasswordConfirmation": "Підтвердження пароля",
|
||||
"PreviouslyInstalled": "Раніше встановлений",
|
||||
"LogSizeLimit": "Обмеження розміру журналу",
|
||||
"LogSizeLimitHelpText": "Максимальний розмір файлу журналу в МБ перед архівацією. За замовчуванням - 1 МБ.",
|
||||
"SelectDownloadClientModalTitle": "{modalTitle} - Вибрати клієнт завантаження",
|
||||
"IndexerSettingsApiPath": "Шлях API",
|
||||
"IndexerSettingsApiPathHelpText": "Шлях до API, зазвичай {url}",
|
||||
"IndexerSettingsApiUser": "API Користувач",
|
||||
"Implementation": "Реалізація",
|
||||
"ManageDownloadClients": "Керування клієнтами завантаження",
|
||||
"No": "Ні",
|
||||
"IndexerSettingsSeedRatioHelpText": "Рейтинг, якого має досягти торрент перед зупинкою. Якщо порожньо — використовується значення за замовчуванням клієнта завантаження. Рейтинг має бути не менше 1,0 і відповідати правилам індексаторів",
|
||||
"IndexerSettingsSeedTimeHelpText": "Час, протягом якого торрент має залишатися на роздачі перед зупинкою, якщо порожньо — використовується значення клієнта завантаження за замовчуванням",
|
||||
"NotificationsTelegramSettingsIncludeAppName": "Включити {appName} у заголовок",
|
||||
"NotificationsTelegramSettingsIncludeAppNameHelpText": "При необхідності додати до заголовка повідомлення префікс {appName}, щоб відрізняти сповіщення від різних додатків",
|
||||
"DownloadClientQbittorrentSettingsContentLayout": "Макет контента",
|
||||
"External": "Зовнішній",
|
||||
"TorrentBlackholeTorrentFolder": "Тека торрента",
|
||||
"Donate": "Задонатити",
|
||||
"EditSelectedIndexers": "Редагувати вибраний індексатор",
|
||||
"IndexerSettingsSeedTime": "Час сидіння",
|
||||
"Label": "Мітка",
|
||||
"LabelIsRequired": "Необхідна мітка",
|
||||
"UsenetBlackholeNzbFolder": "Тека NZB",
|
||||
"NoHistoryFound": "Історія не знайдена",
|
||||
"NoIndexersFound": "Индексаторі не знайдено",
|
||||
"DownloadClientNzbgetSettingsAddPausedHelpText": "Для роботи цього параметра потрібна версія NzbGet не нижче 16.0",
|
||||
"DownloadClientPneumaticSettingsNzbFolder": "Тека NZB",
|
||||
"IndexerHDBitsSettingsCodecsHelpText": "Якщо не вказано, використовуються всі параметри.",
|
||||
"DefaultNameCopiedProfile": "{name} - Копіювати",
|
||||
"Destination": "Місце призначення",
|
||||
"DownloadClientFloodSettingsTagsHelpText": "Початкові теги завантаження. Щоб бути розпізнаним, завантаження повинно мати всі початкові теги. Це запобігає конфліктам з незв'язаними завантаженнями.",
|
||||
"DownloadClientFreeboxSettingsAppIdHelpText": "ID програми, отримане під час створення доступу до Freebox API (наприклад, 'app_id')",
|
||||
"DownloadClientFreeboxSettingsAppToken": "Токен додатку",
|
||||
"DownloadClientFreeboxSettingsAppTokenHelpText": "Токен додатку, отриманий під час створення доступу до Freebox API (наприклад, 'app_token')",
|
||||
"DownloadClientFreeboxSettingsHostHelpText": "Ім'я хоста або IP-адреса хоста Freebox, за замовчуванням — '{url}' (працює тільки якщо знаходиться в тій самій мережі)",
|
||||
"DownloadClientFreeboxSettingsPortHelpText": "Порт, що використовується для доступу до інтерфейсу Freebox, за замовчуванням — '{port}'",
|
||||
"DownloadClientQbittorrentSettingsInitialStateHelpText": "Початковий стан торрентів, доданих до qBittorrent. Зверніть увагу, що примусові торренти не дотримуються обмежень на роздачу",
|
||||
"DownloadClientQbittorrentSettingsSequentialOrder": "Завантажувати послідовно",
|
||||
"DownloadClientRTorrentSettingsAddStopped": "Додати зупинені",
|
||||
"DownloadClientRTorrentSettingsAddStoppedHelpText": "Увімкнення додасть торренти та магнет-посилання в rTorrent у зупиненому стані. Це може призвести до пошкодження магнет-файлів.",
|
||||
"DownloadClientRTorrentSettingsUrlPath": "URL-путь",
|
||||
"NotificationsEmailSettingsUseEncryptionHelpText": "Виберіть режим шифрування: віддавати перевагу шифруванню, якщо воно налаштоване на сервері; завжди використовувати шифрування через SSL (тільки порт 465) або StartTLS (будь-який інший порт); ніколи не використовувати шифрування",
|
||||
"DownloadClientFreeboxSettingsApiUrlHelpText": "Вкажіть базову URL-адресу Freebox API з версією API, наприклад, '{url}', за замовчуванням — '{defaultApiUrl}'",
|
||||
"DownloadClientSettingsDestinationHelpText": "Ручне налаштування місця для завантаження, залиште порожнім для використання значення за замовчуванням",
|
||||
"DownloadClientSettingsUseSslHelpText": "Використовувати захищене з'єднання при підключенні до {clientName}",
|
||||
"HealthMessagesInfoBox": "Додаткову інформацію про причину появи цих повідомлень перевірки працездатності можна знайти, перейшовши за посиланням wiki (іконка книги) в кінці рядка або перевірити [журнали]({link}). Якщо у вас виникли труднощі з розумінням цих повідомлень, ви можете звернутися до нашої служби підтримки за посиланнями нижче.",
|
||||
"IndexerDownloadClientHealthCheckMessage": "Індексатори з недопустимими клієнтами завантаження: {indexerNames}.",
|
||||
"Episode": "Епізод",
|
||||
"InstallMajorVersionUpdate": "Встановити оновлення",
|
||||
"ManageClients": "Керування клієнтами",
|
||||
"PrioritySettings": "Пріоритет: {0}",
|
||||
"IndexerPassThePopcornSettingsApiUserHelpText": "Ці налаштування можна знайти в налаштуваннях безпеки вашого PassThePopcorn (Редагувати профіль > Безпека).",
|
||||
"NotificationsEmailSettingsUseEncryption": "Використовувати шифрування",
|
||||
"TorrentBlackholeSaveMagnetFiles": "Зберігати магнітні файли",
|
||||
"TorrentBlackholeSaveMagnetFilesExtension": "Зберегти магнет-файли з розширенням",
|
||||
"TorrentBlackholeSaveMagnetFilesExtensionHelpText": "Розширення для магнет-посилань, за замовчуванням '.magnet'",
|
||||
"TorrentBlackholeSaveMagnetFilesHelpText": "Зберегти магнет-посилання, якщо файл .torrent недоступний (корисно тільки в разі, якщо клієнт завантаження підтримує магнет-посилання, збережені у файлі)",
|
||||
"DownloadClientDelugeSettingsUrlBaseHelpText": "Додає префікс до URL-адреси json, {url}",
|
||||
"DownloadClientTransmissionSettingsUrlBaseHelpText": "Додає префікс до URL-адреси RPC {clientName}, наприклад {url}, за замовчуванням — '{defaultUrl}'",
|
||||
"IndexerSettingsSeedRatio": "Коефіцієнт роздачі",
|
||||
"ManualGrab": "Захват вручну",
|
||||
"StopSelecting": "Скасувати вибір"
|
||||
}
|
||||
|
||||
@@ -3,5 +3,7 @@
|
||||
"Add": "添加",
|
||||
"Analytics": "分析",
|
||||
"Username": "用户名",
|
||||
"AcceptConfirmationModal": "中文"
|
||||
"AcceptConfirmationModal": "中文",
|
||||
"Backup": "备份",
|
||||
"BackupNow": "立即备份"
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace NzbDrone.Core.Notifications.Apprise
|
||||
{
|
||||
if (httpException.Response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
_logger.Error(ex, $"HTTP Auth credentials are invalid: {0}", ex.Message);
|
||||
_logger.Error(ex, "HTTP Auth credentials are invalid: {0}", ex.Message);
|
||||
return new ValidationFailure("AuthUsername", $"HTTP Auth credentials are invalid: {ex.Message}");
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace NzbDrone.Core.Notifications.Apprise
|
||||
{
|
||||
var error = Json.Deserialize<AppriseError>(httpException.Response.Content);
|
||||
|
||||
_logger.Error(ex, $"Unable to send test message. Response from API: {0}", error.Error);
|
||||
_logger.Error(ex, "Unable to send test message. Response from API: {0}", error.Error);
|
||||
return new ValidationFailure(string.Empty, $"Unable to send test message. Response from API: {error.Error}");
|
||||
}
|
||||
|
||||
|
||||
14
yarn.lock
14
yarn.lock
@@ -2260,9 +2260,9 @@ camelcase@^5.3.1:
|
||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||
|
||||
caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001663:
|
||||
version "1.0.30001667"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz#99fc5ea0d9c6e96897a104a8352604378377f949"
|
||||
integrity sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==
|
||||
version "1.0.30001715"
|
||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz"
|
||||
integrity sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==
|
||||
|
||||
chalk@^2.4.1, chalk@^2.4.2:
|
||||
version "2.4.2"
|
||||
@@ -2478,10 +2478,10 @@ core-js-compat@^3.38.0, core-js-compat@^3.38.1:
|
||||
dependencies:
|
||||
browserslist "^4.23.3"
|
||||
|
||||
core-js@3.39.0:
|
||||
version "3.39.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.39.0.tgz#57f7647f4d2d030c32a72ea23a0555b2eaa30f83"
|
||||
integrity sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==
|
||||
core-js@3.41.0:
|
||||
version "3.41.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.41.0.tgz#57714dafb8c751a6095d028a7428f1fb5834a776"
|
||||
integrity sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==
|
||||
|
||||
core-js@^2.4.0:
|
||||
version "2.6.12"
|
||||
|
||||
Reference in New Issue
Block a user