Compare commits
17 Commits
mark-as-fa
...
develop
Author | SHA1 | Date |
---|---|---|
Bogdan | 2f04b037a1 | |
Bogdan | 7b87de2e93 | |
Bogdan | eb2fd13509 | |
Bogdan | ffdb08cfe6 | |
Mark McDowall | 37c4647f24 | |
Mark McDowall | f7a58aab33 | |
Mark McDowall | 4b186e894e | |
kephasdev | 35a2bc9403 | |
Bogdan | cc03ce04f1 | |
Bogdan | 363f8fc347 | |
RaZaSB | 0877a6718d | |
Bogdan | 8b253c36ea | |
Bogdan | e6f82270a9 | |
Mark McDowall | 813965e6a2 | |
Mark McDowall | 0d914f4c53 | |
Mark McDowall | ae7f73208a | |
Weblate | 4c86d673ea |
|
@ -59,7 +59,7 @@ app_guid=$(echo "$app_guid" | tr -d ' ')
|
|||
app_guid=${app_guid:-media}
|
||||
|
||||
echo "This will install [${app^}] to [$bindir] and use [$datadir] for the AppData Directory"
|
||||
echo "${app^} will run as the user [$app_uid] and group [$app_guid]. By continuing, you've confirmed that that user and group will have READ and WRITE access to your Media Library and Download Client Completed Download directories"
|
||||
echo "${app^} will run as the user [$app_uid] and group [$app_guid]. By continuing, you've confirmed that the selected user and group will have READ and WRITE access to your Media Library and Download Client Completed Download directories"
|
||||
read -n 1 -r -s -p $'Press enter to continue or ctrl+c to exit...\n' < /dev/tty
|
||||
|
||||
# Create User / Group as needed
|
||||
|
@ -114,7 +114,7 @@ case "$ARCH" in
|
|||
esac
|
||||
echo ""
|
||||
echo "Removing previous tarballs"
|
||||
# -f to Force so we fail if it doesnt exist
|
||||
# -f to Force so we fail if it doesn't exist
|
||||
rm -f "${app^}".*.tar.gz
|
||||
echo ""
|
||||
echo "Downloading..."
|
||||
|
|
|
@ -26,4 +26,5 @@
|
|||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 70px;
|
||||
text-align: right;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ interface RootFolderRowProps {
|
|||
}
|
||||
|
||||
function RootFolderRow(props: RootFolderRowProps) {
|
||||
const { id, path, accessible, freeSpace, unmappedFolders = [] } = props;
|
||||
const { id, path, accessible, freeSpace = 0, unmappedFolders = [] } = props;
|
||||
|
||||
const isUnavailable = !accessible;
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||
|
@ -6,14 +5,19 @@ import formatBytes from 'Utilities/Number/formatBytes';
|
|||
import translate from 'Utilities/String/translate';
|
||||
import styles from './SeasonInfo.css';
|
||||
|
||||
function SeasonInfo(props) {
|
||||
const {
|
||||
totalEpisodeCount,
|
||||
monitoredEpisodeCount,
|
||||
episodeFileCount,
|
||||
sizeOnDisk
|
||||
} = props;
|
||||
interface SeasonInfoProps {
|
||||
totalEpisodeCount: number;
|
||||
monitoredEpisodeCount: number;
|
||||
episodeFileCount: number;
|
||||
sizeOnDisk: number;
|
||||
}
|
||||
|
||||
function SeasonInfo({
|
||||
totalEpisodeCount,
|
||||
monitoredEpisodeCount,
|
||||
episodeFileCount,
|
||||
sizeOnDisk,
|
||||
}: SeasonInfoProps) {
|
||||
return (
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
|
@ -47,11 +51,4 @@ function SeasonInfo(props) {
|
|||
);
|
||||
}
|
||||
|
||||
SeasonInfo.propTypes = {
|
||||
totalEpisodeCount: PropTypes.number.isRequired,
|
||||
monitoredEpisodeCount: PropTypes.number.isRequired,
|
||||
episodeFileCount: PropTypes.number.isRequired,
|
||||
sizeOnDisk: PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
export default SeasonInfo;
|
|
@ -212,8 +212,8 @@ class SeriesDetails extends Component {
|
|||
} = this.props;
|
||||
|
||||
const {
|
||||
episodeFileCount,
|
||||
sizeOnDisk
|
||||
episodeFileCount = 0,
|
||||
sizeOnDisk = 0
|
||||
} = statistics;
|
||||
|
||||
const {
|
||||
|
@ -454,10 +454,9 @@ class SeriesDetails extends Component {
|
|||
name={icons.DRIVE}
|
||||
size={17}
|
||||
/>
|
||||
|
||||
<span className={styles.sizeOnDisk}>
|
||||
{
|
||||
formatBytes(sizeOnDisk || 0)
|
||||
}
|
||||
{formatBytes(sizeOnDisk)}
|
||||
</span>
|
||||
</div>
|
||||
</Label>
|
||||
|
|
|
@ -194,10 +194,12 @@ function getInfoRowProps(
|
|||
}
|
||||
|
||||
if (name === 'sizeOnDisk') {
|
||||
const { sizeOnDisk = 0 } = props;
|
||||
|
||||
return {
|
||||
title: translate('SizeOnDisk'),
|
||||
iconName: icons.DRIVE,
|
||||
label: formatBytes(props.sizeOnDisk),
|
||||
label: formatBytes(sizeOnDisk),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ function SeriesIndexPosterInfo(props: SeriesIndexPosterInfoProps) {
|
|||
added,
|
||||
seasonCount,
|
||||
path,
|
||||
sizeOnDisk,
|
||||
sizeOnDisk = 0,
|
||||
tags,
|
||||
sortKey,
|
||||
showRelativeDates,
|
||||
|
|
|
@ -32,7 +32,7 @@ function EditImportListExclusionModal(
|
|||
<Modal size={sizes.MEDIUM} isOpen={isOpen} onModalClose={onModalClosePress}>
|
||||
<EditImportListExclusionModalContent
|
||||
{...otherProps}
|
||||
onModalClose={onModalClose}
|
||||
onModalClose={onModalClosePress}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
@ -7,7 +7,7 @@ function createRemoveItemHandler(section, url) {
|
|||
return function(getState, payload, dispatch) {
|
||||
const {
|
||||
id,
|
||||
...queryParams
|
||||
queryParams
|
||||
} = payload;
|
||||
|
||||
dispatch(set({ section, isDeleting: true }));
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
import { filesize } from 'filesize';
|
||||
|
||||
function formatBytes(input?: string | number) {
|
||||
if (!input) {
|
||||
return '';
|
||||
}
|
||||
|
||||
function formatBytes(input: string | number) {
|
||||
const size = Number(input);
|
||||
|
||||
if (isNaN(size)) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
using FluentAssertions;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Common.Test.ExtensionTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class Int64ExtensionFixture
|
||||
public class NumberExtensionFixture
|
||||
{
|
||||
[TestCase(0, "0 B")]
|
||||
[TestCase(1000, "1,000.0 B")]
|
|
@ -1,9 +1,9 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace NzbDrone.Common.Extensions
|
||||
{
|
||||
public static class Int64Extensions
|
||||
public static class NumberExtensions
|
||||
{
|
||||
private static readonly string[] SizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
|
||||
|
||||
|
@ -26,5 +26,25 @@ namespace NzbDrone.Common.Extensions
|
|||
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0:n1} {1}", adjustedSize, SizeSuffixes[mag]);
|
||||
}
|
||||
|
||||
public static long Megabytes(this int megabytes)
|
||||
{
|
||||
return Convert.ToInt64(megabytes * 1024L * 1024L);
|
||||
}
|
||||
|
||||
public static long Gigabytes(this int gigabytes)
|
||||
{
|
||||
return Convert.ToInt64(gigabytes * 1024L * 1024L * 1024L);
|
||||
}
|
||||
|
||||
public static long Megabytes(this double megabytes)
|
||||
{
|
||||
return Convert.ToInt64(megabytes * 1024L * 1024L);
|
||||
}
|
||||
|
||||
public static long Gigabytes(this double gigabytes)
|
||||
{
|
||||
return Convert.ToInt64(gigabytes * 1024L * 1024L * 1024L);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NLog.Fluent;
|
||||
|
||||
namespace NzbDrone.Common.Instrumentation.Extensions
|
||||
{
|
||||
|
@ -8,47 +8,46 @@ namespace NzbDrone.Common.Instrumentation.Extensions
|
|||
{
|
||||
public static readonly Logger SentryLogger = LogManager.GetLogger("Sentry");
|
||||
|
||||
public static LogBuilder SentryFingerprint(this LogBuilder logBuilder, params string[] fingerprint)
|
||||
public static LogEventBuilder SentryFingerprint(this LogEventBuilder logBuilder, params string[] fingerprint)
|
||||
{
|
||||
return logBuilder.Property("Sentry", fingerprint);
|
||||
}
|
||||
|
||||
public static LogBuilder WriteSentryDebug(this LogBuilder logBuilder, params string[] fingerprint)
|
||||
public static LogEventBuilder WriteSentryDebug(this LogEventBuilder logBuilder, params string[] fingerprint)
|
||||
{
|
||||
return LogSentryMessage(logBuilder, LogLevel.Debug, fingerprint);
|
||||
}
|
||||
|
||||
public static LogBuilder WriteSentryInfo(this LogBuilder logBuilder, params string[] fingerprint)
|
||||
public static LogEventBuilder WriteSentryInfo(this LogEventBuilder logBuilder, params string[] fingerprint)
|
||||
{
|
||||
return LogSentryMessage(logBuilder, LogLevel.Info, fingerprint);
|
||||
}
|
||||
|
||||
public static LogBuilder WriteSentryWarn(this LogBuilder logBuilder, params string[] fingerprint)
|
||||
public static LogEventBuilder WriteSentryWarn(this LogEventBuilder logBuilder, params string[] fingerprint)
|
||||
{
|
||||
return LogSentryMessage(logBuilder, LogLevel.Warn, fingerprint);
|
||||
}
|
||||
|
||||
public static LogBuilder WriteSentryError(this LogBuilder logBuilder, params string[] fingerprint)
|
||||
public static LogEventBuilder WriteSentryError(this LogEventBuilder logBuilder, params string[] fingerprint)
|
||||
{
|
||||
return LogSentryMessage(logBuilder, LogLevel.Error, fingerprint);
|
||||
}
|
||||
|
||||
private static LogBuilder LogSentryMessage(LogBuilder logBuilder, LogLevel level, string[] fingerprint)
|
||||
private static LogEventBuilder LogSentryMessage(LogEventBuilder logBuilder, LogLevel level, string[] fingerprint)
|
||||
{
|
||||
SentryLogger.Log(level)
|
||||
.CopyLogEvent(logBuilder.LogEventInfo)
|
||||
SentryLogger.ForLogEvent(level)
|
||||
.CopyLogEvent(logBuilder.LogEvent)
|
||||
.SentryFingerprint(fingerprint)
|
||||
.Write();
|
||||
.Log();
|
||||
|
||||
return logBuilder.Property("Sentry", null);
|
||||
return logBuilder.Property<string>("Sentry", null);
|
||||
}
|
||||
|
||||
private static LogBuilder CopyLogEvent(this LogBuilder logBuilder, LogEventInfo logEvent)
|
||||
private static LogEventBuilder CopyLogEvent(this LogEventBuilder logBuilder, LogEventInfo logEvent)
|
||||
{
|
||||
return logBuilder.LoggerName(logEvent.LoggerName)
|
||||
.TimeStamp(logEvent.TimeStamp)
|
||||
return logBuilder.TimeStamp(logEvent.TimeStamp)
|
||||
.Message(logEvent.Message, logEvent.Parameters)
|
||||
.Properties(logEvent.Properties.ToDictionary(v => v.Key, v => v.Value))
|
||||
.Properties(logEvent.Properties.Select(p => new KeyValuePair<string, object>(p.Key.ToString(), p.Value)))
|
||||
.Exception(logEvent.Exception);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
using NLog;
|
||||
using System.Text;
|
||||
using NLog;
|
||||
using NLog.Targets;
|
||||
|
||||
namespace NzbDrone.Common.Instrumentation
|
||||
{
|
||||
public class NzbDroneFileTarget : FileTarget
|
||||
{
|
||||
protected override string GetFormattedMessage(LogEventInfo logEvent)
|
||||
protected override void RenderFormattedMessage(LogEventInfo logEvent, StringBuilder target)
|
||||
{
|
||||
return CleanseLogMessage.Cleanse(Layout.Render(logEvent));
|
||||
var result = CleanseLogMessage.Cleanse(Layout.Render(logEvent));
|
||||
target.Append(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Diagnostics;
|
|||
using System.IO;
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
using NLog.Layouts.ClefJsonLayout;
|
||||
using NLog.Targets;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
@ -13,6 +14,8 @@ namespace NzbDrone.Common.Instrumentation
|
|||
public static class NzbDroneLogger
|
||||
{
|
||||
private const string FILE_LOG_LAYOUT = @"${date:format=yyyy-MM-dd HH\:mm\:ss.f}|${level}|${logger}|${message}${onexception:inner=${newline}${newline}[v${assembly-version}] ${exception:format=ToString}${newline}}";
|
||||
public const string ConsoleLogLayout = "[${level}] ${logger}: ${message} ${onexception:inner=${newline}${newline}[v${assembly-version}] ${exception:format=ToString}${newline}}";
|
||||
public static CompactJsonLayout ClefLogLayout = new CompactJsonLayout();
|
||||
|
||||
private static bool _isConfigured;
|
||||
|
||||
|
@ -34,6 +37,8 @@ namespace NzbDrone.Common.Instrumentation
|
|||
|
||||
var appFolderInfo = new AppFolderInfo(startupContext);
|
||||
|
||||
RegisterGlobalFilters();
|
||||
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
RegisterDebugger();
|
||||
|
@ -122,7 +127,16 @@ namespace NzbDrone.Common.Instrumentation
|
|||
var coloredConsoleTarget = new ColoredConsoleTarget();
|
||||
|
||||
coloredConsoleTarget.Name = "consoleLogger";
|
||||
coloredConsoleTarget.Layout = "[${level}] ${logger}: ${message} ${onexception:inner=${newline}${newline}[v${assembly-version}] ${exception:format=ToString}${newline}}";
|
||||
|
||||
var logFormat = Enum.TryParse<ConsoleLogFormat>(Environment.GetEnvironmentVariable("SONARR__LOG__CONSOLEFORMAT"), out var formatEnumValue)
|
||||
? formatEnumValue
|
||||
: ConsoleLogFormat.Standard;
|
||||
|
||||
coloredConsoleTarget.Layout = logFormat switch
|
||||
{
|
||||
ConsoleLogFormat.Clef => ClefLogLayout,
|
||||
_ => ConsoleLogLayout
|
||||
};
|
||||
|
||||
var loggingRule = new LoggingRule("*", level, coloredConsoleTarget);
|
||||
|
||||
|
@ -148,7 +162,7 @@ namespace NzbDrone.Common.Instrumentation
|
|||
fileTarget.ConcurrentWrites = false;
|
||||
fileTarget.ConcurrentWriteAttemptDelay = 50;
|
||||
fileTarget.ConcurrentWriteAttempts = 10;
|
||||
fileTarget.ArchiveAboveSize = 1024000;
|
||||
fileTarget.ArchiveAboveSize = 1.Megabytes();
|
||||
fileTarget.MaxArchiveFiles = maxArchiveFiles;
|
||||
fileTarget.EnableFileDelete = true;
|
||||
fileTarget.ArchiveNumbering = ArchiveNumberingMode.Rolling;
|
||||
|
@ -196,6 +210,17 @@ namespace NzbDrone.Common.Instrumentation
|
|||
LogManager.Configuration.LoggingRules.Insert(0, rule);
|
||||
}
|
||||
|
||||
private static void RegisterGlobalFilters()
|
||||
{
|
||||
LogManager.Setup().LoadConfiguration(c =>
|
||||
{
|
||||
c.ForLogger("System.*").WriteToNil(LogLevel.Warn);
|
||||
c.ForLogger("Microsoft.*").WriteToNil(LogLevel.Warn);
|
||||
c.ForLogger("Microsoft.Hosting.Lifetime*").WriteToNil(LogLevel.Info);
|
||||
c.ForLogger("Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware").WriteToNil(LogLevel.Fatal);
|
||||
});
|
||||
}
|
||||
|
||||
public static Logger GetLogger(Type obj)
|
||||
{
|
||||
return LogManager.GetLogger(obj.Name.Replace("NzbDrone.", ""));
|
||||
|
@ -206,4 +231,10 @@ namespace NzbDrone.Common.Instrumentation
|
|||
return GetLogger(obj.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
public enum ConsoleLogFormat
|
||||
{
|
||||
Standard,
|
||||
Clef
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,10 @@ public class LogOptions
|
|||
public string Level { get; set; }
|
||||
public bool? FilterSentryEvents { get; set; }
|
||||
public int? Rotate { get; set; }
|
||||
public int? SizeLimit { get; set; }
|
||||
public bool? Sql { get; set; }
|
||||
public string ConsoleLevel { get; set; }
|
||||
public string ConsoleFormat { get; set; }
|
||||
public bool? AnalyticsEnabled { get; set; }
|
||||
public string SyslogServer { get; set; }
|
||||
public int? SyslogPort { get; set; }
|
||||
|
|
|
@ -8,9 +8,10 @@
|
|||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="4.7.14" />
|
||||
<PackageReference Include="NLog.Targets.Syslog" Version="6.0.3" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="1.7.4" />
|
||||
<PackageReference Include="NLog" Version="5.3.2" />
|
||||
<PackageReference Include="NLog.Layouts.ClefJsonLayout" Version="1.0.0" />
|
||||
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.11" />
|
||||
<PackageReference Include="Sentry" Version="4.0.2" />
|
||||
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageReference Include="System.Text.Json" Version="6.0.9" />
|
||||
|
|
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
|||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
|
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore.Migration;
|
||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||
|
|
|
@ -4,6 +4,7 @@ using FizzWare.NBuilder;
|
|||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
};
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()))
|
||||
.Setup(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<SearchCriteriaBase>()))
|
||||
.Returns(_remoteEpisode);
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
|
||||
Subject.GetRssDecision(_reports).ToList();
|
||||
|
||||
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()), Times.Never());
|
||||
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<SearchCriteriaBase>()), Times.Never());
|
||||
|
||||
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
|
||||
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
|
||||
|
@ -169,7 +169,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
|
||||
var results = Subject.GetRssDecision(_reports).ToList();
|
||||
|
||||
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()), Times.Never());
|
||||
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<SearchCriteriaBase>()), Times.Never());
|
||||
|
||||
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
|
||||
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
|
||||
|
@ -186,7 +186,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
|
||||
Subject.GetSearchDecision(_reports, new SingleEpisodeSearchCriteria()).ToList();
|
||||
|
||||
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()), Times.Never());
|
||||
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<SearchCriteriaBase>()), Times.Never());
|
||||
|
||||
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
|
||||
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null), Times.Never());
|
||||
|
@ -212,7 +212,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
{
|
||||
GivenSpecifications(_pass1);
|
||||
|
||||
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()))
|
||||
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<SearchCriteriaBase>()))
|
||||
.Throws<TestException>();
|
||||
|
||||
_reports = new List<ReleaseInfo>
|
||||
|
@ -224,7 +224,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
|
||||
Subject.GetRssDecision(_reports);
|
||||
|
||||
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()), Times.Exactly(_reports.Count));
|
||||
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<SearchCriteriaBase>()), Times.Exactly(_reports.Count));
|
||||
|
||||
ExceptionVerification.ExpectedErrors(3);
|
||||
}
|
||||
|
@ -263,8 +263,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
}).ToList();
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(v => v.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()))
|
||||
.Returns<ParsedEpisodeInfo, int, int, SearchCriteriaBase>((p, tvdbid, tvrageid, c) =>
|
||||
.Setup(v => v.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<SearchCriteriaBase>()))
|
||||
.Returns<ParsedEpisodeInfo, int, int, string, SearchCriteriaBase>((p, _, _, _, _) =>
|
||||
new RemoteEpisode
|
||||
{
|
||||
DownloadAllowed = true,
|
||||
|
@ -318,7 +318,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
{
|
||||
GivenSpecifications(_pass1);
|
||||
|
||||
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>()))
|
||||
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<SearchCriteriaBase>()))
|
||||
.Throws<TestException>();
|
||||
|
||||
_reports = new List<ReleaseInfo>
|
||||
|
|
|
@ -4,6 +4,8 @@ using FizzWare.NBuilder;
|
|||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Download.Aggregation.Aggregators;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.TorrentRss;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
@ -62,6 +64,63 @@ namespace NzbDrone.Core.Test.Download.Aggregation.Aggregators
|
|||
Subject.Aggregate(_remoteEpisode).Languages.Should().Equal(_remoteEpisode.ParsedEpisodeInfo.Languages);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_multi_languages_when_indexer_has_multi_languages_configuration()
|
||||
{
|
||||
var releaseTitle = "Series.Title.S01E01.MULTi.1080p.WEB.H265-RlsGroup";
|
||||
var indexerDefinition = new IndexerDefinition
|
||||
{
|
||||
Settings = new TorrentRssIndexerSettings { MultiLanguages = new List<int> { Language.Original.Id, Language.French.Id } }
|
||||
};
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(v => v.Get(1))
|
||||
.Returns(indexerDefinition);
|
||||
|
||||
_remoteEpisode.ParsedEpisodeInfo = GetParsedEpisodeInfo(new List<Language> { }, releaseTitle);
|
||||
_remoteEpisode.Release.IndexerId = 1;
|
||||
_remoteEpisode.Release.Title = releaseTitle;
|
||||
|
||||
Subject.Aggregate(_remoteEpisode).Languages.Should().BeEquivalentTo(new List<Language> { _series.OriginalLanguage, Language.French });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_multi_languages_when_release_as_unknown_as_default_language_and_indexer_has_multi_languages_configuration()
|
||||
{
|
||||
var releaseTitle = "Series.Title.S01E01.MULTi.1080p.WEB.H265-RlsGroup";
|
||||
var indexerDefinition = new IndexerDefinition
|
||||
{
|
||||
Settings = new TorrentRssIndexerSettings { MultiLanguages = new List<int> { Language.Original.Id, Language.French.Id } }
|
||||
};
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(v => v.Get(1))
|
||||
.Returns(indexerDefinition);
|
||||
|
||||
_remoteEpisode.ParsedEpisodeInfo = GetParsedEpisodeInfo(new List<Language> { Language.Unknown }, releaseTitle);
|
||||
_remoteEpisode.Release.IndexerId = 1;
|
||||
_remoteEpisode.Release.Title = releaseTitle;
|
||||
|
||||
Subject.Aggregate(_remoteEpisode).Languages.Should().BeEquivalentTo(new List<Language> { _series.OriginalLanguage, Language.French });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_original_when_indexer_has_no_multi_languages_configuration()
|
||||
{
|
||||
var releaseTitle = "Series.Title.S01E01.MULTi.1080p.WEB.H265-RlsGroup";
|
||||
var indexerDefinition = new IndexerDefinition
|
||||
{
|
||||
Settings = new TorrentRssIndexerSettings { }
|
||||
};
|
||||
Mocker.GetMock<IIndexerFactory>()
|
||||
.Setup(v => v.Get(1))
|
||||
.Returns(indexerDefinition);
|
||||
|
||||
_remoteEpisode.ParsedEpisodeInfo = GetParsedEpisodeInfo(new List<Language> { }, releaseTitle);
|
||||
_remoteEpisode.Release.IndexerId = 1;
|
||||
_remoteEpisode.Release.Title = releaseTitle;
|
||||
|
||||
Subject.Aggregate(_remoteEpisode).Languages.Should().BeEquivalentTo(new List<Language> { _series.OriginalLanguage });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_exclude_language_that_is_part_of_episode_title_when_release_tokens_contains_episode_title()
|
||||
{
|
||||
|
|
|
@ -10,7 +10,6 @@ using NzbDrone.Common.Http;
|
|||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Localization;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
@ -35,7 +34,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
|
|||
.Returns(30);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), (SearchCriteriaBase)null))
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), null))
|
||||
.Returns(() => CreateRemoteEpisode());
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
|
|
|
@ -118,7 +118,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
|||
.Returns(remoteEpisode);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.ParseSpecialEpisodeTitle(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Setup(s => s.ParseSpecialEpisodeTitle(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), null))
|
||||
.Returns(remoteEpisode.ParsedEpisodeInfo);
|
||||
|
||||
var client = new DownloadClientDefinition()
|
||||
|
@ -169,7 +169,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
|||
};
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), null))
|
||||
.Returns(remoteEpisode);
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
|
@ -199,7 +199,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
|||
Subject.GetTrackedDownloads().Should().HaveCount(1);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), null))
|
||||
.Returns(default(RemoteEpisode));
|
||||
|
||||
Subject.Handle(new EpisodeInfoRefreshedEvent(remoteEpisode.Series, new List<Episode>(), new List<Episode>(), remoteEpisode.Episodes));
|
||||
|
@ -228,7 +228,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
|||
};
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), null))
|
||||
.Returns(default(RemoteEpisode));
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
|
@ -258,7 +258,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
|||
Subject.GetTrackedDownloads().Should().HaveCount(1);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), null))
|
||||
.Returns(default(RemoteEpisode));
|
||||
|
||||
Subject.Handle(new EpisodeInfoRefreshedEvent(remoteEpisode.Series, new List<Episode>(), new List<Episode>(), remoteEpisode.Episodes));
|
||||
|
@ -287,7 +287,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
|||
};
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), null))
|
||||
.Returns(default(RemoteEpisode));
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
|
@ -317,7 +317,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
|||
Subject.GetTrackedDownloads().Should().HaveCount(1);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), null))
|
||||
.Returns(default(RemoteEpisode));
|
||||
|
||||
Subject.Handle(new SeriesDeletedEvent(new List<Series> { remoteEpisode.Series }, true, true));
|
||||
|
|
|
@ -15,6 +15,10 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
|
|||
[TestCase("Franklin & Bash", "Franklin+and+Bash")]
|
||||
[TestCase("Chicago P.D.", "Chicago+PD")]
|
||||
[TestCase("Kourtney And Khlo\u00E9 Take The Hamptons", "Kourtney+And+Khloe+Take+The+Hamptons")]
|
||||
[TestCase("Betty White`s Off Their Rockers", "Betty+Whites+Off+Their+Rockers")]
|
||||
[TestCase("Betty White\u00b4s Off Their Rockers", "Betty+Whites+Off+Their+Rockers")]
|
||||
[TestCase("Betty White‘s Off Their Rockers", "Betty+Whites+Off+Their+Rockers")]
|
||||
[TestCase("Betty White’s Off Their Rockers", "Betty+Whites+Off+Their+Rockers")]
|
||||
public void should_replace_some_special_characters(string input, string expected)
|
||||
{
|
||||
Subject.SceneTitles = new List<string> { input };
|
||||
|
|
|
@ -7,6 +7,7 @@ using FluentAssertions;
|
|||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
|
|
|
@ -6,6 +6,7 @@ using FluentAssertions;
|
|||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport.Specifications;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
|
|
@ -233,11 +233,11 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||
GivenEpisodes(actualInfo, actualInfo.EpisodeNumbers);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(v => v.ParseSpecialEpisodeTitle(fileInfo, It.IsAny<string>(), 0, 0, null))
|
||||
.Setup(v => v.ParseSpecialEpisodeTitle(fileInfo, It.IsAny<string>(), 0, 0, null, null))
|
||||
.Returns(actualInfo);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(v => v.ParseSpecialEpisodeTitle(folderInfo, It.IsAny<string>(), 0, 0, null))
|
||||
.Setup(v => v.ParseSpecialEpisodeTitle(folderInfo, It.IsAny<string>(), 0, 0, null, null))
|
||||
.Returns(actualInfo);
|
||||
|
||||
Subject.IsSatisfiedBy(localEpisode, null).Accepted.Should().BeTrue();
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
GivenDailySeries();
|
||||
GivenDailyParseResult();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>(), null), Times.Once());
|
||||
|
@ -103,7 +103,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
GivenDailySeries();
|
||||
GivenDailyParseResult();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>(), null), Times.Never());
|
||||
|
@ -115,7 +115,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
GivenDailySeries();
|
||||
_parsedEpisodeInfo.AirDate = DateTime.Today.AddDays(-5).ToString(Episode.AIR_DATE_FORMAT);
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>(), null), Times.Once());
|
||||
|
@ -128,7 +128,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
GivenDailyParseResult();
|
||||
_parsedEpisodeInfo.DailyPart = 1;
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>(), 1), Times.Once());
|
||||
|
@ -143,7 +143,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
.Setup(s => s.FindEpisodesBySceneNumbering(It.IsAny<int>(), It.IsAny<int>()))
|
||||
.Returns(new List<Episode>());
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>(), null), Times.Never());
|
||||
|
@ -154,7 +154,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
GivenSceneNumberingSeries();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>()), Times.Once());
|
||||
|
@ -165,7 +165,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
GivenSceneNumberingSeries();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>()), Times.Never());
|
||||
|
@ -177,7 +177,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
GivenSceneNumberingSeries();
|
||||
_episodes.First().SceneEpisodeNumber = 10;
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>()), Times.Once());
|
||||
|
@ -186,7 +186,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
[Test]
|
||||
public void should_find_episode()
|
||||
{
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>()), Times.Once());
|
||||
|
@ -195,7 +195,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
[Test]
|
||||
public void should_match_episode_with_search_criteria()
|
||||
{
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>()), Times.Never());
|
||||
|
@ -206,7 +206,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
_episodes.First().EpisodeNumber = 10;
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>()), Times.Once());
|
||||
|
@ -537,7 +537,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
.With(e => e.EpisodeNumber = 1)
|
||||
.Build());
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisode(_series.TvdbId, 0, 1), Times.Once());
|
||||
|
@ -555,7 +555,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
.Setup(s => s.FindEpisodeByTitle(_series.TvdbId, 0, _parsedEpisodeInfo.ReleaseTitle))
|
||||
.Returns((Episode)null);
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisode(_series.TvdbId, _parsedEpisodeInfo.SeasonNumber, _parsedEpisodeInfo.EpisodeNumbers.First()), Times.Once());
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
GivenMatchBySeriesTitle();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>()), Times.Once());
|
||||
|
@ -97,7 +97,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
GivenMatchByTvdbId();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTvdbId(It.IsAny<int>()), Times.Once());
|
||||
|
@ -108,7 +108,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
GivenMatchByTvRageId();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 0, _series.TvRageId);
|
||||
Subject.Map(_parsedEpisodeInfo, 0, _series.TvRageId, null);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTvRageId(It.IsAny<int>()), Times.Once());
|
||||
|
@ -123,7 +123,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
.Setup(v => v.FindSceneMapping(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()))
|
||||
.Returns(new SceneMapping { TvdbId = 10 });
|
||||
|
||||
var result = Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
var result = Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTvRageId(It.IsAny<int>()), Times.Never());
|
||||
|
@ -136,7 +136,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
GivenMatchBySeriesTitle();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>()), Times.Never());
|
||||
|
@ -147,7 +147,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, null, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>()), Times.Once());
|
||||
|
@ -169,7 +169,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
.Setup(s => s.FindByTitle(_parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear, _parsedEpisodeInfo.SeriesTitleInfo.Year))
|
||||
.Returns(_series);
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, null, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>(), It.IsAny<int>()), Times.Once());
|
||||
|
@ -180,7 +180,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, null, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTvdbId(It.IsAny<int>()), Times.Once());
|
||||
|
@ -191,7 +191,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 0, 10, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, 0, 10, null, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTvRageId(It.IsAny<int>()), Times.Once());
|
||||
|
@ -202,12 +202,34 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, null, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTvRageId(It.IsAny<int>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_FindByImdbId_when_search_criteria_and_FindByTitle_matching_fails()
|
||||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 0, 0, "tt12345", _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByImdbId(It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_FindByImdbId_when_search_criteria_and_FindByTitle_matching_fails_and_tvdb_id_is_specified()
|
||||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, "tt12345", _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByImdbId(It.IsAny<string>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_tvdbid_matching_when_alias_is_found()
|
||||
{
|
||||
|
@ -215,7 +237,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
.Setup(s => s.FindTvdbId(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()))
|
||||
.Returns(_series.TvdbId);
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>()), Times.Never());
|
||||
|
@ -226,7 +248,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _series.ImdbId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>()), Times.Never());
|
||||
|
|
|
@ -10,6 +10,7 @@ using NzbDrone.Common.Cache;
|
|||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Instrumentation;
|
||||
using NzbDrone.Common.Options;
|
||||
using NzbDrone.Core.Authentication;
|
||||
using NzbDrone.Core.Configuration.Events;
|
||||
|
@ -38,8 +39,10 @@ namespace NzbDrone.Core.Configuration
|
|||
bool AnalyticsEnabled { get; }
|
||||
string LogLevel { get; }
|
||||
string ConsoleLogLevel { get; }
|
||||
ConsoleLogFormat ConsoleLogFormat { get; }
|
||||
bool LogSql { get; }
|
||||
int LogRotate { get; }
|
||||
int LogSizeLimit { get; }
|
||||
bool FilterSentryEvents { get; }
|
||||
string Branch { get; }
|
||||
string ApiKey { get; }
|
||||
|
@ -223,6 +226,11 @@ namespace NzbDrone.Core.Configuration
|
|||
public string LogLevel => _logOptions.Level ?? GetValue("LogLevel", "debug").ToLowerInvariant();
|
||||
public string ConsoleLogLevel => _logOptions.ConsoleLevel ?? GetValue("ConsoleLogLevel", string.Empty, persist: false);
|
||||
|
||||
public ConsoleLogFormat ConsoleLogFormat =>
|
||||
Enum.TryParse<ConsoleLogFormat>(_logOptions.ConsoleFormat, out var enumValue)
|
||||
? enumValue
|
||||
: GetValueEnum("ConsoleLogFormat", ConsoleLogFormat.Standard, false);
|
||||
|
||||
public string Theme => _appOptions.Theme ?? GetValue("Theme", "auto", persist: false);
|
||||
|
||||
public string PostgresHost => _postgresOptions?.Host ?? GetValue("PostgresHost", string.Empty, persist: false);
|
||||
|
@ -234,6 +242,7 @@ namespace NzbDrone.Core.Configuration
|
|||
public bool LogDbEnabled => _logOptions.DbEnabled ?? GetValueBoolean("LogDbEnabled", true, persist: false);
|
||||
public bool LogSql => _logOptions.Sql ?? GetValueBoolean("LogSql", false, persist: false);
|
||||
public int LogRotate => _logOptions.Rotate ?? GetValueInt("LogRotate", 50, persist: false);
|
||||
public int LogSizeLimit => Math.Min(Math.Max(_logOptions.SizeLimit ?? GetValueInt("LogSizeLimit", 1, persist: false), 0), 10);
|
||||
public bool FilterSentryEvents => _logOptions.FilterSentryEvents ?? GetValueBoolean("FilterSentryEvents", true, persist: false);
|
||||
public string SslCertPath => _serverOptions.SslCertPath ?? GetValue("SslCertPath", "");
|
||||
public string SslCertPassword => _serverOptions.SslCertPassword ?? GetValue("SslCertPassword", "");
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
|
|
|
@ -63,7 +63,9 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
|||
sceneSeasonNumbers.Contains(n.SceneSeasonNumber ?? -1) ||
|
||||
((n.SeasonNumber ?? -1) == -1 && (n.SceneSeasonNumber ?? -1) == -1 && n.SceneOrigin != "tvdb"))
|
||||
.Where(n => IsEnglish(n.SearchTerm))
|
||||
.Select(n => n.SearchTerm).Distinct().ToList();
|
||||
.Select(n => n.SearchTerm)
|
||||
.Distinct(StringComparer.InvariantCultureIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
return names;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
|
||||
if (parsedEpisodeInfo == null || parsedEpisodeInfo.IsPossibleSpecialEpisode)
|
||||
{
|
||||
var specialEpisodeInfo = _parsingService.ParseSpecialEpisodeTitle(parsedEpisodeInfo, report.Title, report.TvdbId, report.TvRageId, searchCriteria);
|
||||
var specialEpisodeInfo = _parsingService.ParseSpecialEpisodeTitle(parsedEpisodeInfo, report.Title, report.TvdbId, report.TvRageId, report.ImdbId, searchCriteria);
|
||||
|
||||
if (specialEpisodeInfo != null)
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
|
||||
if (parsedEpisodeInfo != null && !parsedEpisodeInfo.SeriesTitle.IsNullOrWhiteSpace())
|
||||
{
|
||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, report.TvdbId, report.TvRageId, searchCriteria);
|
||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, report.TvdbId, report.TvRageId, report.ImdbId, searchCriteria);
|
||||
remoteEpisode.Release = report;
|
||||
|
||||
if (remoteEpisode.Series == null)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using NLog;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
@ -10,10 +12,13 @@ namespace NzbDrone.Core.Download.Aggregation.Aggregators
|
|||
{
|
||||
public class AggregateLanguages : IAggregateRemoteEpisode
|
||||
{
|
||||
private readonly IIndexerFactory _indexerFactory;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public AggregateLanguages(Logger logger)
|
||||
public AggregateLanguages(IIndexerFactory indexerFactory,
|
||||
Logger logger)
|
||||
{
|
||||
_indexerFactory = indexerFactory;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -71,6 +76,17 @@ namespace NzbDrone.Core.Download.Aggregation.Aggregators
|
|||
languages = languages.Except(languagesToRemove).ToList();
|
||||
}
|
||||
|
||||
if ((languages.Count == 0 || (languages.Count == 1 && languages.First() == Language.Unknown)) && releaseInfo is { IndexerId: > 0 } && releaseInfo.Title.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
var indexer = _indexerFactory.Get(releaseInfo.IndexerId);
|
||||
|
||||
if (indexer?.Settings is IIndexerSettings settings && settings.MultiLanguages.Any() && Parser.Parser.HasMultipleLanguages(releaseInfo.Title))
|
||||
{
|
||||
// Use indexer setting for Multi-languages
|
||||
languages = settings.MultiLanguages.Select(i => (Language)i).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
// Use series language as fallback if we couldn't parse a language
|
||||
if (languages.Count == 0 || (languages.Count == 1 && languages.First() == Language.Unknown))
|
||||
{
|
||||
|
|
|
@ -201,7 +201,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
|||
|
||||
if (ignoredCount > 0)
|
||||
{
|
||||
_logger.Warn("{0} torrent(s) were ignored becuase they did not have a title, check Deluge and remove any invalid torrents");
|
||||
_logger.Warn("{0} torrent(s) were ignored because they did not have a title. Check Deluge and remove any invalid torrents");
|
||||
}
|
||||
|
||||
return items;
|
||||
|
|
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NLog.Fluent;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Instrumentation.Extensions;
|
||||
|
@ -247,14 +246,14 @@ namespace NzbDrone.Core.Download
|
|||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug()
|
||||
_logger.ForDebugEvent()
|
||||
.Message("No Episodes were just imported, but all episodes were previously imported, possible issue with download history.")
|
||||
.Property("SeriesId", trackedDownload.RemoteEpisode.Series.Id)
|
||||
.Property("DownloadId", trackedDownload.DownloadItem.DownloadId)
|
||||
.Property("Title", trackedDownload.DownloadItem.Title)
|
||||
.Property("Path", trackedDownload.ImportItem.OutputPath.ToString())
|
||||
.WriteSentryWarn("DownloadHistoryIncomplete")
|
||||
.Write();
|
||||
.Log();
|
||||
}
|
||||
|
||||
var episodes = _episodeService.GetEpisodes(trackedDownload.RemoteEpisode.Episodes.Select(e => e.Id));
|
||||
|
|
|
@ -119,7 +119,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
|||
|
||||
if (parsedEpisodeInfo != null)
|
||||
{
|
||||
trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0);
|
||||
trackedDownload.RemoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0, null);
|
||||
|
||||
_aggregationService.Augment(trackedDownload.RemoteEpisode);
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
|||
// Try parsing the original source title and if that fails, try parsing it as a special
|
||||
// TODO: Pass the TVDB ID and TVRage IDs in as well so we have a better chance for finding the item
|
||||
parsedEpisodeInfo = Parser.Parser.ParseTitle(firstHistoryItem.SourceTitle) ??
|
||||
_parsingService.ParseSpecialEpisodeTitle(parsedEpisodeInfo, firstHistoryItem.SourceTitle, 0, 0);
|
||||
_parsingService.ParseSpecialEpisodeTitle(parsedEpisodeInfo, firstHistoryItem.SourceTitle, 0, 0, null);
|
||||
|
||||
if (parsedEpisodeInfo != null)
|
||||
{
|
||||
|
@ -234,7 +234,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
|||
{
|
||||
var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title);
|
||||
|
||||
trackedDownload.RemoteEpisode = parsedEpisodeInfo == null ? null : _parsingService.Map(parsedEpisodeInfo, 0, 0);
|
||||
trackedDownload.RemoteEpisode = parsedEpisodeInfo == null ? null : _parsingService.Map(parsedEpisodeInfo, 0, 0, null);
|
||||
|
||||
_aggregationService.Augment(trackedDownload.RemoteEpisode);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Text.RegularExpressions;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
|
||||
{
|
||||
|
|
|
@ -20,26 +20,6 @@ namespace NzbDrone.Core
|
|||
return actual;
|
||||
}
|
||||
|
||||
public static long Megabytes(this int megabytes)
|
||||
{
|
||||
return Convert.ToInt64(megabytes * 1024L * 1024L);
|
||||
}
|
||||
|
||||
public static long Gigabytes(this int gigabytes)
|
||||
{
|
||||
return Convert.ToInt64(gigabytes * 1024L * 1024L * 1024L);
|
||||
}
|
||||
|
||||
public static long Megabytes(this double megabytes)
|
||||
{
|
||||
return Convert.ToInt64(megabytes * 1024L * 1024L);
|
||||
}
|
||||
|
||||
public static long Gigabytes(this double gigabytes)
|
||||
{
|
||||
return Convert.ToInt64(gigabytes * 1024L * 1024L * 1024L);
|
||||
}
|
||||
|
||||
public static long Round(this long number, long level)
|
||||
{
|
||||
return Convert.ToInt64(Math.Floor((decimal)number / level) * level);
|
||||
|
|
|
@ -165,6 +165,7 @@ namespace NzbDrone.Core.History
|
|||
history.Data.Add("Guid", message.Episode.Release.Guid);
|
||||
history.Data.Add("TvdbId", message.Episode.Release.TvdbId.ToString());
|
||||
history.Data.Add("TvRageId", message.Episode.Release.TvRageId.ToString());
|
||||
history.Data.Add("ImdbId", message.Episode.Release.ImdbId);
|
||||
history.Data.Add("Protocol", ((int)message.Episode.Release.DownloadProtocol).ToString());
|
||||
history.Data.Add("CustomFormatScore", message.Episode.CustomFormatScore.ToString());
|
||||
history.Data.Add("SeriesMatchType", message.Episode.SeriesMatchType.ToString());
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
|||
{
|
||||
public abstract class SearchCriteriaBase
|
||||
{
|
||||
private static readonly Regex SpecialCharacter = new Regex(@"[`'.]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
private static readonly Regex SpecialCharacter = new Regex(@"['.\u0060\u00B4\u2018\u2019]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
private static readonly Regex NonWord = new Regex(@"[\W]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
private static readonly Regex BeginningThe = new Regex(@"^the\s", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ namespace NzbDrone.Core.IndexerSearch
|
|||
foreach (var item in dict)
|
||||
{
|
||||
item.Value.Episodes = item.Value.Episodes.Distinct().ToList();
|
||||
item.Value.SceneTitles = item.Value.SceneTitles.Distinct().ToList();
|
||||
item.Value.SceneTitles = item.Value.SceneTitles.Distinct(StringComparer.InvariantCultureIgnoreCase).ToList();
|
||||
}
|
||||
|
||||
return dict.Values.ToList();
|
||||
|
@ -221,7 +221,7 @@ namespace NzbDrone.Core.IndexerSearch
|
|||
|
||||
foreach (var item in dict)
|
||||
{
|
||||
item.Value.SceneTitles = item.Value.SceneTitles.Distinct().ToList();
|
||||
item.Value.SceneTitles = item.Value.SceneTitles.Distinct(StringComparer.InvariantCultureIgnoreCase).ToList();
|
||||
}
|
||||
|
||||
return dict.Values.ToList();
|
||||
|
@ -463,7 +463,7 @@ namespace NzbDrone.Core.IndexerSearch
|
|||
spec.UserInvokedSearch = userInvokedSearch;
|
||||
spec.InteractiveSearch = interactiveSearch;
|
||||
|
||||
if (!spec.SceneTitles.Contains(series.Title))
|
||||
if (!spec.SceneTitles.Contains(series.Title, StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
spec.SceneTitles.Add(series.Title);
|
||||
}
|
||||
|
|
|
@ -95,6 +95,11 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
|||
torrentInfo.TvRageId = torrent.TvrageID.Value;
|
||||
}
|
||||
|
||||
if (torrent.ImdbID.IsNotNullOrWhiteSpace() && int.TryParse(torrent.ImdbID, out var imdbId) && imdbId > 0)
|
||||
{
|
||||
torrentInfo.ImdbId = $"tt{imdbId:D7}";
|
||||
}
|
||||
|
||||
results.Add(torrentInfo);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace NzbDrone.Core.Indexers.FileList
|
|||
{
|
||||
var id = result.Id;
|
||||
|
||||
torrentInfos.Add(new TorrentInfo
|
||||
var torrentInfo = new TorrentInfo
|
||||
{
|
||||
Guid = $"FileList-{id}",
|
||||
Title = result.Name,
|
||||
|
@ -48,9 +48,15 @@ namespace NzbDrone.Core.Indexers.FileList
|
|||
Seeders = result.Seeders,
|
||||
Peers = result.Leechers + result.Seeders,
|
||||
PublishDate = result.UploadDate.ToUniversalTime(),
|
||||
ImdbId = result.ImdbId,
|
||||
IndexerFlags = GetIndexerFlags(result)
|
||||
});
|
||||
};
|
||||
|
||||
if (result.ImdbId is { Length: > 2 } && int.TryParse(result.ImdbId.TrimStart('t'), out var imdbId) && imdbId > 0)
|
||||
{
|
||||
torrentInfo.ImdbId = $"tt{imdbId:D7}";
|
||||
}
|
||||
|
||||
torrentInfos.Add(torrentInfo);
|
||||
}
|
||||
|
||||
return torrentInfos.ToArray();
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace NzbDrone.Core.Indexers.HDBits
|
|||
Seeders = result.Seeders,
|
||||
Peers = result.Leechers + result.Seeders,
|
||||
PublishDate = result.Added.ToUniversalTime(),
|
||||
TvdbId = result.TvdbInfo?.Id ?? 0,
|
||||
IndexerFlags = GetIndexerFlags(result)
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using FluentValidation.Results;
|
||||
using NLog;
|
||||
|
@ -20,8 +19,6 @@ namespace NzbDrone.Core.Indexers
|
|||
public abstract class IndexerBase<TSettings> : IIndexer
|
||||
where TSettings : IIndexerSettings, new()
|
||||
{
|
||||
private static readonly Regex MultiRegex = new (@"[_. ](?<multi>multi)[_. ]", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
protected readonly IIndexerStatusService _indexerStatusService;
|
||||
protected readonly IConfigService _configService;
|
||||
protected readonly IParsingService _parsingService;
|
||||
|
@ -94,7 +91,7 @@ namespace NzbDrone.Core.Indexers
|
|||
result.ForEach(c =>
|
||||
{
|
||||
// Use multi languages from setting if ReleaseInfo languages is empty
|
||||
if (c.Languages.Empty() && MultiRegex.IsMatch(c.Title) && settings.MultiLanguages.Any())
|
||||
if (c.Languages.Empty() && settings.MultiLanguages.Any() && Parser.Parser.HasMultipleLanguages(c.Title))
|
||||
{
|
||||
c.Languages = settings.MultiLanguages.Select(i => (Language)i).ToList();
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||
|
||||
releaseInfo.TvdbId = GetTvdbId(item);
|
||||
releaseInfo.TvRageId = GetTvRageId(item);
|
||||
releaseInfo.ImdbId = GetImdbId(item);
|
||||
|
||||
return releaseInfo;
|
||||
}
|
||||
|
@ -182,6 +183,18 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||
return 0;
|
||||
}
|
||||
|
||||
protected virtual string GetImdbId(XElement item)
|
||||
{
|
||||
var imdbIdString = TryGetNewznabAttribute(item, "imdb");
|
||||
|
||||
if (!imdbIdString.IsNullOrWhiteSpace() && int.TryParse(imdbIdString, out var imdbId) && imdbId > 0)
|
||||
{
|
||||
return $"tt{imdbId:D7}";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected string TryGetNewznabAttribute(XElement item, string key, string defaultValue = "")
|
||||
{
|
||||
var attrElement = item.Elements(ns + "attr").FirstOrDefault(e => e.Attribute("name").Value.Equals(key, StringComparison.OrdinalIgnoreCase));
|
||||
|
|
|
@ -83,6 +83,7 @@ namespace NzbDrone.Core.Indexers.Torznab
|
|||
{
|
||||
torrentInfo.TvdbId = GetTvdbId(item);
|
||||
torrentInfo.TvRageId = GetTvRageId(item);
|
||||
releaseInfo.ImdbId = GetImdbId(item);
|
||||
torrentInfo.IndexerFlags = GetFlags(item);
|
||||
}
|
||||
|
||||
|
@ -177,6 +178,18 @@ namespace NzbDrone.Core.Indexers.Torznab
|
|||
return 0;
|
||||
}
|
||||
|
||||
protected virtual string GetImdbId(XElement item)
|
||||
{
|
||||
var imdbIdString = TryGetTorznabAttribute(item, "imdb");
|
||||
|
||||
if (!imdbIdString.IsNullOrWhiteSpace() && int.TryParse(imdbIdString, out var imdbId) && imdbId > 0)
|
||||
{
|
||||
return $"tt{imdbId:D7}";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override string GetInfoHash(XElement item)
|
||||
{
|
||||
return TryGetTorznabAttribute(item, "infohash");
|
||||
|
|
|
@ -33,22 +33,25 @@ namespace NzbDrone.Core.Instrumentation
|
|||
|
||||
LogManager.Configuration.AddTarget("DbLogger", target);
|
||||
LogManager.Configuration.LoggingRules.Add(Rule);
|
||||
LogManager.ConfigurationReloaded += OnLogManagerOnConfigurationReloaded;
|
||||
LogManager.ConfigurationChanged += OnLogManagerOnConfigurationReloaded;
|
||||
LogManager.ReconfigExistingLoggers();
|
||||
}
|
||||
|
||||
public void UnRegister()
|
||||
{
|
||||
LogManager.ConfigurationReloaded -= OnLogManagerOnConfigurationReloaded;
|
||||
LogManager.ConfigurationChanged -= OnLogManagerOnConfigurationReloaded;
|
||||
LogManager.Configuration.RemoveTarget("DbLogger");
|
||||
LogManager.Configuration.LoggingRules.Remove(Rule);
|
||||
LogManager.ReconfigExistingLoggers();
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private void OnLogManagerOnConfigurationReloaded(object sender, LoggingConfigurationReloadedEventArgs args)
|
||||
private void OnLogManagerOnConfigurationReloaded(object sender, LoggingConfigurationChangedEventArgs args)
|
||||
{
|
||||
Register();
|
||||
if (args.ActivatedConfiguration != null)
|
||||
{
|
||||
Register();
|
||||
}
|
||||
}
|
||||
|
||||
public LoggingRule Rule { get; set; }
|
||||
|
|
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
using NLog.Targets;
|
||||
using NLog.Targets.Syslog;
|
||||
using NLog.Targets.Syslog.Settings;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
|
@ -51,13 +52,14 @@ namespace NzbDrone.Core.Instrumentation
|
|||
var rules = LogManager.Configuration.LoggingRules;
|
||||
|
||||
// Console
|
||||
ReconfigureConsole();
|
||||
SetMinimumLogLevel(rules, "consoleLogger", minimumConsoleLogLevel);
|
||||
|
||||
// Log Files
|
||||
SetMinimumLogLevel(rules, "appFileInfo", minimumLogLevel <= LogLevel.Info ? LogLevel.Info : LogLevel.Off);
|
||||
SetMinimumLogLevel(rules, "appFileDebug", minimumLogLevel <= LogLevel.Debug ? LogLevel.Debug : LogLevel.Off);
|
||||
SetMinimumLogLevel(rules, "appFileTrace", minimumLogLevel <= LogLevel.Trace ? LogLevel.Trace : LogLevel.Off);
|
||||
SetLogRotation();
|
||||
ReconfigureFile();
|
||||
|
||||
// Log Sql
|
||||
SqlBuilderExtensions.LogSql = _configFileProvider.LogSql;
|
||||
|
@ -91,11 +93,12 @@ namespace NzbDrone.Core.Instrumentation
|
|||
}
|
||||
}
|
||||
|
||||
private void SetLogRotation()
|
||||
private void ReconfigureFile()
|
||||
{
|
||||
foreach (var target in LogManager.Configuration.AllTargets.OfType<NzbDroneFileTarget>())
|
||||
{
|
||||
target.MaxArchiveFiles = _configFileProvider.LogRotate;
|
||||
target.ArchiveAboveSize = _configFileProvider.LogSizeLimit.Megabytes();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,6 +112,22 @@ namespace NzbDrone.Core.Instrumentation
|
|||
}
|
||||
}
|
||||
|
||||
private void ReconfigureConsole()
|
||||
{
|
||||
var consoleTarget = LogManager.Configuration.AllTargets.OfType<ColoredConsoleTarget>().FirstOrDefault();
|
||||
|
||||
if (consoleTarget != null)
|
||||
{
|
||||
var format = _configFileProvider.ConsoleLogFormat;
|
||||
|
||||
consoleTarget.Layout = format switch
|
||||
{
|
||||
ConsoleLogFormat.Clef => NzbDroneLogger.ClefLogLayout,
|
||||
_ => NzbDroneLogger.ConsoleLogLayout
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void SetSyslogParameters(string syslogServer, int syslogPort, LogLevel minimumLogLevel)
|
||||
{
|
||||
var syslogTarget = new SyslogTarget();
|
||||
|
@ -117,7 +136,7 @@ namespace NzbDrone.Core.Instrumentation
|
|||
syslogTarget.MessageSend.Protocol = ProtocolType.Udp;
|
||||
syslogTarget.MessageSend.Udp.Port = syslogPort;
|
||||
syslogTarget.MessageSend.Udp.Server = syslogServer;
|
||||
syslogTarget.MessageSend.Udp.ReconnectInterval = 500;
|
||||
syslogTarget.MessageSend.Retry.ConstantBackoff.BaseDelay = 500;
|
||||
syslogTarget.MessageCreation.Rfc = RfcNumber.Rfc5424;
|
||||
syslogTarget.MessageCreation.Rfc5424.AppName = _configFileProvider.InstanceName;
|
||||
|
||||
|
|
|
@ -1401,7 +1401,7 @@
|
|||
"NotificationsEmailSettingsBccAddressHelpText": "Lista separada por coma de destinatarios de e-mail bcc",
|
||||
"NotificationsEmailSettingsName": "E-mail",
|
||||
"NotificationsEmailSettingsRecipientAddress": "Dirección(es) de destinatario",
|
||||
"NotificationsEmbySettingsSendNotificationsHelpText": "Hacer que MediaBrowser envíe notificaciones a los proveedores configurados",
|
||||
"NotificationsEmbySettingsSendNotificationsHelpText": "Hace que Emby envíe notificaciones a los proveedores configurados. No soportado en Jellyfin.",
|
||||
"NotificationsGotifySettingsAppToken": "Token de app",
|
||||
"NotificationsGotifySettingIncludeSeriesPosterHelpText": "Incluye poster de serie en mensaje",
|
||||
"NotificationsJoinSettingsDeviceNames": "Nombres de dispositivo",
|
||||
|
@ -1919,7 +1919,7 @@
|
|||
"NotificationsDiscordSettingsWebhookUrlHelpText": "URL de canal webhook de Discord",
|
||||
"NotificationsEmailSettingsCcAddress": "Dirección(es) CC",
|
||||
"NotificationsEmbySettingsSendNotifications": "Enviar notificaciones",
|
||||
"NotificationsEmbySettingsUpdateLibraryHelpText": "¿Actualiza biblioteca en importar, renombrar o borrar?",
|
||||
"NotificationsEmbySettingsUpdateLibraryHelpText": "Actualiza biblioteca al importar, renombrar o borrar",
|
||||
"NotificationsJoinSettingsDeviceIdsHelpText": "En desuso, usar Nombres de dispositivo en su lugar. Lista separada por coma de los IDs de dispositivo a los que te gustaría enviar notificaciones. Si no se establece, todos los dispositivos recibirán notificaciones.",
|
||||
"NotificationsPushoverSettingsExpire": "Caduca",
|
||||
"NotificationsMailgunSettingsSenderDomain": "Dominio del remitente",
|
||||
|
|
|
@ -299,7 +299,7 @@
|
|||
"Sunday": "Dimanche",
|
||||
"TorrentDelay": "Retard du torrent",
|
||||
"DownloadClients": "Clients de télécharg.",
|
||||
"CustomFormats": "Formats perso.",
|
||||
"CustomFormats": "Formats personnalisés",
|
||||
"NoIndexersFound": "Aucun indexeur n'a été trouvé",
|
||||
"Profiles": "Profils",
|
||||
"Dash": "Tiret",
|
||||
|
@ -431,7 +431,7 @@
|
|||
"Replace": "Remplacer",
|
||||
"ResetAPIKeyMessageText": "Êtes-vous sûr de vouloir réinitialiser votre clé API ?",
|
||||
"StopSelecting": "Effacer la sélection",
|
||||
"WhatsNew": "Quoi de neuf ?",
|
||||
"WhatsNew": "Quoi de neuf ?",
|
||||
"EditDownloadClientImplementation": "Modifier le client de téléchargement - {implementationName}",
|
||||
"External": "Externe",
|
||||
"Monday": "Lundi",
|
||||
|
@ -452,7 +452,7 @@
|
|||
"RootFolderSelectFreeSpace": "{freeSpace} Libre",
|
||||
"WantMoreControlAddACustomFormat": "Vous souhaitez avoir plus de contrôle sur les téléchargements préférés ? Ajoutez un [Format personnalisé](/settings/customformats)",
|
||||
"RemoveSelectedItemsQueueMessageText": "Voulez-vous vraiment supprimer {selectedCount} éléments de la file d'attente ?",
|
||||
"UpdateAll": "Actualiser",
|
||||
"UpdateAll": "Tout mettre à jour",
|
||||
"EnableSslHelpText": "Nécessite un redémarrage en tant qu'administrateur pour être effectif",
|
||||
"UnmonitorDeletedEpisodesHelpText": "Les épisodes effacés du disque dur ne seront plus surveillés dans {appName}",
|
||||
"RssSync": "Synchronisation RSS",
|
||||
|
@ -1130,7 +1130,7 @@
|
|||
"NotificationsTagsSeriesHelpText": "N'envoyer des notifications que pour les séries avec au moins une balise correspondante",
|
||||
"OnApplicationUpdate": "Lors de la mise à jour de l'application",
|
||||
"OnEpisodeFileDelete": "Lors de la suppression du fichier de l'épisode",
|
||||
"OnHealthIssue": "Sur la question de la santé",
|
||||
"OnHealthIssue": "Lors de problème de santé",
|
||||
"OnManualInteractionRequired": "Sur l'interaction manuelle requise",
|
||||
"OnRename": "Au renommage",
|
||||
"PreferredSize": "Taille préférée",
|
||||
|
@ -1176,7 +1176,7 @@
|
|||
"Total": "Total",
|
||||
"Upcoming": "À venir",
|
||||
"UpdateAutomaticallyHelpText": "Téléchargez et installez automatiquement les mises à jour. Vous pourrez toujours installer à partir du système : mises à jour",
|
||||
"UpdateAvailableHealthCheckMessage": "Une nouvelle mise à jour est disponible",
|
||||
"UpdateAvailableHealthCheckMessage": "Une nouvelle mise à jour est disponible : {version}",
|
||||
"UpdateFiltered": "Mise à jour filtrée",
|
||||
"IconForSpecialsHelpText": "Afficher l'icône pour les épisodes spéciaux (saison 0)",
|
||||
"Ignored": "Ignoré",
|
||||
|
@ -1276,7 +1276,7 @@
|
|||
"ConnectSettingsSummary": "Notifications, connexions aux serveurs/lecteurs de médias et scripts personnalisés",
|
||||
"CopyToClipboard": "Copier dans le presse-papier",
|
||||
"CreateEmptySeriesFolders": "Créer des dossiers de séries vides",
|
||||
"Custom": "Customisé",
|
||||
"Custom": "Personnaliser",
|
||||
"CopyUsingHardlinksSeriesHelpText": "Les liens physiques permettent à {appName} d'importer des torrents dans le dossier de la série sans prendre d'espace disque supplémentaire ni copier l'intégralité du contenu du fichier. Les liens physiques ne fonctionneront que si la source et la destination sont sur le même volume",
|
||||
"CustomFormatsSettingsSummary": "Formats et paramètres personnalisés",
|
||||
"CustomFormatsSettings": "Paramètre des formats personnalisés",
|
||||
|
@ -1724,8 +1724,8 @@
|
|||
"NotificationsGotifySettingsPriorityHelpText": "Priorité de la notification",
|
||||
"NotificationsGotifySettingsAppTokenHelpText": "Le jeton d'application généré par Gotify",
|
||||
"NotificationsGotifySettingsAppToken": "Jeton d'app",
|
||||
"NotificationsEmbySettingsUpdateLibraryHelpText": "Mettre à jour la bibliothèque lors d'import, de renommage ou de suppression ?",
|
||||
"NotificationsEmbySettingsSendNotificationsHelpText": "Faire en sorte que MediaBrowser envoie des notifications aux fournisseurs configurés",
|
||||
"NotificationsEmbySettingsUpdateLibraryHelpText": "Mettre à jour la bibliothèque lors de l'importation, du changement de nom ou de la suppression",
|
||||
"NotificationsEmbySettingsSendNotificationsHelpText": "Demandez à Emby d'envoyer des notifications aux fournisseurs configurés. Non pris en charge sur Jellyfin.",
|
||||
"NotificationsEmbySettingsSendNotifications": "Envoyer des notifications",
|
||||
"NotificationsEmailSettingsServerHelpText": "Nom d'hôte ou adresse IP du serveur de courriel",
|
||||
"NotificationsEmailSettingsServer": "Serveur",
|
||||
|
@ -2078,5 +2078,27 @@
|
|||
"TomorrowAt": "Demain à {time}",
|
||||
"TodayAt": "Aujourd'hui à {time}",
|
||||
"ShowTagsHelpText": "Afficher les labels sous l'affiche",
|
||||
"ShowTags": "Afficher les labels"
|
||||
"ShowTags": "Afficher les labels",
|
||||
"CountVotes": "{votes} votes",
|
||||
"NoBlocklistItems": "Aucun élément de la liste de blocage",
|
||||
"NotificationsTelegramSettingsMetadataLinksHelpText": "Ajouter un lien vers les métadonnées de la série lors de l'envoi de notifications",
|
||||
"RatingVotes": "Votes de notation",
|
||||
"OnFileImport": "Lors de l'importation du fichier",
|
||||
"OnImportComplete": "Une fois l'importation terminée",
|
||||
"NotificationsPlexSettingsServer": "Serveur",
|
||||
"NotificationsPlexSettingsServerHelpText": "Sélectionnez le serveur à partir du compte plex.tv après l'authentification",
|
||||
"OnFileUpgrade": "Lors de la mise à jour du fichier",
|
||||
"NextAiringDate": "Prochaine diffusion : {date}",
|
||||
"CustomColonReplacement": "Remplacement personnalisé des deux‐points",
|
||||
"CustomColonReplacementFormatHelpText": "Caractères à utiliser en remplacement des deux-points",
|
||||
"CustomColonReplacementFormatHint": "Caractère valide du système de fichiers tel que deux-points (lettre)",
|
||||
"Install": "Installer",
|
||||
"InstallMajorVersionUpdate": "Installer la mise à jour",
|
||||
"InstallMajorVersionUpdateMessage": "Cette mise à jour installera une nouvelle version majeure et pourrait ne pas être compatible avec votre système. Êtes-vous sûr de vouloir installer cette mise à jour ?",
|
||||
"InstallMajorVersionUpdateMessageLink": "Veuillez consulter [{domain}]({url}) pour plus d'informations.",
|
||||
"SeasonsMonitoredAll": "Toutes",
|
||||
"SeasonsMonitoredPartial": "Partielle",
|
||||
"SeasonsMonitoredNone": "Aucune",
|
||||
"SeasonsMonitoredStatus": "Saisons surveillées",
|
||||
"NotificationsTelegramSettingsMetadataLinks": "Liens de métadonnées"
|
||||
}
|
||||
|
|
|
@ -1733,7 +1733,7 @@
|
|||
"NotificationsEmailSettingsServer": "Servidor",
|
||||
"NotificationsEmailSettingsServerHelpText": "Nome do host ou IP do servidor de e-mail",
|
||||
"NotificationsEmbySettingsSendNotifications": "Enviar Notificações",
|
||||
"NotificationsEmbySettingsUpdateLibraryHelpText": "Atualizar Biblioteca ao Importar, Renomear ou Excluir?",
|
||||
"NotificationsEmbySettingsUpdateLibraryHelpText": "Atualizar Biblioteca ao Importar, Renomear ou Excluir",
|
||||
"NotificationsGotifySettingIncludeSeriesPoster": "Incluir Pôster da Série",
|
||||
"NotificationsGotifySettingIncludeSeriesPosterHelpText": "Incluir Pôster da Série na Mensagem",
|
||||
"NotificationsGotifySettingsAppToken": "Token do Aplicativo",
|
||||
|
@ -1841,7 +1841,7 @@
|
|||
"NotificationsValidationUnableToSendTestMessage": "Não foi possível enviar a mensagem de teste: {exceptionMessage}",
|
||||
"NotificationsValidationUnableToSendTestMessageApiResponse": "Não foi possível enviar mensagem de teste. Resposta da API: {error}",
|
||||
"NotificationsAppriseSettingsStatelessUrlsHelpText": "Uma ou mais URLs separadas por vírgulas identificando para onde a notificação deve ser enviada. Deixe em branco se o armazenamento persistente for usado.",
|
||||
"NotificationsEmbySettingsSendNotificationsHelpText": "Faça com que o MediaBrowser envie notificações para provedores configurados",
|
||||
"NotificationsEmbySettingsSendNotificationsHelpText": "Faça com que Emby envie notificações para provedores configurados. Não compatível com Jellyfin.",
|
||||
"NotificationsJoinSettingsDeviceIdsHelpText": "Obsoleto, use nomes de dispositivos. Lista separada por vírgulas de IDs de dispositivos para os quais você gostaria de enviar notificações. Se não for definido, todos os dispositivos receberão notificações.",
|
||||
"NotificationsTwitterSettingsConnectToTwitter": "Conecte-se ao Twitter / X",
|
||||
"NotificationsTelegramSettingsBotToken": "Token do Bot",
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
|
|
|
@ -33,12 +33,12 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
|||
|
||||
if (fileInfo != null && fileInfo.IsPossibleSceneSeasonSpecial)
|
||||
{
|
||||
fileInfo = _parsingService.ParseSpecialEpisodeTitle(fileInfo, fileInfo.ReleaseTitle, localEpisode.Series.TvdbId, 0);
|
||||
fileInfo = _parsingService.ParseSpecialEpisodeTitle(fileInfo, fileInfo.ReleaseTitle, localEpisode.Series.TvdbId, 0, null);
|
||||
}
|
||||
|
||||
if (folderInfo != null && folderInfo.IsPossibleSceneSeasonSpecial)
|
||||
{
|
||||
folderInfo = _parsingService.ParseSpecialEpisodeTitle(folderInfo, folderInfo.ReleaseTitle, localEpisode.Series.TvdbId, 0);
|
||||
folderInfo = _parsingService.ParseSpecialEpisodeTitle(folderInfo, folderInfo.ReleaseTitle, localEpisode.Series.TvdbId, 0, null);
|
||||
}
|
||||
|
||||
if (folderInfo == null)
|
||||
|
|
|
@ -2,7 +2,6 @@ using System.Globalization;
|
|||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using NLog;
|
||||
using NLog.Fluent;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Instrumentation;
|
||||
using NzbDrone.Common.Instrumentation.Extensions;
|
||||
|
@ -153,10 +152,10 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
|||
return "WMA";
|
||||
}
|
||||
|
||||
Logger.Debug()
|
||||
Logger.ForDebugEvent()
|
||||
.Message("Unknown audio format: '{0}' in '{1}'. Streams: {2}", audioFormat, sceneName, mediaInfo.RawStreamData)
|
||||
.WriteSentryWarn("UnknownAudioFormatFFProbe", mediaInfo.ContainerFormat, mediaInfo.AudioFormat, audioCodecID)
|
||||
.Write();
|
||||
.Log();
|
||||
|
||||
return mediaInfo.AudioFormat;
|
||||
}
|
||||
|
@ -268,10 +267,10 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
|||
return "";
|
||||
}
|
||||
|
||||
Logger.Debug()
|
||||
Logger.ForDebugEvent()
|
||||
.Message("Unknown video format: '{0}' in '{1}'. Streams: {2}", videoFormat, sceneName, mediaInfo.RawStreamData)
|
||||
.WriteSentryWarn("UnknownVideoFormatFFProbe", mediaInfo.ContainerFormat, videoFormat, videoCodecID)
|
||||
.Write();
|
||||
.Log();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -103,6 +103,7 @@ namespace NzbDrone.Core.Parser.Model
|
|||
stringBuilder.AppendLine("DownloadProtocol: " + DownloadProtocol ?? "Empty");
|
||||
stringBuilder.AppendLine("TvdbId: " + TvdbId ?? "Empty");
|
||||
stringBuilder.AppendLine("TvRageId: " + TvRageId ?? "Empty");
|
||||
stringBuilder.AppendLine("ImdbId: " + ImdbId ?? "Empty");
|
||||
stringBuilder.AppendLine("PublishDate: " + PublishDate ?? "Empty");
|
||||
return stringBuilder.ToString();
|
||||
default:
|
||||
|
|
|
@ -575,6 +575,8 @@ namespace NzbDrone.Core.Parser
|
|||
|
||||
private static readonly string[] Numbers = new[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
|
||||
|
||||
private static readonly Regex MultiRegex = new (@"[_. ](?<multi>multi)[_. ]", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public static ParsedEpisodeInfo ParsePath(string path)
|
||||
{
|
||||
var fileInfo = new FileInfo(path);
|
||||
|
@ -959,6 +961,11 @@ namespace NzbDrone.Core.Parser
|
|||
return title;
|
||||
}
|
||||
|
||||
public static bool HasMultipleLanguages(string title)
|
||||
{
|
||||
return MultiRegex.IsMatch(title);
|
||||
}
|
||||
|
||||
private static SeriesTitleInfo GetSeriesTitleInfo(string title, MatchCollection matchCollection)
|
||||
{
|
||||
var seriesTitleInfo = new SeriesTitleInfo();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NLog.Fluent;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Instrumentation.Extensions;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
|
@ -14,11 +14,11 @@ namespace NzbDrone.Core.Parser
|
|||
public interface IParsingService
|
||||
{
|
||||
Series GetSeries(string title);
|
||||
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null);
|
||||
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, string imdbId, SearchCriteriaBase searchCriteria = null);
|
||||
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, Series series);
|
||||
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int seriesId, IEnumerable<int> episodeIds);
|
||||
List<Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series series, bool sceneSource, SearchCriteriaBase searchCriteria = null);
|
||||
ParsedEpisodeInfo ParseSpecialEpisodeTitle(ParsedEpisodeInfo parsedEpisodeInfo, string releaseTitle, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null);
|
||||
ParsedEpisodeInfo ParseSpecialEpisodeTitle(ParsedEpisodeInfo parsedEpisodeInfo, string releaseTitle, int tvdbId, int tvRageId, string imdbId, SearchCriteriaBase searchCriteria = null);
|
||||
ParsedEpisodeInfo ParseSpecialEpisodeTitle(ParsedEpisodeInfo parsedEpisodeInfo, string releaseTitle, Series series);
|
||||
}
|
||||
|
||||
|
@ -116,14 +116,14 @@ namespace NzbDrone.Core.Parser
|
|||
return foundSeries;
|
||||
}
|
||||
|
||||
public RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null)
|
||||
public RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, string imdbId, SearchCriteriaBase searchCriteria = null)
|
||||
{
|
||||
return Map(parsedEpisodeInfo, tvdbId, tvRageId, null, searchCriteria);
|
||||
return Map(parsedEpisodeInfo, tvdbId, tvRageId, imdbId, null, searchCriteria);
|
||||
}
|
||||
|
||||
public RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, Series series)
|
||||
{
|
||||
return Map(parsedEpisodeInfo, 0, 0, series, null);
|
||||
return Map(parsedEpisodeInfo, 0, 0, null, series, null);
|
||||
}
|
||||
|
||||
public RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int seriesId, IEnumerable<int> episodeIds)
|
||||
|
@ -136,7 +136,7 @@ namespace NzbDrone.Core.Parser
|
|||
};
|
||||
}
|
||||
|
||||
private RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, Series series, SearchCriteriaBase searchCriteria)
|
||||
private RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, string imdbId, Series series, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var sceneMapping = _sceneMappingService.FindSceneMapping(parsedEpisodeInfo.SeriesTitle, parsedEpisodeInfo.ReleaseTitle, parsedEpisodeInfo.SeasonNumber);
|
||||
|
||||
|
@ -172,7 +172,7 @@ namespace NzbDrone.Core.Parser
|
|||
|
||||
if (series == null)
|
||||
{
|
||||
var seriesMatch = FindSeries(parsedEpisodeInfo, tvdbId, tvRageId, sceneMapping, searchCriteria);
|
||||
var seriesMatch = FindSeries(parsedEpisodeInfo, tvdbId, tvRageId, imdbId, sceneMapping, searchCriteria);
|
||||
|
||||
if (seriesMatch != null)
|
||||
{
|
||||
|
@ -211,7 +211,7 @@ namespace NzbDrone.Core.Parser
|
|||
{
|
||||
if (sceneSource)
|
||||
{
|
||||
var remoteEpisode = Map(parsedEpisodeInfo, 0, 0, series, searchCriteria);
|
||||
var remoteEpisode = Map(parsedEpisodeInfo, 0, 0, null, series, searchCriteria);
|
||||
|
||||
return remoteEpisode.Episodes;
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ namespace NzbDrone.Core.Parser
|
|||
return GetStandardEpisodes(series, parsedEpisodeInfo, mappedSeasonNumber, sceneSource, searchCriteria);
|
||||
}
|
||||
|
||||
public ParsedEpisodeInfo ParseSpecialEpisodeTitle(ParsedEpisodeInfo parsedEpisodeInfo, string releaseTitle, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null)
|
||||
public ParsedEpisodeInfo ParseSpecialEpisodeTitle(ParsedEpisodeInfo parsedEpisodeInfo, string releaseTitle, int tvdbId, int tvRageId, string imdbId, SearchCriteriaBase searchCriteria = null)
|
||||
{
|
||||
if (searchCriteria != null)
|
||||
{
|
||||
|
@ -286,6 +286,11 @@ namespace NzbDrone.Core.Parser
|
|||
{
|
||||
return ParseSpecialEpisodeTitle(parsedEpisodeInfo, releaseTitle, searchCriteria.Series);
|
||||
}
|
||||
|
||||
if (imdbId.IsNotNullOrWhiteSpace() && imdbId.Equals(searchCriteria.Series.ImdbId, StringComparison.Ordinal))
|
||||
{
|
||||
return ParseSpecialEpisodeTitle(parsedEpisodeInfo, releaseTitle, searchCriteria.Series);
|
||||
}
|
||||
}
|
||||
|
||||
var series = GetSeries(releaseTitle);
|
||||
|
@ -305,6 +310,11 @@ namespace NzbDrone.Core.Parser
|
|||
series = _seriesService.FindByTvRageId(tvRageId);
|
||||
}
|
||||
|
||||
if (series == null && imdbId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
series = _seriesService.FindByImdbId(imdbId);
|
||||
}
|
||||
|
||||
if (series == null)
|
||||
{
|
||||
_logger.Debug("No matching series {0}", releaseTitle);
|
||||
|
@ -355,7 +365,7 @@ namespace NzbDrone.Core.Parser
|
|||
return null;
|
||||
}
|
||||
|
||||
private FindSeriesResult FindSeries(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SceneMapping sceneMapping, SearchCriteriaBase searchCriteria)
|
||||
private FindSeriesResult FindSeries(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, string imdbId, SceneMapping sceneMapping, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
Series series = null;
|
||||
|
||||
|
@ -386,24 +396,36 @@ namespace NzbDrone.Core.Parser
|
|||
|
||||
if (tvdbId > 0 && tvdbId == searchCriteria.Series.TvdbId)
|
||||
{
|
||||
_logger.Debug()
|
||||
_logger.ForDebugEvent()
|
||||
.Message("Found matching series by TVDB ID {0}, an alias may be needed for: {1}", tvdbId, parsedEpisodeInfo.SeriesTitle)
|
||||
.Property("TvdbId", tvdbId)
|
||||
.Property("ParsedEpisodeInfo", parsedEpisodeInfo)
|
||||
.WriteSentryWarn("TvdbIdMatch", tvdbId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
||||
.Write();
|
||||
.Log();
|
||||
|
||||
return new FindSeriesResult(searchCriteria.Series, SeriesMatchType.Id);
|
||||
}
|
||||
|
||||
if (tvRageId > 0 && tvRageId == searchCriteria.Series.TvRageId && tvdbId <= 0)
|
||||
{
|
||||
_logger.Debug()
|
||||
_logger.ForDebugEvent()
|
||||
.Message("Found matching series by TVRage ID {0}, an alias may be needed for: {1}", tvRageId, parsedEpisodeInfo.SeriesTitle)
|
||||
.Property("TvRageId", tvRageId)
|
||||
.Property("ParsedEpisodeInfo", parsedEpisodeInfo)
|
||||
.WriteSentryWarn("TvRageIdMatch", tvRageId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
||||
.Write();
|
||||
.Log();
|
||||
|
||||
return new FindSeriesResult(searchCriteria.Series, SeriesMatchType.Id);
|
||||
}
|
||||
|
||||
if (imdbId.IsNotNullOrWhiteSpace() && imdbId.Equals(searchCriteria.Series.ImdbId, StringComparison.Ordinal) && tvdbId <= 0)
|
||||
{
|
||||
_logger.ForDebugEvent()
|
||||
.Message("Found matching series by IMDb ID {0}, an alias may be needed for: {1}", imdbId, parsedEpisodeInfo.SeriesTitle)
|
||||
.Property("ImdbId", imdbId)
|
||||
.Property("ParsedEpisodeInfo", parsedEpisodeInfo)
|
||||
.WriteSentryWarn("ImdbIdMatch", imdbId, parsedEpisodeInfo.SeriesTitle)
|
||||
.Log();
|
||||
|
||||
return new FindSeriesResult(searchCriteria.Series, SeriesMatchType.Id);
|
||||
}
|
||||
|
@ -435,12 +457,12 @@ namespace NzbDrone.Core.Parser
|
|||
|
||||
if (series != null)
|
||||
{
|
||||
_logger.Debug()
|
||||
_logger.ForDebugEvent()
|
||||
.Message("Found matching series by TVDB ID {0}, an alias may be needed for: {1}", tvdbId, parsedEpisodeInfo.SeriesTitle)
|
||||
.Property("TvdbId", tvdbId)
|
||||
.Property("ParsedEpisodeInfo", parsedEpisodeInfo)
|
||||
.WriteSentryWarn("TvdbIdMatch", tvdbId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
||||
.Write();
|
||||
.Log();
|
||||
|
||||
matchType = SeriesMatchType.Id;
|
||||
}
|
||||
|
@ -452,12 +474,29 @@ namespace NzbDrone.Core.Parser
|
|||
|
||||
if (series != null)
|
||||
{
|
||||
_logger.Debug()
|
||||
_logger.ForDebugEvent()
|
||||
.Message("Found matching series by TVRage ID {0}, an alias may be needed for: {1}", tvRageId, parsedEpisodeInfo.SeriesTitle)
|
||||
.Property("TvRageId", tvRageId)
|
||||
.Property("ParsedEpisodeInfo", parsedEpisodeInfo)
|
||||
.WriteSentryWarn("TvRageIdMatch", tvRageId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
||||
.Write();
|
||||
.Log();
|
||||
|
||||
matchType = SeriesMatchType.Id;
|
||||
}
|
||||
}
|
||||
|
||||
if (series == null && imdbId.IsNotNullOrWhiteSpace() && tvdbId <= 0)
|
||||
{
|
||||
series = _seriesService.FindByImdbId(imdbId);
|
||||
|
||||
if (series != null)
|
||||
{
|
||||
_logger.ForDebugEvent()
|
||||
.Message("Found matching series by IMDb ID {0}, an alias may be needed for: {1}", imdbId, parsedEpisodeInfo.SeriesTitle)
|
||||
.Property("ImdbId", imdbId)
|
||||
.Property("ParsedEpisodeInfo", parsedEpisodeInfo)
|
||||
.WriteSentryWarn("ImdbIdMatch", imdbId, parsedEpisodeInfo.SeriesTitle)
|
||||
.Log();
|
||||
|
||||
matchType = SeriesMatchType.Id;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<PackageReference Include="FluentValidation" Version="9.5.4" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="4.7.14" />
|
||||
<PackageReference Include="NLog" Version="5.3.2" />
|
||||
<PackageReference Include="MonoTorrent" Version="2.0.7" />
|
||||
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
|
||||
<PackageReference Include="System.Text.Json" Version="6.0.9" />
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace NzbDrone.Core.Tv
|
|||
List<Series> FindByTitleInexact(string cleanTitle);
|
||||
Series FindByTvdbId(int tvdbId);
|
||||
Series FindByTvRageId(int tvRageId);
|
||||
Series FindByImdbId(string imdbId);
|
||||
Series FindByPath(string path);
|
||||
List<int> AllSeriesTvdbIds();
|
||||
Dictionary<int, string> AllSeriesPaths();
|
||||
|
@ -73,6 +74,11 @@ namespace NzbDrone.Core.Tv
|
|||
return Query(s => s.TvRageId == tvRageId).SingleOrDefault();
|
||||
}
|
||||
|
||||
public Series FindByImdbId(string imdbId)
|
||||
{
|
||||
return Query(s => s.ImdbId == imdbId).SingleOrDefault();
|
||||
}
|
||||
|
||||
public Series FindByPath(string path)
|
||||
{
|
||||
return Query(s => s.Path == path)
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace NzbDrone.Core.Tv
|
|||
List<Series> AddSeries(List<Series> newSeries);
|
||||
Series FindByTvdbId(int tvdbId);
|
||||
Series FindByTvRageId(int tvRageId);
|
||||
Series FindByImdbId(string imdbId);
|
||||
Series FindByTitle(string title);
|
||||
Series FindByTitle(string title, int year);
|
||||
Series FindByTitleInexact(string title);
|
||||
|
@ -94,6 +95,11 @@ namespace NzbDrone.Core.Tv
|
|||
return _seriesRepository.FindByTvRageId(tvRageId);
|
||||
}
|
||||
|
||||
public Series FindByImdbId(string imdbId)
|
||||
{
|
||||
return _seriesRepository.FindByImdbId(imdbId);
|
||||
}
|
||||
|
||||
public Series FindByTitle(string title)
|
||||
{
|
||||
return _seriesRepository.FindByTitle(title.CleanSeriesTitle());
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Owin" Version="6.0.21" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="1.7.4" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.11" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.6.2" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.2" />
|
||||
|
|
|
@ -49,8 +49,8 @@ namespace NzbDrone.Host
|
|||
services.AddLogging(b =>
|
||||
{
|
||||
b.ClearProviders();
|
||||
b.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
|
||||
b.AddFilter("Microsoft.AspNetCore", Microsoft.Extensions.Logging.LogLevel.Warning);
|
||||
b.SetMinimumLevel(LogLevel.Trace);
|
||||
b.AddFilter("Microsoft.AspNetCore", LogLevel.Warning);
|
||||
b.AddFilter("Sonarr.Http.Authentication", LogLevel.Information);
|
||||
b.AddFilter("Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager", LogLevel.Error);
|
||||
b.AddNLog();
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace NzbDrone.Test.Common.AutoMoq
|
|||
|
||||
if (behavior != MockBehavior.Default && mock.Behavior == MockBehavior.Default)
|
||||
{
|
||||
throw new InvalidOperationException("Unable to change be behaviour of a an existing mock.");
|
||||
throw new InvalidOperationException("Unable to change be behaviour of an existing mock.");
|
||||
}
|
||||
|
||||
return mock;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<PackageReference Include="FluentAssertions" Version="6.10.0" />
|
||||
<PackageReference Include="FluentValidation" Version="9.5.4" />
|
||||
<PackageReference Include="Moq" Version="4.18.4" />
|
||||
<PackageReference Include="NLog" Version="4.7.14" />
|
||||
<PackageReference Include="NLog" Version="5.3.2" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="RestSharp" Version="106.15.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
|
||||
<PackageReference Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
|
||||
<PackageReference Include="NLog" Version="4.7.14" />
|
||||
<PackageReference Include="NLog" Version="5.3.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NzbDrone.Common\Sonarr.Common.csproj" />
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="4.7.14" />
|
||||
<PackageReference Include="NLog" Version="5.3.2" />
|
||||
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="6.0.0-preview.5.21301.5" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace Sonarr.Api.V3.Indexers
|
|||
public bool Rejected { get; set; }
|
||||
public int TvdbId { get; set; }
|
||||
public int TvRageId { get; set; }
|
||||
public string ImdbId { get; set; }
|
||||
public IEnumerable<string> Rejections { get; set; }
|
||||
public DateTime PublishDate { get; set; }
|
||||
public string CommentUrl { get; set; }
|
||||
|
@ -136,6 +137,7 @@ namespace Sonarr.Api.V3.Indexers
|
|||
Rejected = model.Rejected,
|
||||
TvdbId = releaseInfo.TvdbId,
|
||||
TvRageId = releaseInfo.TvRageId,
|
||||
ImdbId = releaseInfo.ImdbId,
|
||||
Rejections = model.Rejections.Select(r => r.Reason).ToList(),
|
||||
PublishDate = releaseInfo.PublishDate,
|
||||
CommentUrl = releaseInfo.CommentUrl,
|
||||
|
@ -194,6 +196,7 @@ namespace Sonarr.Api.V3.Indexers
|
|||
model.DownloadProtocol = resource.Protocol;
|
||||
model.TvdbId = resource.TvdbId;
|
||||
model.TvRageId = resource.TvRageId;
|
||||
model.ImdbId = resource.ImdbId;
|
||||
model.PublishDate = resource.PublishDate.ToUniversalTime();
|
||||
|
||||
return model;
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace Sonarr.Api.V3.Parse
|
|||
};
|
||||
}
|
||||
|
||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0);
|
||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0, null);
|
||||
|
||||
if (remoteEpisode != null)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
|
@ -14,11 +15,13 @@ namespace Sonarr.Api.V3.Series
|
|||
{
|
||||
private readonly ISeriesService _seriesService;
|
||||
private readonly IManageCommandQueue _commandQueueManager;
|
||||
private readonly SeriesEditorValidator _seriesEditorValidator;
|
||||
|
||||
public SeriesEditorController(ISeriesService seriesService, IManageCommandQueue commandQueueManager)
|
||||
public SeriesEditorController(ISeriesService seriesService, IManageCommandQueue commandQueueManager, SeriesEditorValidator seriesEditorValidator)
|
||||
{
|
||||
_seriesService = seriesService;
|
||||
_commandQueueManager = commandQueueManager;
|
||||
_seriesEditorValidator = seriesEditorValidator;
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
|
@ -58,10 +61,10 @@ namespace Sonarr.Api.V3.Series
|
|||
{
|
||||
series.RootFolderPath = resource.RootFolderPath;
|
||||
seriesToMove.Add(new BulkMoveSeries
|
||||
{
|
||||
SeriesId = series.Id,
|
||||
SourcePath = series.Path
|
||||
});
|
||||
{
|
||||
SeriesId = series.Id,
|
||||
SourcePath = series.Path
|
||||
});
|
||||
}
|
||||
|
||||
if (resource.Tags != null)
|
||||
|
@ -82,15 +85,22 @@ namespace Sonarr.Api.V3.Series
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var validationResult = _seriesEditorValidator.Validate(series);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
throw new ValidationException(validationResult.Errors);
|
||||
}
|
||||
}
|
||||
|
||||
if (resource.MoveFiles && seriesToMove.Any())
|
||||
{
|
||||
_commandQueueManager.Push(new BulkMoveSeriesCommand
|
||||
{
|
||||
DestinationRootFolder = resource.RootFolderPath,
|
||||
Series = seriesToMove
|
||||
});
|
||||
{
|
||||
DestinationRootFolder = resource.RootFolderPath,
|
||||
Series = seriesToMove
|
||||
});
|
||||
}
|
||||
|
||||
return Accepted(_seriesService.UpdateSeries(seriesToUpdate, !resource.MoveFiles).ToResource());
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
|
||||
namespace Sonarr.Api.V3.Series
|
||||
{
|
||||
public class SeriesEditorValidator : AbstractValidator<NzbDrone.Core.Tv.Series>
|
||||
{
|
||||
public SeriesEditorValidator(RootFolderExistsValidator rootFolderExistsValidator, QualityProfileExistsValidator qualityProfileExistsValidator)
|
||||
{
|
||||
RuleFor(s => s.RootFolderPath).Cascade(CascadeMode.Stop)
|
||||
.IsValidPath()
|
||||
.SetValidator(rootFolderExistsValidator)
|
||||
.When(s => s.RootFolderPath.IsNotNullOrWhiteSpace());
|
||||
|
||||
RuleFor(c => c.QualityProfileId).Cascade(CascadeMode.Stop)
|
||||
.ValidId()
|
||||
.SetValidator(qualityProfileExistsValidator);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="9.5.4" />
|
||||
<PackageReference Include="Ical.Net" Version="4.2.0" />
|
||||
<PackageReference Include="NLog" Version="4.7.14" />
|
||||
<PackageReference Include="NLog" Version="5.3.2" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.6.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="9.5.4" />
|
||||
<PackageReference Include="ImpromptuInterface" Version="7.0.1" />
|
||||
<PackageReference Include="NLog" Version="4.7.14" />
|
||||
<PackageReference Include="NLog" Version="5.3.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NzbDrone.Core\Sonarr.Core.csproj" />
|
||||
|
|
Loading…
Reference in New Issue