mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-17 21:26:13 -04:00
Compare commits
23 Commits
v4.0.4.166
...
v4.0.5.171
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9b771ab0b | ||
|
|
6b08e849b8 | ||
|
|
9c1f48ebc9 | ||
|
|
fd3dd1ab7d | ||
|
|
11e5c5a11b | ||
|
|
48f0291884 | ||
|
|
af0e55aef4 | ||
|
|
39a439eb4c | ||
|
|
66940b283b | ||
|
|
2a662afaef | ||
|
|
62a9c2519b | ||
|
|
ca372bee25 | ||
|
|
0904a0737e | ||
|
|
70bc26dc19 | ||
|
|
a2e0002a08 | ||
|
|
d7ceb11a64 | ||
|
|
cc5b5463f2 | ||
|
|
9b4ff657af | ||
|
|
aea50fa47e | ||
|
|
05edd44ed6 | ||
|
|
4440aa3cac | ||
|
|
084fcc2295 | ||
|
|
536ff142c3 |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -22,7 +22,7 @@ env:
|
||||
FRAMEWORK: net6.0
|
||||
RAW_BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||
SONARR_MAJOR_VERSION: 4
|
||||
VERSION: 4.0.4
|
||||
VERSION: 4.0.5
|
||||
|
||||
jobs:
|
||||
backend:
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
|
||||
echo "SDK_PATH=${{ env.DOTNET_ROOT }}/sdk/${DOTNET_VERSION}" >> "$GITHUB_ENV"
|
||||
echo "SONARR_VERSION=$SONARR_VERSION" >> "$GITHUB_ENV"
|
||||
echo "BRANCH=${RAW_BRANCH_NAME/\//-}" >> "$GITHUB_ENV"
|
||||
echo "BRANCH=${RAW_BRANCH_NAME//\//-}" >> "$GITHUB_ENV"
|
||||
|
||||
echo "framework=${{ env.FRAMEWORK }}" >> "$GITHUB_OUTPUT"
|
||||
echo "major_version=${{ env.SONARR_MAJOR_VERSION }}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
1
.github/workflows/labeler.yml
vendored
1
.github/workflows/labeler.yml
vendored
@@ -8,5 +8,6 @@ jobs:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'Sonarr/Sonarr'
|
||||
steps:
|
||||
- uses: actions/labeler@v5
|
||||
|
||||
1
.github/workflows/lock.yml
vendored
1
.github/workflows/lock.yml
vendored
@@ -8,6 +8,7 @@ on:
|
||||
jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'Sonarr/Sonarr'
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v5
|
||||
with:
|
||||
|
||||
@@ -24,7 +24,11 @@ function TimeleftCell(props) {
|
||||
} = props;
|
||||
|
||||
if (status === 'delay') {
|
||||
const date = getRelativeDate(estimatedCompletionTime, shortDateFormat, showRelativeDates);
|
||||
const date = getRelativeDate({
|
||||
date: estimatedCompletionTime,
|
||||
shortDateFormat,
|
||||
showRelativeDates
|
||||
});
|
||||
const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true });
|
||||
|
||||
return (
|
||||
@@ -40,7 +44,11 @@ function TimeleftCell(props) {
|
||||
}
|
||||
|
||||
if (status === 'downloadClientUnavailable') {
|
||||
const date = getRelativeDate(estimatedCompletionTime, shortDateFormat, showRelativeDates);
|
||||
const date = getRelativeDate({
|
||||
date: estimatedCompletionTime,
|
||||
shortDateFormat,
|
||||
showRelativeDates
|
||||
});
|
||||
const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true });
|
||||
|
||||
return (
|
||||
|
||||
@@ -28,7 +28,7 @@ class DayOfWeek extends Component {
|
||||
if (view === calendarViews.WEEK) {
|
||||
formatedDate = momentDate.format(calendarWeekColumnHeader);
|
||||
} else if (view === calendarViews.FORECAST) {
|
||||
formatedDate = getRelativeDate(date, shortDateFormat, showRelativeDates);
|
||||
formatedDate = getRelativeDate({ date, shortDateFormat, showRelativeDates });
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -244,7 +244,7 @@ class SignalRConnector extends Component {
|
||||
handleWantedCutoff = (body) => {
|
||||
if (body.action === 'updated') {
|
||||
this.props.dispatchUpdateItem({
|
||||
section: 'cutoffUnmet',
|
||||
section: 'wanted.cutoffUnmet',
|
||||
updateOnly: true,
|
||||
...body.resource
|
||||
});
|
||||
@@ -254,7 +254,7 @@ class SignalRConnector extends Component {
|
||||
handleWantedMissing = (body) => {
|
||||
if (body.action === 'updated') {
|
||||
this.props.dispatchUpdateItem({
|
||||
section: 'missing',
|
||||
section: 'wanted.missing',
|
||||
updateOnly: true,
|
||||
...body.resource
|
||||
});
|
||||
|
||||
@@ -15,6 +15,7 @@ class RelativeDateCell extends PureComponent {
|
||||
className,
|
||||
date,
|
||||
includeSeconds,
|
||||
includeTime,
|
||||
showRelativeDates,
|
||||
shortDateFormat,
|
||||
longDateFormat,
|
||||
@@ -39,7 +40,7 @@ class RelativeDateCell extends PureComponent {
|
||||
title={formatDateTime(date, longDateFormat, timeFormat, { includeSeconds, includeRelativeDay: !showRelativeDates })}
|
||||
{...otherProps}
|
||||
>
|
||||
{getRelativeDate(date, shortDateFormat, showRelativeDates, { timeFormat, includeSeconds, timeForToday: true })}
|
||||
{getRelativeDate({ date, shortDateFormat, showRelativeDates, timeFormat, includeSeconds, includeTime, timeForToday: true })}
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
@@ -49,6 +50,7 @@ RelativeDateCell.propTypes = {
|
||||
className: PropTypes.string.isRequired,
|
||||
date: PropTypes.string,
|
||||
includeSeconds: PropTypes.bool.isRequired,
|
||||
includeTime: PropTypes.bool.isRequired,
|
||||
showRelativeDates: PropTypes.bool.isRequired,
|
||||
shortDateFormat: PropTypes.string.isRequired,
|
||||
longDateFormat: PropTypes.string.isRequired,
|
||||
@@ -60,6 +62,7 @@ RelativeDateCell.propTypes = {
|
||||
RelativeDateCell.defaultProps = {
|
||||
className: styles.cell,
|
||||
includeSeconds: false,
|
||||
includeTime: false,
|
||||
component: TableRowCell
|
||||
};
|
||||
|
||||
|
||||
@@ -111,6 +111,8 @@ class EpisodeHistoryRow extends Component {
|
||||
|
||||
<RelativeDateCellConnector
|
||||
date={date}
|
||||
includeSeconds={true}
|
||||
includeTime={true}
|
||||
/>
|
||||
|
||||
<TableRowCell className={styles.actions}>
|
||||
|
||||
@@ -14,7 +14,7 @@ function SeriesHistoryModal(props) {
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
size={sizes.EXTRA_LARGE}
|
||||
size={sizes.EXTRA_EXTRA_LARGE}
|
||||
onModalClose={onModalClose}
|
||||
>
|
||||
<SeriesHistoryModalContentConnector
|
||||
|
||||
@@ -135,6 +135,8 @@ class SeriesHistoryRow extends Component {
|
||||
|
||||
<RelativeDateCellConnector
|
||||
date={date}
|
||||
includeSeconds={true}
|
||||
includeTime={true}
|
||||
/>
|
||||
|
||||
<TableRowCell className={styles.actions}>
|
||||
|
||||
@@ -138,7 +138,10 @@ function getInfoRowProps(
|
||||
}),
|
||||
iconName: icons.CALENDAR,
|
||||
label:
|
||||
getRelativeDate(previousAiring, shortDateFormat, showRelativeDates, {
|
||||
getRelativeDate({
|
||||
date: previousAiring,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
}) ?? '',
|
||||
@@ -156,7 +159,10 @@ function getInfoRowProps(
|
||||
}),
|
||||
iconName: icons.ADD,
|
||||
label:
|
||||
getRelativeDate(added, shortDateFormat, showRelativeDates, {
|
||||
getRelativeDate({
|
||||
date: added,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
}) ?? '',
|
||||
@@ -232,15 +238,13 @@ function SeriesIndexOverviewInfo(props: SeriesIndexOverviewInfoProps) {
|
||||
<SeriesIndexOverviewInfoRow
|
||||
title={formatDateTime(nextAiring, longDateFormat, timeFormat)}
|
||||
iconName={icons.SCHEDULED}
|
||||
label={getRelativeDate(
|
||||
nextAiring,
|
||||
label={getRelativeDate({
|
||||
date: nextAiring,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
{
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
}
|
||||
)}
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@@ -217,7 +217,10 @@ function SeriesIndexPoster(props: SeriesIndexPosterProps) {
|
||||
timeFormat
|
||||
)}`}
|
||||
>
|
||||
{getRelativeDate(nextAiring, shortDateFormat, showRelativeDates, {
|
||||
{getRelativeDate({
|
||||
date: nextAiring,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
})}
|
||||
|
||||
@@ -80,7 +80,10 @@ function SeriesIndexPosterInfo(props: SeriesIndexPosterInfoProps) {
|
||||
timeFormat
|
||||
)}`}
|
||||
>
|
||||
{getRelativeDate(previousAiring, shortDateFormat, showRelativeDates, {
|
||||
{getRelativeDate({
|
||||
date: previousAiring,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
})}
|
||||
@@ -89,15 +92,13 @@ function SeriesIndexPosterInfo(props: SeriesIndexPosterInfoProps) {
|
||||
}
|
||||
|
||||
if (sortKey === 'added' && added) {
|
||||
const addedDate = getRelativeDate(
|
||||
added,
|
||||
const addedDate = getRelativeDate({
|
||||
date: added,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
{
|
||||
timeFormat,
|
||||
timeForToday: false,
|
||||
}
|
||||
);
|
||||
timeFormat,
|
||||
timeForToday: false,
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import moment from 'moment';
|
||||
import formatTime from 'Utilities/Date/formatTime';
|
||||
import isInNextWeek from 'Utilities/Date/isInNextWeek';
|
||||
import isToday from 'Utilities/Date/isToday';
|
||||
import isTomorrow from 'Utilities/Date/isTomorrow';
|
||||
import isYesterday from 'Utilities/Date/isYesterday';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
function getRelativeDate(date, shortDateFormat, showRelativeDates, { timeFormat, includeSeconds = false, timeForToday = false } = {}) {
|
||||
if (!date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isTodayDate = isToday(date);
|
||||
|
||||
if (isTodayDate && timeForToday && timeFormat) {
|
||||
return formatTime(date, timeFormat, { includeMinuteZero: true, includeSeconds });
|
||||
}
|
||||
|
||||
if (!showRelativeDates) {
|
||||
return moment(date).format(shortDateFormat);
|
||||
}
|
||||
|
||||
if (isYesterday(date)) {
|
||||
return translate('Yesterday');
|
||||
}
|
||||
|
||||
if (isTodayDate) {
|
||||
return translate('Today');
|
||||
}
|
||||
|
||||
if (isTomorrow(date)) {
|
||||
return translate('Tomorrow');
|
||||
}
|
||||
|
||||
if (isInNextWeek(date)) {
|
||||
return moment(date).format('dddd');
|
||||
}
|
||||
|
||||
return moment(date).format(shortDateFormat);
|
||||
}
|
||||
|
||||
export default getRelativeDate;
|
||||
82
frontend/src/Utilities/Date/getRelativeDate.tsx
Normal file
82
frontend/src/Utilities/Date/getRelativeDate.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import moment from 'moment';
|
||||
import formatTime from 'Utilities/Date/formatTime';
|
||||
import isInNextWeek from 'Utilities/Date/isInNextWeek';
|
||||
import isToday from 'Utilities/Date/isToday';
|
||||
import isTomorrow from 'Utilities/Date/isTomorrow';
|
||||
import isYesterday from 'Utilities/Date/isYesterday';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import formatDateTime from './formatDateTime';
|
||||
|
||||
interface GetRelativeDateOptions {
|
||||
date?: string;
|
||||
shortDateFormat: string;
|
||||
showRelativeDates: boolean;
|
||||
timeFormat?: string;
|
||||
includeSeconds?: boolean;
|
||||
timeForToday?: boolean;
|
||||
includeTime?: boolean;
|
||||
}
|
||||
|
||||
function getRelativeDate({
|
||||
date,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
timeFormat,
|
||||
includeSeconds = false,
|
||||
timeForToday = false,
|
||||
includeTime = false,
|
||||
}: GetRelativeDateOptions) {
|
||||
if (!date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((includeTime || timeForToday) && !timeFormat) {
|
||||
throw new Error(
|
||||
"getRelativeDate: 'timeFormat' is required when 'includeTime' or 'timeForToday' is true"
|
||||
);
|
||||
}
|
||||
|
||||
const isTodayDate = isToday(date);
|
||||
const time = timeFormat
|
||||
? formatTime(date, timeFormat, {
|
||||
includeMinuteZero: true,
|
||||
includeSeconds,
|
||||
})
|
||||
: '';
|
||||
|
||||
if (isTodayDate && timeForToday) {
|
||||
return time;
|
||||
}
|
||||
|
||||
if (!showRelativeDates) {
|
||||
return moment(date).format(shortDateFormat);
|
||||
}
|
||||
|
||||
if (isYesterday(date)) {
|
||||
return includeTime
|
||||
? translate('YesterdayAt', { time })
|
||||
: translate('Yesterday');
|
||||
}
|
||||
|
||||
if (isTodayDate) {
|
||||
return includeTime ? translate('TodayAt', { time }) : translate('Today');
|
||||
}
|
||||
|
||||
if (isTomorrow(date)) {
|
||||
return includeTime
|
||||
? translate('TomorrowAt', { time })
|
||||
: translate('Tomorrow');
|
||||
}
|
||||
|
||||
if (isInNextWeek(date)) {
|
||||
const day = moment(date).format('dddd');
|
||||
|
||||
return includeTime ? translate('DayOfWeekAt', { day, time }) : day;
|
||||
}
|
||||
|
||||
return includeTime
|
||||
? formatDateTime(date, shortDateFormat, timeFormat, { includeSeconds })
|
||||
: moment(date).format(shortDateFormat);
|
||||
}
|
||||
|
||||
export default getRelativeDate;
|
||||
@@ -608,5 +608,47 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
|
||||
allCriteria.Last().As<SingleEpisodeSearchCriteria>().SeasonNumber.Should().Be(2);
|
||||
allCriteria.Last().As<SingleEpisodeSearchCriteria>().EpisodeNumber.Should().Be(3);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task episode_search_should_include_series_title_when_not_a_direct_title_match()
|
||||
{
|
||||
_xemSeries.Title = "Sonarr's Title";
|
||||
_xemSeries.CleanTitle = "sonarrstitle";
|
||||
|
||||
WithEpisode(1, 12, 2, 3);
|
||||
|
||||
Mocker.GetMock<ISceneMappingService>()
|
||||
.Setup(s => s.FindByTvdbId(It.IsAny<int>()))
|
||||
.Returns(new List<SceneMapping>
|
||||
{
|
||||
new SceneMapping
|
||||
{
|
||||
TvdbId = _xemSeries.TvdbId,
|
||||
SearchTerm = "Sonarrs Title",
|
||||
ParseTerm = _xemSeries.CleanTitle,
|
||||
SeasonNumber = 1,
|
||||
SceneSeasonNumber = 1,
|
||||
SceneOrigin = "tvdb",
|
||||
Type = "ServicesProvider"
|
||||
}
|
||||
});
|
||||
|
||||
var allCriteria = WatchForSearchCriteria();
|
||||
|
||||
await Subject.EpisodeSearch(_xemEpisodes.First(), false, false);
|
||||
|
||||
Mocker.GetMock<ISceneMappingService>()
|
||||
.Verify(v => v.FindByTvdbId(_xemSeries.Id), Times.Once());
|
||||
|
||||
allCriteria.Should().HaveCount(2);
|
||||
|
||||
allCriteria.First().Should().BeOfType<SingleEpisodeSearchCriteria>();
|
||||
allCriteria.First().As<SingleEpisodeSearchCriteria>().SeasonNumber.Should().Be(1);
|
||||
allCriteria.First().As<SingleEpisodeSearchCriteria>().EpisodeNumber.Should().Be(12);
|
||||
|
||||
allCriteria.Last().Should().BeOfType<SingleEpisodeSearchCriteria>();
|
||||
allCriteria.Last().As<SingleEpisodeSearchCriteria>().SeasonNumber.Should().Be(2);
|
||||
allCriteria.Last().As<SingleEpisodeSearchCriteria>().EpisodeNumber.Should().Be(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
|
||||
[TestCase(10, "", "", "", null, HdrFormat.None)]
|
||||
[TestCase(10, "bt709", "bt709", "", null, HdrFormat.None)]
|
||||
[TestCase(8, "bt2020", "smpte2084", "", null, HdrFormat.None)]
|
||||
[TestCase(10, "bt2020", "bt2020-10", "", null, HdrFormat.Hlg10)]
|
||||
[TestCase(10, "bt2020", "bt2020-10", "", null, HdrFormat.None)]
|
||||
[TestCase(10, "bt2020", "arib-std-b67", "", null, HdrFormat.Hlg10)]
|
||||
[TestCase(10, "bt2020", "smpte2084", "", null, HdrFormat.Pq10)]
|
||||
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.SideData", null, HdrFormat.Pq10)]
|
||||
|
||||
@@ -5,7 +5,6 @@ using FluentValidation.Results;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Notifications;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Test.Common;
|
||||
@@ -15,9 +14,9 @@ namespace NzbDrone.Core.Test.NotificationTests
|
||||
[TestFixture]
|
||||
public class NotificationBaseFixture : TestBase
|
||||
{
|
||||
private class TestSetting : IProviderConfig
|
||||
private class TestSetting : NotificationSettingsBase<TestSetting>
|
||||
{
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult();
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ namespace NzbDrone.Core.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
var urlBase = _serverOptions.UrlBase ?? GetValue("UrlBase", "").Trim('/');
|
||||
var urlBase = (_serverOptions.UrlBase ?? GetValue("UrlBase", "")).Trim('/');
|
||||
|
||||
if (urlBase.IsNullOrWhiteSpace())
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Aria2
|
||||
@@ -13,9 +12,9 @@ namespace NzbDrone.Core.Download.Clients.Aria2
|
||||
}
|
||||
}
|
||||
|
||||
public class Aria2Settings : IProviderConfig
|
||||
public class Aria2Settings : DownloadClientSettingsBase<Aria2Settings>
|
||||
{
|
||||
private static readonly Aria2SettingsValidator Validator = new Aria2SettingsValidator();
|
||||
private static readonly Aria2SettingsValidator Validator = new ();
|
||||
|
||||
public Aria2Settings()
|
||||
{
|
||||
@@ -44,7 +43,7 @@ namespace NzbDrone.Core.Download.Clients.Aria2
|
||||
[FieldDefinition(5, Label = "Directory", Type = FieldType.Textbox, HelpText = "DownloadClientAriaSettingsDirectoryHelpText")]
|
||||
public string Directory { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using System.ComponentModel;
|
||||
using FluentValidation;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
|
||||
@@ -18,7 +17,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
}
|
||||
}
|
||||
|
||||
public class TorrentBlackholeSettings : IProviderConfig
|
||||
public class TorrentBlackholeSettings : DownloadClientSettingsBase<TorrentBlackholeSettings>
|
||||
{
|
||||
public TorrentBlackholeSettings()
|
||||
{
|
||||
@@ -26,7 +25,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
ReadOnly = true;
|
||||
}
|
||||
|
||||
private static readonly TorrentBlackholeSettingsValidator Validator = new TorrentBlackholeSettingsValidator();
|
||||
private static readonly TorrentBlackholeSettingsValidator Validator = new ();
|
||||
|
||||
[FieldDefinition(0, Label = "TorrentBlackholeTorrentFolder", Type = FieldType.Path, HelpText = "BlackholeFolderHelpText")]
|
||||
[FieldToken(TokenField.HelpText, "TorrentBlackholeTorrentFolder", "extension", ".torrent")]
|
||||
@@ -48,7 +47,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
[FieldDefinition(4, Label = "TorrentBlackholeSaveMagnetFilesReadOnly", Type = FieldType.Checkbox, HelpText = "TorrentBlackholeSaveMagnetFilesReadOnlyHelpText")]
|
||||
public bool ReadOnly { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
|
||||
@@ -15,9 +14,9 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
}
|
||||
}
|
||||
|
||||
public class UsenetBlackholeSettings : IProviderConfig
|
||||
public class UsenetBlackholeSettings : DownloadClientSettingsBase<UsenetBlackholeSettings>
|
||||
{
|
||||
private static readonly UsenetBlackholeSettingsValidator Validator = new UsenetBlackholeSettingsValidator();
|
||||
private static readonly UsenetBlackholeSettingsValidator Validator = new ();
|
||||
|
||||
[FieldDefinition(0, Label = "UsenetBlackholeNzbFolder", Type = FieldType.Path, HelpText = "BlackholeFolderHelpText")]
|
||||
[FieldToken(TokenField.HelpText, "UsenetBlackholeNzbFolder", "extension", ".nzb")]
|
||||
@@ -26,7 +25,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
[FieldDefinition(1, Label = "BlackholeWatchFolder", Type = FieldType.Path, HelpText = "BlackholeWatchFolderHelpText")]
|
||||
public string WatchFolder { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
@@ -17,9 +16,9 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
}
|
||||
}
|
||||
|
||||
public class DelugeSettings : IProviderConfig
|
||||
public class DelugeSettings : DownloadClientSettingsBase<DelugeSettings>
|
||||
{
|
||||
private static readonly DelugeSettingsValidator Validator = new DelugeSettingsValidator();
|
||||
private static readonly DelugeSettingsValidator Validator = new ();
|
||||
|
||||
public DelugeSettings()
|
||||
{
|
||||
@@ -67,7 +66,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
[FieldDefinition(11, Label = "DownloadClientDelugeSettingsDirectoryCompleted", Type = FieldType.Textbox, Advanced = true, HelpText = "DownloadClientDelugeSettingsDirectoryCompletedHelpText")]
|
||||
public string CompletedDirectory { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using Equ;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients
|
||||
{
|
||||
public abstract class DownloadClientSettingsBase<TSettings> : IProviderConfig, IEquatable<TSettings>
|
||||
where TSettings : DownloadClientSettingsBase<TSettings>
|
||||
{
|
||||
private static readonly MemberwiseEqualityComparer<TSettings> Comparer = MemberwiseEqualityComparer<TSettings>.ByProperties;
|
||||
|
||||
public abstract NzbDroneValidationResult Validate();
|
||||
|
||||
public bool Equals(TSettings other)
|
||||
{
|
||||
return Comparer.Equals(this as TSettings, other);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as TSettings);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Comparer.GetHashCode(this as TSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
@@ -26,9 +25,9 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
}
|
||||
}
|
||||
|
||||
public class DownloadStationSettings : IProviderConfig
|
||||
public class DownloadStationSettings : DownloadClientSettingsBase<DownloadStationSettings>
|
||||
{
|
||||
private static readonly DownloadStationSettingsValidator Validator = new DownloadStationSettingsValidator();
|
||||
private static readonly DownloadStationSettingsValidator Validator = new ();
|
||||
|
||||
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
|
||||
public string Host { get; set; }
|
||||
@@ -58,7 +57,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||
this.Port = 5000;
|
||||
}
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Linq;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Download.Clients.Flood.Models;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Flood
|
||||
@@ -17,9 +16,9 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
||||
}
|
||||
}
|
||||
|
||||
public class FloodSettings : IProviderConfig
|
||||
public class FloodSettings : DownloadClientSettingsBase<FloodSettings>
|
||||
{
|
||||
private static readonly FloodSettingsValidator Validator = new FloodSettingsValidator();
|
||||
private static readonly FloodSettingsValidator Validator = new ();
|
||||
|
||||
public FloodSettings()
|
||||
{
|
||||
@@ -69,7 +68,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
||||
[FieldDefinition(10, Label = "DownloadClientFloodSettingsStartOnAdd", Type = FieldType.Checkbox)]
|
||||
public bool StartOnAdd { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
|
||||
@@ -34,9 +33,9 @@ namespace NzbDrone.Core.Download.Clients.FreeboxDownload
|
||||
}
|
||||
}
|
||||
|
||||
public class FreeboxDownloadSettings : IProviderConfig
|
||||
public class FreeboxDownloadSettings : DownloadClientSettingsBase<FreeboxDownloadSettings>
|
||||
{
|
||||
private static readonly FreeboxDownloadSettingsValidator Validator = new FreeboxDownloadSettingsValidator();
|
||||
private static readonly FreeboxDownloadSettingsValidator Validator = new ();
|
||||
|
||||
public FreeboxDownloadSettings()
|
||||
{
|
||||
@@ -84,7 +83,7 @@ namespace NzbDrone.Core.Download.Clients.FreeboxDownload
|
||||
[FieldDefinition(10, Label = "DownloadClientSettingsAddPaused", Type = FieldType.Checkbox)]
|
||||
public bool AddPaused { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Hadouken
|
||||
@@ -22,9 +21,9 @@ namespace NzbDrone.Core.Download.Clients.Hadouken
|
||||
}
|
||||
}
|
||||
|
||||
public class HadoukenSettings : IProviderConfig
|
||||
public class HadoukenSettings : DownloadClientSettingsBase<HadoukenSettings>
|
||||
{
|
||||
private static readonly HadoukenSettingsValidator Validator = new HadoukenSettingsValidator();
|
||||
private static readonly HadoukenSettingsValidator Validator = new ();
|
||||
|
||||
public HadoukenSettings()
|
||||
{
|
||||
@@ -57,7 +56,7 @@ namespace NzbDrone.Core.Download.Clients.Hadouken
|
||||
[FieldDefinition(6, Label = "Category", Type = FieldType.Textbox, HelpText = "DownloadClientSettingsCategoryHelpText")]
|
||||
public string Category { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.NzbVortex
|
||||
@@ -23,9 +22,9 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex
|
||||
}
|
||||
}
|
||||
|
||||
public class NzbVortexSettings : IProviderConfig
|
||||
public class NzbVortexSettings : DownloadClientSettingsBase<NzbVortexSettings>
|
||||
{
|
||||
private static readonly NzbVortexSettingsValidator Validator = new NzbVortexSettingsValidator();
|
||||
private static readonly NzbVortexSettingsValidator Validator = new ();
|
||||
|
||||
public NzbVortexSettings()
|
||||
{
|
||||
@@ -59,7 +58,7 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex
|
||||
[FieldDefinition(6, Label = "DownloadClientSettingsOlderPriority", Type = FieldType.Select, SelectOptions = typeof(NzbVortexPriority), HelpText = "DownloadClientSettingsOlderPriorityEpisodeHelpText")]
|
||||
public int OlderTvPriority { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
@@ -21,9 +20,9 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
}
|
||||
}
|
||||
|
||||
public class NzbgetSettings : IProviderConfig
|
||||
public class NzbgetSettings : DownloadClientSettingsBase<NzbgetSettings>
|
||||
{
|
||||
private static readonly NzbgetSettingsValidator Validator = new NzbgetSettingsValidator();
|
||||
private static readonly NzbgetSettingsValidator Validator = new ();
|
||||
|
||||
public NzbgetSettings()
|
||||
{
|
||||
@@ -67,7 +66,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
[FieldDefinition(9, Label = "DownloadClientSettingsAddPaused", Type = FieldType.Checkbox, HelpText = "DownloadClientNzbgetSettingsAddPausedHelpText")]
|
||||
public bool AddPaused { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
|
||||
@@ -15,9 +14,9 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
|
||||
}
|
||||
}
|
||||
|
||||
public class PneumaticSettings : IProviderConfig
|
||||
public class PneumaticSettings : DownloadClientSettingsBase<PneumaticSettings>
|
||||
{
|
||||
private static readonly PneumaticSettingsValidator Validator = new PneumaticSettingsValidator();
|
||||
private static readonly PneumaticSettingsValidator Validator = new ();
|
||||
|
||||
[FieldDefinition(0, Label = "DownloadClientPneumaticSettingsNzbFolder", Type = FieldType.Path, HelpText = "DownloadClientPneumaticSettingsNzbFolderHelpText")]
|
||||
public string NzbFolder { get; set; }
|
||||
@@ -25,7 +24,7 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
|
||||
[FieldDefinition(1, Label = "DownloadClientPneumaticSettingsStrmFolder", Type = FieldType.Path, HelpText = "DownloadClientPneumaticSettingsStrmFolderHelpText")]
|
||||
public string StrmFolder { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
@@ -19,9 +18,9 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
}
|
||||
}
|
||||
|
||||
public class QBittorrentSettings : IProviderConfig
|
||||
public class QBittorrentSettings : DownloadClientSettingsBase<QBittorrentSettings>
|
||||
{
|
||||
private static readonly QBittorrentSettingsValidator Validator = new QBittorrentSettingsValidator();
|
||||
private static readonly QBittorrentSettingsValidator Validator = new ();
|
||||
|
||||
public QBittorrentSettings()
|
||||
{
|
||||
@@ -74,7 +73,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
[FieldDefinition(13, Label = "DownloadClientQbittorrentSettingsContentLayout", Type = FieldType.Select, SelectOptions = typeof(QBittorrentContentLayout), HelpText = "DownloadClientQbittorrentSettingsContentLayoutHelpText")]
|
||||
public int ContentLayout { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
@@ -32,9 +31,9 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
}
|
||||
}
|
||||
|
||||
public class SabnzbdSettings : IProviderConfig
|
||||
public class SabnzbdSettings : DownloadClientSettingsBase<SabnzbdSettings>
|
||||
{
|
||||
private static readonly SabnzbdSettingsValidator Validator = new SabnzbdSettingsValidator();
|
||||
private static readonly SabnzbdSettingsValidator Validator = new ();
|
||||
|
||||
public SabnzbdSettings()
|
||||
{
|
||||
@@ -78,7 +77,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
[FieldDefinition(9, Label = "DownloadClientSettingsOlderPriority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "DownloadClientSettingsOlderPriorityEpisodeHelpText")]
|
||||
public int OlderTvPriority { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients
|
||||
{
|
||||
public class TorrentSeedConfiguration
|
||||
{
|
||||
public static TorrentSeedConfiguration DefaultConfiguration = new TorrentSeedConfiguration();
|
||||
public static TorrentSeedConfiguration DefaultConfiguration = new ();
|
||||
|
||||
public double? Ratio { get; set; }
|
||||
public TimeSpan? SeedTime { get; set; }
|
||||
|
||||
@@ -2,7 +2,6 @@ using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
@@ -24,9 +23,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
}
|
||||
}
|
||||
|
||||
public class TransmissionSettings : IProviderConfig
|
||||
public class TransmissionSettings : DownloadClientSettingsBase<TransmissionSettings>
|
||||
{
|
||||
private static readonly TransmissionSettingsValidator Validator = new TransmissionSettingsValidator();
|
||||
private static readonly TransmissionSettingsValidator Validator = new ();
|
||||
|
||||
public TransmissionSettings()
|
||||
{
|
||||
@@ -72,7 +71,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
[FieldDefinition(10, Label = "DownloadClientSettingsAddPaused", Type = FieldType.Checkbox)]
|
||||
public bool AddPaused { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
@@ -17,9 +16,9 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
}
|
||||
}
|
||||
|
||||
public class RTorrentSettings : IProviderConfig
|
||||
public class RTorrentSettings : DownloadClientSettingsBase<RTorrentSettings>
|
||||
{
|
||||
private static readonly RTorrentSettingsValidator Validator = new RTorrentSettingsValidator();
|
||||
private static readonly RTorrentSettingsValidator Validator = new ();
|
||||
|
||||
public RTorrentSettings()
|
||||
{
|
||||
@@ -70,7 +69,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
[FieldDefinition(11, Label = "DownloadClientRTorrentSettingsAddStopped", Type = FieldType.Checkbox, HelpText = "DownloadClientRTorrentSettingsAddStoppedHelpText")]
|
||||
public bool AddStopped { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.UTorrent
|
||||
@@ -17,9 +16,9 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
|
||||
}
|
||||
}
|
||||
|
||||
public class UTorrentSettings : IProviderConfig
|
||||
public class UTorrentSettings : DownloadClientSettingsBase<UTorrentSettings>
|
||||
{
|
||||
private static readonly UTorrentSettingsValidator Validator = new UTorrentSettingsValidator();
|
||||
private static readonly UTorrentSettingsValidator Validator = new ();
|
||||
|
||||
public UTorrentSettings()
|
||||
{
|
||||
@@ -65,7 +64,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
|
||||
[FieldToken(TokenField.HelpText, "DownloadClientSettingsInitialState", "clientName", "uTorrent")]
|
||||
public int IntialState { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,14 +1,35 @@
|
||||
using NzbDrone.Core.Indexers;
|
||||
using System;
|
||||
using Equ;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
public class DownloadClientDefinition : ProviderDefinition
|
||||
public class DownloadClientDefinition : ProviderDefinition, IEquatable<DownloadClientDefinition>
|
||||
{
|
||||
private static readonly MemberwiseEqualityComparer<DownloadClientDefinition> Comparer = MemberwiseEqualityComparer<DownloadClientDefinition>.ByProperties;
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
|
||||
public int Priority { get; set; } = 1;
|
||||
|
||||
public bool RemoveCompletedDownloads { get; set; } = true;
|
||||
public bool RemoveFailedDownloads { get; set; } = true;
|
||||
|
||||
public bool Equals(DownloadClientDefinition other)
|
||||
{
|
||||
return Comparer.Equals(this, other);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as DownloadClientDefinition);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Comparer.GetHashCode(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,18 +29,17 @@ namespace NzbDrone.Core.ImportLists.AniList
|
||||
}
|
||||
}
|
||||
|
||||
public class AniListSettingsBase<TSettings> : IImportListSettings
|
||||
public class AniListSettingsBase<TSettings> : ImportListSettingsBase<TSettings>
|
||||
where TSettings : AniListSettingsBase<TSettings>
|
||||
{
|
||||
protected virtual AbstractValidator<TSettings> Validator => new AniListSettingsBaseValidator<TSettings>();
|
||||
private static readonly AniListSettingsBaseValidator<TSettings> Validator = new ();
|
||||
|
||||
public AniListSettingsBase()
|
||||
{
|
||||
BaseUrl = "https://graphql.anilist.co";
|
||||
SignIn = "startOAuth";
|
||||
}
|
||||
|
||||
public string BaseUrl { get; set; }
|
||||
public override string BaseUrl { get; set; } = "https://graphql.anilist.co";
|
||||
|
||||
[FieldDefinition(0, Label = "ImportListsSettingsAccessToken", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)]
|
||||
public string AccessToken { get; set; }
|
||||
@@ -54,7 +53,7 @@ namespace NzbDrone.Core.ImportLists.AniList
|
||||
[FieldDefinition(99, Label = "ImportListsAniListSettingsAuthenticateWithAniList", Type = FieldType.OAuth)]
|
||||
public string SignIn { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate((TSettings)this));
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists.AniList.List
|
||||
{
|
||||
public class AniListSettingsValidator : AniListSettingsBaseValidator<AniListSettings>
|
||||
{
|
||||
public AniListSettingsValidator()
|
||||
: base()
|
||||
{
|
||||
RuleFor(c => c.Username).NotEmpty();
|
||||
|
||||
@@ -18,10 +18,11 @@ namespace NzbDrone.Core.ImportLists.AniList.List
|
||||
|
||||
public class AniListSettings : AniListSettingsBase<AniListSettings>
|
||||
{
|
||||
public const string sectionImport = "Import List Status";
|
||||
public const string SectionImport = "Import List Status";
|
||||
|
||||
private static readonly AniListSettingsValidator Validator = new ();
|
||||
|
||||
public AniListSettings()
|
||||
: base()
|
||||
{
|
||||
ImportCurrent = true;
|
||||
ImportPlanning = true;
|
||||
@@ -29,42 +30,45 @@ namespace NzbDrone.Core.ImportLists.AniList.List
|
||||
ImportFinished = true;
|
||||
}
|
||||
|
||||
protected override AbstractValidator<AniListSettings> Validator => new AniListSettingsValidator();
|
||||
|
||||
[FieldDefinition(1, Label = "Username", HelpText = "ImportListsAniListSettingsUsernameHelpText")]
|
||||
public string Username { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "ImportListsAniListSettingsImportWatching", Type = FieldType.Checkbox, Section = sectionImport, HelpText = "ImportListsAniListSettingsImportWatchingHelpText")]
|
||||
[FieldDefinition(2, Label = "ImportListsAniListSettingsImportWatching", Type = FieldType.Checkbox, Section = SectionImport, HelpText = "ImportListsAniListSettingsImportWatchingHelpText")]
|
||||
public bool ImportCurrent { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "ImportListsAniListSettingsImportPlanning", Type = FieldType.Checkbox, Section = sectionImport, HelpText = "ImportListsAniListSettingsImportPlanningHelpText")]
|
||||
[FieldDefinition(3, Label = "ImportListsAniListSettingsImportPlanning", Type = FieldType.Checkbox, Section = SectionImport, HelpText = "ImportListsAniListSettingsImportPlanningHelpText")]
|
||||
public bool ImportPlanning { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "ImportListsAniListSettingsImportCompleted", Type = FieldType.Checkbox, Section = sectionImport, HelpText = "ImportListsAniListSettingsImportCompletedHelpText")]
|
||||
[FieldDefinition(4, Label = "ImportListsAniListSettingsImportCompleted", Type = FieldType.Checkbox, Section = SectionImport, HelpText = "ImportListsAniListSettingsImportCompletedHelpText")]
|
||||
public bool ImportCompleted { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "ImportListsAniListSettingsImportDropped", Type = FieldType.Checkbox, Section = sectionImport, HelpText = "ImportListsAniListSettingsImportDroppedHelpText")]
|
||||
[FieldDefinition(5, Label = "ImportListsAniListSettingsImportDropped", Type = FieldType.Checkbox, Section = SectionImport, HelpText = "ImportListsAniListSettingsImportDroppedHelpText")]
|
||||
public bool ImportDropped { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "ImportListsAniListSettingsImportPaused", Type = FieldType.Checkbox, Section = sectionImport, HelpText = "ImportListsAniListSettingsImportPausedHelpText")]
|
||||
[FieldDefinition(6, Label = "ImportListsAniListSettingsImportPaused", Type = FieldType.Checkbox, Section = SectionImport, HelpText = "ImportListsAniListSettingsImportPausedHelpText")]
|
||||
public bool ImportPaused { get; set; }
|
||||
|
||||
[FieldDefinition(7, Label = "ImportListsAniListSettingsImportRepeating", Type = FieldType.Checkbox, Section = sectionImport, HelpText = "ImportListsAniListSettingsImportRepeatingHelpText")]
|
||||
[FieldDefinition(7, Label = "ImportListsAniListSettingsImportRepeating", Type = FieldType.Checkbox, Section = SectionImport, HelpText = "ImportListsAniListSettingsImportRepeatingHelpText")]
|
||||
public bool ImportRepeating { get; set; }
|
||||
|
||||
[FieldDefinition(8, Label = "ImportListsAniListSettingsImportFinished", Type = FieldType.Checkbox, Section = sectionImport, HelpText = "ImportListsAniListSettingsImportFinishedHelpText")]
|
||||
[FieldDefinition(8, Label = "ImportListsAniListSettingsImportFinished", Type = FieldType.Checkbox, Section = SectionImport, HelpText = "ImportListsAniListSettingsImportFinishedHelpText")]
|
||||
public bool ImportFinished { get; set; }
|
||||
|
||||
[FieldDefinition(9, Label = "ImportListsAniListSettingsImportReleasing", Type = FieldType.Checkbox, Section = sectionImport, HelpText = "ImportListsAniListSettingsImportReleasingHelpText")]
|
||||
[FieldDefinition(9, Label = "ImportListsAniListSettingsImportReleasing", Type = FieldType.Checkbox, Section = SectionImport, HelpText = "ImportListsAniListSettingsImportReleasingHelpText")]
|
||||
public bool ImportReleasing { get; set; }
|
||||
|
||||
[FieldDefinition(10, Label = "ImportListsAniListSettingsImportNotYetReleased", Type = FieldType.Checkbox, Section = sectionImport, HelpText = "ImportListsAniListSettingsImportNotYetReleasedHelpText")]
|
||||
[FieldDefinition(10, Label = "ImportListsAniListSettingsImportNotYetReleased", Type = FieldType.Checkbox, Section = SectionImport, HelpText = "ImportListsAniListSettingsImportNotYetReleasedHelpText")]
|
||||
public bool ImportUnreleased { get; set; }
|
||||
|
||||
[FieldDefinition(11, Label = "ImportListsAniListSettingsImportCancelled", Type = FieldType.Checkbox, Section = sectionImport, HelpText = "ImportListsAniListSettingsImportCancelledHelpText")]
|
||||
[FieldDefinition(11, Label = "ImportListsAniListSettingsImportCancelled", Type = FieldType.Checkbox, Section = SectionImport, HelpText = "ImportListsAniListSettingsImportCancelledHelpText")]
|
||||
public bool ImportCancelled { get; set; }
|
||||
|
||||
[FieldDefinition(12, Label = "ImportListsAniListSettingsImportHiatus", Type = FieldType.Checkbox, Section = sectionImport, HelpText = "ImportListsAniListSettingsImportHiatusHelpText")]
|
||||
[FieldDefinition(12, Label = "ImportListsAniListSettingsImportHiatus", Type = FieldType.Checkbox, Section = SectionImport, HelpText = "ImportListsAniListSettingsImportHiatusHelpText")]
|
||||
public bool ImportHiatus { get; set; }
|
||||
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,19 +13,14 @@ namespace NzbDrone.Core.ImportLists.Custom
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomSettings : IImportListSettings
|
||||
public class CustomSettings : ImportListSettingsBase<CustomSettings>
|
||||
{
|
||||
private static readonly CustomSettingsValidator Validator = new CustomSettingsValidator();
|
||||
|
||||
public CustomSettings()
|
||||
{
|
||||
BaseUrl = "";
|
||||
}
|
||||
private static readonly CustomSettingsValidator Validator = new ();
|
||||
|
||||
[FieldDefinition(0, Label = "ImportListsCustomListSettingsUrl", HelpText = "ImportListsCustomListSettingsUrlHelpText")]
|
||||
public string BaseUrl { get; set; }
|
||||
public override string BaseUrl { get; set; } = string.Empty;
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -14,16 +14,16 @@ namespace NzbDrone.Core.ImportLists.Imdb
|
||||
}
|
||||
}
|
||||
|
||||
public class ImdbListSettings : IImportListSettings
|
||||
public class ImdbListSettings : ImportListSettingsBase<ImdbListSettings>
|
||||
{
|
||||
private static readonly ImdbSettingsValidator Validator = new ImdbSettingsValidator();
|
||||
private static readonly ImdbSettingsValidator Validator = new ();
|
||||
|
||||
public string BaseUrl { get; set; }
|
||||
public override string BaseUrl { get; set; }
|
||||
|
||||
[FieldDefinition(1, Label = "ImportListsImdbSettingsListId", HelpText = "ImportListsImdbSettingsListIdHelpText")]
|
||||
public string ListId { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using System;
|
||||
using Equ;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists
|
||||
{
|
||||
public class ImportListDefinition : ProviderDefinition
|
||||
public class ImportListDefinition : ProviderDefinition, IEquatable<ImportListDefinition>
|
||||
{
|
||||
private static readonly MemberwiseEqualityComparer<ImportListDefinition> Comparer = MemberwiseEqualityComparer<ImportListDefinition>.ByProperties;
|
||||
|
||||
public bool EnableAutomaticAdd { get; set; }
|
||||
public bool SearchForMissingEpisodes { get; set; }
|
||||
public MonitorTypes ShouldMonitor { get; set; }
|
||||
@@ -15,10 +18,31 @@ namespace NzbDrone.Core.ImportLists
|
||||
public bool SeasonFolder { get; set; }
|
||||
public string RootFolderPath { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public override bool Enable => EnableAutomaticAdd;
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public ImportListStatus Status { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public ImportListType ListType { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public TimeSpan MinRefreshInterval { get; set; }
|
||||
|
||||
public bool Equals(ImportListDefinition other)
|
||||
{
|
||||
return Comparer.Equals(this, other);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as ImportListDefinition);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Comparer.GetHashCode(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
src/NzbDrone.Core/ImportLists/ImportListSettingsBase.cs
Normal file
31
src/NzbDrone.Core/ImportLists/ImportListSettingsBase.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using Equ;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists
|
||||
{
|
||||
public abstract class ImportListSettingsBase<TSettings> : IImportListSettings, IEquatable<TSettings>
|
||||
where TSettings : ImportListSettingsBase<TSettings>
|
||||
{
|
||||
private static readonly MemberwiseEqualityComparer<TSettings> Comparer = MemberwiseEqualityComparer<TSettings>.ByProperties;
|
||||
|
||||
public abstract string BaseUrl { get; set; }
|
||||
|
||||
public abstract NzbDroneValidationResult Validate();
|
||||
|
||||
public bool Equals(TSettings other)
|
||||
{
|
||||
return Comparer.Equals(this as TSettings, other);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as TSettings);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Comparer.GetHashCode(this as TSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,16 +24,11 @@ namespace NzbDrone.Core.ImportLists.MyAnimeList
|
||||
}
|
||||
}
|
||||
|
||||
public class MyAnimeListSettings : IImportListSettings
|
||||
public class MyAnimeListSettings : ImportListSettingsBase<MyAnimeListSettings>
|
||||
{
|
||||
public string BaseUrl { get; set; }
|
||||
private static readonly MalSettingsValidator Validator = new ();
|
||||
|
||||
protected AbstractValidator<MyAnimeListSettings> Validator => new MalSettingsValidator();
|
||||
|
||||
public MyAnimeListSettings()
|
||||
{
|
||||
BaseUrl = "https://api.myanimelist.net/v2";
|
||||
}
|
||||
public override string BaseUrl { get; set; } = "https://api.myanimelist.net/v2";
|
||||
|
||||
[FieldDefinition(0, Label = "ImportListsMyAnimeListSettingsListStatus", Type = FieldType.Select, SelectOptions = typeof(MyAnimeListStatus), HelpText = "ImportListsMyAnimeListSettingsListStatusHelpText")]
|
||||
public int ListStatus { get; set; }
|
||||
@@ -50,7 +45,7 @@ namespace NzbDrone.Core.ImportLists.MyAnimeList
|
||||
[FieldDefinition(99, Label = "ImportListsMyAnimeListSettingsAuthenticateWithMyAnimeList", Type = FieldType.OAuth)]
|
||||
public string SignIn { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace NzbDrone.Core.ImportLists.Plex
|
||||
}
|
||||
}
|
||||
|
||||
public class PlexListSettings : IImportListSettings
|
||||
public class PlexListSettings : ImportListSettingsBase<PlexListSettings>
|
||||
{
|
||||
protected virtual PlexListSettingsValidator Validator => new PlexListSettingsValidator();
|
||||
private static readonly PlexListSettingsValidator Validator = new ();
|
||||
|
||||
public PlexListSettings()
|
||||
{
|
||||
@@ -25,7 +25,7 @@ namespace NzbDrone.Core.ImportLists.Plex
|
||||
|
||||
public virtual string Scope => "";
|
||||
|
||||
public string BaseUrl { get; set; }
|
||||
public override string BaseUrl { get; set; }
|
||||
|
||||
[FieldDefinition(0, Label = "ImportListsSettingsAccessToken", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)]
|
||||
public string AccessToken { get; set; }
|
||||
@@ -33,7 +33,7 @@ namespace NzbDrone.Core.ImportLists.Plex
|
||||
[FieldDefinition(99, Label = "ImportListsPlexSettingsAuthenticateWithPlex", Type = FieldType.OAuth)]
|
||||
public string SignIn { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ namespace NzbDrone.Core.ImportLists.Rss.Plex
|
||||
}
|
||||
}
|
||||
|
||||
public class PlexRssImportSettings : RssImportBaseSettings
|
||||
public class PlexRssImportSettings : RssImportBaseSettings<PlexRssImportSettings>
|
||||
{
|
||||
private PlexRssImportSettingsValidator Validator => new ();
|
||||
private static readonly PlexRssImportSettingsValidator Validator = new ();
|
||||
|
||||
[FieldDefinition(0, Label = "ImportListsSettingsRssUrl", Type = FieldType.Textbox, HelpLink = "https://app.plex.tv/desktop/#!/settings/watchlist")]
|
||||
public override string Url { get; set; }
|
||||
|
||||
@@ -8,7 +8,7 @@ using NzbDrone.Core.Parser;
|
||||
namespace NzbDrone.Core.ImportLists.Rss
|
||||
{
|
||||
public class RssImportBase<TSettings> : HttpImportListBase<TSettings>
|
||||
where TSettings : RssImportBaseSettings, new()
|
||||
where TSettings : RssImportBaseSettings<TSettings>, new()
|
||||
{
|
||||
public override string Name => "RSS List Base";
|
||||
public override ImportListType ListType => ImportListType.Advanced;
|
||||
@@ -36,7 +36,7 @@ namespace NzbDrone.Core.ImportLists.Rss
|
||||
|
||||
public override IImportListRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new RssImportRequestGenerator
|
||||
return new RssImportRequestGenerator<TSettings>
|
||||
{
|
||||
Settings = Settings
|
||||
};
|
||||
|
||||
@@ -4,7 +4,8 @@ using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists.Rss
|
||||
{
|
||||
public class RssImportSettingsValidator : AbstractValidator<RssImportBaseSettings>
|
||||
public class RssImportSettingsValidator<TSettings> : AbstractValidator<TSettings>
|
||||
where TSettings : RssImportBaseSettings<TSettings>
|
||||
{
|
||||
public RssImportSettingsValidator()
|
||||
{
|
||||
@@ -12,18 +13,19 @@ namespace NzbDrone.Core.ImportLists.Rss
|
||||
}
|
||||
}
|
||||
|
||||
public class RssImportBaseSettings : IImportListSettings
|
||||
public class RssImportBaseSettings<TSettings> : ImportListSettingsBase<TSettings>
|
||||
where TSettings : RssImportBaseSettings<TSettings>
|
||||
{
|
||||
private RssImportSettingsValidator Validator => new ();
|
||||
private static readonly RssImportSettingsValidator<TSettings> Validator = new ();
|
||||
|
||||
public string BaseUrl { get; set; }
|
||||
public override string BaseUrl { get; set; }
|
||||
|
||||
[FieldDefinition(0, Label = "ImportListsSettingsRssUrl", Type = FieldType.Textbox)]
|
||||
public virtual string Url { get; set; }
|
||||
|
||||
public virtual NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
return new NzbDroneValidationResult(Validator.Validate(this as TSettings));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,10 @@ using NzbDrone.Common.Http;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists.Rss
|
||||
{
|
||||
public class RssImportRequestGenerator : IImportListRequestGenerator
|
||||
public class RssImportRequestGenerator<TSettings> : IImportListRequestGenerator
|
||||
where TSettings : RssImportBaseSettings<TSettings>, new()
|
||||
{
|
||||
public RssImportBaseSettings Settings { get; set; }
|
||||
public RssImportBaseSettings<TSettings> Settings { get; set; }
|
||||
|
||||
public virtual ImportListPageableRequestChain GetListItems()
|
||||
{
|
||||
@@ -18,9 +19,7 @@ namespace NzbDrone.Core.ImportLists.Rss
|
||||
|
||||
private IEnumerable<ImportListRequest> GetSeriesRequest()
|
||||
{
|
||||
var request = new ImportListRequest(Settings.Url, HttpAccept.Rss);
|
||||
|
||||
yield return request;
|
||||
yield return new ImportListRequest(Settings.Url, HttpAccept.Rss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,18 +24,17 @@ namespace NzbDrone.Core.ImportLists.Simkl
|
||||
}
|
||||
}
|
||||
|
||||
public class SimklSettingsBase<TSettings> : IImportListSettings
|
||||
public class SimklSettingsBase<TSettings> : ImportListSettingsBase<TSettings>
|
||||
where TSettings : SimklSettingsBase<TSettings>
|
||||
{
|
||||
protected virtual AbstractValidator<TSettings> Validator => new SimklSettingsBaseValidator<TSettings>();
|
||||
private static readonly SimklSettingsBaseValidator<TSettings> Validator = new ();
|
||||
|
||||
public SimklSettingsBase()
|
||||
{
|
||||
BaseUrl = "https://api.simkl.com";
|
||||
SignIn = "startOAuth";
|
||||
}
|
||||
|
||||
public string BaseUrl { get; set; }
|
||||
public override string BaseUrl { get; set; } = "https://api.simkl.com";
|
||||
|
||||
[FieldDefinition(0, Label = "ImportListsSettingsAccessToken", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)]
|
||||
public string AccessToken { get; set; }
|
||||
@@ -52,7 +51,7 @@ namespace NzbDrone.Core.ImportLists.Simkl
|
||||
[FieldDefinition(99, Label = "ImportListsSimklSettingsAuthenticatewithSimkl", Type = FieldType.OAuth)]
|
||||
public string SignIn { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate((TSettings)this));
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists.Simkl.User
|
||||
{
|
||||
public class SimklUserSettingsValidator : SimklSettingsBaseValidator<SimklUserSettings>
|
||||
{
|
||||
public SimklUserSettingsValidator()
|
||||
: base()
|
||||
{
|
||||
RuleFor(c => c.ListType).NotNull();
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace NzbDrone.Core.ImportLists.Simkl.User
|
||||
|
||||
public class SimklUserSettings : SimklSettingsBase<SimklUserSettings>
|
||||
{
|
||||
protected override AbstractValidator<SimklUserSettings> Validator => new SimklUserSettingsValidator();
|
||||
private static readonly SimklUserSettingsValidator Validator = new ();
|
||||
|
||||
public SimklUserSettings()
|
||||
{
|
||||
@@ -27,5 +27,10 @@ namespace NzbDrone.Core.ImportLists.Simkl.User
|
||||
|
||||
[FieldDefinition(1, Label = "ImportListsSimklSettingsShowType", Type = FieldType.Select, SelectOptions = typeof(SimklUserShowType), HelpText = "ImportListsSimklSettingsShowTypeHelpText")]
|
||||
public int ShowType { get; set; }
|
||||
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,12 @@ namespace NzbDrone.Core.ImportLists.Sonarr
|
||||
}
|
||||
}
|
||||
|
||||
public class SonarrSettings : IImportListSettings
|
||||
public class SonarrSettings : ImportListSettingsBase<SonarrSettings>
|
||||
{
|
||||
private static readonly SonarrSettingsValidator Validator = new SonarrSettingsValidator();
|
||||
private static readonly SonarrSettingsValidator Validator = new ();
|
||||
|
||||
public SonarrSettings()
|
||||
{
|
||||
BaseUrl = "";
|
||||
ApiKey = "";
|
||||
ProfileIds = Array.Empty<int>();
|
||||
LanguageProfileIds = Array.Empty<int>();
|
||||
@@ -30,7 +29,7 @@ namespace NzbDrone.Core.ImportLists.Sonarr
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "ImportListsSonarrSettingsFullUrl", HelpText = "ImportListsSonarrSettingsFullUrlHelpText")]
|
||||
public string BaseUrl { get; set; }
|
||||
public override string BaseUrl { get; set; } = string.Empty;
|
||||
|
||||
[FieldDefinition(1, Label = "ApiKey", HelpText = "ImportListsSonarrSettingsApiKeyHelpText")]
|
||||
public string ApiKey { get; set; }
|
||||
@@ -51,7 +50,7 @@ namespace NzbDrone.Core.ImportLists.Sonarr
|
||||
[FieldDefinition(6, Type = FieldType.Select, SelectOptionsProviderAction = "getLanguageProfiles", Label = "Language Profiles", HelpText = "Language Profiles from the source instance to import from")]
|
||||
public IEnumerable<int> LanguageProfileIds { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists.Trakt.List
|
||||
{
|
||||
public class TraktListSettingsValidator : TraktSettingsBaseValidator<TraktListSettings>
|
||||
{
|
||||
public TraktListSettingsValidator()
|
||||
: base()
|
||||
{
|
||||
RuleFor(c => c.Username).NotEmpty();
|
||||
RuleFor(c => c.Listname).NotEmpty();
|
||||
@@ -15,12 +15,17 @@ namespace NzbDrone.Core.ImportLists.Trakt.List
|
||||
|
||||
public class TraktListSettings : TraktSettingsBase<TraktListSettings>
|
||||
{
|
||||
protected override AbstractValidator<TraktListSettings> Validator => new TraktListSettingsValidator();
|
||||
private static readonly TraktListSettingsValidator Validator = new ();
|
||||
|
||||
[FieldDefinition(1, Label = "Username", HelpText = "ImportListsTraktSettingsUsernameHelpText")]
|
||||
public string Username { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "ImportListsTraktSettingsListName", HelpText = "ImportListsTraktSettingsListNameHelpText")]
|
||||
public string Listname { get; set; }
|
||||
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@ using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists.Trakt.Popular
|
||||
{
|
||||
public class TraktPopularSettingsValidator : TraktSettingsBaseValidator<TraktPopularSettings>
|
||||
{
|
||||
public TraktPopularSettingsValidator()
|
||||
: base()
|
||||
{
|
||||
RuleFor(c => c.TraktListType).NotNull();
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.ImportLists.Trakt.Popular
|
||||
|
||||
public class TraktPopularSettings : TraktSettingsBase<TraktPopularSettings>
|
||||
{
|
||||
protected override AbstractValidator<TraktPopularSettings> Validator => new TraktPopularSettingsValidator();
|
||||
private static readonly TraktPopularSettingsValidator Validator = new ();
|
||||
|
||||
public TraktPopularSettings()
|
||||
{
|
||||
@@ -46,5 +46,10 @@ namespace NzbDrone.Core.ImportLists.Trakt.Popular
|
||||
|
||||
[FieldDefinition(5, Label = "ImportListsTraktSettingsYears", HelpText = "ImportListsTraktSettingsYearsHelpText")]
|
||||
public string Years { get; set; }
|
||||
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,19 +34,18 @@ namespace NzbDrone.Core.ImportLists.Trakt
|
||||
}
|
||||
}
|
||||
|
||||
public class TraktSettingsBase<TSettings> : IImportListSettings
|
||||
public class TraktSettingsBase<TSettings> : ImportListSettingsBase<TSettings>
|
||||
where TSettings : TraktSettingsBase<TSettings>
|
||||
{
|
||||
protected virtual AbstractValidator<TSettings> Validator => new TraktSettingsBaseValidator<TSettings>();
|
||||
private static readonly TraktSettingsBaseValidator<TSettings> Validator = new ();
|
||||
|
||||
public TraktSettingsBase()
|
||||
{
|
||||
BaseUrl = "https://api.trakt.tv";
|
||||
SignIn = "startOAuth";
|
||||
Limit = 100;
|
||||
}
|
||||
|
||||
public string BaseUrl { get; set; }
|
||||
public override string BaseUrl { get; set; } = "https://api.trakt.tv";
|
||||
|
||||
[FieldDefinition(0, Label = "ImportListsSettingsAccessToken", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)]
|
||||
public string AccessToken { get; set; }
|
||||
@@ -69,7 +68,7 @@ namespace NzbDrone.Core.ImportLists.Trakt
|
||||
[FieldDefinition(99, Label = "ImportListsTraktSettingsAuthenticateWithTrakt", Type = FieldType.OAuth)]
|
||||
public string SignIn { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate((TSettings)this));
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.ImportLists.Trakt.User
|
||||
{
|
||||
public class TraktUserSettingsValidator : TraktSettingsBaseValidator<TraktUserSettings>
|
||||
{
|
||||
public TraktUserSettingsValidator()
|
||||
: base()
|
||||
{
|
||||
RuleFor(c => c.TraktListType).NotNull();
|
||||
RuleFor(c => c.TraktWatchedListType).NotNull();
|
||||
@@ -16,7 +16,7 @@ namespace NzbDrone.Core.ImportLists.Trakt.User
|
||||
|
||||
public class TraktUserSettings : TraktSettingsBase<TraktUserSettings>
|
||||
{
|
||||
protected override AbstractValidator<TraktUserSettings> Validator => new TraktUserSettingsValidator();
|
||||
private static readonly TraktUserSettingsValidator Validator = new ();
|
||||
|
||||
public TraktUserSettings()
|
||||
{
|
||||
@@ -36,6 +36,11 @@ namespace NzbDrone.Core.ImportLists.Trakt.User
|
||||
|
||||
[FieldDefinition(4, Label = "Username", HelpText = "ImportListsTraktSettingsUserListUsernameHelpText")]
|
||||
public string Username { get; set; }
|
||||
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
|
||||
public enum TraktUserWatchSorting
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
||||
public virtual bool UserInvokedSearch { get; set; }
|
||||
public virtual bool InteractiveSearch { get; set; }
|
||||
|
||||
public List<string> AllSceneTitles => SceneTitles.Concat(CleanSceneTitles).Distinct().ToList();
|
||||
public List<string> CleanSceneTitles => SceneTitles.Select(GetCleanSceneTitle).Distinct().ToList();
|
||||
|
||||
public static string GetCleanSceneTitle(string title)
|
||||
|
||||
@@ -265,7 +265,7 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
}
|
||||
}
|
||||
|
||||
if (sceneMapping.ParseTerm == series.CleanTitle && sceneMapping.FilterRegex.IsNullOrWhiteSpace())
|
||||
if (sceneMapping.SearchTerm == series.Title && sceneMapping.FilterRegex.IsNullOrWhiteSpace())
|
||||
{
|
||||
// Disable the implied mapping if we have an explicit mapping by the same name
|
||||
includeGlobal = false;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Languages;
|
||||
@@ -18,7 +19,7 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
}
|
||||
}
|
||||
|
||||
public class BroadcastheNetSettings : ITorrentIndexerSettings
|
||||
public class BroadcastheNetSettings : PropertywiseEquatable<BroadcastheNetSettings>, ITorrentIndexerSettings
|
||||
{
|
||||
private static readonly BroadcastheNetSettingsValidator Validator = new ();
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Languages;
|
||||
@@ -15,9 +16,9 @@ namespace NzbDrone.Core.Indexers.Fanzub
|
||||
}
|
||||
}
|
||||
|
||||
public class FanzubSettings : IIndexerSettings
|
||||
public class FanzubSettings : PropertywiseEquatable<FanzubSettings>, IIndexerSettings
|
||||
{
|
||||
private static readonly FanzubSettingsValidator Validator = new FanzubSettingsValidator();
|
||||
private static readonly FanzubSettingsValidator Validator = new ();
|
||||
|
||||
public FanzubSettings()
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Languages;
|
||||
@@ -19,9 +20,9 @@ namespace NzbDrone.Core.Indexers.FileList
|
||||
}
|
||||
}
|
||||
|
||||
public class FileListSettings : ITorrentIndexerSettings
|
||||
public class FileListSettings : PropertywiseEquatable<FileListSettings>, ITorrentIndexerSettings
|
||||
{
|
||||
private static readonly FileListSettingsValidator Validator = new FileListSettingsValidator();
|
||||
private static readonly FileListSettingsValidator Validator = new ();
|
||||
|
||||
public FileListSettings()
|
||||
{
|
||||
@@ -61,7 +62,7 @@ namespace NzbDrone.Core.Indexers.FileList
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(7)]
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new ();
|
||||
|
||||
[FieldDefinition(8, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)]
|
||||
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Languages;
|
||||
@@ -18,7 +19,7 @@ namespace NzbDrone.Core.Indexers.HDBits
|
||||
}
|
||||
}
|
||||
|
||||
public class HDBitsSettings : ITorrentIndexerSettings
|
||||
public class HDBitsSettings : PropertywiseEquatable<HDBitsSettings>, ITorrentIndexerSettings
|
||||
{
|
||||
private static readonly HDBitsSettingsValidator Validator = new ();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
@@ -25,9 +26,9 @@ namespace NzbDrone.Core.Indexers.IPTorrents
|
||||
}
|
||||
}
|
||||
|
||||
public class IPTorrentsSettings : ITorrentIndexerSettings
|
||||
public class IPTorrentsSettings : PropertywiseEquatable<IPTorrentsSettings>, ITorrentIndexerSettings
|
||||
{
|
||||
private static readonly IPTorrentsSettingsValidator Validator = new IPTorrentsSettingsValidator();
|
||||
private static readonly IPTorrentsSettingsValidator Validator = new ();
|
||||
|
||||
public IPTorrentsSettings()
|
||||
{
|
||||
@@ -42,7 +43,7 @@ namespace NzbDrone.Core.Indexers.IPTorrents
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(2)]
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new ();
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)]
|
||||
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
using System;
|
||||
using Equ;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Indexers
|
||||
{
|
||||
public class IndexerDefinition : ProviderDefinition
|
||||
public class IndexerDefinition : ProviderDefinition, IEquatable<IndexerDefinition>
|
||||
{
|
||||
private static readonly MemberwiseEqualityComparer<IndexerDefinition> Comparer = MemberwiseEqualityComparer<IndexerDefinition>.ByProperties;
|
||||
|
||||
public const int DefaultPriority = 25;
|
||||
|
||||
public IndexerDefinition()
|
||||
@@ -11,18 +15,41 @@ namespace NzbDrone.Core.Indexers
|
||||
Priority = DefaultPriority;
|
||||
}
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsRss { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsSearch { get; set; }
|
||||
|
||||
public bool EnableRss { get; set; }
|
||||
public bool EnableAutomaticSearch { get; set; }
|
||||
public bool EnableInteractiveSearch { get; set; }
|
||||
public int DownloadClientId { get; set; }
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
public bool SupportsRss { get; set; }
|
||||
public bool SupportsSearch { get; set; }
|
||||
public int Priority { get; set; }
|
||||
public int SeasonSearchMaximumSingleEpisodeAge { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public override bool Enable => EnableRss || EnableAutomaticSearch || EnableInteractiveSearch;
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public IndexerStatus Status { get; set; }
|
||||
|
||||
public bool Equals(IndexerDefinition other)
|
||||
{
|
||||
return Comparer.Equals(this, other);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as IndexerDefinition);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Comparer.GetHashCode(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +410,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
$"&season={NewznabifySeasonNumber(searchCriteria.SeasonNumber)}&ep={searchCriteria.EpisodeNumber}");
|
||||
}
|
||||
|
||||
var queryTitles = TextSearchEngine == "raw" ? searchCriteria.SceneTitles : searchCriteria.CleanSceneTitles;
|
||||
var queryTitles = TextSearchEngine == "raw" ? searchCriteria.AllSceneTitles : searchCriteria.CleanSceneTitles;
|
||||
|
||||
foreach (var queryTitle in queryTitles)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
@@ -28,7 +29,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
return settings.BaseUrl != null && ApiKeyWhiteList.Any(c => settings.BaseUrl.ToLowerInvariant().Contains(c));
|
||||
}
|
||||
|
||||
private static readonly Regex AdditionalParametersRegex = new Regex(@"(&.+?\=.+?)+", RegexOptions.Compiled);
|
||||
private static readonly Regex AdditionalParametersRegex = new (@"(&.+?\=.+?)+", RegexOptions.Compiled);
|
||||
|
||||
public NewznabSettingsValidator()
|
||||
{
|
||||
@@ -48,9 +49,9 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
}
|
||||
}
|
||||
|
||||
public class NewznabSettings : IIndexerSettings
|
||||
public class NewznabSettings : PropertywiseEquatable<NewznabSettings>, IIndexerSettings
|
||||
{
|
||||
private static readonly NewznabSettingsValidator Validator = new NewznabSettingsValidator();
|
||||
private static readonly NewznabSettingsValidator Validator = new ();
|
||||
|
||||
public NewznabSettings()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Languages;
|
||||
@@ -19,9 +20,9 @@ namespace NzbDrone.Core.Indexers.Nyaa
|
||||
}
|
||||
}
|
||||
|
||||
public class NyaaSettings : ITorrentIndexerSettings
|
||||
public class NyaaSettings : PropertywiseEquatable<NyaaSettings>, ITorrentIndexerSettings
|
||||
{
|
||||
private static readonly NyaaSettingsValidator Validator = new NyaaSettingsValidator();
|
||||
private static readonly NyaaSettingsValidator Validator = new ();
|
||||
|
||||
public NyaaSettings()
|
||||
{
|
||||
@@ -44,7 +45,7 @@ namespace NzbDrone.Core.Indexers.Nyaa
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(4)]
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new ();
|
||||
|
||||
[FieldDefinition(5, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)]
|
||||
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Validation;
|
||||
@@ -46,7 +47,7 @@ namespace NzbDrone.Core.Indexers
|
||||
}
|
||||
}
|
||||
|
||||
public class SeedCriteriaSettings
|
||||
public class SeedCriteriaSettings : PropertywiseEquatable<SeedCriteriaSettings>
|
||||
{
|
||||
[FieldDefinition(0, Type = FieldType.Number, Label = "IndexerSettingsSeedRatio", HelpText = "IndexerSettingsSeedRatioHelpText")]
|
||||
public double? SeedRatio { get; set; }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Languages;
|
||||
@@ -17,9 +18,9 @@ namespace NzbDrone.Core.Indexers.TorrentRss
|
||||
}
|
||||
}
|
||||
|
||||
public class TorrentRssIndexerSettings : ITorrentIndexerSettings
|
||||
public class TorrentRssIndexerSettings : PropertywiseEquatable<TorrentRssIndexerSettings>, ITorrentIndexerSettings
|
||||
{
|
||||
private static readonly TorrentRssIndexerSettingsValidator Validator = new TorrentRssIndexerSettingsValidator();
|
||||
private static readonly TorrentRssIndexerSettingsValidator Validator = new ();
|
||||
|
||||
public TorrentRssIndexerSettings()
|
||||
{
|
||||
@@ -42,7 +43,7 @@ namespace NzbDrone.Core.Indexers.TorrentRss
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(4)]
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new ();
|
||||
|
||||
[FieldDefinition(5, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)]
|
||||
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Languages;
|
||||
@@ -18,9 +19,9 @@ namespace NzbDrone.Core.Indexers.Torrentleech
|
||||
}
|
||||
}
|
||||
|
||||
public class TorrentleechSettings : ITorrentIndexerSettings
|
||||
public class TorrentleechSettings : PropertywiseEquatable<TorrentleechSettings>, ITorrentIndexerSettings
|
||||
{
|
||||
private static readonly TorrentleechSettingsValidator Validator = new TorrentleechSettingsValidator();
|
||||
private static readonly TorrentleechSettingsValidator Validator = new ();
|
||||
|
||||
public TorrentleechSettings()
|
||||
{
|
||||
@@ -39,7 +40,7 @@ namespace NzbDrone.Core.Indexers.Torrentleech
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(3)]
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new ();
|
||||
|
||||
[FieldDefinition(4, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)]
|
||||
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Equ;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
@@ -18,7 +19,7 @@ namespace NzbDrone.Core.Indexers.Torznab
|
||||
return settings.BaseUrl != null && ApiKeyWhiteList.Any(c => settings.BaseUrl.ToLowerInvariant().Contains(c));
|
||||
}
|
||||
|
||||
private static readonly Regex AdditionalParametersRegex = new Regex(@"(&.+?\=.+?)+", RegexOptions.Compiled);
|
||||
private static readonly Regex AdditionalParametersRegex = new (@"(&.+?\=.+?)+", RegexOptions.Compiled);
|
||||
|
||||
public TorznabSettingsValidator()
|
||||
{
|
||||
@@ -40,9 +41,11 @@ namespace NzbDrone.Core.Indexers.Torznab
|
||||
}
|
||||
}
|
||||
|
||||
public class TorznabSettings : NewznabSettings, ITorrentIndexerSettings
|
||||
public class TorznabSettings : NewznabSettings, ITorrentIndexerSettings, IEquatable<TorznabSettings>
|
||||
{
|
||||
private static readonly TorznabSettingsValidator Validator = new TorznabSettingsValidator();
|
||||
private static readonly TorznabSettingsValidator Validator = new ();
|
||||
|
||||
private static readonly MemberwiseEqualityComparer<TorznabSettings> Comparer = MemberwiseEqualityComparer<TorznabSettings>.ByProperties;
|
||||
|
||||
public TorznabSettings()
|
||||
{
|
||||
@@ -53,7 +56,7 @@ namespace NzbDrone.Core.Indexers.Torznab
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(9)]
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings();
|
||||
public SeedCriteriaSettings SeedCriteria { get; set; } = new ();
|
||||
|
||||
[FieldDefinition(10, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)]
|
||||
public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; }
|
||||
@@ -62,5 +65,20 @@ namespace NzbDrone.Core.Indexers.Torznab
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
public bool Equals(TorznabSettings other)
|
||||
{
|
||||
return Comparer.Equals(this, other);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as TorznabSettings);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Comparer.GetHashCode(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -743,5 +743,14 @@
|
||||
"IndexerHDBitsSettingsMediums": "Mitjans",
|
||||
"UpdateStartupTranslocationHealthCheckMessage": "No es pot instal·lar l'actualització perquè la carpeta d'inici '{startupFolder}' es troba en una carpeta de translocació d'aplicacions.",
|
||||
"UpdateStartupNotWritableHealthCheckMessage": "No es pot instal·lar l'actualització perquè l'usuari '{userName}' no té permisos d'escriptura de la carpeta d'inici '{startupFolder}'.",
|
||||
"DownloadClientTransmissionSettingsDirectoryHelpText": "Ubicació opcional per a les baixades, deixeu-lo en blanc per utilitzar la ubicació predeterminada de Transmission"
|
||||
"DownloadClientTransmissionSettingsDirectoryHelpText": "Ubicació opcional per a les baixades, deixeu-lo en blanc per utilitzar la ubicació predeterminada de Transmission",
|
||||
"Mixed": "Combinat",
|
||||
"Proxy": "Servidor intermediari",
|
||||
"Mapping": "Mapejat",
|
||||
"More": "Més",
|
||||
"MultiLanguages": "Multi-idioma",
|
||||
"Organize": "Organitza",
|
||||
"Search": "Cerca",
|
||||
"SelectDropdown": "Seleccioneu...",
|
||||
"Shutdown": "Apaga"
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
"AddConnectionImplementation": "Verbindung hinzufügen - {implementationName}",
|
||||
"AddDownloadClientImplementation": "Download-Client hinzufügen - {implementationName}",
|
||||
"AddIndexerImplementation": "Indexer hinzufügen - {implementationName}",
|
||||
"AddNotificationError": "Neue Benachrichtigung konnte nicht hinzugefügt werden, bitte versuchen Sie es erneut.",
|
||||
"AddNotificationError": "Die neue Benachrichtigung konnte nicht hinzugefügt werden, bitte erneut probieren.",
|
||||
"AddQualityProfileError": "Qualitätsprofil konnte nicht hinzugefügt werden. Bitte versuchen Sie es erneut.",
|
||||
"AddNewSeriesRootFolderHelpText": "Unterordner '{folder}' wird automatisch erstellt",
|
||||
"AddNewSeriesSearchForMissingEpisodes": "Suche für fehlende Episoden starten",
|
||||
@@ -144,7 +144,7 @@
|
||||
"AuthenticationRequiredPasswordHelpTextWarning": "Gib ein neues Passwort ein",
|
||||
"AuthenticationRequiredUsernameHelpTextWarning": "Gib einen neuen Benutzernamen ein",
|
||||
"AuthenticationRequiredHelpText": "Ändern, welche anfragen Authentifizierung benötigen. Ändere nichts wenn du dir nicht des Risikos bewusst bist.",
|
||||
"AnalyseVideoFilesHelpText": "Videoinformationen wie Auflösung, Laufzeit und Codec-Informationen aus Dateien extrahieren. Dies erfordert, dass {appName} Teile der Datei liest, was bei Scans zu hoher Festplatten- oder Netzwerkaktivität führen kann.",
|
||||
"AnalyseVideoFilesHelpText": "Videoinformationen wie Auflösung, Laufzeit und Codec aus Datien erkennen. Dazu ist es erforderlich, dass {appName} Teile der Datei liest, was zu hoher Festplatten- oder Netzwerkaktivität während der Scans führen kann.",
|
||||
"AnalyticsEnabledHelpText": "Senden Sie anonyme Nutzungs- und Fehlerinformationen an die Server von {appName}. Dazu gehören Informationen zu Ihrem Browser, welche {appName}-WebUI-Seiten Sie verwenden, Fehlerberichte sowie Betriebssystem- und Laufzeitversion. Wir werden diese Informationen verwenden, um Funktionen und Fehlerbehebungen zu priorisieren.",
|
||||
"AutoTaggingNegateHelpText": "Falls aktiviert wird die Auto Tagging Regel nicht angewendet, solange diese Bedingung {implementationName} zutrifft.",
|
||||
"CopyUsingHardlinksSeriesHelpText": "Mithilfe von Hardlinks kann {appName} Seeding-Torrents in den Serienordner importieren, ohne zusätzlichen Speicherplatz zu beanspruchen oder den gesamten Inhalt der Datei zu kopieren. Hardlinks funktionieren nur, wenn sich Quelle und Ziel auf demselben Volume befinden",
|
||||
@@ -164,7 +164,7 @@
|
||||
"RestartReloadNote": "Hinweis: {appName} startet während des Wiederherstellungsvorgangs automatisch neu und lädt die Benutzeroberfläche neu.",
|
||||
"AutoRedownloadFailedHelpText": "Suchen Sie automatisch nach einer anderen Version und versuchen Sie, sie herunterzuladen",
|
||||
"AirDate": "Ausstrahlungsdatum",
|
||||
"AgeWhenGrabbed": "Alter (zum Zeitpunkt der Entführung)",
|
||||
"AgeWhenGrabbed": "Alter (bei Erfassung)",
|
||||
"ApplyTagsHelpTextHowToApplySeries": "So wenden Sie Tags auf die ausgewählte Serie an",
|
||||
"ApiKey": "API-Schlüssel",
|
||||
"AutoTaggingLoadError": "Automatisches Tagging konnte nicht geladen werden",
|
||||
@@ -272,7 +272,7 @@
|
||||
"ContinuingOnly": "Nur fortlaufend",
|
||||
"ContinuingSeriesDescription": "Weitere Episoden/eine weitere Staffel werden erwartet",
|
||||
"CopyToClipboard": "In die Zwischenablage kopieren",
|
||||
"CouldNotFindResults": "Es konnten keine Ergebnisse für „{term}“ gefunden werden.",
|
||||
"CouldNotFindResults": "Es konnten keine Ergebnisse für „{term}“ gefunden werden",
|
||||
"CountSeriesSelected": "{count} Serie ausgewählt",
|
||||
"CreateEmptySeriesFoldersHelpText": "Erstellen Sie beim Festplatten-Scan Ordner für fehlende Serien",
|
||||
"CreateGroup": "Gruppe erstellen",
|
||||
@@ -416,7 +416,7 @@
|
||||
"DownloadClientSabnzbdValidationEnableDisableDateSorting": "Deaktivieren Sie die Datumssortierung",
|
||||
"DownloadClientSabnzbdValidationEnableDisableDateSortingDetail": "Sie müssen die Datumssortierung für die von {appName} verwendete Kategorie deaktivieren, um Importprobleme zu vermeiden. Gehen Sie zu Sabnzbd, um das Problem zu beheben.",
|
||||
"DownloadClientSabnzbdValidationEnableDisableMovieSorting": "Deaktivieren Sie die Filmsortierung",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Alle Resultate werden wegen des angewandten Filters nicht angezeigt",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Alle Ergebnisse werden durch den angewendeten Filter ausgeblendet",
|
||||
"RegularExpressionsCanBeTested": "Reguläre Ausdrücke können [hier] getestet werden ({url}).",
|
||||
"ReleaseSceneIndicatorUnknownSeries": "Unbekannte Folge oder Serie.",
|
||||
"RemoveFilter": "Filter entfernen",
|
||||
@@ -549,7 +549,7 @@
|
||||
"CountImportListsSelected": "{count} Importliste(n) ausgewählt",
|
||||
"CountIndexersSelected": "{count} Indexer ausgewählt",
|
||||
"CountSelectedFiles": "{selectedCount} ausgewählte Dateien",
|
||||
"CustomFormatUnknownConditionOption": "Unbekannte Option „{key}“ für Bedingung „{implementation}“",
|
||||
"CustomFormatUnknownConditionOption": "Unbekannte Option '{key}' für die Bedingung '{implementation}'",
|
||||
"CustomFormatsSettings": "Einstellungen für eigene Formate",
|
||||
"Daily": "Täglich",
|
||||
"Dash": "Bindestrich",
|
||||
@@ -580,7 +580,7 @@
|
||||
"SslCertPassword": "SSL-Zertifikatskennwort",
|
||||
"SpecialsFolderFormat": "Specials-Ordnerformat",
|
||||
"SourceTitle": "Quellentitel",
|
||||
"Agenda": "Tagesordnung",
|
||||
"Agenda": "Agenda",
|
||||
"AnEpisodeIsDownloading": "Eine Episode wird heruntergeladen",
|
||||
"CollapseMultipleEpisodesHelpText": "Reduzieren Sie mehrere Episoden, die am selben Tag ausgestrahlt werden",
|
||||
"Connect": "Verbinden",
|
||||
@@ -792,5 +792,86 @@
|
||||
"MediaManagement": "Medienverwaltung",
|
||||
"StartupDirectory": "Start-Verzeichnis",
|
||||
"OnRename": "Bei Umbenennung",
|
||||
"MaintenanceRelease": "Maintenance Release: Fehlerbehebungen und andere Verbesserungen. Siehe Github Commit Verlauf für weitere Details"
|
||||
"MaintenanceRelease": "Maintenance Release: Fehlerbehebungen und andere Verbesserungen. Siehe Github Commit Verlauf für weitere Details",
|
||||
"BlocklistRelease": "Release sperren",
|
||||
"BranchUpdateMechanism": "Git-Branch für den externen Updateablauf",
|
||||
"AutoTaggingSpecificationGenre": "Genre(s)",
|
||||
"AutoTaggingSpecificationOriginalLanguage": "Sprache",
|
||||
"AutoTaggingSpecificationQualityProfile": "Qualitätsprofil",
|
||||
"AutoTaggingSpecificationRootFolder": "Stammverzeichnis",
|
||||
"AutoTaggingSpecificationStatus": "Status",
|
||||
"ConnectionSettingsUrlBaseHelpText": "Fügt ein Präfix zur {connectionName} URL hinzu, z. B. {url}",
|
||||
"DeleteImportListExclusion": "Importlisten Ausschluss löschen",
|
||||
"DeleteTag": "Tag löschen",
|
||||
"DoNotBlocklistHint": "Entfernen ohne Sperren",
|
||||
"DownloadClientPriorityHelpText": "Download-Client-Priorität von 1 (Höchste) bis 50 (Niedrigste). Standard: 1. Round-Robin wird für Clients mit der gleichen Priorität verwendet.",
|
||||
"DownloadClientSettingsRecentPriority": "Neueste Priorität",
|
||||
"DownloadClientValidationApiKeyIncorrect": "API-Key fehlerhaft",
|
||||
"ClientPriority": "Priorität",
|
||||
"Cutoff": "Schwelle",
|
||||
"DownloadClient": "Downloader",
|
||||
"DownloadClientSabnzbdValidationUnknownVersion": "Unbekannte Version: {rawVersion}",
|
||||
"CutoffUnmet": "Schwelle nicht erreicht",
|
||||
"DownloadClientSettingsInitialState": "Ausgangszustand",
|
||||
"DownloadClientValidationApiKeyRequired": "API-Key benötigt",
|
||||
"CustomFormatsSpecificationRegularExpressionHelpText": "Benutzerdefiniertes Format RegEx ist nicht groß-/kleinschreibungssensitiv",
|
||||
"CustomFormatsSpecificationMinimumSize": "Mindestgröße",
|
||||
"CustomFormatsSpecificationRegularExpression": "Regulären Ausdruck",
|
||||
"CustomFormatsSpecificationReleaseGroup": "Release-Gruppe",
|
||||
"CustomFormatsSpecificationResolution": "Auflösung",
|
||||
"DeleteImportListExclusionMessageText": "Bist du sicher, dass du diesen Importlisten Ausschluss löschen willst?",
|
||||
"DownloadClientSabnzbdValidationEnableDisableTvSorting": "TV-Sortierung deaktivieren",
|
||||
"CustomFormatUnknownCondition": "Unbekannte Eigene Formatbedingung '{implementation}'",
|
||||
"ReleaseGroups": "Release Gruppen",
|
||||
"DownloadClientSettingsUseSslHelpText": "Sichere Verbindung verwenden, wenn Verbindung zu {clientName} hergestellt wird",
|
||||
"ReleaseRejected": "Release abgelehnt",
|
||||
"Clear": "Leeren",
|
||||
"DownloadClientValidationCategoryMissing": "Kategorie existiert nicht",
|
||||
"DownloadClientValidationAuthenticationFailure": "Authentifizierung fehlgeschlagen",
|
||||
"DownloadClientValidationErrorVersion": "{clientName} Version sollte mindestens {requiredVersion} sein. Die gemeldete Version ist {reportedVersion}",
|
||||
"DownloadClientValidationGroupMissing": "Gruppe existiert nicht",
|
||||
"DownloadClientValidationSslConnectFailure": "Verbindung über SSL nicht möglich",
|
||||
"ReleaseProfilesLoadError": "Release-Profile können nicht geladen werden",
|
||||
"DownloadClientDelugeSettingsDirectory": "Download Verzeichnis",
|
||||
"DownloadClientDelugeSettingsDirectoryCompleted": "Verschieben, wenn Verzeichnis abgeschlossen",
|
||||
"DownloadClientSettings": "Downloader Einstellungen",
|
||||
"IgnoreDownloadHint": "Hält {appName} von der weiteren Verarbeitung dieses Downloads ab",
|
||||
"ClearBlocklist": "Sperrliste leeren",
|
||||
"CleanLibraryLevel": "Mediathek aufräumen",
|
||||
"CloneAutoTag": "Automatische Tags kopieren",
|
||||
"DownloadClientSettingsOlderPriorityEpisodeHelpText": "Priorität beim Abrufen von Episoden, die vor mehr als 14 Tagen ausgestrahlt wurden",
|
||||
"DownloadClientSettingsInitialStateHelpText": "Anfangszustand für zu {clientName} hinzugefügte Torrents",
|
||||
"DownloadClientSettingsOlderPriority": "Ältere Priorität",
|
||||
"IgnoreDownload": "Download ignorieren",
|
||||
"CustomFormatsSettingsTriggerInfo": "Ein Eigenes Format wird auf eine Veröffentlichung oder Datei angewandt, wenn sie mindestens einer der verschiedenen ausgewählten Bedingungen entspricht.",
|
||||
"DatabaseMigration": "DB Migration",
|
||||
"DownloadClientSettingsDestinationHelpText": "Legt das Ziel für den Download manuell fest; lassen Sie es leer, um die Standardeinstellung zu verwenden",
|
||||
"DownloadClientSettingsCategorySubFolderHelpText": "Das Hinzufügen einer spezifischen Kategorie für {appName} vermeidet Konflikte mit nicht verwandten Downloads, die nicht {appName} sind. Die Verwendung einer Kategorie ist optional, wird aber dringend empfohlen. Erzeugt ein Unterverzeichnis [category] im Ausgabeverzeichnis.",
|
||||
"BlocklistReleases": "Release sperren",
|
||||
"DownloadClientQbittorrentTorrentStateMissingFiles": "qBittorrent meldet fehlende Dateien",
|
||||
"ChangeCategoryHint": "Änderung des Downloads in die 'Post-Import-Kategorie' vom Download-Client",
|
||||
"ChangeCategoryMultipleHint": "Änderung der Downloads in die 'Post-Import-Kategorie' vom Download-Client",
|
||||
"CustomFormatsSpecificationSource": "Quelle",
|
||||
"BlocklistFilterHasNoItems": "Ausgewählter Blocklistenfilter enthält keine Elemente",
|
||||
"CustomFilter": "Benutzerdefinierter Filter",
|
||||
"CustomFormatsSpecificationFlag": "Markierung",
|
||||
"CustomFormatScore": "Eigenes Format Bewertungspunkte",
|
||||
"CustomFormatsSpecificationLanguage": "Sprache",
|
||||
"CustomFormatsSpecificationMaximumSize": "Maximale Größe",
|
||||
"AutoTaggingSpecificationTag": "Tag",
|
||||
"BindAddress": "Adresse binden",
|
||||
"DownloadClientSettingsRecentPriorityEpisodeHelpText": "Priorität beim Abrufen von Episoden, die innerhalb der letzten 14 Tage ausgestrahlt wurden",
|
||||
"DownloadClientSettingsUrlBaseHelpText": "Fügt ein Präfix zur {clientName} Url hinzu, z.B. {url}",
|
||||
"DownloadClientTransmissionSettingsDirectoryHelpText": "Optionaler Speicherort für Downloads; leer lassen, um den Standardspeicherort für Übertragungen zu verwenden",
|
||||
"DownloadClientUTorrentTorrentStateError": "uTorrent meldet einen Fehler",
|
||||
"DoNotBlocklist": "Nicht Sperren",
|
||||
"ReleaseHash": "Release Hash",
|
||||
"DownloadClientAriaSettingsDirectoryHelpText": "Optionaler Speicherort für Downloads. Lassen Sie das Feld leer, um den standardmäßigen rTorrent-Speicherort zu verwenden",
|
||||
"DownloadClientSeriesTagHelpText": "Verwenden Sie diesen Downloader nur für Serien mit mindestens einem passenden Tag. Lassen Sie ihn leer, um ihn für alle Serien zu verwenden.",
|
||||
"DownloadClientSettingsCategoryHelpText": "Das Hinzufügen einer spezifischen Kategorie für {appName} vermeidet Konflikte mit nicht verwandten Downloads, die nicht {appName} sind. Die Verwendung einer Kategorie ist optional, wird aber dringend empfohlen.",
|
||||
"DownloadClientSettingsPostImportCategoryHelpText": "Kategorie für {appName}, die nach dem Importieren des Downloads festgelegt wird. {appName} wird Torrents in dieser Kategorie nicht entfernen, auch wenn das Seeding beendet ist. Leer lassen, um dieselbe Kategorie beizubehalten.",
|
||||
"DownloadClientValidationCategoryMissingDetail": "Die von Ihnen eingegebene Kategorie existiert nicht in {clientName}. Erstellen Sie sie zuerst in {clientName}.",
|
||||
"DownloadClientValidationGroupMissingDetail": "Die von Ihnen eingegebene Gruppe existiert nicht in {clientName}. Erstellen Sie sie zuerst in {clientName}.",
|
||||
"IgnoreDownloads": "Downloads ignorieren",
|
||||
"IgnoreDownloadsHint": "Hindert {appName}, diese Downloads weiter zu verarbeiten"
|
||||
}
|
||||
|
||||
@@ -308,6 +308,7 @@
|
||||
"Date": "Date",
|
||||
"Dates": "Dates",
|
||||
"Day": "Day",
|
||||
"DayOfWeekAt": "{day} at {time}",
|
||||
"Debug": "Debug",
|
||||
"Default": "Default",
|
||||
"DefaultCase": "Default Case",
|
||||
@@ -1949,10 +1950,12 @@
|
||||
"Title": "Title",
|
||||
"Titles": "Titles",
|
||||
"Today": "Today",
|
||||
"TodayAt": "Today at {time}",
|
||||
"ToggleMonitoredSeriesUnmonitored ": "Cannot toggle monitored state when series is unmonitored",
|
||||
"ToggleMonitoredToUnmonitored": "Monitored, click to unmonitor",
|
||||
"ToggleUnmonitoredToMonitored": "Unmonitored, click to monitor",
|
||||
"Tomorrow": "Tomorrow",
|
||||
"TomorrowAt": "Tomorrow at {time}",
|
||||
"TorrentBlackhole": "Torrent Blackhole",
|
||||
"TorrentBlackholeSaveMagnetFiles": "Save Magnet Files",
|
||||
"TorrentBlackholeSaveMagnetFilesExtension": "Save Magnet Files Extension",
|
||||
@@ -2074,5 +2077,6 @@
|
||||
"Year": "Year",
|
||||
"Yes": "Yes",
|
||||
"YesCancel": "Yes, Cancel",
|
||||
"Yesterday": "Yesterday"
|
||||
"Yesterday": "Yesterday",
|
||||
"YesterdayAt": "Yesterday at {time}"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
"Condition": "Condición",
|
||||
"Component": "Componente",
|
||||
"Custom": "Personalizado",
|
||||
"Cutoff": "Umbral",
|
||||
"Cutoff": "Límite",
|
||||
"Dates": "Fechas",
|
||||
"Debug": "Debug",
|
||||
"Date": "Fecha",
|
||||
@@ -181,7 +181,7 @@
|
||||
"AddNewSeriesError": "Falló al cargar los resultados de la búsqueda, inténtelo de nuevo.",
|
||||
"AddNewSeriesHelpText": "Es fácil añadir una nueva serie, empiece escribiendo el nombre de la serie que desea añadir.",
|
||||
"AddNewSeriesRootFolderHelpText": "La subcarpeta '{folder}' será creada automáticamente",
|
||||
"AddNewSeriesSearchForCutoffUnmetEpisodes": "Empezar la búsqueda de episodios con umbrales no alcanzados",
|
||||
"AddNewSeriesSearchForCutoffUnmetEpisodes": "Empezar la búsqueda de episodios con límites no alcanzados",
|
||||
"AddNewSeriesSearchForMissingEpisodes": "Empezar búsqueda de episodios faltantes",
|
||||
"AddQualityProfile": "Añadir Perfil de Calidad",
|
||||
"AddQualityProfileError": "No se pudo añadir un nuevo perfil de calidad, inténtelo de nuevo.",
|
||||
@@ -272,7 +272,7 @@
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirma la nueva contraseña",
|
||||
"MonitorPilotEpisode": "Episodio Piloto",
|
||||
"MonitorRecentEpisodesDescription": "Monitorizar episodios emitidos en los últimos 90 días y los episodios futuros",
|
||||
"MonitorSelected": "Monitorizar Seleccionados",
|
||||
"MonitorSelected": "Monitorizar seleccionados",
|
||||
"MonitorSeries": "Monitorizar Series",
|
||||
"NoHistory": "Sin historial",
|
||||
"NoHistoryFound": "No se encontró historial",
|
||||
@@ -436,7 +436,7 @@
|
||||
"CustomFormatsLoadError": "No se pudo cargar Formatos Personalizados",
|
||||
"CustomFormatsSettings": "Configuración de formatos personalizados",
|
||||
"CustomFormatsSettingsSummary": "Formatos y configuraciones personalizados",
|
||||
"CutoffUnmet": "Umbrales no alcanzados",
|
||||
"CutoffUnmet": "Límite no alcanzado",
|
||||
"DailyEpisodeFormat": "Formato de episodio diario",
|
||||
"Database": "Base de datos",
|
||||
"DelayMinutes": "{delay} minutos",
|
||||
@@ -463,14 +463,14 @@
|
||||
"InteractiveImportLoadError": "No se pueden cargar elementos de la importación manual",
|
||||
"InteractiveImportNoFilesFound": "No se han encontrado archivos de vídeo en la carpeta seleccionada",
|
||||
"InteractiveImportNoQuality": "La calidad debe elegirse para cada archivo seleccionado",
|
||||
"InteractiveSearchModalHeader": "Búsqueda Interactiva",
|
||||
"InteractiveSearchModalHeader": "Búsqueda interactiva",
|
||||
"InvalidUILanguage": "Su interfaz de usuario está configurada en un idioma no válido, corríjalo y guarde la configuración",
|
||||
"ChownGroup": "chown grupo",
|
||||
"DelayProfileProtocol": "Protocolo: {preferredProtocol}",
|
||||
"DelayProfilesLoadError": "Incapaz de cargar Perfiles de Retardo",
|
||||
"ContinuingSeriesDescription": "Se esperan más episodios u otra temporada",
|
||||
"CutoffUnmetLoadError": "Error cargando elementos con umbrales no alcanzados",
|
||||
"CutoffUnmetNoItems": "No hay elementos con umbrales no alcanzados",
|
||||
"CutoffUnmetLoadError": "Error cargando elementos con límites no alcanzados",
|
||||
"CutoffUnmetNoItems": "Ningún elemento con límites no alcanzados",
|
||||
"DelayProfile": "Perfil de retardo",
|
||||
"Delete": "Eliminar",
|
||||
"DeleteDelayProfile": "Eliminar Perfil de Retardo",
|
||||
@@ -530,7 +530,7 @@
|
||||
"DeleteEpisodesFilesHelpText": "Eliminar archivos de episodios y directorio de series",
|
||||
"DoNotPrefer": "No preferir",
|
||||
"DoNotUpgradeAutomatically": "No actualizar automáticamente",
|
||||
"IndexerSettingsSeedRatioHelpText": "El ratio que un torrent debería alcanzar antes de detenerse, vacío usa el predeterminado del cliente de descarga. El ratio debería ser al menos 1.0 y seguir las reglas de los indexadores",
|
||||
"IndexerSettingsSeedRatioHelpText": "El ratio que un torrent debería alcanzar antes de parar, vacío usa el predeterminado del cliente de descarga. El ratio debería ser al menos 1.0 y seguir las reglas de los indexadores",
|
||||
"Download": "Descargar",
|
||||
"Donate": "Donar",
|
||||
"DownloadClientDelugeValidationLabelPluginFailure": "La configuración de etiqueta falló",
|
||||
@@ -816,7 +816,7 @@
|
||||
"FirstDayOfWeek": "Primer día de la semana",
|
||||
"Forums": "Foros",
|
||||
"FreeSpace": "Espacio libre",
|
||||
"MissingNoItems": "No hay elementos faltantes",
|
||||
"MissingNoItems": "Ningún elemento faltante",
|
||||
"ImportListRootFolderMissingRootHealthCheckMessage": "Carpeta raíz faltante para importar lista(s): {rootFolderInfo}",
|
||||
"MissingLoadError": "Error cargando elementos faltantes",
|
||||
"RemoveSelectedBlocklistMessageText": "¿Estás seguro que quieres eliminar los elementos seleccionados de la lista de bloqueos?",
|
||||
@@ -890,8 +890,8 @@
|
||||
"ImportListSettings": "Importar ajustes de lista",
|
||||
"ImportListsSettingsSummary": "Importar desde otra instancia de {appName} o listas de Trakt y gestionar exclusiones de lista",
|
||||
"IncludeCustomFormatWhenRenamingHelpText": "Incluir en formato de renombrado {Custom Formats}",
|
||||
"QualityCutoffNotMet": "Calidad del umbral que no ha sido alcanzado",
|
||||
"SearchForCutoffUnmetEpisodesConfirmationCount": "¿Estás seguro que quieres buscar los {totalRecords} episodios en Umbrales no alcanzados?",
|
||||
"QualityCutoffNotMet": "No se ha alcanzado el límite de calidad",
|
||||
"SearchForCutoffUnmetEpisodesConfirmationCount": "¿Estás seguro que quieres buscar los {totalRecords} episodios con límites no alcanzados?",
|
||||
"IndexerOptionsLoadError": "No se pudieron cargar las opciones del indexador",
|
||||
"IndexerIPTorrentsSettingsFeedUrl": "URL del canal",
|
||||
"ICalFeed": "Canal de iCal",
|
||||
@@ -991,7 +991,7 @@
|
||||
"ImportScriptPathHelpText": "La ruta al script a usar para importar",
|
||||
"ImportUsingScriptHelpText": "Copiar archivos para importar usando un script (p. ej. para transcodificación)",
|
||||
"Importing": "Importando",
|
||||
"IncludeUnmonitored": "Incluir sin monitorizar",
|
||||
"IncludeUnmonitored": "Incluir no monitorizadas",
|
||||
"IndexerLongTermStatusAllUnavailableHealthCheckMessage": "Ningún indexador está disponible debido a errores durante más de 6 horas",
|
||||
"IRC": "IRC",
|
||||
"ICalShowAsAllDayEvents": "Mostrar como eventos para todo el día",
|
||||
@@ -1041,7 +1041,7 @@
|
||||
"ImportedTo": "Importar a",
|
||||
"IncludeCustomFormatWhenRenaming": "Incluir formato personalizado cuando se renombra",
|
||||
"CleanLibraryLevel": "Limpiar el nivel de la librería",
|
||||
"SearchForCutoffUnmetEpisodes": "Buscar todos los episodios en Umbrales no alcanzados",
|
||||
"SearchForCutoffUnmetEpisodes": "Buscar todos los episodios con límites no alcanzados",
|
||||
"IconForSpecials": "Icono para Especiales",
|
||||
"ImportListExclusions": "Importar lista de exclusiones",
|
||||
"ImportListStatusAllPossiblePartialFetchHealthCheckMessage": "Todas las listas requieren interacción manual debido a posibles búsquedas parciales",
|
||||
@@ -1057,8 +1057,8 @@
|
||||
"HourShorthand": "h",
|
||||
"ICalFeedHelpText": "Copia esta URL a tu(s) cliente(s) o pulsa para suscribirse si tu navegador soporta Webcal",
|
||||
"ICalTagsSeriesHelpText": "El canal solo contendrá series con al menos una etiqueta coincidente",
|
||||
"IconForCutoffUnmet": "Icono para Umbrales no alcanzados",
|
||||
"IconForCutoffUnmetHelpText": "Mostrar icono para archivos cuando el umbral no haya sido alcanzado",
|
||||
"IconForCutoffUnmet": "Icono de límite no alcanzado",
|
||||
"IconForCutoffUnmetHelpText": "Muestra un icono para archivos cuando el límite no haya sido alcanzado",
|
||||
"EpisodeCount": "Recuento de episodios",
|
||||
"IndexerSettings": "Opciones del indexador",
|
||||
"AddDelayProfileError": "No se pudo añadir un nuevo perfil de retraso, por favor inténtalo de nuevo.",
|
||||
@@ -1102,7 +1102,7 @@
|
||||
"IndexerSettingsRssUrlHelpText": "Introduzca la URL de un canal RSS compatible con {indexer}",
|
||||
"IndexerStatusUnavailableHealthCheckMessage": "Indexadores no disponibles debido a errores: {indexerNames}",
|
||||
"IndexerHDBitsSettingsMediums": "Medios",
|
||||
"IndexerSettingsSeedTimeHelpText": "El tiempo que un torrent debería ser compartido antes de detenerse, vació usa el predeterminado del cliente de descarga",
|
||||
"IndexerSettingsSeedTimeHelpText": "El tiempo que un torrent debería ser sembrado antes de parar, vacío usa el predeterminado del cliente de descarga",
|
||||
"IndexerValidationCloudFlareCaptchaRequired": "Sitio protegido por CloudFlare CAPTCHA. Se requiere un token CAPTCHA válido.",
|
||||
"NotificationsEmailSettingsUseEncryption": "Usar Cifrado",
|
||||
"LastDuration": "Última Duración",
|
||||
@@ -1226,7 +1226,7 @@
|
||||
"MetadataSourceSettings": "Opciones de fuente de metadatos",
|
||||
"MetadataSettingsSeriesSummary": "Crea archivos de metadatos cuando los episodios son importados o las series son refrescadas",
|
||||
"Metadata": "Metadatos",
|
||||
"MassSearchCancelWarning": "Esto no puede ser cancelado una vez empiece sin reiniciar {appName} o deshabilitar todos tus indexadores.",
|
||||
"MassSearchCancelWarning": "No puede ser cancelado una vez comience sin reiniciar {appName} o deshabilitar todos tus indexadores.",
|
||||
"MaximumSingleEpisodeAgeHelpText": "Durante una búsqueda completa de temporada, solo serán permitidos los paquetes de temporada cuando el último episodio de temporada sea más antiguo que esta configuración. Solo series estándar. Usa 0 para deshabilitar.",
|
||||
"MaximumSize": "Tamaño máximo",
|
||||
"IndexerValidationNoResultsInConfiguredCategories": "Petición con éxito, pero no se devolvió ningún resultado en las categorías configuradas de tu indexador. Esto puede ser un problema con el indexador o tus ajustes de categoría de tu indexador.",
|
||||
@@ -1710,7 +1710,7 @@
|
||||
"SeriesIndexFooterEnded": "FInalizado (Todos los episodios descargados)",
|
||||
"ShowDateAdded": "Mostrar fecha de adición",
|
||||
"UnmonitorDeletedEpisodesHelpText": "Los episodios borrados del disco son dejados de monitorizar automáticamente en {appName}",
|
||||
"UnmonitorSelected": "Dejar de monitorizar seleccionados",
|
||||
"UnmonitorSelected": "No monitorizar seleccionados",
|
||||
"UpdateSelected": "Actualizar seleccionados",
|
||||
"UpdateUiNotWritableHealthCheckMessage": "No se puede instalar la actualización porque la carpeta de interfaz '{uiFolder}' no es modificable por el usuario '{userName}'.",
|
||||
"UpgradeUntil": "Actualizar hasta",
|
||||
@@ -2073,6 +2073,10 @@
|
||||
"IndexerSettingsMultiLanguageRelease": "Múltiples idiomas",
|
||||
"IndexerSettingsMultiLanguageReleaseHelpText": "¿Qué idiomas están normalmente en un lanzamiento múltiple en este indexador?",
|
||||
"DownloadClientQbittorrentTorrentStateMissingFiles": "qBittorrent está reportando archivos faltantes",
|
||||
"BlocklistFilterHasNoItems": "El filtro de lista de bloqueo seleccionado no contiene ningún elemento",
|
||||
"HasUnmonitoredSeason": "Tiene temporada sin monitorizar"
|
||||
"BlocklistFilterHasNoItems": "El filtro de lista de bloqueo seleccionado no contiene elementos",
|
||||
"HasUnmonitoredSeason": "Tiene temporada sin monitorizar",
|
||||
"TomorrowAt": "Mañana a las {time}",
|
||||
"YesterdayAt": "Ayer a las {time}",
|
||||
"TodayAt": "Hoy a las {time}",
|
||||
"DayOfWeekAt": "{day} a las {time}"
|
||||
}
|
||||
|
||||
@@ -616,7 +616,7 @@
|
||||
"OnSeriesDelete": "Lors de la suppression de la série",
|
||||
"OnlyTorrent": "Uniquement Torrent",
|
||||
"OpenBrowserOnStart": "Ouvrir le navigateur au démarrage",
|
||||
"OpenSeries": "Série ouverte",
|
||||
"OpenSeries": "Ouvrir la série",
|
||||
"Options": "Options",
|
||||
"Organize": "Organiser",
|
||||
"OrganizeLoadError": "Erreur lors du chargement des aperçus",
|
||||
@@ -1344,7 +1344,7 @@
|
||||
"DeleteDelayProfile": "Supprimer le profil de retard",
|
||||
"DeleteDelayProfileMessageText": "Êtes-vous sûr de vouloir supprimer ce profil de retard ?",
|
||||
"DeleteEpisodeFile": "Supprimer le fichier de l'épisode",
|
||||
"DeleteEpisodeFileMessage": "Supprimer le fichier de l'épisode '{path}'?",
|
||||
"DeleteEpisodeFileMessage": "Êtes-vous sûr de vouloir supprimer « {path} » ?",
|
||||
"DeleteEpisodeFromDisk": "Supprimer l'épisode du disque",
|
||||
"DeleteImportListMessageText": "Êtes-vous sûr de vouloir supprimer la liste « {name} » ?",
|
||||
"DeleteSelectedEpisodeFiles": "Supprimer les fichiers d'épisode sélectionnés",
|
||||
@@ -1884,7 +1884,7 @@
|
||||
"CustomFormatsSpecificationSource": "Source",
|
||||
"ImportListsAniListSettingsAuthenticateWithAniList": "S'authentifier avec AniList",
|
||||
"ImportListsAniListSettingsImportCancelled": "Importation annulée",
|
||||
"ImportListsAniListSettingsImportCancelledHelpText": "Médias : La série est annulée",
|
||||
"ImportListsAniListSettingsImportCancelledHelpText": "Médias : Série annulée",
|
||||
"ImportListsAniListSettingsImportCompleted": "Importation terminée",
|
||||
"ImportListsAniListSettingsImportFinished": "Importation terminée",
|
||||
"ImportListsAniListSettingsUsernameHelpText": "Nom d'utilisateur pour la liste à importer",
|
||||
|
||||
@@ -205,5 +205,7 @@
|
||||
"Category": "Categorie",
|
||||
"BlocklistReleaseHelpText": "Voorkom dat deze release opnieuw wordt gedownload door {appName} door een RSS lijst of een automatische zoekopdracht",
|
||||
"ChangeCategory": "Verander categorie",
|
||||
"ChownGroup": "chown groep"
|
||||
"ChownGroup": "chown groep",
|
||||
"AutoTaggingSpecificationTag": "Tag",
|
||||
"AddDelayProfileError": "Mislukt om vertragingsprofiel toe te voegen, probeer het later nog eens."
|
||||
}
|
||||
|
||||
@@ -186,5 +186,28 @@
|
||||
"AutomaticSearch": "Pesquisa automática",
|
||||
"AutoTaggingRequiredHelpText": "Esta condição de {implementationName} deve corresponder para que a regra de marcação automática seja aplicada. Caso contrário, uma única correspondência de {implementationName} é suficiente.",
|
||||
"Backup": "Backup",
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirmar nova senha"
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirmar nova senha",
|
||||
"Conditions": "Condições",
|
||||
"ClickToChangeIndexerFlags": "Clique para alterar os sinalizadores do indexador",
|
||||
"CustomFormatsSpecificationRegularExpression": "Expressão regular (regex)",
|
||||
"Dash": "Traço",
|
||||
"ConnectionSettingsUrlBaseHelpText": "Adiciona um prefixo ao URL {connectionName}, como {url}",
|
||||
"CustomFormatsSpecificationFlag": "Sinalizar",
|
||||
"CustomFormatsSpecificationRegularExpressionHelpText": "O regex do formato personalizado não diferencia maiúsculas e minúsculas",
|
||||
"AutoTaggingSpecificationTag": "Etiqueta",
|
||||
"ClearBlocklist": "Limpar lista de bloqueio",
|
||||
"ClearBlocklistMessageText": "Tem a certeza de que deseja limpar todos os itens da lista de bloqueio?",
|
||||
"CustomFormatsSettingsTriggerInfo": "Um formato personalizado será aplicado a uma versão ou ficheiro quando corresponder a pelo menos um dos diferentes tipos de condição escolhidos.",
|
||||
"BlocklistOnly": "Apenas adicionar à lista de bloqueio",
|
||||
"BlocklistAndSearch": "Adicionar à lista de bloqueio e pesquisar",
|
||||
"BlocklistAndSearchHint": "Iniciar uma pesquisa por um substituto após adicionar à lista de bloqueio",
|
||||
"BlocklistAndSearchMultipleHint": "Iniciar pesquisas por substitutos após adicionar à lista de bloqueio",
|
||||
"BlocklistMultipleOnlyHint": "Adicionar à lista de bloqueio sem procurar por substitutos",
|
||||
"BlocklistOnlyHint": "Adicionar à lista de bloqueio sem procurar por um substituto",
|
||||
"ChangeCategory": "Alterar categoria",
|
||||
"ChangeCategoryHint": "Altera o download para a \"Categoria pós-importação\" do cliente de download",
|
||||
"ChangeCategoryMultipleHint": "Altera os downloads para a \"Categoria pós-importação' do cliente de download",
|
||||
"ChownGroup": "Fazer chown em grupo",
|
||||
"Clone": "Clonar",
|
||||
"ContinuingOnly": "Continuando apenas"
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
"Calendar": "Calendário",
|
||||
"Connect": "Conectar",
|
||||
"CustomFormats": "Formatos personalizados",
|
||||
"CutoffUnmet": "Corte não alcançado",
|
||||
"CutoffUnmet": "Limite não alcançado",
|
||||
"DownloadClients": "Clientes de download",
|
||||
"Events": "Eventos",
|
||||
"General": "Geral",
|
||||
@@ -465,7 +465,7 @@
|
||||
"ChmodFolder": "chmod Pasta",
|
||||
"ChmodFolderHelpText": "Octal, aplicado durante a importação/renomeação de pastas e arquivos de mídia (sem bits de execução)",
|
||||
"ChmodFolderHelpTextWarning": "Isso só funciona se o usuário que executa {appName} for o proprietário do arquivo. É melhor garantir que o cliente de download defina as permissões corretamente.",
|
||||
"ChownGroup": "chown Grupo",
|
||||
"ChownGroup": "Fazer chown em grupo",
|
||||
"ChownGroupHelpText": "Nome do grupo ou gid. Use gid para sistemas de arquivos remotos.",
|
||||
"ChownGroupHelpTextWarning": "Isso só funciona se o usuário que executa {appName} for o proprietário do arquivo. É melhor garantir que o cliente de download use o mesmo grupo que {appName}.",
|
||||
"ClientPriority": "Prioridade do Cliente",
|
||||
@@ -493,8 +493,8 @@
|
||||
"CustomFormatsLoadError": "Não foi possível carregar Formatos Personalizados",
|
||||
"CustomFormatsSettings": "Configurações de Formatos Personalizados",
|
||||
"CustomFormatsSettingsSummary": "Configurações e Formatos Personalizados",
|
||||
"DailyEpisodeFormat": "Formato do Episódio Diário",
|
||||
"Cutoff": "Corte",
|
||||
"DailyEpisodeFormat": "Formato do episódio diário",
|
||||
"Cutoff": "Limite",
|
||||
"Dash": "Traço",
|
||||
"Dates": "Datas",
|
||||
"Debug": "Depuração",
|
||||
@@ -683,7 +683,7 @@
|
||||
"OnApplicationUpdate": "Na Atualização do Aplicativo",
|
||||
"OnEpisodeFileDelete": "Ao Excluir o Arquivo do Episódio",
|
||||
"OnEpisodeFileDeleteForUpgrade": "No Arquivo do Episódio Excluir para Atualização",
|
||||
"OnGrab": "Ao Baixar",
|
||||
"OnGrab": "Ao obter",
|
||||
"OnHealthIssue": "Ao Problema de Saúde",
|
||||
"OnHealthRestored": "Com a Saúde Restaurada",
|
||||
"OnImport": "Ao Importar",
|
||||
@@ -1447,12 +1447,12 @@
|
||||
"MissingLoadError": "Erro ao carregar itens ausentes",
|
||||
"MissingNoItems": "Nenhum item ausente",
|
||||
"SearchAll": "Pesquisar Todos",
|
||||
"UnmonitorSelected": "Não Monitorar Selecionado",
|
||||
"CutoffUnmetNoItems": "Nenhum item com limite não atendido",
|
||||
"MonitorSelected": "Monitorar selecionados",
|
||||
"UnmonitorSelected": "Não Monitorar os Selecionados",
|
||||
"CutoffUnmetNoItems": "Nenhum item com limite não atingido",
|
||||
"MonitorSelected": "Monitorar Selecionados",
|
||||
"SearchForAllMissingEpisodesConfirmationCount": "Tem certeza de que deseja pesquisar todos os episódios ausentes de {totalRecords}?",
|
||||
"SearchSelected": "Pesquisar Selecionado",
|
||||
"CutoffUnmetLoadError": "Erro ao carregar itens de limite não atendido",
|
||||
"CutoffUnmetLoadError": "Erro ao carregar itens de limite não atingido",
|
||||
"MassSearchCancelWarning": "Isso não pode ser cancelado depois de iniciado sem reiniciar {appName} ou desabilitar todos os seus indexadores.",
|
||||
"SearchForAllMissingEpisodes": "Pesquisar por todos os episódios ausentes",
|
||||
"SearchForCutoffUnmetEpisodes": "Pesquise todos os episódios que o corte não foi atingido",
|
||||
@@ -1503,11 +1503,11 @@
|
||||
"NzbgetHistoryItemMessage": "Status PAR: {parStatus} - Status de descompactação: {unpackStatus} - Status de movimentação: {moveStatus} - Status do script: {scriptStatus} - Status de exclusão: {deleteStatus} - Status de marcação: {markStatus}",
|
||||
"PostImportCategory": "Categoria Pós-Importação",
|
||||
"SecretToken": "Token Secreto",
|
||||
"TorrentBlackhole": "Torrent Blackhole",
|
||||
"TorrentBlackhole": "Blackhole para torrent",
|
||||
"TorrentBlackholeSaveMagnetFiles": "Salvar Arquivos Magnets",
|
||||
"TorrentBlackholeSaveMagnetFilesHelpText": "Salve o link magnet se nenhum arquivo .torrent estiver disponível (útil apenas se o cliente de download suportar magnets salvos em um arquivo)",
|
||||
"UnknownDownloadState": "Estado de download desconhecido: {state}",
|
||||
"UsenetBlackhole": "Usenet Blackhole",
|
||||
"UsenetBlackhole": "Blackhole para Usenet",
|
||||
"DownloadClientQbittorrentSettingsInitialStateHelpText": "Estado inicial para torrents adicionados ao qBittorrent. Observe que os Torrents Forçados não obedecem às restrições de semeação",
|
||||
"DownloadClientQbittorrentTorrentStatePathError": "Não foi possível importar. O caminho corresponde ao diretório de download da base do cliente, é possível que 'Manter pasta de nível superior' esteja desabilitado para este torrent ou 'Layout de conteúdo de torrent' NÃO esteja definido como 'Original' ou 'Criar subpasta'?",
|
||||
"DownloadClientQbittorrentValidationCategoryUnsupportedDetail": "As categorias não são suportadas até a versão 3.3.0 do qBittorrent. Atualize ou tente novamente com uma categoria vazia.",
|
||||
@@ -1645,8 +1645,8 @@
|
||||
"IndexerSettingsPasskey": "Passkey",
|
||||
"IndexerSettingsRssUrl": "URL do RSS",
|
||||
"IndexerSettingsSeasonPackSeedTime": "Tempo de Seed de Pack de Temporada",
|
||||
"IndexerSettingsSeedRatio": "Proporção de Semeação",
|
||||
"IndexerSettingsSeedTime": "Tempo de Semeação",
|
||||
"IndexerSettingsSeedRatio": "Proporção de semeação",
|
||||
"IndexerSettingsSeedTime": "Tempo de semeação",
|
||||
"IndexerSettingsSeedTimeHelpText": "O tempo que um torrent deve ser semeado antes de parar, vazio usa o padrão do cliente de download",
|
||||
"IndexerSettingsWebsiteUrl": "URL do Website",
|
||||
"IndexerValidationCloudFlareCaptchaExpired": "O token CloudFlare CAPTCHA expirou, atualize-o.",
|
||||
@@ -1892,8 +1892,8 @@
|
||||
"CustomFormatsSpecificationMaximumSizeHelpText": "O lançamento deve ser menor ou igual a este tamanho",
|
||||
"CustomFormatsSpecificationMinimumSize": "Tamanho Mínimo",
|
||||
"CustomFormatsSpecificationMinimumSizeHelpText": "O lançamento deve ser maior que esse tamanho",
|
||||
"CustomFormatsSpecificationRegularExpression": "Expressão Regular",
|
||||
"CustomFormatsSpecificationRegularExpressionHelpText": "RegEx do Formato Personalizado Não Diferencia Maiúsculas de Minúsculas",
|
||||
"CustomFormatsSpecificationRegularExpression": "Expressão regular (regex)",
|
||||
"CustomFormatsSpecificationRegularExpressionHelpText": "O regex do formato personalizado não diferencia maiúsculas e minúsculas",
|
||||
"CustomFormatsSpecificationReleaseGroup": "Grupo do Lançamento",
|
||||
"CustomFormatsSpecificationResolution": "Resolução",
|
||||
"CustomFormatsSpecificationSource": "Fonte",
|
||||
@@ -2010,24 +2010,24 @@
|
||||
"IgnoreDownloadsHint": "Impede que {appName} processe ainda mais esses downloads",
|
||||
"RemoveFromDownloadClientHint": "Remove download e arquivo(s) do cliente de download",
|
||||
"RemoveQueueItemRemovalMethodHelpTextWarning": "'Remover do cliente de download' removerá o download e os arquivos do cliente de download.",
|
||||
"BlocklistMultipleOnlyHint": "Adiciona a Lista de bloqueio sem procurar substitutos",
|
||||
"BlocklistOnly": "Apenas Adicionar a Lista de Bloqueio",
|
||||
"BlocklistAndSearchMultipleHint": "Iniciar pesquisas por substitutos após adicionar a lista de bloqueio",
|
||||
"BlocklistMultipleOnlyHint": "Adicionar à lista de bloqueio sem procurar por substitutos",
|
||||
"BlocklistOnly": "Apenas adicionar à lista de bloqueio",
|
||||
"BlocklistAndSearchMultipleHint": "Iniciar pesquisas por substitutos após adicionar à lista de bloqueio",
|
||||
"BlocklistReleaseHelpText": "Impede que esta versão seja baixada novamente por {appName} via RSS ou Pesquisa Automática",
|
||||
"ChangeCategoryHint": "Altera o download para a 'Categoria Pós-Importação' do Cliente de Download",
|
||||
"ChangeCategoryMultipleHint": "Altera os downloads para a 'Categoria Pós-Importação' do Cliente de Download",
|
||||
"DatabaseMigration": "Migração de Banco de Dados",
|
||||
"ChangeCategoryHint": "Altera o download para a \"Categoria pós-importação\" do cliente de download",
|
||||
"ChangeCategoryMultipleHint": "Altera os downloads para a \"Categoria pós-importação' do cliente de download",
|
||||
"DatabaseMigration": "Migração de banco de dados",
|
||||
"DoNotBlocklistHint": "Remover sem colocar na lista de bloqueio",
|
||||
"ChangeCategory": "Alterar Categoria",
|
||||
"ChangeCategory": "Alterar categoria",
|
||||
"DoNotBlocklist": "Não coloque na lista de bloqueio",
|
||||
"IgnoreDownloads": "Ignorar Downloads",
|
||||
"IgnoreDownloadHint": "Impede que {appName} processe ainda mais este download",
|
||||
"RemoveMultipleFromDownloadClientHint": "Remove downloads e arquivos do cliente de download",
|
||||
"RemoveQueueItemRemovalMethod": "Método de Remoção",
|
||||
"RemoveQueueItemsRemovalMethodHelpTextWarning": "'Remover do Cliente de Download' removerá os downloads e os arquivos do cliente de download.",
|
||||
"BlocklistAndSearch": "Lista de Bloqueio e Pesquisa",
|
||||
"BlocklistAndSearchHint": "Inicie uma busca por um substituto após adicionar a lista de bloqueio",
|
||||
"BlocklistOnlyHint": "Adiciona a Lista de bloqueio sem procurar um substituto",
|
||||
"BlocklistAndSearch": "Adicionar à lista de bloqueio e pesquisar",
|
||||
"BlocklistAndSearchHint": "Iniciar uma pesquisa por um substituto após adicionar à lista de bloqueio",
|
||||
"BlocklistOnlyHint": "Adicionar à lista de bloqueio sem procurar por um substituto",
|
||||
"IgnoreDownload": "Ignorar Download",
|
||||
"ImportListStatusAllPossiblePartialFetchHealthCheckMessage": "Todas as listas requerem interação manual devido a possíveis buscas parciais",
|
||||
"KeepAndTagSeries": "Manter e Etiquetar Séries",
|
||||
@@ -2038,10 +2038,10 @@
|
||||
"LogOnly": "Só Registro",
|
||||
"CleanLibraryLevel": "Limpar Nível da Biblioteca",
|
||||
"AddDelayProfileError": "Não foi possível adicionar um novo perfil de atraso. Tente novamente.",
|
||||
"ClickToChangeIndexerFlags": "Clique para alterar sinalizadores do indexador",
|
||||
"ClickToChangeIndexerFlags": "Clique para alterar os sinalizadores do indexador",
|
||||
"SelectIndexerFlags": "Selecionar Sinalizadores do Indexador",
|
||||
"SetIndexerFlagsModalTitle": "{modalTitle} - Definir Sinalizadores do Indexador",
|
||||
"CustomFormatsSpecificationFlag": "Sinalizador",
|
||||
"CustomFormatsSpecificationFlag": "Sinalizar",
|
||||
"IndexerFlags": "Sinalizadores do Indexador",
|
||||
"SetIndexerFlags": "Definir Sinalizadores de Indexador",
|
||||
"ImportListsSonarrSettingsSyncSeasonMonitoring": "Sincronização do Monitoramento da Temporada",
|
||||
@@ -2050,7 +2050,7 @@
|
||||
"Filters": "Filtros",
|
||||
"Label": "Rótulo",
|
||||
"LabelIsRequired": "Rótulo é requerido",
|
||||
"ConnectionSettingsUrlBaseHelpText": "Adiciona um prefixo a URL {connectionName}, como {url}",
|
||||
"ConnectionSettingsUrlBaseHelpText": "Adiciona um prefixo ao URL {connectionName}, como {url}",
|
||||
"ReleaseType": "Tipo de Lançamento",
|
||||
"DownloadClientDelugeSettingsDirectory": "Diretório de Download",
|
||||
"DownloadClientDelugeSettingsDirectoryCompleted": "Mover para o Diretório Quando Concluído",
|
||||
@@ -2061,7 +2061,7 @@
|
||||
"ImportListsMyAnimeListSettingsAuthenticateWithMyAnimeList": "Autenticar com MyAnimeList",
|
||||
"ImportListsMyAnimeListSettingsListStatus": "Status da Lista",
|
||||
"ImportListsMyAnimeListSettingsListStatusHelpText": "Tipo de lista da qual você deseja importar, defina como 'Todas' para todas as listas",
|
||||
"CustomFormatsSettingsTriggerInfo": "Um formato personalizado será aplicado a um lançamento ou arquivo quando corresponder a pelo menos um de cada um dos diferentes tipos de condição escolhidos.",
|
||||
"CustomFormatsSettingsTriggerInfo": "Um formato personalizado será aplicado a um lançamento ou arquivo quando corresponder a pelo menos um dos diferentes tipos de condição escolhidos.",
|
||||
"EpisodeTitleFootNote": "Opcionalmente, controle o truncamento para um número máximo de bytes, incluindo reticências (`...`). Truncar do final (por exemplo, `{Episode Title:30}`) ou do início (por exemplo, `{Episode Title:-30}`) é suportado. Os títulos dos episódios serão automaticamente truncados de acordo com as limitações do sistema de arquivos, se necessário.",
|
||||
"NotificationsTelegramSettingsIncludeAppNameHelpText": "Opcionalmente, prefixe o título da mensagem com {appName} para diferenciar notificações de diferentes aplicativos",
|
||||
"ReleaseGroupFootNote": "Opcionalmente, controle o truncamento para um número máximo de bytes, incluindo reticências (`...`). Truncar do final (por exemplo, `{Release Group:30}`) ou do início (por exemplo, `{Release Group:-30}`) é suportado.`).",
|
||||
@@ -2073,5 +2073,10 @@
|
||||
"AutoTaggingSpecificationTag": "Etiqueta",
|
||||
"IndexerSettingsMultiLanguageRelease": "Multi Idiomas",
|
||||
"DownloadClientQbittorrentTorrentStateMissingFiles": "qBittorrent está relatando arquivos perdidos",
|
||||
"BlocklistFilterHasNoItems": "O filtro da lista de bloqueio selecionado não contém itens"
|
||||
"BlocklistFilterHasNoItems": "O filtro selecionado para a lista de bloqueio não contém itens",
|
||||
"DayOfWeekAt": "{day} às {time}",
|
||||
"TodayAt": "Hoje às {time}",
|
||||
"TomorrowAt": "Amanhã às {time}",
|
||||
"HasUnmonitoredSeason": "Tem Temporada Não Monitorada",
|
||||
"YesterdayAt": "Ontem às {time}"
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
"AddDownloadClientError": "Yeni bir indirme istemcisi eklenemiyor, lütfen tekrar deneyin.",
|
||||
"AddCustomFilter": "Özel Filtre Ekleyin",
|
||||
"AddDownloadClientImplementation": "İndirme İstemcisi Ekle - {implementationName}",
|
||||
"AddExclusion": "Hariç Tutma Ekleme",
|
||||
"AddExclusion": "Dışlananlara Ekle",
|
||||
"AddList": "Liste Ekleyin",
|
||||
"AddListError": "Yeni bir liste eklenemiyor, lütfen tekrar deneyin.",
|
||||
"AddNew": "Yeni Ekle",
|
||||
@@ -134,11 +134,11 @@
|
||||
"AutoRedownloadFailedFromInteractiveSearchHelpText": "Başarısız indirmeler, etkileşimli aramada bulunduğunda otomatik olarak farklı bir versiyonu arayın ve indirmeyi deneyin",
|
||||
"ApplyTagsHelpTextReplace": "Değiştir: Etiketleri girilen etiketlerle değiştirin (tüm etiketleri kaldırmak için etiket girmeyin)",
|
||||
"AuthenticationMethod": "Kimlik Doğrulama Yöntemi",
|
||||
"AuthenticationRequired": "Kimlik Doğrulama Gerekli",
|
||||
"AuthenticationRequired": "Kimlik Doğrulama",
|
||||
"AuthenticationRequiredWarning": "Kimlik doğrulaması olmadan uzaktan erişimi engellemek için, {appName}'da artık kimlik doğrulamanın etkinleştirilmesini gerektiriyor. İsteğe bağlı olarak yerel adresler için kimlik doğrulamayı devre dışı bırakabilirsiniz.",
|
||||
"ApiKeyValidationHealthCheckMessage": "Lütfen API anahtarınızı en az {length} karakter sayısı kadar güncelleyiniz. Bunu ayarlar veya yapılandırma dosyası üzerinden yapabilirsiniz",
|
||||
"ClearBlocklistMessageText": "Engellenenler listesindeki tüm öğeleri temizlemek istediğinizden emin misiniz?",
|
||||
"AutomaticUpdatesDisabledDocker": "Docker güncelleme mekanizması kullanıldığında otomatik güncellemeler doğrudan desteklenmez. Kapsayıcı görüntüsünü {appName} dışında güncellemeniz veya bir komut dosyası kullanmanız gerekecek",
|
||||
"AutomaticUpdatesDisabledDocker": "Docker güncelleme mekanizması kullanıldığında otomatik güncellemeler doğrudan desteklenmez. Konteyner görüntüsünü {appName} dışında güncellemeniz veya bir komut dosyası kullanmanız gerekecek",
|
||||
"ConnectionLostReconnect": "{appName} otomatik bağlanmayı deneyecek veya aşağıda yeniden yükle seçeneğini işaretleyebilirsiniz.",
|
||||
"BlackholeWatchFolderHelpText": "{appName} uygulamasının tamamlanmış indirmeleri içe aktaracağı klasör",
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Yeni şifreyi onayla",
|
||||
@@ -196,7 +196,7 @@
|
||||
"DownloadClientDownloadStationValidationSharedFolderMissing": "Paylaşılan klasör mevcut değil",
|
||||
"DeleteImportList": "İçe Aktarma Listesini Sil",
|
||||
"IndexerPriorityHelpText": "Dizinleyici Önceliği (En Yüksek) 1'den (En Düşük) 50'ye kadar. Varsayılan: 25'dir. Eşit olmayan yayınlar için eşitlik bozucu olarak yayınlar alınırken kullanılan {appName}, RSS Senkronizasyonu ve Arama için etkinleştirilmiş tüm dizin oluşturucuları kullanmaya devam edecek",
|
||||
"DisabledForLocalAddresses": "Yerel Adresler için Devre Dışı Bırakıldı",
|
||||
"DisabledForLocalAddresses": "Yerel Adreslerde Devre Dışı Bırak",
|
||||
"DownloadClientDelugeValidationLabelPluginInactive": "Etiket eklentisi etkinleştirilmedi",
|
||||
"DownloadClientDelugeValidationLabelPluginInactiveDetail": "Kategorileri kullanmak için {clientName} uygulamasında Etiket eklentisini etkinleştirmiş olmanız gerekir.",
|
||||
"DownloadClientDownloadStationValidationNoDefaultDestinationDetail": "Diskstation'ınızda {username} olarak oturum açmalı ve BT/HTTP/FTP/NZB -> Konum altında DownloadStation ayarlarında manuel olarak ayarlamalısınız.",
|
||||
@@ -383,7 +383,7 @@
|
||||
"NotificationsKodiSettingAlwaysUpdate": "Daima Güncelle",
|
||||
"NotificationsKodiSettingsCleanLibrary": "Kütüphaneyi Temizle",
|
||||
"NotificationsKodiSettingsCleanLibraryHelpText": "Güncellemeden sonra kitaplığı temizle",
|
||||
"Unmonitored": "İzlenmeyen",
|
||||
"Unmonitored": "Takip Edilmiyor",
|
||||
"FormatAgeHour": "saat",
|
||||
"FormatAgeHours": "saat",
|
||||
"NoHistory": "Geçmiş yok",
|
||||
@@ -549,7 +549,7 @@
|
||||
"VideoDynamicRange": "Video Dinamik Aralığı",
|
||||
"WouldYouLikeToRestoreBackup": "'{name}' yedeğini geri yüklemek ister misiniz?",
|
||||
"NotificationsTwitterSettingsDirectMessage": "Direk mesaj",
|
||||
"PasswordConfirmation": "Şifre onayı",
|
||||
"PasswordConfirmation": "Şifre Tekrarı",
|
||||
"OrganizeRenamingDisabled": "Yeniden adlandırma devre dışı bırakıldı, yeniden adlandırılacak bir şey yok",
|
||||
"ResetQualityDefinitionsMessageText": "Kalite tanımlarını sıfırlamak istediğinizden emin misiniz?",
|
||||
"SelectFolderModalTitle": "{modalTitle} - Klasör seç",
|
||||
@@ -689,7 +689,7 @@
|
||||
"NotificationsValidationUnableToConnectToService": "{serviceName} hizmetine bağlanılamıyor",
|
||||
"OrganizeLoadError": "Önizlemeler yüklenirken hata oluştu",
|
||||
"ParseModalHelpTextDetails": "{appName}, başlığı ayrıştırmaya ve size konuyla ilgili ayrıntıları göstermeye çalışacak",
|
||||
"NegateHelpText": "İşaretlenirse, bu {implementationName} koşulu eşleşirse özel format uygulanmayacaktır.",
|
||||
"NegateHelpText": "İşaretlenirse, {implementationName} koşulu eşleşirse özel format uygulanmayacaktır.",
|
||||
"ParseModalHelpText": "Yukarıdaki girişe bir yayın başlığı girin",
|
||||
"Period": "Periyot",
|
||||
"NotificationsPushoverSettingsSound": "Ses",
|
||||
@@ -802,5 +802,40 @@
|
||||
"MustContain": "İçermeli",
|
||||
"MustNotContain": "İçermemeli",
|
||||
"RssSyncIntervalHelpTextWarning": "Bu, tüm dizinleyiciler için geçerli olacaktır, lütfen onlar tarafından belirlenen kurallara uyun",
|
||||
"DownloadClientQbittorrentTorrentStateMissingFiles": "qBittorrent eksik dosya raporluyor"
|
||||
"DownloadClientQbittorrentTorrentStateMissingFiles": "qBittorrent eksik dosya raporluyor",
|
||||
"ImportListExclusions": "İçe Aktarma Listesinden Hariç Bırakılan(lar)",
|
||||
"UiLanguage": "Arayüz Dili",
|
||||
"IndexerSettingsSeedTimeHelpText": "Bir torrentin durmadan önce seed edilmesi gereken süre. Boş bırakılırsa indirme istemcisinin varsayılan ayarını kullanır",
|
||||
"IndexerSettingsSeedRatioHelpText": "Bir torrentin durmadan önce ulaşması gereken oran. Boş bırakılırsa indirme istemcisinin varsayılan değerini kullanır. Oran en az 1,0 olmalı ve indeksleyici kurallarına uygun olmalıdır",
|
||||
"EditImportListExclusion": "Hariç Tutulanlar Listesini Düzenle",
|
||||
"UiLanguageHelpText": "{appName}'ın arayüz için kullanacağı dil",
|
||||
"IndexerSettingsSeedTime": "Seed Süresi",
|
||||
"BlocklistFilterHasNoItems": "Seçilen engelleme listesi filtresi hiçbir öğe içermiyor",
|
||||
"IndexerSettingsSeedRatio": "Seed Oranı",
|
||||
"Password": "Şifre",
|
||||
"CutoffUnmetNoItems": "Karşılanmayan son öğe yok",
|
||||
"MissingLoadError": "Eksik öğeler yüklenirken hata oluştu",
|
||||
"MissingNoItems": "Eksik öğe yok",
|
||||
"CutoffUnmet": "Kesinti Karşılanmayan",
|
||||
"Monitor": "Takip",
|
||||
"CutoffUnmetLoadError": "Karşılanmamış kesinti öğeleri yüklenirken hata oluştu",
|
||||
"Monitored": "Takip Ediliyor",
|
||||
"MonitoredOnly": "Sadece Takip Edilen",
|
||||
"External": "Harici",
|
||||
"MassSearchCancelWarning": "Bu işlem, {appName} yeniden başlatılmadan veya tüm dizin oluşturucularınız devre dışı bırakılmadan başlatılır ise iptal edilemez.",
|
||||
"IncludeUnmonitored": "Takip Edilmeyenleri Dahil Et",
|
||||
"MonitorSelected": "Takip Edilen Seçildi",
|
||||
"MonitoredStatus": "Takip Edilen/Durum",
|
||||
"UnmonitorSelected": "Seçili Takipleri Kaldır",
|
||||
"ShowMonitored": "Takip Edilenleri Göster",
|
||||
"ShowMonitoredHelpText": "Posterin altında takip durumu göster",
|
||||
"Ui": "Arayüz",
|
||||
"Mechanism": "İşleyiş",
|
||||
"UiSettings": "Arayüz Ayarları",
|
||||
"Script": "Hazır Metin",
|
||||
"UiSettingsLoadError": "Arayüz ayarları yüklenemiyor",
|
||||
"UpdateAutomaticallyHelpText": "Güncelleştirmeleri otomatik olarak indirip yükleyin. Sistem: Güncellemeler'den yükleme yapmaya devam edebileceksiniz",
|
||||
"Wanted": "Arananlar",
|
||||
"Cutoff": "Kesinti",
|
||||
"Required": "Gerekli"
|
||||
}
|
||||
|
||||
@@ -5,5 +5,7 @@
|
||||
"ApiKeyValidationHealthCheckMessage": "Hãy cập nhật mã API để dài ít nhất {length} kí tự. Bạn có thể làm điều này trong cài đặt hoặc trong tập config",
|
||||
"AppDataLocationHealthCheckMessage": "Việc cập nhật sẽ không xảy ra để tránh xóa AppData khi cập nhật",
|
||||
"ApplyChanges": "Áp dụng thay đổi",
|
||||
"AutomaticAdd": "Tự động thêm"
|
||||
"AutomaticAdd": "Tự động thêm",
|
||||
"CalendarOptions": "Tùy chọn lịch",
|
||||
"UpdateMechanismHelpText": "Sử dụng trình cập nhật tích hợp của {appName} hoặc một tập lệnh"
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@
|
||||
"CountIndexersSelected": "已选择 {count} 个索引器",
|
||||
"CurrentlyInstalled": "已安装",
|
||||
"CustomFormats": "自定义命名格式",
|
||||
"CutoffUnmet": "未达截止条件",
|
||||
"CutoffUnmet": "未达设定标准",
|
||||
"Date": "日期",
|
||||
"DeleteBackup": "删除备份",
|
||||
"DeleteCustomFormat": "删除自定义命名格式",
|
||||
@@ -293,7 +293,7 @@
|
||||
"RootFolderMultipleMissingHealthCheckMessage": "多个根目录缺失:{rootFolderPaths}",
|
||||
"SkipRedownloadHelpText": "阻止{appName}尝试下载此项目的替代版本",
|
||||
"Tasks": "任务",
|
||||
"Wanted": "已追踪",
|
||||
"Wanted": "待获取",
|
||||
"Yes": "确定",
|
||||
"AbsoluteEpisodeNumbers": "准确的集数",
|
||||
"RemoveCompleted": "移除已完成",
|
||||
@@ -518,7 +518,7 @@
|
||||
"AnEpisodeIsDownloading": "集正在下载",
|
||||
"AuthenticationRequiredWarning": "为了防止未经身份验证的远程访问,{appName} 现在需要启用身份验证。您可以禁用本地地址的身份验证。",
|
||||
"AutomaticSearch": "自动搜索",
|
||||
"BackupFolderHelpText": "相对路径将在{appName}的AppData目录下",
|
||||
"BackupFolderHelpText": "相对路径将在 {appName} 的 AppData 目录下",
|
||||
"BindAddress": "绑定地址",
|
||||
"BindAddressHelpText": "有效的 IP 地址、localhost、或以'*'代表所有接口",
|
||||
"BlocklistLoadError": "无法加载黑名单",
|
||||
@@ -688,7 +688,7 @@
|
||||
"ICalShowAsAllDayEventsHelpText": "事件将以全天事件的形式显示在日历中",
|
||||
"ICalSeasonPremieresOnlyHelpText": "每季中只有第一集会出现在订阅中",
|
||||
"IconForFinalesHelpText": "根据可用的集信息为完结的剧集或季显示图标",
|
||||
"IconForCutoffUnmet": "未达截止条件的图标",
|
||||
"IconForCutoffUnmet": "未达设定标准的图标",
|
||||
"IconForCutoffUnmetHelpText": "终止监控条件未满足前为文件显示图标",
|
||||
"IconForFinales": "剧集或季完结的图标",
|
||||
"Images": "图像",
|
||||
@@ -1459,8 +1459,8 @@
|
||||
"TotalFileSize": "文件总大小",
|
||||
"TotalRecords": "记录总数: {totalRecords}",
|
||||
"Trace": "追踪",
|
||||
"CutoffUnmetLoadError": "加载未达截止条件项目错误",
|
||||
"CutoffUnmetNoItems": "没有未达截止条件的项目",
|
||||
"CutoffUnmetLoadError": "加载未达设定标准项目时出错",
|
||||
"CutoffUnmetNoItems": "没有未达设定标准的项目",
|
||||
"DeleteSeriesFolderHelpText": "删除剧集文件夹及其所含文件",
|
||||
"DeleteSeriesModalHeader": "删除 - {title}",
|
||||
"DeletedSeriesDescription": "剧集已从 TheTVDB 移除",
|
||||
@@ -1827,5 +1827,14 @@
|
||||
"CustomFormatsSpecificationMaximumSizeHelpText": "必须小于或等于该尺寸时才会发布",
|
||||
"AutoTaggingSpecificationGenre": "类型",
|
||||
"AutoTaggingSpecificationSeriesType": "系列类型",
|
||||
"AutoTaggingSpecificationStatus": "状态"
|
||||
"AutoTaggingSpecificationStatus": "状态",
|
||||
"ClickToChangeIndexerFlags": "点击修改索引器标志",
|
||||
"ConnectionSettingsUrlBaseHelpText": "向 {clientName} url 添加前缀,例如 {url}",
|
||||
"BlocklistFilterHasNoItems": "所选的黑名单过滤器没有项目",
|
||||
"CustomFormatsSpecificationReleaseGroup": "发布组",
|
||||
"MetadataSettingsSeriesMetadata": "季元数据",
|
||||
"CustomFormatsSpecificationResolution": "分辨率",
|
||||
"CustomFormatsSpecificationSource": "来源",
|
||||
"ClickToChangeReleaseType": "点击更改发布类型",
|
||||
"CustomFormatsSettingsTriggerInfo": "当一个发布版本或文件至少匹配其中一个条件时,自定义格式将会被应用到这个版本或文件上。"
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
private readonly List<FFProbePixelFormat> _pixelFormats;
|
||||
|
||||
public const int MINIMUM_MEDIA_INFO_SCHEMA_REVISION = 8;
|
||||
public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 10;
|
||||
public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 11;
|
||||
|
||||
private static readonly string[] ValidHdrColourPrimaries = { "bt2020" };
|
||||
private static readonly string[] HlgTransferFunctions = { "bt2020-10", "arib-std-b67" };
|
||||
private static readonly string[] HlgTransferFunctions = { "arib-std-b67" };
|
||||
private static readonly string[] PqTransferFunctions = { "smpte2084" };
|
||||
private static readonly string[] ValidHdrTransferFunctions = HlgTransferFunctions.Concat(PqTransferFunctions).ToArray();
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Apprise
|
||||
@@ -35,7 +34,7 @@ namespace NzbDrone.Core.Notifications.Apprise
|
||||
}
|
||||
}
|
||||
|
||||
public class AppriseSettings : IProviderConfig
|
||||
public class AppriseSettings : NotificationSettingsBase<AppriseSettings>
|
||||
{
|
||||
private static readonly AppriseSettingsValidator Validator = new ();
|
||||
|
||||
@@ -66,7 +65,7 @@ namespace NzbDrone.Core.Notifications.Apprise
|
||||
[FieldDefinition(7, Label = "Password", Type = FieldType.Password, HelpText = "NotificationsAppriseSettingsPasswordHelpText", Privacy = PrivacyLevel.Password)]
|
||||
public string AuthPassword { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
|
||||
@@ -16,9 +15,9 @@ namespace NzbDrone.Core.Notifications.CustomScript
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomScriptSettings : IProviderConfig
|
||||
public class CustomScriptSettings : NotificationSettingsBase<CustomScriptSettings>
|
||||
{
|
||||
private static readonly CustomScriptSettingsValidator Validator = new CustomScriptSettingsValidator();
|
||||
private static readonly CustomScriptSettingsValidator Validator = new ();
|
||||
|
||||
[FieldDefinition(0, Label = "Path", Type = FieldType.FilePath)]
|
||||
public string Path { get; set; }
|
||||
@@ -26,7 +25,7 @@ namespace NzbDrone.Core.Notifications.CustomScript
|
||||
[FieldDefinition(1, Label = "NotificationsCustomScriptSettingsArguments", HelpText = "NotificationsCustomScriptSettingsArgumentsHelpText", Hidden = HiddenType.HiddenIfNotSet)]
|
||||
public string Arguments { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Discord
|
||||
@@ -14,7 +13,7 @@ namespace NzbDrone.Core.Notifications.Discord
|
||||
}
|
||||
}
|
||||
|
||||
public class DiscordSettings : IProviderConfig
|
||||
public class DiscordSettings : NotificationSettingsBase<DiscordSettings>
|
||||
{
|
||||
public DiscordSettings()
|
||||
{
|
||||
@@ -89,7 +88,7 @@ namespace NzbDrone.Core.Notifications.Discord
|
||||
[FieldDefinition(6, Label = "NotificationsDiscordSettingsOnManualInteractionFields", Advanced = true, SelectOptions = typeof(DiscordManualInteractionFieldType), HelpText = "NotificationsDiscordSettingsOnManualInteractionFieldsHelpText", Type = FieldType.Select)]
|
||||
public IEnumerable<int> ManualInteractionFields { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Email
|
||||
@@ -26,9 +25,9 @@ namespace NzbDrone.Core.Notifications.Email
|
||||
}
|
||||
}
|
||||
|
||||
public class EmailSettings : IProviderConfig
|
||||
public class EmailSettings : NotificationSettingsBase<EmailSettings>
|
||||
{
|
||||
private static readonly EmailSettingsValidator Validator = new EmailSettingsValidator();
|
||||
private static readonly EmailSettingsValidator Validator = new ();
|
||||
|
||||
public EmailSettings()
|
||||
{
|
||||
@@ -66,7 +65,7 @@ namespace NzbDrone.Core.Notifications.Email
|
||||
[FieldDefinition(8, Label = "NotificationsEmailSettingsBccAddress", HelpText = "NotificationsEmailSettingsBccAddressHelpText", Advanced = true)]
|
||||
public IEnumerable<string> Bcc { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Gotify
|
||||
@@ -14,9 +13,9 @@ namespace NzbDrone.Core.Notifications.Gotify
|
||||
}
|
||||
}
|
||||
|
||||
public class GotifySettings : IProviderConfig
|
||||
public class GotifySettings : NotificationSettingsBase<GotifySettings>
|
||||
{
|
||||
private static readonly GotifySettingsValidator Validator = new GotifySettingsValidator();
|
||||
private static readonly GotifySettingsValidator Validator = new ();
|
||||
|
||||
public GotifySettings()
|
||||
{
|
||||
@@ -35,7 +34,7 @@ namespace NzbDrone.Core.Notifications.Gotify
|
||||
[FieldDefinition(3, Label = "NotificationsGotifySettingIncludeSeriesPoster", Type = FieldType.Checkbox, HelpText = "NotificationsGotifySettingIncludeSeriesPosterHelpText")]
|
||||
public bool IncludeSeriesPoster { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Join
|
||||
@@ -14,15 +13,15 @@ namespace NzbDrone.Core.Notifications.Join
|
||||
}
|
||||
}
|
||||
|
||||
public class JoinSettings : IProviderConfig
|
||||
public class JoinSettings : NotificationSettingsBase<JoinSettings>
|
||||
{
|
||||
private static readonly JoinSettingsValidator Validator = new ();
|
||||
|
||||
public JoinSettings()
|
||||
{
|
||||
Priority = (int)JoinPriority.Normal;
|
||||
}
|
||||
|
||||
private static readonly JoinSettingsValidator Validator = new JoinSettingsValidator();
|
||||
|
||||
[FieldDefinition(0, Label = "ApiKey", HelpText = "NotificationsJoinSettingsApiKeyHelpText", HelpLink = "https://joinjoaomgcd.appspot.com/")]
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
@@ -35,7 +34,7 @@ namespace NzbDrone.Core.Notifications.Join
|
||||
[FieldDefinition(3, Label = "NotificationsJoinSettingsNotificationPriority", Type = FieldType.Select, SelectOptions = typeof(JoinPriority))]
|
||||
public int Priority { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Mailgun
|
||||
@@ -17,9 +16,9 @@ namespace NzbDrone.Core.Notifications.Mailgun
|
||||
}
|
||||
}
|
||||
|
||||
public class MailgunSettings : IProviderConfig
|
||||
public class MailgunSettings : NotificationSettingsBase<MailgunSettings>
|
||||
{
|
||||
private static readonly MailGunSettingsValidator Validator = new MailGunSettingsValidator();
|
||||
private static readonly MailGunSettingsValidator Validator = new ();
|
||||
|
||||
public MailgunSettings()
|
||||
{
|
||||
@@ -41,7 +40,7 @@ namespace NzbDrone.Core.Notifications.Mailgun
|
||||
[FieldDefinition(4, Label = "NotificationsEmailSettingsRecipientAddress", Type = FieldType.Tag)]
|
||||
public IEnumerable<string> Recipients { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using FluentValidation;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Emby
|
||||
@@ -19,9 +18,9 @@ namespace NzbDrone.Core.Notifications.Emby
|
||||
}
|
||||
}
|
||||
|
||||
public class MediaBrowserSettings : IProviderConfig
|
||||
public class MediaBrowserSettings : NotificationSettingsBase<MediaBrowserSettings>
|
||||
{
|
||||
private static readonly MediaBrowserSettingsValidator Validator = new MediaBrowserSettingsValidator();
|
||||
private static readonly MediaBrowserSettingsValidator Validator = new ();
|
||||
|
||||
public MediaBrowserSettings()
|
||||
{
|
||||
@@ -65,7 +64,7 @@ namespace NzbDrone.Core.Notifications.Emby
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(Host) && Port > 0;
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using FluentValidation.Results;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Localization;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Notifications.Webhook;
|
||||
using NzbDrone.Core.Tags;
|
||||
@@ -15,8 +16,8 @@ namespace NzbDrone.Core.Notifications.Notifiarr
|
||||
{
|
||||
private readonly INotifiarrProxy _proxy;
|
||||
|
||||
public Notifiarr(INotifiarrProxy proxy, IConfigFileProvider configFileProvider, IConfigService configService, ILocalizationService localizationService, ITagRepository tagRepository)
|
||||
: base(configFileProvider, configService, localizationService, tagRepository)
|
||||
public Notifiarr(INotifiarrProxy proxy, IConfigFileProvider configFileProvider, IConfigService configService, ILocalizationService localizationService, ITagRepository tagRepository, IMapCoversToLocal mediaCoverService)
|
||||
: base(configFileProvider, configService, localizationService, tagRepository, mediaCoverService)
|
||||
{
|
||||
_proxy = proxy;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Notifiarr
|
||||
@@ -13,14 +12,14 @@ namespace NzbDrone.Core.Notifications.Notifiarr
|
||||
}
|
||||
}
|
||||
|
||||
public class NotifiarrSettings : IProviderConfig
|
||||
public class NotifiarrSettings : NotificationSettingsBase<NotifiarrSettings>
|
||||
{
|
||||
private static readonly NotifiarrSettingsValidator Validator = new NotifiarrSettingsValidator();
|
||||
private static readonly NotifiarrSettingsValidator Validator = new ();
|
||||
|
||||
[FieldDefinition(0, Label = "ApiKey", Privacy = PrivacyLevel.ApiKey, HelpText = "NotificationsNotifiarrSettingsApiKeyHelpText", HelpLink = "https://notifiarr.com")]
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ using NzbDrone.Core.Tv;
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public abstract class NotificationBase<TSettings> : INotification
|
||||
where TSettings : IProviderConfig, new()
|
||||
where TSettings : NotificationSettingsBase<TSettings>, new()
|
||||
{
|
||||
protected const string EPISODE_GRABBED_TITLE = "Episode Grabbed";
|
||||
protected const string EPISODE_DOWNLOADED_TITLE = "Episode Downloaded";
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
using System;
|
||||
using Equ;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public class NotificationDefinition : ProviderDefinition
|
||||
public class NotificationDefinition : ProviderDefinition, IEquatable<NotificationDefinition>
|
||||
{
|
||||
private static readonly MemberwiseEqualityComparer<NotificationDefinition> Comparer = MemberwiseEqualityComparer<NotificationDefinition>.ByProperties;
|
||||
|
||||
public bool OnGrab { get; set; }
|
||||
public bool OnDownload { get; set; }
|
||||
public bool OnUpgrade { get; set; }
|
||||
@@ -13,23 +17,63 @@ namespace NzbDrone.Core.Notifications
|
||||
public bool OnEpisodeFileDelete { get; set; }
|
||||
public bool OnEpisodeFileDeleteForUpgrade { get; set; }
|
||||
public bool OnHealthIssue { get; set; }
|
||||
public bool IncludeHealthWarnings { get; set; }
|
||||
public bool OnHealthRestored { get; set; }
|
||||
public bool OnApplicationUpdate { get; set; }
|
||||
public bool OnManualInteractionRequired { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnGrab { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnDownload { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnUpgrade { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnRename { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnSeriesAdd { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnSeriesDelete { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnEpisodeFileDelete { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnEpisodeFileDeleteForUpgrade { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnHealthIssue { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnHealthRestored { get; set; }
|
||||
public bool IncludeHealthWarnings { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnApplicationUpdate { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool SupportsOnManualInteractionRequired { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public override bool Enable => OnGrab || OnDownload || (OnDownload && OnUpgrade) || OnRename || OnSeriesAdd || OnSeriesDelete || OnEpisodeFileDelete || (OnEpisodeFileDelete && OnEpisodeFileDeleteForUpgrade) || OnHealthIssue || OnHealthRestored || OnApplicationUpdate || OnManualInteractionRequired;
|
||||
|
||||
public bool Equals(NotificationDefinition other)
|
||||
{
|
||||
return Comparer.Equals(this, other);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as NotificationDefinition);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Comparer.GetHashCode(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace NzbDrone.Core.Notifications
|
||||
|
||||
public void Handle(ManualInteractionRequiredEvent message)
|
||||
{
|
||||
var series = message.Episode.Series;
|
||||
var series = message.Episode?.Series;
|
||||
var mess = "";
|
||||
|
||||
if (series != null)
|
||||
@@ -255,7 +255,7 @@ namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
Message = mess,
|
||||
Series = series,
|
||||
Quality = message.Episode.ParsedEpisodeInfo.Quality,
|
||||
Quality = message.Episode?.ParsedEpisodeInfo.Quality,
|
||||
Episode = message.Episode,
|
||||
TrackedDownload = message.TrackedDownload,
|
||||
DownloadClientInfo = message.TrackedDownload.DownloadItem?.DownloadClientInfo,
|
||||
|
||||
30
src/NzbDrone.Core/Notifications/NotificationSettingsBase.cs
Normal file
30
src/NzbDrone.Core/Notifications/NotificationSettingsBase.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using Equ;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public abstract class NotificationSettingsBase<TSettings> : IProviderConfig, IEquatable<TSettings>
|
||||
where TSettings : NotificationSettingsBase<TSettings>
|
||||
{
|
||||
private static readonly MemberwiseEqualityComparer<TSettings> Comparer = MemberwiseEqualityComparer<TSettings>.ByProperties;
|
||||
|
||||
public abstract NzbDroneValidationResult Validate();
|
||||
|
||||
public bool Equals(TSettings other)
|
||||
{
|
||||
return Comparer.Equals(this as TSettings, other);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as TSettings);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Comparer.GetHashCode(this as TSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Ntfy
|
||||
@@ -21,12 +20,12 @@ namespace NzbDrone.Core.Notifications.Ntfy
|
||||
RuleForEach(c => c.Topics).NotEmpty().Matches("[a-zA-Z0-9_-]+").Must(c => !InvalidTopics.Contains(c)).WithMessage("Invalid topic");
|
||||
}
|
||||
|
||||
private static List<string> InvalidTopics => new List<string> { "announcements", "app", "docs", "settings", "stats", "mytopic-rw", "mytopic-ro", "mytopic-wo" };
|
||||
private static List<string> InvalidTopics => new () { "announcements", "app", "docs", "settings", "stats", "mytopic-rw", "mytopic-ro", "mytopic-wo" };
|
||||
}
|
||||
|
||||
public class NtfySettings : IProviderConfig
|
||||
public class NtfySettings : NotificationSettingsBase<NtfySettings>
|
||||
{
|
||||
private static readonly NtfySettingsValidator Validator = new NtfySettingsValidator();
|
||||
private static readonly NtfySettingsValidator Validator = new ();
|
||||
|
||||
public NtfySettings()
|
||||
{
|
||||
@@ -59,7 +58,7 @@ namespace NzbDrone.Core.Notifications.Ntfy
|
||||
[FieldDefinition(7, Label = "NotificationsNtfySettingsClickUrl", Type = FieldType.Url, HelpText = "NotificationsNtfySettingsClickUrlHelpText")]
|
||||
public string ClickUrl { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Plex.Server
|
||||
@@ -17,9 +16,9 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
||||
}
|
||||
}
|
||||
|
||||
public class PlexServerSettings : IProviderConfig
|
||||
public class PlexServerSettings : NotificationSettingsBase<PlexServerSettings>
|
||||
{
|
||||
private static readonly PlexServerSettingsValidator Validator = new PlexServerSettingsValidator();
|
||||
private static readonly PlexServerSettingsValidator Validator = new ();
|
||||
|
||||
public PlexServerSettings()
|
||||
{
|
||||
@@ -62,7 +61,7 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(Host);
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user