mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2026-04-17 21:44:48 -04:00
Compare commits
27 Commits
v1.19.0.45
...
v1.21.0.46
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7bada440d2 | ||
|
|
803c4752db | ||
|
|
c0777474c0 | ||
|
|
66dcea5604 | ||
|
|
a2a12d2450 | ||
|
|
39593bd5a8 | ||
|
|
45d8a8a4e6 | ||
|
|
a4546c77ce | ||
|
|
d69bf6360a | ||
|
|
da9ce5b5c3 | ||
|
|
e092098101 | ||
|
|
1a89a79b74 | ||
|
|
cb6bf49922 | ||
|
|
4bcaba0be0 | ||
|
|
220ef723c7 | ||
|
|
9c599a6be4 | ||
|
|
715ce1fc6c | ||
|
|
8c3a192dd0 | ||
|
|
d22bf93dfd | ||
|
|
886054fdf8 | ||
|
|
4188510586 | ||
|
|
fedebca5e1 | ||
|
|
e2ce6437e9 | ||
|
|
bdae60bac9 | ||
|
|
2d6c818aec | ||
|
|
a1d19852dc | ||
|
|
104c95f28f |
@@ -9,7 +9,7 @@ variables:
|
||||
testsFolder: './_tests'
|
||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||
majorVersion: '1.19.0'
|
||||
majorVersion: '1.21.0'
|
||||
minorVersion: $[counter('minorVersion', 1)]
|
||||
prowlarrVersion: '$(majorVersion).$(minorVersion)'
|
||||
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
|
||||
@@ -20,7 +20,7 @@ variables:
|
||||
innoVersion: '6.2.2'
|
||||
windowsImage: 'windows-2022'
|
||||
linuxImage: 'ubuntu-20.04'
|
||||
macImage: 'macOS-11'
|
||||
macImage: 'macOS-12'
|
||||
|
||||
trigger:
|
||||
branches:
|
||||
@@ -1169,7 +1169,7 @@ stages:
|
||||
submodules: true
|
||||
- powershell: Set-Service SCardSvr -StartupType Manual
|
||||
displayName: Enable Windows Test Service
|
||||
- task: SonarCloudPrepare@1
|
||||
- task: SonarCloudPrepare@2
|
||||
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
||||
inputs:
|
||||
SonarCloud: 'SonarCloud'
|
||||
@@ -1187,21 +1187,16 @@ stages:
|
||||
./build.sh --backend -f net6.0 -r win-x64
|
||||
TEST_DIR=_tests/net6.0/win-x64/publish/ ./test.sh Windows Unit Coverage
|
||||
displayName: Coverage Unit Tests
|
||||
- task: SonarCloudAnalyze@1
|
||||
- task: SonarCloudAnalyze@2
|
||||
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
||||
displayName: Publish SonarCloud Results
|
||||
- task: reportgenerator@4
|
||||
- task: reportgenerator@5
|
||||
displayName: Generate Coverage Report
|
||||
inputs:
|
||||
reports: '$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml'
|
||||
targetdir: '$(Build.SourcesDirectory)/CoverageResults/combined'
|
||||
reporttypes: 'HtmlInline_AzurePipelines;Cobertura;Badges'
|
||||
- task: PublishCodeCoverageResults@1
|
||||
displayName: Publish Coverage Report
|
||||
inputs:
|
||||
codeCoverageTool: 'cobertura'
|
||||
summaryFileLocation: './CoverageResults/combined/Cobertura.xml'
|
||||
reportDirectory: './CoverageResults/combined/'
|
||||
publishCodeCoverageResults: true
|
||||
|
||||
- stage: Report_Out
|
||||
dependsOn:
|
||||
|
||||
@@ -271,26 +271,29 @@ class EnhancedSelectInput extends Component {
|
||||
this.setState({ isOpen: !this.state.isOpen });
|
||||
};
|
||||
|
||||
onSelect = (value) => {
|
||||
if (Array.isArray(this.props.value)) {
|
||||
let newValue = null;
|
||||
const index = this.props.value.indexOf(value);
|
||||
onSelect = (newValue) => {
|
||||
const { name, value, values, onChange } = this.props;
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
let arrayValue = null;
|
||||
const index = value.indexOf(newValue);
|
||||
|
||||
if (index === -1) {
|
||||
newValue = this.props.values.map((v) => v.key).filter((v) => (v === value) || this.props.value.includes(v));
|
||||
arrayValue = values.map((v) => v.key).filter((v) => (v === newValue) || value.includes(v));
|
||||
} else {
|
||||
newValue = [...this.props.value];
|
||||
newValue.splice(index, 1);
|
||||
arrayValue = [...value];
|
||||
arrayValue.splice(index, 1);
|
||||
}
|
||||
this.props.onChange({
|
||||
name: this.props.name,
|
||||
value: newValue
|
||||
onChange({
|
||||
name,
|
||||
value: arrayValue
|
||||
});
|
||||
} else {
|
||||
this.setState({ isOpen: false });
|
||||
|
||||
this.props.onChange({
|
||||
name: this.props.name,
|
||||
value
|
||||
onChange({
|
||||
name,
|
||||
value: newValue
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -485,7 +488,7 @@ class EnhancedSelectInput extends Component {
|
||||
values.map((v, index) => {
|
||||
const hasParent = v.parentKey !== undefined;
|
||||
const depth = hasParent ? 1 : 0;
|
||||
const parentSelected = hasParent && value.includes(v.parentKey);
|
||||
const parentSelected = hasParent && Array.isArray(value) && value.includes(v.parentKey);
|
||||
return (
|
||||
<OptionComponent
|
||||
key={v.key}
|
||||
|
||||
@@ -34,7 +34,8 @@ function getSelectOptions(items) {
|
||||
key: option.value,
|
||||
value: option.name,
|
||||
hint: option.hint,
|
||||
parentKey: option.parentValue
|
||||
parentKey: option.parentValue,
|
||||
isDisabled: option.isDisabled
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,16 +4,16 @@ import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import TableRowButton from 'Components/Table/TableRowButton';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import CapabilitiesLabel from 'Indexer/Index/Table/CapabilitiesLabel';
|
||||
import PrivacyLabel from 'Indexer/Index/Table/PrivacyLabel';
|
||||
import ProtocolLabel from 'Indexer/Index/Table/ProtocolLabel';
|
||||
import { IndexerCapabilities } from 'Indexer/Indexer';
|
||||
import firstCharToUpper from 'Utilities/String/firstCharToUpper';
|
||||
import { IndexerCapabilities, IndexerPrivacy } from 'Indexer/Indexer';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './SelectIndexerRow.css';
|
||||
|
||||
interface SelectIndexerRowProps {
|
||||
name: string;
|
||||
protocol: string;
|
||||
privacy: string;
|
||||
privacy: IndexerPrivacy;
|
||||
language: string;
|
||||
description: string;
|
||||
capabilities: IndexerCapabilities;
|
||||
@@ -63,7 +63,9 @@ function SelectIndexerRow(props: SelectIndexerRowProps) {
|
||||
|
||||
<TableRowCell>{description}</TableRowCell>
|
||||
|
||||
<TableRowCell>{translate(firstCharToUpper(privacy))}</TableRowCell>
|
||||
<TableRowCell>
|
||||
<PrivacyLabel privacy={privacy} />
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell>
|
||||
<CapabilitiesLabel capabilities={capabilities} />
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { SelectProvider } from 'App/SelectContext';
|
||||
import ClientSideCollectionAppState from 'App/State/ClientSideCollectionAppState';
|
||||
@@ -22,12 +28,17 @@ import AddIndexerModal from 'Indexer/Add/AddIndexerModal';
|
||||
import EditIndexerModalConnector from 'Indexer/Edit/EditIndexerModalConnector';
|
||||
import NoIndexer from 'Indexer/NoIndexer';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import { cloneIndexer, testAllIndexers } from 'Store/Actions/indexerActions';
|
||||
import {
|
||||
cloneIndexer,
|
||||
fetchIndexers,
|
||||
testAllIndexers,
|
||||
} from 'Store/Actions/indexerActions';
|
||||
import {
|
||||
setIndexerFilter,
|
||||
setIndexerSort,
|
||||
setIndexerTableOption,
|
||||
} from 'Store/Actions/indexerIndexActions';
|
||||
import { fetchIndexerStatus } from 'Store/Actions/indexerStatusActions';
|
||||
import scrollPositions from 'Store/scrollPositions';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
@@ -82,6 +93,11 @@ const IndexerIndex = withScrollPosition((props: IndexerIndexProps) => {
|
||||
);
|
||||
const [isSelectMode, setIsSelectMode] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchIndexers());
|
||||
dispatch(fetchIndexerStatus());
|
||||
}, [dispatch]);
|
||||
|
||||
const onAddIndexerPress = useCallback(() => {
|
||||
setIsAddIndexerModalOpen(true);
|
||||
}, [setIsAddIndexerModalOpen]);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useSelect } from 'App/SelectContext';
|
||||
import Label from 'Components/Label';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import RelativeDateCell from 'Components/Table/Cells/RelativeDateCell';
|
||||
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
|
||||
@@ -15,10 +14,10 @@ import createIndexerIndexItemSelector from 'Indexer/Index/createIndexerIndexItem
|
||||
import Indexer from 'Indexer/Indexer';
|
||||
import IndexerTitleLink from 'Indexer/IndexerTitleLink';
|
||||
import { SelectStateInputProps } from 'typings/props';
|
||||
import firstCharToUpper from 'Utilities/String/firstCharToUpper';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import CapabilitiesLabel from './CapabilitiesLabel';
|
||||
import IndexerStatusCell from './IndexerStatusCell';
|
||||
import PrivacyLabel from './PrivacyLabel';
|
||||
import ProtocolLabel from './ProtocolLabel';
|
||||
import styles from './IndexerIndexRow.css';
|
||||
|
||||
@@ -175,7 +174,7 @@ function IndexerIndexRow(props: IndexerIndexRowProps) {
|
||||
if (name === 'privacy') {
|
||||
return (
|
||||
<VirtualTableRowCell key={name} className={styles[name]}>
|
||||
<Label>{translate(firstCharToUpper(privacy))}</Label>
|
||||
<PrivacyLabel privacy={privacy} />
|
||||
</VirtualTableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
20
frontend/src/Indexer/Index/Table/PrivacyLabel.css
Normal file
20
frontend/src/Indexer/Index/Table/PrivacyLabel.css
Normal file
@@ -0,0 +1,20 @@
|
||||
.publicLabel {
|
||||
composes: label from '~Components/Label.css';
|
||||
|
||||
border-color: var(--dangerColor);
|
||||
background-color: var(--dangerColor);
|
||||
}
|
||||
|
||||
.semiPrivateLabel {
|
||||
composes: label from '~Components/Label.css';
|
||||
|
||||
border-color: var(--warningColor);
|
||||
background-color: var(--warningColor);
|
||||
}
|
||||
|
||||
.privateLabel {
|
||||
composes: label from '~Components/Label.css';
|
||||
|
||||
border-color: var(--infoColor);
|
||||
background-color: var(--infoColor);
|
||||
}
|
||||
9
frontend/src/Indexer/Index/Table/PrivacyLabel.css.d.ts
vendored
Normal file
9
frontend/src/Indexer/Index/Table/PrivacyLabel.css.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'privateLabel': string;
|
||||
'publicLabel': string;
|
||||
'semiPrivateLabel': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
20
frontend/src/Indexer/Index/Table/PrivacyLabel.tsx
Normal file
20
frontend/src/Indexer/Index/Table/PrivacyLabel.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import Label from 'Components/Label';
|
||||
import { IndexerPrivacy } from 'Indexer/Indexer';
|
||||
import firstCharToUpper from 'Utilities/String/firstCharToUpper';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './PrivacyLabel.css';
|
||||
|
||||
interface PrivacyLabelProps {
|
||||
privacy: IndexerPrivacy;
|
||||
}
|
||||
|
||||
function PrivacyLabel({ privacy }: PrivacyLabelProps) {
|
||||
return (
|
||||
<Label className={styles[`${privacy}Label`]}>
|
||||
{translate(firstCharToUpper(privacy))}
|
||||
</Label>
|
||||
);
|
||||
}
|
||||
|
||||
export default PrivacyLabel;
|
||||
@@ -24,6 +24,8 @@ export interface IndexerCapabilities extends ModelBase {
|
||||
categories: IndexerCategory[];
|
||||
}
|
||||
|
||||
export type IndexerPrivacy = 'public' | 'semiPrivate' | 'private';
|
||||
|
||||
export interface IndexerField extends ModelBase {
|
||||
order: number;
|
||||
name: string;
|
||||
@@ -47,7 +49,7 @@ interface Indexer extends ModelBase {
|
||||
supportsRedirect: boolean;
|
||||
supportsPagination: boolean;
|
||||
protocol: string;
|
||||
privacy: string;
|
||||
privacy: IndexerPrivacy;
|
||||
priority: number;
|
||||
fields: IndexerField[];
|
||||
tags: number[];
|
||||
|
||||
@@ -24,6 +24,7 @@ import TagListConnector from 'Components/TagListConnector';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import DeleteIndexerModal from 'Indexer/Delete/DeleteIndexerModal';
|
||||
import EditIndexerModalConnector from 'Indexer/Edit/EditIndexerModalConnector';
|
||||
import PrivacyLabel from 'Indexer/Index/Table/PrivacyLabel';
|
||||
import Indexer, { IndexerCapabilities } from 'Indexer/Indexer';
|
||||
import { createIndexerSelectorForHook } from 'Store/Selectors/createIndexerSelector';
|
||||
import translate from 'Utilities/String/translate';
|
||||
@@ -64,6 +65,7 @@ function IndexerInfoModalContent(props: IndexerInfoModalContentProps) {
|
||||
fields,
|
||||
tags,
|
||||
protocol,
|
||||
privacy,
|
||||
capabilities = {} as IndexerCapabilities,
|
||||
} = indexer as Indexer;
|
||||
|
||||
@@ -160,6 +162,11 @@ function IndexerInfoModalContent(props: IndexerInfoModalContentProps) {
|
||||
title={translate('Language')}
|
||||
data={language ?? '-'}
|
||||
/>
|
||||
<DescriptionListItem
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('Privacy')}
|
||||
data={privacy ? <PrivacyLabel privacy={privacy} /> : '-'}
|
||||
/>
|
||||
{vipExpiration ? (
|
||||
<DescriptionListItem
|
||||
descriptionClassName={styles.description}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace NzbDrone.Core.Applications.Sonarr
|
||||
public IEnumerable<int> AnimeSyncCategories { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Sync Anime Standard Format Search", Type = FieldType.Checkbox, HelpText = "Sync also searching for anime using the standard numbering", Advanced = true)]
|
||||
public bool SyncAnimeStandardFormatSearch { get; set; }
|
||||
public bool SyncAnimeStandardFormatSearch { get; set; } = true;
|
||||
|
||||
[FieldDefinition(6, Type = FieldType.Checkbox, Label = "ApplicationSettingsSyncRejectBlocklistedTorrentHashes", HelpText = "ApplicationSettingsSyncRejectBlocklistedTorrentHashesHelpText", Advanced = true)]
|
||||
public bool SyncRejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
using NzbDrone.Core.Instrumentation;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Instrumentation;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
{
|
||||
public class TrimLogDatabase : IHousekeepingTask
|
||||
{
|
||||
private readonly ILogRepository _logRepo;
|
||||
private readonly IConfigFileProvider _configFileProvider;
|
||||
|
||||
public TrimLogDatabase(ILogRepository logRepo)
|
||||
public TrimLogDatabase(ILogRepository logRepo, IConfigFileProvider configFileProvider)
|
||||
{
|
||||
_logRepo = logRepo;
|
||||
_configFileProvider = configFileProvider;
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
if (!_configFileProvider.LogDbEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_logRepo.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,7 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
||||
!IsIdSearch;
|
||||
|
||||
public override bool IsIdSearch =>
|
||||
Episode.IsNotNullOrWhiteSpace() ||
|
||||
ImdbId.IsNotNullOrWhiteSpace() ||
|
||||
Season.HasValue ||
|
||||
TvdbId.HasValue ||
|
||||
RId.HasValue ||
|
||||
TraktId.HasValue ||
|
||||
@@ -116,7 +114,7 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
||||
string episodeString;
|
||||
if (DateTime.TryParseExact($"{Season} {Episode}", "yyyy MM/dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var showDate))
|
||||
{
|
||||
episodeString = showDate.ToString("yyyy.MM.dd");
|
||||
episodeString = showDate.ToString("yyyy.MM.dd", CultureInfo.InvariantCulture);
|
||||
}
|
||||
else if (Episode.IsNullOrWhiteSpace())
|
||||
{
|
||||
|
||||
@@ -26,11 +26,15 @@ namespace NzbDrone.Core.IndexerStats
|
||||
{
|
||||
var history = _historyService.Between(start, end);
|
||||
|
||||
var filteredHistory = history.Where(h => indexerIds.Contains(h.IndexerId));
|
||||
var filteredHistory = history.Where(h => indexerIds.Contains(h.IndexerId)).ToArray();
|
||||
|
||||
var groupedByIndexer = filteredHistory.GroupBy(h => h.IndexerId);
|
||||
var groupedByUserAgent = filteredHistory.GroupBy(h => h.Data.GetValueOrDefault("source") ?? "");
|
||||
var groupedByHost = filteredHistory.GroupBy(h => h.Data.GetValueOrDefault("host") ?? "");
|
||||
var groupedByIndexer = filteredHistory.GroupBy(h => h.IndexerId).ToArray();
|
||||
var groupedByUserAgent = filteredHistory
|
||||
.Where(h => h.EventType != HistoryEventType.IndexerAuth)
|
||||
.GroupBy(h => h.Data.GetValueOrDefault("source") ?? "").ToArray();
|
||||
var groupedByHost = filteredHistory
|
||||
.Where(h => h.EventType != HistoryEventType.IndexerAuth)
|
||||
.GroupBy(h => h.Data.GetValueOrDefault("host") ?? "").ToArray();
|
||||
|
||||
var indexerStatsList = new List<IndexerStatistics>();
|
||||
var userAgentStatsList = new List<UserAgentStatistics>();
|
||||
@@ -60,7 +64,7 @@ namespace NzbDrone.Core.IndexerStats
|
||||
var temp = 0;
|
||||
var elapsedTimeEvents = sortedEvents
|
||||
.Where(h => int.TryParse(h.Data.GetValueOrDefault("elapsedTime"), out temp) && h.Data.GetValueOrDefault("cached") != "1")
|
||||
.Select(h => temp)
|
||||
.Select(_ => temp)
|
||||
.ToArray();
|
||||
|
||||
indexerStats.AverageResponseTime = elapsedTimeEvents.Any() ? (int)elapsedTimeEvents.Average() : 0;
|
||||
@@ -68,6 +72,7 @@ namespace NzbDrone.Core.IndexerStats
|
||||
foreach (var historyEvent in sortedEvents)
|
||||
{
|
||||
var failed = !historyEvent.Successful;
|
||||
|
||||
switch (historyEvent.EventType)
|
||||
{
|
||||
case HistoryEventType.IndexerQuery:
|
||||
@@ -101,8 +106,6 @@ namespace NzbDrone.Core.IndexerStats
|
||||
indexerStats.NumberOfFailedRssQueries++;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -118,8 +121,8 @@ namespace NzbDrone.Core.IndexerStats
|
||||
};
|
||||
|
||||
var sortedEvents = indexer.OrderBy(v => v.Date)
|
||||
.ThenBy(v => v.Id)
|
||||
.ToArray();
|
||||
.ThenBy(v => v.Id)
|
||||
.ToArray();
|
||||
|
||||
foreach (var historyEvent in sortedEvents)
|
||||
{
|
||||
@@ -128,13 +131,10 @@ namespace NzbDrone.Core.IndexerStats
|
||||
case HistoryEventType.IndexerRss:
|
||||
case HistoryEventType.IndexerQuery:
|
||||
indexerStats.NumberOfQueries++;
|
||||
|
||||
break;
|
||||
case HistoryEventType.ReleaseGrabbed:
|
||||
indexerStats.NumberOfGrabs++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,8 +149,8 @@ namespace NzbDrone.Core.IndexerStats
|
||||
};
|
||||
|
||||
var sortedEvents = indexer.OrderBy(v => v.Date)
|
||||
.ThenBy(v => v.Id)
|
||||
.ToArray();
|
||||
.ThenBy(v => v.Id)
|
||||
.ToArray();
|
||||
|
||||
foreach (var historyEvent in sortedEvents)
|
||||
{
|
||||
@@ -163,8 +163,6 @@ namespace NzbDrone.Core.IndexerStats
|
||||
case HistoryEventType.ReleaseGrabbed:
|
||||
indexerStats.NumberOfGrabs++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace NzbDrone.Core.IndexerVersions
|
||||
/* Update Service will fall back if version # does not exist for an indexer per Ta */
|
||||
|
||||
private const string DEFINITION_BRANCH = "master";
|
||||
private const int DEFINITION_VERSION = 10;
|
||||
private const int DEFINITION_VERSION = 11;
|
||||
|
||||
// Used when moving yml to C#
|
||||
private readonly List<string> _definitionBlocklist = new ()
|
||||
|
||||
@@ -644,16 +644,16 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
|
||||
private static int? ParseSeasonFromTitles(IReadOnlyCollection<string> titles)
|
||||
{
|
||||
var advancedSeasonRegex = new Regex(@"(\d+)(st|nd|rd|th) Season", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
var advancedSeasonRegex = new Regex(@"\b(?:(?<season>\d+)(?:st|nd|rd|th) Season|Season (?<season>\d+))\b", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
var seasonCharactersRegex = new Regex(@"(I{2,})$", RegexOptions.Compiled);
|
||||
var seasonNumberRegex = new Regex(@"\b(?:S)?([2-9])$", RegexOptions.Compiled);
|
||||
var seasonNumberRegex = new Regex(@"\b(?<!Part[- ._])(?:S)?(?<season>[2-9])$", RegexOptions.Compiled);
|
||||
|
||||
foreach (var title in titles)
|
||||
{
|
||||
var advancedSeasonRegexMatch = advancedSeasonRegex.Match(title);
|
||||
if (advancedSeasonRegexMatch.Success)
|
||||
{
|
||||
return ParseUtil.CoerceInt(advancedSeasonRegexMatch.Groups[1].Value);
|
||||
return ParseUtil.CoerceInt(advancedSeasonRegexMatch.Groups["season"].Value);
|
||||
}
|
||||
|
||||
var seasonCharactersRegexMatch = seasonCharactersRegex.Match(title);
|
||||
@@ -665,7 +665,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
var seasonNumberRegexMatch = seasonNumberRegex.Match(title);
|
||||
if (seasonNumberRegexMatch.Success)
|
||||
{
|
||||
return ParseUtil.CoerceInt(seasonNumberRegexMatch.Groups[1].Value);
|
||||
return ParseUtil.CoerceInt(seasonNumberRegexMatch.Groups["season"].Value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
else if (DateTime.TryParseExact($"{searchCriteria.Season} {searchCriteria.Episode}", "yyyy MM/dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var showDate))
|
||||
{
|
||||
// Daily Episode
|
||||
parameters.Name = showDate.ToString("yyyy.MM.dd");
|
||||
parameters.Name = showDate.ToString("yyyy.MM.dd", CultureInfo.InvariantCulture);
|
||||
parameters.Category = "Episode";
|
||||
pageableRequests.Add(GetPagedRequests(parameters, btnResults, btnOffset));
|
||||
}
|
||||
|
||||
@@ -139,20 +139,13 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
|
||||
{
|
||||
var selectorSelector = ApplyGoTemplateText(selector.Selector, variables);
|
||||
|
||||
if (dom.Matches(selectorSelector))
|
||||
{
|
||||
selection = dom;
|
||||
}
|
||||
else
|
||||
{
|
||||
selection = QuerySelector(dom, selectorSelector);
|
||||
}
|
||||
selection = dom.Matches(selectorSelector) ? dom : QuerySelector(dom, selectorSelector);
|
||||
|
||||
if (selection == null)
|
||||
{
|
||||
if (required)
|
||||
{
|
||||
throw new Exception(string.Format("Selector \"{0}\" didn't match {1}", selectorSelector, dom.ToHtmlPretty()));
|
||||
throw new Exception($"Selector \"{selectorSelector}\" didn't match {dom.ToHtmlPretty()}");
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -195,7 +188,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
|
||||
{
|
||||
if (required)
|
||||
{
|
||||
throw new Exception(string.Format("Attribute \"{0}\" is not set for element {1}", selector.Attribute, selection.ToHtmlPretty()));
|
||||
throw new Exception($"Attribute \"{selector.Attribute}\" is not set for element {selection.ToHtmlPretty()}");
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -340,6 +333,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
|
||||
case "info_cookie":
|
||||
case "info_flaresolverr":
|
||||
case "info_useragent":
|
||||
case "info_category_8000":
|
||||
case "cardigannCaptcha":
|
||||
// no-op
|
||||
break;
|
||||
|
||||
@@ -332,37 +332,47 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
|
||||
}
|
||||
|
||||
// selector inputs
|
||||
if (login.Selectorinputs != null)
|
||||
if (login.Selectorinputs != null && login.Selectorinputs.Any())
|
||||
{
|
||||
foreach (var selectorinput in login.Selectorinputs)
|
||||
foreach (var selectorInput in login.Selectorinputs)
|
||||
{
|
||||
string value = null;
|
||||
try
|
||||
{
|
||||
value = HandleSelector(selectorinput.Value, landingResultDocument.FirstElementChild);
|
||||
pairs[selectorinput.Key] = value;
|
||||
var value = HandleSelector(selectorInput.Value, landingResultDocument.FirstElementChild, required: !selectorInput.Value.Optional);
|
||||
|
||||
if (selectorInput.Value.Optional && value == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pairs[selectorInput.Key] = value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new CardigannException(string.Format("Error while parsing selector input={0}, selector={1}, value={2}: {3}", selectorinput.Key, selectorinput.Value.Selector, value, ex.Message));
|
||||
throw new CardigannException($"Error while parsing selector input={selectorInput.Key}, selector={selectorInput.Value.Selector}: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// getselector inputs
|
||||
if (login.Getselectorinputs != null)
|
||||
if (login.Getselectorinputs != null && login.Getselectorinputs.Any())
|
||||
{
|
||||
foreach (var selectorinput in login.Getselectorinputs)
|
||||
foreach (var selectorInput in login.Getselectorinputs)
|
||||
{
|
||||
string value = null;
|
||||
try
|
||||
{
|
||||
value = HandleSelector(selectorinput.Value, landingResultDocument.FirstElementChild);
|
||||
queryCollection[selectorinput.Key] = value;
|
||||
var value = HandleSelector(selectorInput.Value, landingResultDocument.FirstElementChild, required: !selectorInput.Value.Optional);
|
||||
|
||||
if (selectorInput.Value.Optional && value == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
queryCollection[selectorInput.Key] = value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new CardigannException(string.Format("Error while parsing get selector input={0}, selector={1}, value={2}: {3}", selectorinput.Key, selectorinput.Value.Selector, value, ex.Message));
|
||||
throw new CardigannException($"Error while parsing get selector input={selectorInput.Key}, selector={selectorInput.Value.Selector}: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace NzbDrone.Core.Indexers.Definitions.HDBits
|
||||
|
||||
if (DateTime.TryParseExact($"{searchCriteria.Season} {searchCriteria.Episode}", "yyyy MM/dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var showDate))
|
||||
{
|
||||
query.Search = showDate.ToString("yyyy-MM-dd");
|
||||
query.Search = showDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -70,16 +70,17 @@ namespace NzbDrone.Core.Indexers.Headphones
|
||||
protected override bool PostProcess(IndexerResponse indexerResponse, List<XElement> items, List<ReleaseInfo> releases)
|
||||
{
|
||||
var enclosureTypes = items.SelectMany(GetEnclosures).Select(v => v.Type).Distinct().ToArray();
|
||||
|
||||
if (enclosureTypes.Any() && enclosureTypes.Intersect(PreferredEnclosureMimeTypes).Empty())
|
||||
{
|
||||
if (enclosureTypes.Intersect(TorrentEnclosureMimeTypes).Any())
|
||||
{
|
||||
_logger.Warn("Feed does not contain {0}, found {1}, did you intend to add a Torznab indexer?", NzbEnclosureMimeType, enclosureTypes[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("Feed does not contain {0}, found {1}.", NzbEnclosureMimeType, enclosureTypes[0]);
|
||||
_logger.Warn("{0} does not contain {1}, found {2}, did you intend to add a Torznab indexer?", indexerResponse.Request.Url, NzbEnclosureMimeType, enclosureTypes[0]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_logger.Warn("{0} does not contain {1}, found {2}.", indexerResponse.Request.Url, NzbEnclosureMimeType, enclosureTypes[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
@@ -42,7 +41,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
|
||||
public override IIndexerRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new NebulanceRequestGenerator(Settings);
|
||||
return new NebulanceRequestGenerator(Settings, _logger);
|
||||
}
|
||||
|
||||
public override IParseIndexerResponse GetParser()
|
||||
@@ -68,26 +67,6 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
return Task.FromResult(request);
|
||||
}
|
||||
|
||||
protected override IList<ReleaseInfo> CleanupReleases(IEnumerable<ReleaseInfo> releases, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var cleanReleases = base.CleanupReleases(releases, searchCriteria);
|
||||
|
||||
return FilterReleasesByQuery(cleanReleases, searchCriteria).ToList();
|
||||
}
|
||||
|
||||
protected override IEnumerable<ReleaseInfo> FilterReleasesByQuery(IEnumerable<ReleaseInfo> releases, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (!searchCriteria.IsRssSearch &&
|
||||
searchCriteria.IsIdSearch &&
|
||||
searchCriteria is TvSearchCriteria tvSearchCriteria &&
|
||||
tvSearchCriteria.EpisodeSearchString.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
releases = releases.Where(r => r.Title.IsNotNullOrWhiteSpace() && r.Title.ContainsIgnoreCase(tvSearchCriteria.EpisodeSearchString)).ToList();
|
||||
}
|
||||
|
||||
return releases;
|
||||
}
|
||||
|
||||
private IndexerCapabilities SetCapabilities()
|
||||
{
|
||||
var caps = new IndexerCapabilities
|
||||
@@ -111,10 +90,12 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
public class NebulanceRequestGenerator : IIndexerRequestGenerator
|
||||
{
|
||||
private readonly NebulanceSettings _settings;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public NebulanceRequestGenerator(NebulanceSettings settings)
|
||||
public NebulanceRequestGenerator(NebulanceSettings settings, Logger logger)
|
||||
{
|
||||
_settings = settings;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||
@@ -136,40 +117,53 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
Age = ">0"
|
||||
};
|
||||
|
||||
if (searchCriteria.SanitizedTvSearchString.IsNotNullOrWhiteSpace())
|
||||
if (searchCriteria.TvMazeId is > 0)
|
||||
{
|
||||
queryParams.Name = "%" + Regex.Replace(searchCriteria.SanitizedTvSearchString, "[\\W]+", "%").Trim() + "%";
|
||||
queryParams.TvMaze = searchCriteria.TvMazeId.Value;
|
||||
}
|
||||
else if (searchCriteria.ImdbId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
queryParams.Imdb = searchCriteria.FullImdbId;
|
||||
}
|
||||
|
||||
if (searchCriteria.TvMazeId.HasValue)
|
||||
{
|
||||
queryParams.Tvmaze = searchCriteria.TvMazeId.Value;
|
||||
var searchQuery = searchCriteria.SanitizedSearchTerm.Trim();
|
||||
|
||||
if (searchCriteria.EpisodeSearchString.IsNotNullOrWhiteSpace())
|
||||
if (searchQuery.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
queryParams.Release = searchQuery;
|
||||
}
|
||||
|
||||
if (DateTime.TryParseExact($"{searchCriteria.Season} {searchCriteria.Episode}", "yyyy MM/dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var showDate))
|
||||
{
|
||||
queryParams.Name = searchQuery;
|
||||
queryParams.Release = showDate.ToString("yyyy.MM.dd", CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (searchCriteria.Season.HasValue)
|
||||
{
|
||||
queryParams.Name = "%" + Regex.Replace(searchCriteria.EpisodeSearchString, "[\\W]+", "%").Trim() + "%";
|
||||
queryParams.Season = searchCriteria.Season.Value;
|
||||
}
|
||||
|
||||
if (searchCriteria.Episode.IsNotNullOrWhiteSpace() && int.TryParse(searchCriteria.Episode, out var episodeNumber))
|
||||
{
|
||||
queryParams.Episode = episodeNumber;
|
||||
}
|
||||
}
|
||||
else if (searchCriteria.ImdbId.IsNotNullOrWhiteSpace() && int.TryParse(searchCriteria.ImdbId, out var intImdb))
|
||||
{
|
||||
queryParams.Imdb = intImdb;
|
||||
|
||||
if (searchCriteria.EpisodeSearchString.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
queryParams.Name = "%" + Regex.Replace(searchCriteria.EpisodeSearchString, "[\\W]+", "%").Trim() + "%";
|
||||
}
|
||||
if ((queryParams.Season.HasValue || queryParams.Episode.HasValue) &&
|
||||
queryParams.Name.IsNullOrWhiteSpace() &&
|
||||
queryParams.Release.IsNullOrWhiteSpace() &&
|
||||
!queryParams.TvMaze.HasValue &&
|
||||
queryParams.Imdb.IsNullOrWhiteSpace())
|
||||
{
|
||||
_logger.Debug("NBL API does not support season calls without name, series, id, imdb, tvmaze, or time keys.");
|
||||
|
||||
return new IndexerPageableRequestChain();
|
||||
}
|
||||
|
||||
pageableRequests.Add(GetPagedRequests(queryParams, searchCriteria.Limit, searchCriteria.Offset));
|
||||
|
||||
if (queryParams.Name.IsNotNullOrWhiteSpace() && (queryParams.Tvmaze is > 0 || queryParams.Imdb is > 0))
|
||||
{
|
||||
queryParams = queryParams.Clone();
|
||||
queryParams.Name = null;
|
||||
|
||||
pageableRequests.Add(GetPagedRequests(queryParams, searchCriteria.Limit, searchCriteria.Offset));
|
||||
}
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
@@ -187,9 +181,11 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
Age = ">0"
|
||||
};
|
||||
|
||||
if (searchCriteria.SanitizedSearchTerm.IsNotNullOrWhiteSpace())
|
||||
var searchQuery = searchCriteria.SanitizedSearchTerm.Trim();
|
||||
|
||||
if (searchQuery.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
queryParams.Name = "%" + Regex.Replace(searchCriteria.SanitizedSearchTerm, "[\\W]+", "%").Trim() + "%";
|
||||
queryParams.Release = searchQuery;
|
||||
}
|
||||
|
||||
pageableRequests.Add(GetPagedRequests(queryParams, searchCriteria.Limit, searchCriteria.Offset));
|
||||
@@ -231,11 +227,11 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
throw new IndexerException(indexerResponse, "Unexpected response status '{0}' code from indexer request", indexerResponse.HttpResponse.StatusCode);
|
||||
}
|
||||
|
||||
JsonRpcResponse<NebulanceTorrents> jsonResponse;
|
||||
JsonRpcResponse<NebulanceResponse> jsonResponse;
|
||||
|
||||
try
|
||||
{
|
||||
jsonResponse = STJson.Deserialize<JsonRpcResponse<NebulanceTorrents>>(indexerResponse.HttpResponse.Content);
|
||||
jsonResponse = STJson.Deserialize<JsonRpcResponse<NebulanceResponse>>(indexerResponse.HttpResponse.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -249,7 +245,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
throw new IndexerException(indexerResponse, "Indexer API call returned an error [{0}]", jsonResponse.Error);
|
||||
}
|
||||
|
||||
if (jsonResponse.Result.Items.Count == 0)
|
||||
if (jsonResponse.Result?.Items == null || jsonResponse.Result.Items.Count == 0)
|
||||
{
|
||||
return torrentInfos;
|
||||
}
|
||||
@@ -264,14 +260,13 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
|
||||
var release = new TorrentInfo
|
||||
{
|
||||
Title = title,
|
||||
Guid = details,
|
||||
InfoUrl = details,
|
||||
PosterUrl = row.Banner,
|
||||
DownloadUrl = row.Download,
|
||||
Title = title.Trim(),
|
||||
Categories = new List<IndexerCategory> { TvCategoryFromQualityParser.ParseTvShowQuality(row.ReleaseTitle) },
|
||||
Size = ParseUtil.CoerceLong(row.Size),
|
||||
Files = row.FileList.Length,
|
||||
Files = row.FileList.Count(),
|
||||
PublishDate = DateTime.Parse(row.PublishDateUtc, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal),
|
||||
Grabs = ParseUtil.CoerceInt(row.Snatch),
|
||||
Seeders = ParseUtil.CoerceInt(row.Seed),
|
||||
@@ -280,7 +275,8 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
MinimumRatio = 0, // ratioless
|
||||
MinimumSeedTime = row.Category.ToLower() == "season" ? 432000 : 86400, // 120 hours for seasons and 24 hours for episodes
|
||||
DownloadVolumeFactor = 0, // ratioless tracker
|
||||
UploadVolumeFactor = 1
|
||||
UploadVolumeFactor = 1,
|
||||
PosterUrl = row.Banner
|
||||
};
|
||||
|
||||
if (row.TvMazeId.IsNotNullOrWhiteSpace())
|
||||
@@ -312,60 +308,86 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
{
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Time { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName="age", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Age { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName="tvmaze", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public int? Tvmaze { get; set; }
|
||||
public int? TvMaze { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName="imdb", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public int? Imdb { get; set; }
|
||||
public string Imdb { get; set; }
|
||||
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Hash { get; set; }
|
||||
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string[] Tags { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName="name", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName="release", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Release { get; set; }
|
||||
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Category { get; set; }
|
||||
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Series { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName="season", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public int? Season { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName="episode", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public int? Episode { get; set; }
|
||||
|
||||
public NebulanceQuery Clone()
|
||||
{
|
||||
return MemberwiseClone() as NebulanceQuery;
|
||||
}
|
||||
}
|
||||
|
||||
public class NebulanceResponse
|
||||
{
|
||||
public List<NebulanceTorrent> Items { get; set; }
|
||||
}
|
||||
|
||||
public class NebulanceTorrent
|
||||
{
|
||||
[JsonPropertyName("rls_name")]
|
||||
public string ReleaseTitle { get; set; }
|
||||
|
||||
[JsonPropertyName("cat")]
|
||||
public string Category { get; set; }
|
||||
|
||||
public string Size { get; set; }
|
||||
public string Seed { get; set; }
|
||||
public string Leech { get; set; }
|
||||
public string Snatch { get; set; }
|
||||
public string Download { get; set; }
|
||||
|
||||
[JsonPropertyName("file_list")]
|
||||
public string[] FileList { get; set; }
|
||||
public IEnumerable<string> FileList { get; set; } = Array.Empty<string>();
|
||||
|
||||
[JsonPropertyName("group_name")]
|
||||
public string GroupName { get; set; }
|
||||
|
||||
[JsonPropertyName("series_banner")]
|
||||
public string Banner { get; set; }
|
||||
|
||||
[JsonPropertyName("group_id")]
|
||||
public string TorrentId { get; set; }
|
||||
|
||||
[JsonPropertyName("series_id")]
|
||||
public string TvMazeId { get; set; }
|
||||
|
||||
[JsonPropertyName("rls_utc")]
|
||||
public string PublishDateUtc { get; set; }
|
||||
public IEnumerable<string> Tags { get; set; }
|
||||
}
|
||||
|
||||
public class NebulanceTorrents
|
||||
{
|
||||
public List<NebulanceTorrent> Items { get; set; }
|
||||
public int Results { get; set; }
|
||||
public IEnumerable<string> Tags { get; set; } = Array.Empty<string>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,16 +74,17 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
protected override bool PostProcess(IndexerResponse indexerResponse, List<XElement> items, List<ReleaseInfo> releases)
|
||||
{
|
||||
var enclosureTypes = items.SelectMany(GetEnclosures).Select(v => v.Type).Distinct().ToArray();
|
||||
|
||||
if (enclosureTypes.Any() && enclosureTypes.Intersect(PreferredEnclosureMimeTypes).Empty())
|
||||
{
|
||||
if (enclosureTypes.Intersect(TorrentEnclosureMimeTypes).Any())
|
||||
{
|
||||
_logger.Warn("Feed does not contain {0}, found {1}, did you intend to add a Torznab indexer?", NzbEnclosureMimeType, enclosureTypes[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("Feed does not contain {0}, found {1}.", NzbEnclosureMimeType, enclosureTypes[0]);
|
||||
_logger.Warn("{0} does not contain {1}, found {2}, did you intend to add a Torznab indexer?", indexerResponse.Request.Url, NzbEnclosureMimeType, enclosureTypes[0]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_logger.Warn("{0} does not contain {1}, found {2}.", indexerResponse.Request.Url, NzbEnclosureMimeType, enclosureTypes[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -75,6 +75,8 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
|
||||
public class SubsPleaseRequestGenerator : IIndexerRequestGenerator
|
||||
{
|
||||
private static readonly Regex ResolutionRegex = new (@"\d{3,4}p", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
private readonly NoAuthTorrentBaseSettings _settings;
|
||||
|
||||
public SubsPleaseRequestGenerator(NoAuthTorrentBaseSettings settings)
|
||||
@@ -134,15 +136,6 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
|
||||
private IEnumerable<IndexerRequest> GetSearchRequests(string term, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var searchTerm = Regex.Replace(term, "\\[?SubsPlease\\]?\\s*", string.Empty, RegexOptions.IgnoreCase).Trim();
|
||||
|
||||
// If the search terms contain a resolution, remove it from the query sent to the API
|
||||
var resMatch = Regex.Match(searchTerm, "\\d{3,4}[p|P]");
|
||||
if (resMatch.Success)
|
||||
{
|
||||
searchTerm = searchTerm.Replace(resMatch.Value, string.Empty).Trim();
|
||||
}
|
||||
|
||||
var queryParameters = new NameValueCollection
|
||||
{
|
||||
{ "tz", "UTC" }
|
||||
@@ -154,6 +147,16 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
}
|
||||
else
|
||||
{
|
||||
var searchTerm = Regex.Replace(term, "\\[?SubsPlease\\]?\\s*", string.Empty, RegexOptions.IgnoreCase).Trim();
|
||||
|
||||
// If the search terms contain a resolution, remove it from the query sent to the API
|
||||
var resolutionMatch = ResolutionRegex.Match(searchTerm);
|
||||
|
||||
if (resolutionMatch.Success)
|
||||
{
|
||||
searchTerm = searchTerm.Replace(resolutionMatch.Value, string.Empty).Trim();
|
||||
}
|
||||
|
||||
queryParameters.Set("f", "search");
|
||||
queryParameters.Set("s", searchTerm);
|
||||
}
|
||||
@@ -201,7 +204,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
{
|
||||
var release = new TorrentInfo
|
||||
{
|
||||
InfoUrl = _settings.BaseUrl + $"shows/{value.Page}/",
|
||||
InfoUrl = $"{_settings.BaseUrl}shows/{value.Page}/",
|
||||
PublishDate = value.ReleaseDate.LocalDateTime,
|
||||
Files = 1,
|
||||
Categories = new List<IndexerCategory> { NewznabStandardCategory.TVAnime },
|
||||
@@ -213,13 +216,18 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
UploadVolumeFactor = 1
|
||||
};
|
||||
|
||||
if (value.ImageUrl.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
release.PosterUrl = _settings.BaseUrl + value.ImageUrl.TrimStart('/');
|
||||
}
|
||||
|
||||
if (value.Episode.ToLowerInvariant() == "movie")
|
||||
{
|
||||
release.Categories.Add(NewznabStandardCategory.MoviesOther);
|
||||
}
|
||||
|
||||
// Ex: [SubsPlease] Shingeki no Kyojin (The Final Season) - 64 (1080p)
|
||||
release.Title += $"[SubsPlease] {value.Show} - {value.Episode} ({d.Resolution}p)";
|
||||
release.Title = $"[SubsPlease] {value.Show} - {value.Episode} ({d.Resolution}p)";
|
||||
release.MagnetUrl = d.Magnet;
|
||||
release.DownloadUrl = null;
|
||||
release.Guid = d.Magnet;
|
||||
@@ -269,6 +277,8 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
public string Episode { get; set; }
|
||||
public SubPleaseDownloadInfo[] Downloads { get; set; }
|
||||
public string Xdcc { get; set; }
|
||||
|
||||
[JsonProperty("image_url")]
|
||||
public string ImageUrl { get; set; }
|
||||
public string Page { get; set; }
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@ using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Indexers.Settings;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
@@ -145,32 +146,31 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
{
|
||||
var releaseInfos = new List<ReleaseInfo>();
|
||||
|
||||
var jsonContent = JArray.Parse(indexerResponse.Content);
|
||||
var jsonResponse = STJson.Deserialize<TorrentsCSVResponse>(indexerResponse.Content);
|
||||
|
||||
foreach (var torrent in jsonContent)
|
||||
foreach (var torrent in jsonResponse.Torrents)
|
||||
{
|
||||
if (torrent == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var infoHash = torrent.Value<string>("infohash");
|
||||
var title = torrent.Value<string>("name");
|
||||
var size = torrent.Value<long>("size_bytes");
|
||||
var seeders = torrent.Value<int?>("seeders") ?? 0;
|
||||
var leechers = torrent.Value<int?>("leechers") ?? 0;
|
||||
var grabs = torrent.Value<int?>("completed") ?? 0;
|
||||
var publishDate = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(torrent.Value<long>("created_unix"));
|
||||
var infoHash = torrent.InfoHash;
|
||||
var title = torrent.Name;
|
||||
var seeders = torrent.Seeders ?? 0;
|
||||
var leechers = torrent.Leechers ?? 0;
|
||||
var grabs = torrent.Completed ?? 0;
|
||||
var publishDate = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(torrent.Created);
|
||||
|
||||
var release = new TorrentInfo
|
||||
{
|
||||
Title = title,
|
||||
InfoUrl = $"{_settings.BaseUrl.TrimEnd('/')}/search/{title}", // there is no details link
|
||||
Guid = $"magnet:?xt=urn:btih:{infoHash}",
|
||||
InfoUrl = $"{_settings.BaseUrl.TrimEnd('/')}/search?q={title}", // there is no details link
|
||||
Title = title,
|
||||
InfoHash = infoHash, // magnet link is auto generated from infohash
|
||||
Categories = new List<IndexerCategory> { NewznabStandardCategory.Other },
|
||||
PublishDate = publishDate,
|
||||
Size = size,
|
||||
Size = torrent.Size,
|
||||
Grabs = grabs,
|
||||
Seeders = seeders,
|
||||
Peers = leechers + seeders,
|
||||
@@ -188,4 +188,29 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
|
||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||
}
|
||||
|
||||
public class TorrentsCSVResponse
|
||||
{
|
||||
public IReadOnlyCollection<TorrentsCSVTorrent> Torrents { get; set; }
|
||||
}
|
||||
|
||||
public class TorrentsCSVTorrent
|
||||
{
|
||||
[JsonPropertyName("infohash")]
|
||||
public string InfoHash { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("size_bytes")]
|
||||
public long Size { get; set; }
|
||||
|
||||
[JsonPropertyName("created_unix")]
|
||||
public long Created { get; set; }
|
||||
|
||||
public int? Leechers { get; set; }
|
||||
|
||||
public int? Seeders { get; set; }
|
||||
|
||||
public int? Completed { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,16 +100,17 @@ namespace NzbDrone.Core.Indexers.Torznab
|
||||
protected override bool PostProcess(IndexerResponse indexerResponse, List<XElement> items, List<ReleaseInfo> releases)
|
||||
{
|
||||
var enclosureTypes = items.SelectMany(GetEnclosures).Select(v => v.Type).Distinct().ToArray();
|
||||
|
||||
if (enclosureTypes.Any() && enclosureTypes.Intersect(PreferredEnclosureMimeTypes).Empty())
|
||||
{
|
||||
if (enclosureTypes.Intersect(UsenetEnclosureMimeTypes).Any())
|
||||
{
|
||||
_logger.Warn("Feed does not contain {0}, found {1}, did you intend to add a Newznab indexer?", TorrentEnclosureMimeType, enclosureTypes[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("Feed does not contain {0}, found {1}.", TorrentEnclosureMimeType, enclosureTypes[0]);
|
||||
_logger.Warn("{0} does not contain {1}, found {2}, did you intend to add a Newznab indexer?", indexerResponse.Request.Url, TorrentEnclosureMimeType, enclosureTypes[0]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_logger.Warn("{0} does not contain {1}, found {2}.", indexerResponse.Request.Url, TorrentEnclosureMimeType, enclosureTypes[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -290,9 +290,9 @@ namespace NzbDrone.Core.Indexers
|
||||
Length = v.Attribute("length")?.Value?.ParseInt64() ?? 0
|
||||
};
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(e, "Failed to get enclosure for: {0}", item.Title());
|
||||
_logger.Warn(ex, "Failed to get enclosure for: {0}", item.Title());
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace NzbDrone.Core.Indexers
|
||||
}
|
||||
catch
|
||||
{
|
||||
_logger.Info("Invalid torrent file contents: {0}", Encoding.ASCII.GetString(fileData));
|
||||
_logger.Debug("Invalid torrent file contents: {0}", Encoding.ASCII.GetString(fileData));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,5 +468,14 @@
|
||||
"Stats": "Estadístiques",
|
||||
"Private": "Privat",
|
||||
"Proxies": "Servidors intermediaris",
|
||||
"Public": "Públic"
|
||||
"Public": "Públic",
|
||||
"DeleteSelectedIndexer": "Suprimeix els indexadors seleccionats",
|
||||
"EditSyncProfile": "Afegeix perfil de sincronització",
|
||||
"Menu": "Menú",
|
||||
"OnGrabHelpText": "Al capturar llançament",
|
||||
"ProxyValidationBadRequest": "No s'ha pogut provar el servidor intermediari. Codi d'estat: {statusCode}",
|
||||
"Default": "Per defecte",
|
||||
"GrabRelease": "Captura novetat",
|
||||
"ManualGrab": "Captura manual",
|
||||
"PrioritySettings": "Prioritat: {priority}"
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"Events": "Événements",
|
||||
"Edit": "Modifier",
|
||||
"DownloadClientStatusAllClientHealthCheckMessage": "Aucun client de téléchargement n'est disponible en raison d'échecs",
|
||||
"DownloadClients": "Clients de téléchargement",
|
||||
"DownloadClients": "Clients de télécharg.",
|
||||
"Dates": "Dates",
|
||||
"Date": "Date",
|
||||
"Delete": "Supprimer",
|
||||
@@ -404,9 +404,9 @@
|
||||
"Website": "Site internet",
|
||||
"AudioSearch": "Recherche de musique",
|
||||
"BookSearch": "Recherche de livres",
|
||||
"OnApplicationUpdate": "Sur la mise à jour de l'application",
|
||||
"OnApplicationUpdateHelpText": "Lors de la mise à jour de l'app",
|
||||
"IndexerNoDefinitionCheckHealthCheckMessage": "Les indexeurs ne sont pas définis et ne fonctionneront pas: {indexerNames}. Merci de les retirer et (ou) les ajouter à nouveau à {appName}",
|
||||
"OnApplicationUpdate": "Lors de la mise à jour de l'application",
|
||||
"OnApplicationUpdateHelpText": "Lors de la mise à jour de l'application",
|
||||
"IndexerNoDefinitionCheckHealthCheckMessage": "Les indexeurs ne sont pas définis et ne fonctionneront pas : {indexerNames}. Merci de les retirer et (ou) les ajouter à nouveau à {appName}.",
|
||||
"MovieSearch": "Recherche de films",
|
||||
"TvSearch": "Recherche de séries TV",
|
||||
"Application": "Applications",
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
"TagsSettingsSummary": "Vedi tutte le etichette e come vengono utilizzate. Le etichette non utilizzate possono essere rimosse",
|
||||
"SetTags": "Imposta Etichette",
|
||||
"SelectAll": "Seleziona Tutto",
|
||||
"Scheduled": "Programmato",
|
||||
"Scheduled": "Pianificato",
|
||||
"ReleaseBranchCheckOfficialBranchMessage": "La versione {0} non è una versione valida per le release di {appName}, non riceverai aggiornamenti",
|
||||
"ProxyResolveIpHealthCheckMessage": "Impossibile risolvere l'indirizzo IP per l'Host Configurato del Proxy {proxyHostName}",
|
||||
"NoChanges": "Nessuna Modifica",
|
||||
"NoChange": "Nessuna Modifica",
|
||||
"NoChanges": "Nessun Cambiamento",
|
||||
"NoChange": "Nessun Cambio",
|
||||
"LastWriteTime": "Orario di Ultima Scrittura",
|
||||
"Indexer": "Indicizzatore",
|
||||
"HideAdvanced": "Nascondi Avanzate",
|
||||
@@ -35,8 +35,8 @@
|
||||
"ShowAdvanced": "Mostra Avanzate",
|
||||
"Settings": "Impostazioni",
|
||||
"Security": "Sicurezza",
|
||||
"Search": "Cerca",
|
||||
"SaveChanges": "Salva Modifiche",
|
||||
"Search": "Ricerca",
|
||||
"SaveChanges": "Salva Cambiamenti",
|
||||
"RestoreBackup": "Ripristina Backup",
|
||||
"ReleaseStatus": "Stato Release",
|
||||
"Refresh": "Aggiorna",
|
||||
@@ -46,7 +46,7 @@
|
||||
"Proxy": "Proxy",
|
||||
"Protocol": "Protocollo",
|
||||
"Options": "Opzioni",
|
||||
"MoreInfo": "Maggiori Info",
|
||||
"MoreInfo": "Ulteriori Informazioni",
|
||||
"Logging": "Logging",
|
||||
"LogFiles": "File di Log",
|
||||
"Language": "Lingua",
|
||||
@@ -91,15 +91,15 @@
|
||||
"CertificateValidation": "Convalida del Certificato",
|
||||
"Cancel": "Annulla",
|
||||
"BypassProxyForLocalAddresses": "Evita il Proxy per gli Indirizzi Locali",
|
||||
"Branch": "Ramo",
|
||||
"Branch": "Branca",
|
||||
"BindAddressHelpText": "Indirizzi IP validi, localhost o '*' per tutte le interfacce",
|
||||
"BindAddress": "Indirizzo di Ascolto",
|
||||
"Backups": "Backups",
|
||||
"Backups": "Backup",
|
||||
"BackupRetentionHelpText": "I backup più vecchi del periodo specificato saranno cancellati automaticamente",
|
||||
"BackupIntervalHelpText": "Intervallo fra i backup automatici",
|
||||
"BackupFolderHelpText": "I percorsi relativi saranno nella cartella AppData di {appName}",
|
||||
"Automatic": "Automatico",
|
||||
"AuthenticationMethodHelpText": "Inserisci Username e Password per accedere a {appName}",
|
||||
"AuthenticationMethodHelpText": "Utilizza nome utente e password per accedere a {appName}",
|
||||
"Authentication": "Autenticazione",
|
||||
"ApplyTags": "Applica Etichette",
|
||||
"Apply": "Applica",
|
||||
@@ -109,14 +109,14 @@
|
||||
"Warn": "Attenzione",
|
||||
"Type": "Tipo",
|
||||
"Title": "Titolo",
|
||||
"Time": "Ora",
|
||||
"TestAll": "Prova Tutti",
|
||||
"Test": "Test",
|
||||
"Time": "Orario",
|
||||
"TestAll": "Prova Tutto",
|
||||
"Test": "Prova",
|
||||
"TableOptionsColumnsMessage": "Scegli quali colonne rendere visibili ed il loro ordine",
|
||||
"TableOptions": "Opzioni della tabella",
|
||||
"TableOptions": "Opzioni Tabella",
|
||||
"SystemTimeCheckMessage": "L'orario di sistema è sbagliato di più di un giorno. Le attività pianificate potrebbero non essere eseguite correttamente fino alla correzione",
|
||||
"Source": "Fonte",
|
||||
"Shutdown": "Spegni",
|
||||
"Shutdown": "Spegnimento",
|
||||
"Seeders": "Seeders",
|
||||
"Save": "Salva",
|
||||
"Restart": "Riavvia",
|
||||
@@ -139,15 +139,15 @@
|
||||
"DeleteNotification": "Cancella Notifica",
|
||||
"DeleteDownloadClient": "Cancella Client di Download",
|
||||
"DeleteBackup": "Cancella Backup",
|
||||
"DatabaseMigration": "Migrazione DB",
|
||||
"DatabaseMigration": "Migrazione Database",
|
||||
"ConnectSettings": "Impostazioni Collegamento",
|
||||
"ConnectionLost": "Connessione Persa",
|
||||
"Component": "Componente",
|
||||
"Columns": "Colonne",
|
||||
"DeleteBackupMessageText": "Sei sicuro di voler cancellare il backup '{0}'?",
|
||||
"DeleteBackupMessageText": "Sei sicuro di voler cancellare il backup '{name}'?",
|
||||
"CancelPendingTask": "Sei sicuro di voler cancellare questa operazione in sospeso?",
|
||||
"BranchUpdateMechanism": "Ramo utilizzato dal sistema di aggiornamento esterno",
|
||||
"BranchUpdate": "Ramo da usare per aggiornare {appName}",
|
||||
"BranchUpdate": "Branca da usare per aggiornare {appName}",
|
||||
"AddingTag": "Aggiungendo etichetta",
|
||||
"Password": "Password",
|
||||
"OnHealthIssueHelpText": "Quando c'è un problema",
|
||||
@@ -162,41 +162,41 @@
|
||||
"SettingsEnableColorImpairedMode": "Abilità la Modalità Daltonica",
|
||||
"SendAnonymousUsageData": "Invia dati anonimi sull'uso",
|
||||
"ScriptPath": "Percorso dello script",
|
||||
"RssIsNotSupportedWithThisIndexer": "RSS non è supportato con questo Indicizzatore",
|
||||
"RssIsNotSupportedWithThisIndexer": "RSS non è supportato con questo indicizzatore",
|
||||
"Retention": "Ritenzione",
|
||||
"Result": "Risultato",
|
||||
"Restore": "Ripristina",
|
||||
"RestartRequiredHelpTextWarning": "Richiede il riavvio per avere effetto",
|
||||
"RestartProwlarr": "Riavvia {appName}",
|
||||
"RestartNow": "Riavvia adesso",
|
||||
"RestartNow": "Riavvia ora",
|
||||
"ResetAPIKey": "Resetta la Chiave API",
|
||||
"Reset": "Resetta",
|
||||
"Reset": "Reimposta",
|
||||
"RemovingTag": "Eliminando l'etichetta",
|
||||
"RemoveFilter": "Rimuovi filtro",
|
||||
"RemovedFromTaskQueue": "Rimosso dalla coda lavori",
|
||||
"RefreshMovie": "Aggiorna il Film",
|
||||
"ReadTheWikiForMoreInformation": "Leggi la Wiki per maggiori informazioni",
|
||||
"ReadTheWikiForMoreInformation": "Leggi la Wiki per più informazioni",
|
||||
"ProwlarrSupportsAnyIndexer": "{appName} supporta molti indicizzatori oltre a qualsiasi indicizzatore che utilizza lo standard Newznab/Torznab utilizzando \"Generic Newznab\" (per usenet) o \"Generic Torznab\" (per torrent). Cerca e seleziona il tuo indicizzatore da qua sotto.",
|
||||
"ProwlarrSupportsAnyDownloadClient": "{appName} supporta qualunque client di download elencato sotto.",
|
||||
"ProxyUsernameHelpText": "Devi inserire nome utente e password solo se richiesto. Altrimenti lascia vuoto.",
|
||||
"ProxyType": "Tipo di Proxy",
|
||||
"ProxyType": "Tipo Proxy",
|
||||
"ProxyPasswordHelpText": "Devi inserire nome utente e password solo se richiesto. Altrimenti lascia vuoto.",
|
||||
"ProxyBypassFilterHelpText": "Usa ',' come separatore, e '*.' come jolly per i sottodomini",
|
||||
"PortNumber": "Numero di porta",
|
||||
"ProxyBypassFilterHelpText": "Usa ',' come separatore, e '*.' come wildcard per i sottodomini",
|
||||
"PortNumber": "Numero Porta",
|
||||
"Port": "Porta",
|
||||
"PendingChangesStayReview": "Rimani e rivedi modifiche",
|
||||
"PendingChangesMessage": "Hai cambiamenti non salvati, sicuro di voler abbandonare la pagina?",
|
||||
"PendingChangesStayReview": "Rimani e rivedi i cambiamenti",
|
||||
"PendingChangesMessage": "Hai dei cambiamenti non salvati, sei sicuro di volere lasciare questa pagina?",
|
||||
"PendingChangesDiscardChanges": "Abbandona le modifiche ed esci",
|
||||
"PageSizeHelpText": "Numero di voci da mostrare in ogni pagina",
|
||||
"PackageVersion": "Versione del Pacchetto",
|
||||
"OpenBrowserOnStart": "Apri il browser all'avvio",
|
||||
"OpenBrowserOnStart": "Apri browser all'avvio",
|
||||
"NoUpdatesAreAvailable": "Nessun aggiornamento disponibile",
|
||||
"NoTagsHaveBeenAddedYet": "Nessuna etichetta è ancora stata aggiunta",
|
||||
"NoLogFiles": "Nessun file di log",
|
||||
"NoLeaveIt": "No, Lascialo",
|
||||
"NoBackupsAreAvailable": "Nessun Backup disponibile",
|
||||
"NoBackupsAreAvailable": "Nessun backup disponibile",
|
||||
"New": "Nuovo",
|
||||
"Mode": "Modo",
|
||||
"Mode": "Modalità",
|
||||
"Mechanism": "Meccanismo",
|
||||
"Manual": "Manuale",
|
||||
"MaintenanceRelease": "Release di Manutenzione: correzione di bug e altri miglioramenti. Vedi la storia dei Commit su Github per maggiori dettagli",
|
||||
@@ -209,8 +209,7 @@
|
||||
"IgnoredAddresses": "Indirizzi Ignorati",
|
||||
"GeneralSettings": "Impostazioni Generali",
|
||||
"ForMoreInformationOnTheIndividualDownloadClients": "Per più informazioni sui singoli client di download clicca sui pulsanti info.",
|
||||
"Fixed": "Fissato",
|
||||
"FilterPlaceHolder": "Cerca Indicizzatori",
|
||||
"FilterPlaceHolder": "Cerca indicizzatori",
|
||||
"ExistingTag": "Etichetta esistente",
|
||||
"Exception": "Eccezione",
|
||||
"ErrorLoadingContents": "Errore nel caricare i contenuti",
|
||||
@@ -219,22 +218,22 @@
|
||||
"EnableInteractiveSearch": "Abilita la Ricerca Interattiva",
|
||||
"EnableAutomaticSearchHelpText": "Sarà usata quando la ricerca automatica è eseguita dalla l'intrfaccia o da {appName}",
|
||||
"EnableAutomaticSearch": "Attiva la Ricerca Automatica",
|
||||
"DeleteTagMessageText": "Sei sicuro di voler eliminare l'etichetta '{0}'?",
|
||||
"DeleteNotificationMessageText": "Sei sicuro di voler eliminare la notifica '{0}'?",
|
||||
"DeleteDownloadClientMessageText": "Sei sicuro di voler eliminare il client di download '{0}'?",
|
||||
"DeleteTagMessageText": "Sei sicuro di voler eliminare l'etichetta '{label}'?",
|
||||
"DeleteNotificationMessageText": "Sei sicuro di voler eliminare la notifica '{name}'?",
|
||||
"DeleteDownloadClientMessageText": "Sei sicuro di voler eliminare il client di download '{name}'?",
|
||||
"BeforeUpdate": "Prima dell'aggiornamento",
|
||||
"Usenet": "Usenet",
|
||||
"Uptime": "Tempo di attività",
|
||||
"YesCancel": "Si, Cancella",
|
||||
"YesCancel": "Sì, Cancella",
|
||||
"Version": "Versione",
|
||||
"Username": "Nome utente",
|
||||
"Username": "Nome Utente",
|
||||
"UseProxy": "Usa Proxy",
|
||||
"UrlBaseHelpText": "Per il supporto al reverse proxy, di default è vuoto",
|
||||
"URLBase": "Base Url",
|
||||
"UpdateScriptPathHelpText": "Percorso verso uno script personalizzato che prende un pacchetto di aggiornamento estratto e gestisce il resto del processo di aggiornamento",
|
||||
"UpdateMechanismHelpText": "Usa il sistema di aggiornamento interno di {appName} o uno script",
|
||||
"UpdateMechanismHelpText": "Usa il sistema di aggiornamento incorporato di {appName} o uno script",
|
||||
"UpdateAutomaticallyHelpText": "Scarica e installa automaticamente gli aggiornamenti. Sarai comunque in grado in installarli da Sistema: Aggiornamenti",
|
||||
"UnsavedChanges": "Modifiche non salvate",
|
||||
"UnsavedChanges": "Cambiamenti Non Salvati",
|
||||
"UnableToLoadUISettings": "Impossibile caricare le impostazioni interfaccia",
|
||||
"UnableToLoadTags": "Impossibile caricare le Etichette",
|
||||
"UnableToLoadNotifications": "Impossibile caricare le Notifiche",
|
||||
@@ -255,7 +254,7 @@
|
||||
"TagIsNotUsedAndCanBeDeleted": "L'etichetta non è in uso e può essere eliminata",
|
||||
"TagCannotBeDeletedWhileInUse": "Non può essere cancellato mentre è in uso",
|
||||
"SuggestTranslationChange": "Suggerisci un cambio nella traduzione",
|
||||
"StartupDirectory": "Cartella di avvio",
|
||||
"StartupDirectory": "Cartella di Avvio",
|
||||
"StartTypingOrSelectAPathBelow": "Comincia a digitare o seleziona un percorso sotto",
|
||||
"SSLPort": "Porta SSL",
|
||||
"SSLCertPathHelpText": "Percorso file pfx",
|
||||
@@ -300,15 +299,15 @@
|
||||
"Donations": "Donazioni",
|
||||
"EnableRssHelpText": "Abilita feed RSS per l'Indicizzatore",
|
||||
"HomePage": "Pagina Iniziale",
|
||||
"Id": "Id",
|
||||
"Id": "ID",
|
||||
"IndexerHealthCheckNoIndexers": "Nessun Indicizzatore abilitato, {appName} non restituirà risultati di ricerca",
|
||||
"EnableRss": "Abilita RSS",
|
||||
"NoLinks": "Nessun Collegamento",
|
||||
"Rss": "RSS",
|
||||
"Wiki": "Wiki",
|
||||
"AllIndexersHiddenDueToFilter": "Tutti gli Indexer sono nascosti a causa del filtro applicato.",
|
||||
"DeleteApplicationMessageText": "Sei sicuro di voler eliminare l'applicazione '{0}'?",
|
||||
"DeleteIndexerProxyMessageText": "Sei sicuro di voler eliminare il proxy '{0}'?",
|
||||
"DeleteApplicationMessageText": "Sei sicuro di voler eliminare l'applicazione '{name}'?",
|
||||
"DeleteIndexerProxyMessageText": "Sei sicuro di voler eliminare il proxy '{name}'?",
|
||||
"Presets": "Preset",
|
||||
"SearchIndexers": "Cerca Indicizzatori",
|
||||
"UnableToAddANewIndexerProxyPleaseTryAgain": "Impossibile aggiungere un nuovo proxy per l'Indicizzatore, riprova.",
|
||||
@@ -342,7 +341,7 @@
|
||||
"MappedDrivesRunningAsService": "Le unità di rete mappate non sono disponibili eseguendo come servizio di Windows. Vedere le FAQ per maggiori informazioni",
|
||||
"No": "No",
|
||||
"UnableToLoadIndexers": "Impossibile caricare gli Indicizzatori",
|
||||
"Yes": "Si",
|
||||
"Yes": "Sì",
|
||||
"AddIndexerProxy": "Aggiungi proxy dell'Indexer",
|
||||
"AudioSearch": "Ricerca Audio",
|
||||
"BookSearch": "Ricerca Libri",
|
||||
@@ -385,7 +384,7 @@
|
||||
"IndexerDetails": "Dettagli dell'Indicizzatore",
|
||||
"IndexerInfo": "Info sull'Indicizzatore",
|
||||
"IndexerName": "Nome dell'Indicizzatore",
|
||||
"IndexerNoDefinitionCheckHealthCheckMessage": "Gli indicizzatori non hanno una definizione e non funzioneranno: {0}. Si prega di rimuoverli e/o di riaggiungerli a {appName}",
|
||||
"IndexerNoDefinitionCheckHealthCheckMessage": "Gli indicizzatori non hanno una definizione e non funzioneranno: {indexerNames}. Si prega di rimuoverli e/o di riaggiungerli a {appName}",
|
||||
"HistoryCleanup": "Pulizia della Cronologia",
|
||||
"IndexerRss": "RSS dell'Indicizzatore",
|
||||
"IndexerSite": "Sito dell'Indicizzatore",
|
||||
@@ -434,10 +433,10 @@
|
||||
"MinimumSeeders": "Seeder Minimi",
|
||||
"InstanceName": "Nome Istanza",
|
||||
"InstanceNameHelpText": "Nome istanza nella scheda e per il nome dell'app nel Syslog",
|
||||
"ThemeHelpText": "Cambia il Tema dell'interfaccia dell’applicazione, il Tema 'Auto' userà il suo Tema di Sistema per impostare la modalità Chiara o Scura. Ispirato da {0}",
|
||||
"ThemeHelpText": "Cambia il Tema dell'interfaccia dell’applicazione, il Tema 'Auto' userà il tuo Tema di Sistema per impostare la modalità Chiara o Scura. Ispirato da {inspiredBy}.",
|
||||
"LastDuration": "Ultima Durata",
|
||||
"LastExecution": "Ultima esecuzione",
|
||||
"Queued": "In coda",
|
||||
"Queued": "In Coda",
|
||||
"ApplicationLongTermStatusCheckAllClientMessage": "Tutte le app non disponibili da almeno 6 ore a causa di errori",
|
||||
"ApplicationLongTermStatusCheckSingleClientMessage": "Alcune app non sono disponibili da almeno 6 ore a causa di errori: {0}",
|
||||
"Duration": "Durata",
|
||||
@@ -466,9 +465,9 @@
|
||||
"ApplyTagsHelpTextAdd": "Aggiungi: Aggiunge le etichette alla lista esistente di etichette",
|
||||
"ApplyTagsHelpTextHowToApplyApplications": "Come applicare etichette agli autori selezionati",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Come applicare etichette agli indicizzatori selezionati",
|
||||
"CountIndexersSelected": "{0} indicizzatore(i) selezionato(i)",
|
||||
"DeleteSelectedApplicationsMessageText": "Sei sicuro di voler eliminare l'indexer '{0}'?",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Sei sicuro di voler eliminare l'indexer '{0}'?",
|
||||
"CountIndexersSelected": "{count} indicizzatore(i) selezionato(i)",
|
||||
"DeleteSelectedApplicationsMessageText": "Sei sicuro di voler eliminare {count} applicazione(i) selezionata(e)?",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Sei sicuro di voler eliminare i '{count}' client di download selezionato/i?",
|
||||
"SelectIndexers": "Cerca Indicizzatori",
|
||||
"Track": "Traccia",
|
||||
"Book": "Libro",
|
||||
@@ -477,22 +476,21 @@
|
||||
"ApplyTagsHelpTextReplace": "Sostituire: Sostituisce le etichette con quelle inserite (non inserire nessuna etichette per eliminarle tutte)",
|
||||
"DownloadClientPriorityHelpText": "Dai priorità a multipli Client di download. Round-Robin è usato per i client con la stessa priorità.",
|
||||
"DeleteSelectedDownloadClients": "Cancella i Client di Download",
|
||||
"DeleteSelectedIndexersMessageText": "Sei sicuro di voler eliminare l'indexer '{0}'?",
|
||||
"Album": "Album",
|
||||
"Artist": "Artista",
|
||||
"Label": "Etichetta",
|
||||
"More": "Di più",
|
||||
"More": "Altro",
|
||||
"Season": "Stagione",
|
||||
"Year": "Anno",
|
||||
"UpdateAvailableHealthCheckMessage": "É disponibile un nuovo aggiornamento",
|
||||
"UpdateAvailableHealthCheckMessage": "Nuovo aggiornamento disponibile",
|
||||
"Author": "Autore",
|
||||
"ApplyChanges": "Applica Cambiamenti",
|
||||
"ApiKeyValidationHealthCheckMessage": "Aggiorna la tua chiave API in modo che abbia una lunghezza di almeno {length} caratteri. Puoi farlo dalle impostazioni o dal file di configurazione",
|
||||
"DeleteAppProfileMessageText": "Sicuro di voler cancellare il profilo di qualità {0}",
|
||||
"RecentChanges": "Cambiamenti recenti",
|
||||
"DeleteAppProfileMessageText": "Sicuro di voler cancellare il profilo dell'app '{name}'?",
|
||||
"RecentChanges": "Cambiamenti Recenti",
|
||||
"WhatsNew": "Cosa c'è di nuovo?",
|
||||
"ConnectionLostReconnect": "Radarr cercherà di connettersi automaticamente, oppure clicca su ricarica qui sotto.",
|
||||
"ConnectionLostToBackend": "Radarr ha perso la connessione al backend e dovrà essere ricaricato per ripristinare la funzionalità.",
|
||||
"ConnectionLostReconnect": "{appName} cercherà di connettersi automaticamente, oppure clicca su ricarica qui sotto.",
|
||||
"ConnectionLostToBackend": "{appName} ha perso la connessione al backend e dovrà essere ricaricato per ripristinare la funzionalità.",
|
||||
"minutes": "Minuti",
|
||||
"AddConnection": "Aggiungi Connessione",
|
||||
"NotificationStatusAllClientHealthCheckMessage": "Tutte le applicazioni non sono disponibili a causa di errori",
|
||||
@@ -532,9 +530,114 @@
|
||||
"ActiveIndexers": "Indicizzatori Attivi",
|
||||
"IndexerBeyondHDSettingsSearchTypes": "Tipi di Ricerca",
|
||||
"Directory": "Cartella",
|
||||
"CustomFilter": "Filtri Personalizzati",
|
||||
"CustomFilter": "Filtro Personalizzato",
|
||||
"IndexerHDBitsSettingsCodecs": "Codec",
|
||||
"IndexerHDBitsSettingsMediums": "medio",
|
||||
"GrabRelease": "Preleva Release",
|
||||
"ProxyValidationBadRequest": "Il test del proxy è fallito. Codice Stato: {statusCode}"
|
||||
"ProxyValidationBadRequest": "Il test del proxy è fallito. Codice Stato: {statusCode}",
|
||||
"Discord": "Discord",
|
||||
"Donate": "Dona",
|
||||
"Destination": "Destinazione",
|
||||
"DownloadClientFreeboxSettingsApiUrl": "API URL",
|
||||
"DownloadClientFreeboxSettingsAppId": "ID App",
|
||||
"DownloadClientFreeboxSettingsAppToken": "Token App",
|
||||
"DownloadClientPneumaticSettingsNzbFolder": "Cartella Nzb",
|
||||
"DownloadClientPneumaticSettingsNzbFolderHelpText": "Questa cartella dovrà essere raggiungibile da XBMC",
|
||||
"DownloadClientRTorrentSettingsUrlPath": "Percorso Url",
|
||||
"Default": "Predefinito",
|
||||
"DownloadClientPneumaticSettingsStrmFolder": "Cartella Strm",
|
||||
"IndexerDisabled": "Indexer Disattivato",
|
||||
"GoToApplication": "Vai all'applicazione",
|
||||
"AreYouSureYouWantToDeleteIndexer": "Sei sicuro di voler eliminare '{name}' da {appName}?",
|
||||
"IndexerStatus": "Stato Indicizzatore",
|
||||
"XmlRpcPath": "Percorso XML RPC",
|
||||
"EditCategory": "Modifica Categoria",
|
||||
"IndexerSettingsAdditionalParameters": "Parametri Addizionali",
|
||||
"IndexerSettingsApiPath": "Percorso API",
|
||||
"IndexerSettingsVipExpiration": "Scadenza VIP",
|
||||
"DefaultCategory": "Categoria Predefinita",
|
||||
"DownloadClientFloodSettingsAdditionalTags": "Tag addizionali",
|
||||
"IndexerHDBitsSettingsMediumsHelpText": "Se non specificato, saranno utilizzate tutte le opzioni.",
|
||||
"IndexerHDBitsSettingsOrigins": "Origini",
|
||||
"IndexerHDBitsSettingsOriginsHelpText": "Se non specificato, saranno utilizzate tutte le opzioni.",
|
||||
"IndexerSettingsCookie": "Cookie",
|
||||
"DeleteSelectedApplications": "Elimina Applicazioni Selezionate",
|
||||
"IndexerHDBitsSettingsCodecsHelpText": "Se non specificato, saranno utilizzate tutte le opzioni.",
|
||||
"IndexerSettingsApiUser": "Utente API",
|
||||
"PrioritySettings": "Priorità: {priority}",
|
||||
"CountDownloadClientsSelected": "{count} client di download selezionato/i",
|
||||
"NotificationsTelegramSettingsIncludeAppName": "Includi {appName} nel Titolo",
|
||||
"Menu": "Menu",
|
||||
"NoIndexersFound": "Nessun indicizzatore trovato",
|
||||
"PasswordConfirmation": "Conferma Password",
|
||||
"NoHistoryFound": "Nessun storico trovato",
|
||||
"DeleteSelectedIndexersMessageText": "Sei sicuro di voler eliminare {count} applicazione(i) selezionata(e)?",
|
||||
"UsenetBlackholeNzbFolder": "Cartella Nzb",
|
||||
"VipExpiration": "Scadenza VIP",
|
||||
"OverrideAndAddToDownloadClient": "Sovrascrivi e aggiungi alla coda di download",
|
||||
"BasicSearch": "Ricerca basica",
|
||||
"CountIndexersAvailable": "{count} indicizzatore/i disponibili",
|
||||
"EditSelectedIndexers": "Modifica Indicizzatori Selezionati",
|
||||
"FoundCountReleases": "Trovate {itemCount} release",
|
||||
"ManageApplications": "Gestisci Applicazioni",
|
||||
"ManageDownloadClients": "Gestisci Clients di Download",
|
||||
"HistoryDetails": "Dettagli Storico",
|
||||
"NotificationsEmailSettingsUseEncryption": "Usa Crittografia",
|
||||
"SearchAllIndexers": "Cerca tutti gli indicizzatori",
|
||||
"SearchCountIndexers": "Cerca {count} indicizzatore/i",
|
||||
"SearchQueries": "Cerca Richieste",
|
||||
"SeedRatio": "Rapporto Seed",
|
||||
"TorznabUrl": "Url Torznab",
|
||||
"TorrentBlackholeTorrentFolder": "Cartella Torrent",
|
||||
"UseSsl": "Usa SSL",
|
||||
"days": "giorni",
|
||||
"IndexerCategories": "Categorie degli Indicizzatori",
|
||||
"IndexerTorrentSyndikatSettingsApiKeyHelpText": "API Key Sito",
|
||||
"LabelIsRequired": "Etichetta richiesta",
|
||||
"NoIndexerHistory": "Nessun storico trovato per questo indicizzatore",
|
||||
"RssFeed": "Feed RSS",
|
||||
"AverageResponseTimesMs": "Tempo di Risposta Medio dell'Indicizzatore (ms)",
|
||||
"DeleteSelectedIndexer": "Elimina Indicizzatore Selezionato",
|
||||
"DisabledUntil": "Disattiva fino",
|
||||
"DownloadClientDelugeSettingsUrlBaseHelpText": "Aggiungi un prefisso all'url del json di deluge, vedi {url}",
|
||||
"Implementation": "Implementazione",
|
||||
"ManageClients": "Gestisci Clients",
|
||||
"NewznabUrl": "Url Newznab",
|
||||
"NoApplicationsFound": "Nessuna applicazione trovata",
|
||||
"IndexerSettingsBaseUrl": "Url Base",
|
||||
"IndexerId": "ID Indicizzatore",
|
||||
"NoDownloadClientsFound": "Nessun client di download trovato",
|
||||
"BlackholeFolderHelpText": "Cartella nella quale {appName} salverà i file di tipo {extension}",
|
||||
"DownloadClientNzbgetSettingsAddPausedHelpText": "Questa opzione richiede almeno la versione 16.0 di NzbGet",
|
||||
"DownloadClientQbittorrentSettingsSequentialOrderHelpText": "Scarica in ordine sequenziale (qBittorrent 4.1.0+)",
|
||||
"DownloadClientQbittorrentSettingsUseSslHelpText": "Usa una connessione sicura. Vedi Opzioni -> Web UI -> 'Usa HTTPS invece di HTTP' in qBittorrent.",
|
||||
"DownloadClientRTorrentSettingsAddStopped": "Aggiungi Fermato",
|
||||
"DownloadClientSettingsInitialState": "Stato Iniziale",
|
||||
"DownloadClientSettingsInitialStateHelpText": "Stato iniziale per i torrent aggiunti a {clientName}",
|
||||
"DownloadClientSettingsAddPaused": "Aggiungi In Pausa",
|
||||
"DownloadClientSettingsUseSslHelpText": "Usa connessione sicura quando connetti a {clientName}",
|
||||
"IndexerIPTorrentsSettingsCookieUserAgent": "Cookie User-Agent",
|
||||
"IndexerSettingsApiPathHelpText": "Percorso API, solitamente {url}",
|
||||
"IndexerSettingsBaseUrlHelpText": "Seleziona quale url base {appName} userà per le richieste al sito",
|
||||
"NoIndexerCategories": "Nessuna categoria trovata per questo indicizzatore",
|
||||
"SecretToken": "Secret Token",
|
||||
"SeedRatioHelpText": "Il rapporto che un torrent dovrebbe raggiungere prima di essere fermato, vuoto è il predefinito dell'app",
|
||||
"TotalQueries": "Totale Richieste",
|
||||
"IndexerHistoryLoadError": "Errore caricando lo storico dell'indicizzatore",
|
||||
"DeleteSelectedIndexers": "Elimina Indicizzatori Selezionati",
|
||||
"InvalidUILanguage": "L'interfaccia è impostata in una lingua non valida, correggi e salva le tue impostazioni",
|
||||
"IndexerSettingsSeedRatio": "Rapporto Seed",
|
||||
"IndexerSettingsRssKey": "Chiave RSS",
|
||||
"RssQueries": "Richieste RSS",
|
||||
"DownloadClientQbittorrentSettingsSequentialOrder": "Ordine Sequenziale",
|
||||
"External": "Esterno",
|
||||
"IndexerNewznabSettingsAdditionalParametersHelpText": "Parametri Newznab addizionali",
|
||||
"SelectDownloadClientModalTitle": "{modalTitle} - Seleziona Client di Download",
|
||||
"DownloadClientSettingsDestinationHelpText": "Specifica manualmente la destinazione dei download, lascia vuoti per usare la predefinita",
|
||||
"IndexerDownloadClientHealthCheckMessage": "Indicizzatori con client di download non validi: {indexerNames}.",
|
||||
"SeedTimeHelpText": "Il rapporto che un torrent dovrebbe raggiungere prima di essere fermato, vuoto è il predefinito dell'app",
|
||||
"IndexerPassThePopcornSettingsApiKeyHelpText": "API Key Sito",
|
||||
"IndexerNzbIndexSettingsApiKeyHelpText": "API Key Sito",
|
||||
"IndexerNewznabSettingsApiKeyHelpText": "API Key Sito",
|
||||
"Fixed": "Fissato"
|
||||
}
|
||||
|
||||
@@ -152,5 +152,7 @@
|
||||
"AddConnectionImplementation": "Legg til betingelse - {implementationName}",
|
||||
"AddIndexerImplementation": "Legg til betingelse - {implementationName}",
|
||||
"AddIndexerProxyImplementation": "Legg til betingelse - {implementationName}",
|
||||
"UnableToAddANewApplicationPleaseTryAgain": "Ikke mulig å legge til ny betingelse, vennligst prøv igjen"
|
||||
"UnableToAddANewApplicationPleaseTryAgain": "Ikke mulig å legge til ny betingelse, vennligst prøv igjen",
|
||||
"EditIndexerProxyImplementation": "Legg til betingelse - {implementationName}",
|
||||
"UnableToAddANewAppProfilePleaseTryAgain": "Ikke mulig å legge til ny betingelse, vennligst prøv igjen"
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
"IndexerLongTermStatusAllUnavailableHealthCheckMessage": "Todos os indexadores estão indisponíveis devido a falhas por mais de 6 horas",
|
||||
"IndexerLongTermStatusUnavailableHealthCheckMessage": "Indexadores indisponíveis devido a falhas por mais de 6 horas: {indexerNames}",
|
||||
"IndexerName": "Nome do Indexador",
|
||||
"IndexerNoDefinitionCheckHealthCheckMessage": "Os indexadores não têm definição e não funcionarão: {0}. Por favor, remova e (ou) adicione novamente ao {appName}",
|
||||
"IndexerNoDefinitionCheckHealthCheckMessage": "Os indexadores não têm definição e não funcionarão: {indexerNames}. Remova e (ou) adicione novamente ao {appName}.",
|
||||
"IndexerObsoleteCheckMessage": "Os seguintes indexadores são obsoletos ou foram atualizados: {0}. Remova-os e/ou adicione-os novamente ao {appName}",
|
||||
"IndexerPriority": "Prioridade do indexador",
|
||||
"IndexerPriorityHelpText": "Prioridade do Indexador de 1 (Mais Alta) a 50 (Mais Baixa). Padrão: 25.",
|
||||
@@ -479,7 +479,7 @@
|
||||
"UpdateStartupNotWritableHealthCheckMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{startupFolder}' não pode ser gravada pelo usuário '{userName}'.",
|
||||
"UpdateStartupTranslocationHealthCheckMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{startupFolder}' está em uma pasta de translocação de aplicativo.",
|
||||
"UpdateUiNotWritableHealthCheckMessage": "Não é possível instalar a atualização porque a pasta de IU '{uiFolder}' não pode ser gravada pelo usuário '{userName}'.",
|
||||
"UpdateMechanismHelpText": "Use o atualizador integrado do {appName} ou um script",
|
||||
"UpdateMechanismHelpText": "Usar o atualizador integrado do {appName} ou um script",
|
||||
"UpdateScriptPathHelpText": "Caminho para um script personalizado que usa um pacote de atualização extraído e lida com o restante do processo de atualização",
|
||||
"Updates": "Atualizações",
|
||||
"Uptime": "Tempo de atividade",
|
||||
|
||||
@@ -142,5 +142,6 @@
|
||||
"IndexerHDBitsSettingsCodecs": "Kodek",
|
||||
"AddIndexerProxyImplementation": "Pridať Indexer - {implementationName}",
|
||||
"EditIndexerProxyImplementation": "Pridať Indexer - {implementationName}",
|
||||
"EditApplicationImplementation": "Pridať podmienku - {implementationName}"
|
||||
"EditApplicationImplementation": "Pridať podmienku - {implementationName}",
|
||||
"UnableToAddANewAppProfilePleaseTryAgain": "Nie je možné pridať novú podmienku, skúste to znova."
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@
|
||||
"ApplyTagsHelpTextAdd": "Ekle: Etiketleri mevcut etiket listesine ekleyin",
|
||||
"ApplyTagsHelpTextHowToApplyApplications": "Seçilen filmlere etiketler nasıl uygulanır",
|
||||
"ApplyTagsHelpTextRemove": "Kaldır: Girilen etiketleri kaldırın",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Seçilen indeksleyicilere etiketler nasıl uygulanır?",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Seçilen indeksleyicilere etiketler nasıl uygulanır",
|
||||
"ApplyTagsHelpTextReplace": "Değiştir: Etiketleri girilen etiketlerle değiştirin (tüm etiketleri kaldırmak için etiket girmeyin)",
|
||||
"DeleteSelectedDownloadClients": "İndirme İstemcilerini Sil",
|
||||
"DownloadClientPriorityHelpText": "Birden çok İndirme İstemcisine öncelik verin. Round-Robin, aynı önceliğe sahip müşteriler için kullanılır.",
|
||||
|
||||
@@ -420,5 +420,7 @@
|
||||
"CustomFilter": "Користувацькі фільтри",
|
||||
"IndexerHDBitsSettingsMediums": "Середній",
|
||||
"Default": "За замовчуванням",
|
||||
"GrabRelease": "Захопити реліз"
|
||||
"GrabRelease": "Захопити реліз",
|
||||
"Clone": "Клонування",
|
||||
"CountDownloadClientsSelected": "Вибрано {count} клієнтів завантажувача"
|
||||
}
|
||||
|
||||
@@ -128,5 +128,10 @@
|
||||
"ApplyChanges": "應用",
|
||||
"ApplyTagsHelpTextHowToApplyApplications": "如何套用標籤在所選擇的輸入清單",
|
||||
"Artist": "演員",
|
||||
"Id": "ID"
|
||||
"Id": "ID",
|
||||
"Usenet": "Usenet",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "如何套用標籤在所選擇的輸入清單",
|
||||
"Docker": "Docker",
|
||||
"IndexerHDBitsSettingsCodecs": "編解碼器",
|
||||
"Directory": "目錄"
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace NzbDrone.Core.Notifications.Gotify
|
||||
|
||||
public override void OnHealthRestored(HealthCheck.HealthCheck previousCheck)
|
||||
{
|
||||
_proxy.SendNotification(HEALTH_RESTORED_TITLE, $"The following issue is now resolved: {previousCheck.Message}", null);
|
||||
_proxy.SendNotification(HEALTH_RESTORED_TITLE, $"The following issue is now resolved: {previousCheck.Message}", Settings);
|
||||
}
|
||||
|
||||
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
|
||||
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
|
||||
<PackageReference Include="Npgsql" Version="7.0.7" />
|
||||
<PackageReference Include="Polly" Version="8.4.0" />
|
||||
<PackageReference Include="Polly" Version="8.4.1" />
|
||||
<PackageReference Include="Servarr.FluentMigrator.Runner" Version="3.3.2.9" />
|
||||
<PackageReference Include="Servarr.FluentMigrator.Runner.Postgres" Version="3.3.2.9" />
|
||||
<PackageReference Include="Servarr.FluentMigrator.Runner.SQLite" Version="3.3.2.9" />
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Prowlarr.Api.V1.Indexers
|
||||
|
||||
if (definition.Implementation == nameof(Cardigann))
|
||||
{
|
||||
var extraFields = definition.ExtraFields?.Select(MapCardigannField).ToList() ?? new List<Field>();
|
||||
var extraFields = definition.ExtraFields?.Select((field, i) => MapCardigannField(definition, field, i)).ToList() ?? new List<Field>();
|
||||
|
||||
resource.Fields.AddRange(extraFields);
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace Prowlarr.Api.V1.Indexers
|
||||
};
|
||||
}
|
||||
|
||||
private Field MapCardigannField(SettingsField setting, int order)
|
||||
private Field MapCardigannField(IndexerDefinition definition, SettingsField setting, int order)
|
||||
{
|
||||
var field = new Field
|
||||
{
|
||||
@@ -185,7 +185,7 @@ namespace Prowlarr.Api.V1.Indexers
|
||||
{
|
||||
field.Value = bool.TryParse(setting.Default, out var value) && value;
|
||||
}
|
||||
else if (setting.Type is "info_cookie" or "info_flaresolverr" or "info_useragent")
|
||||
else if (setting.Type is "info_cookie" or "info_flaresolverr" or "info_useragent" or "info_category_8000")
|
||||
{
|
||||
field.Type = "info";
|
||||
|
||||
@@ -203,6 +203,10 @@ namespace Prowlarr.Api.V1.Indexers
|
||||
field.Label = "How to get the User-Agent";
|
||||
field.Value = "<ol><li>From the same place you fetched the cookie,</li><li>Find <b>'user-agent:'</b> in the <b>Request Headers</b> section</li><li><b>Select</b> and <b>Copy</b> the whole user-agent string <i>(everything after 'user-agent: ')</i> and <b>Paste</b> here.</li></ol>";
|
||||
break;
|
||||
case "info_category_8000":
|
||||
field.Label = $"About {definition.Name} Categories";
|
||||
field.Value = $"{definition.Name} does not return categories in its search results. To sync to your apps, include 8000(Other) in your Apps' Sync Categories.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user