mirror of
https://github.com/Radarr/Radarr.git
synced 2026-04-18 21:35:51 -04:00
Compare commits
40 Commits
v2.0.0.468
...
v2.0.0.474
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a86f8c241 | ||
|
|
c184e7ddcc | ||
|
|
95c81f8905 | ||
|
|
db15949704 | ||
|
|
a63248401e | ||
|
|
1b32411219 | ||
|
|
cd7368512d | ||
|
|
a5bc4a8f11 | ||
|
|
2ae41a3404 | ||
|
|
312136a57c | ||
|
|
53e51af9c7 | ||
|
|
f852ca91c0 | ||
|
|
413dd51db1 | ||
|
|
9d93fc1092 | ||
|
|
0bbb82c67f | ||
|
|
cd8ae0d036 | ||
|
|
d726a7acb2 | ||
|
|
c94636e2b3 | ||
|
|
3749f3e2e5 | ||
|
|
1f93bec055 | ||
|
|
a003a89b14 | ||
|
|
35fca89dad | ||
|
|
e97e13e897 | ||
|
|
f8d5f1fc94 | ||
|
|
46a1ff3e2d | ||
|
|
f36d5dc881 | ||
|
|
f8b8fcfb8d | ||
|
|
de7f68570e | ||
|
|
fa006d85fd | ||
|
|
413ce1d9a7 | ||
|
|
41f769790d | ||
|
|
b63bcd16a7 | ||
|
|
b485bdaeec | ||
|
|
b70d167911 | ||
|
|
924fe80997 | ||
|
|
cd450a44bf | ||
|
|
35741b9cae | ||
|
|
c9d1807670 | ||
|
|
94886e767b | ||
|
|
e4c3418987 |
@@ -5,7 +5,7 @@ var postcss = require('gulp-postcss');
|
|||||||
var sourcemaps = require('gulp-sourcemaps');
|
var sourcemaps = require('gulp-sourcemaps');
|
||||||
var autoprefixer = require('autoprefixer-core');
|
var autoprefixer = require('autoprefixer-core');
|
||||||
var livereload = require('gulp-livereload');
|
var livereload = require('gulp-livereload');
|
||||||
|
var cleancss = require('gulp-clean-css');
|
||||||
var print = require('gulp-print');
|
var print = require('gulp-print');
|
||||||
var paths = require('./paths');
|
var paths = require('./paths');
|
||||||
var errorHandler = require('./errorHandler');
|
var errorHandler = require('./errorHandler');
|
||||||
@@ -33,12 +33,13 @@ gulp.task('less', function() {
|
|||||||
.pipe(sourcemaps.init())
|
.pipe(sourcemaps.init())
|
||||||
.pipe(less({
|
.pipe(less({
|
||||||
dumpLineNumbers : 'false',
|
dumpLineNumbers : 'false',
|
||||||
compress : true,
|
compress : false,
|
||||||
yuicompress : true,
|
yuicompress : false,
|
||||||
ieCompat : true,
|
ieCompat : true,
|
||||||
strictImports : true
|
strictImports : true
|
||||||
}))
|
}))
|
||||||
.pipe(postcss([ autoprefixer({ browsers: ['last 2 versions'] }) ]))
|
.pipe(postcss([ autoprefixer({ browsers: ['last 2 versions'] }) ]))
|
||||||
|
.pipe(cleancss())
|
||||||
.on('error', errorHandler.onError)
|
.on('error', errorHandler.onError)
|
||||||
.pipe(sourcemaps.write(paths.dest.content))
|
.pipe(sourcemaps.write(paths.dest.content))
|
||||||
.pipe(gulp.dest(paths.dest.content))
|
.pipe(gulp.dest(paths.dest.content))
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
"del": "1.2.0",
|
"del": "1.2.0",
|
||||||
"gulp": "3.9.0",
|
"gulp": "3.9.0",
|
||||||
"gulp-cached": "1.1.0",
|
"gulp-cached": "1.1.0",
|
||||||
|
"gulp-clean-css": "^3.0.4",
|
||||||
"gulp-concat": "2.6.0",
|
"gulp-concat": "2.6.0",
|
||||||
"gulp-declare": "0.3.0",
|
"gulp-declare": "0.3.0",
|
||||||
"gulp-handlebars": "3.0.1",
|
"gulp-handlebars": "3.0.1",
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ namespace NzbDrone.Api.Authentication
|
|||||||
{
|
{
|
||||||
if (_configFileProvider.AuthenticationMethod == AuthenticationType.Forms)
|
if (_configFileProvider.AuthenticationMethod == AuthenticationType.Forms)
|
||||||
{
|
{
|
||||||
RegisterFormsAuth(pipelines);
|
RegisterFormsAuth(pipelines);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (_configFileProvider.AuthenticationMethod == AuthenticationType.Basic)
|
else if (_configFileProvider.AuthenticationMethod == AuthenticationType.Basic)
|
||||||
{
|
{
|
||||||
pipelines.EnableBasicAuthentication(new BasicAuthenticationConfiguration(_authenticationService, "Sonarr"));
|
pipelines.EnableBasicAuthentication(new BasicAuthenticationConfiguration(_authenticationService, "Sonarr"));
|
||||||
}
|
}
|
||||||
|
|
||||||
pipelines.BeforeRequest.AddItemToEndOfPipeline((Func<NancyContext, Response>) RequiresAuthentication);
|
pipelines.BeforeRequest.AddItemToEndOfPipeline((Func<NancyContext, Response>) RequiresAuthentication);
|
||||||
@@ -68,6 +68,7 @@ namespace NzbDrone.Api.Authentication
|
|||||||
{
|
{
|
||||||
RedirectUrl = _configFileProvider.UrlBase + "/login",
|
RedirectUrl = _configFileProvider.UrlBase + "/login",
|
||||||
UserMapper = _authenticationService,
|
UserMapper = _authenticationService,
|
||||||
|
Path = _configFileProvider.UrlBase,
|
||||||
CryptographyConfiguration = cryptographyConfiguration
|
CryptographyConfiguration = cryptographyConfiguration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ namespace NzbDrone.Common.Test
|
|||||||
{
|
{
|
||||||
first.AsOsAgnostic().PathEquals(second.AsOsAgnostic()).Should().BeFalse();
|
first.AsOsAgnostic().PathEquals(second.AsOsAgnostic()).Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_false_when_not_a_child()
|
public void should_return_false_when_not_a_child()
|
||||||
{
|
{
|
||||||
@@ -113,6 +113,7 @@ namespace NzbDrone.Common.Test
|
|||||||
[TestCase(@"C:\Test\", @"C:\Test\mydir")]
|
[TestCase(@"C:\Test\", @"C:\Test\mydir")]
|
||||||
[TestCase(@"C:\Test\", @"C:\Test\mydir\")]
|
[TestCase(@"C:\Test\", @"C:\Test\mydir\")]
|
||||||
[TestCase(@"C:\Test", @"C:\Test\30.Rock.S01E01.Pilot.avi")]
|
[TestCase(@"C:\Test", @"C:\Test\30.Rock.S01E01.Pilot.avi")]
|
||||||
|
[TestCase(@"C:\", @"C:\Test\30.Rock.S01E01.Pilot.avi")]
|
||||||
public void path_should_be_parent(string parentPath, string childPath)
|
public void path_should_be_parent(string parentPath, string childPath)
|
||||||
{
|
{
|
||||||
parentPath.AsOsAgnostic().IsParentPath(childPath.AsOsAgnostic()).Should().BeTrue();
|
parentPath.AsOsAgnostic().IsParentPath(childPath.AsOsAgnostic()).Should().BeTrue();
|
||||||
|
|||||||
@@ -590,7 +590,7 @@ namespace NzbDrone.Common.Disk
|
|||||||
|
|
||||||
private bool ShouldIgnore(FileInfo file)
|
private bool ShouldIgnore(FileInfo file)
|
||||||
{
|
{
|
||||||
if (file.Name.StartsWith(".nfs"))
|
if (file.Name.StartsWith(".nfs") || file.Name == "debug.log" || file.Name.EndsWith(".socket"))
|
||||||
{
|
{
|
||||||
_logger.Trace("Ignoring file {0}", file.FullName);
|
_logger.Trace("Ignoring file {0}", file.FullName);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.IO;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Disk
|
namespace NzbDrone.Common.Disk
|
||||||
@@ -8,10 +9,11 @@ namespace NzbDrone.Common.Disk
|
|||||||
private readonly DriveInfo _driveInfo;
|
private readonly DriveInfo _driveInfo;
|
||||||
private readonly DriveType _driveType;
|
private readonly DriveType _driveType;
|
||||||
|
|
||||||
public DriveInfoMount(DriveInfo driveInfo, DriveType driveType = DriveType.Unknown)
|
public DriveInfoMount(DriveInfo driveInfo, DriveType driveType = DriveType.Unknown, MountOptions mountOptions = null)
|
||||||
{
|
{
|
||||||
_driveInfo = driveInfo;
|
_driveInfo = driveInfo;
|
||||||
_driveType = driveType;
|
_driveType = driveType;
|
||||||
|
MountOptions = mountOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long AvailableFreeSpace => _driveInfo.AvailableFreeSpace;
|
public long AvailableFreeSpace => _driveInfo.AvailableFreeSpace;
|
||||||
@@ -33,6 +35,8 @@ namespace NzbDrone.Common.Disk
|
|||||||
|
|
||||||
public bool IsReady => _driveInfo.IsReady;
|
public bool IsReady => _driveInfo.IsReady;
|
||||||
|
|
||||||
|
public MountOptions MountOptions { get; private set; }
|
||||||
|
|
||||||
public string Name => _driveInfo.Name;
|
public string Name => _driveInfo.Name;
|
||||||
|
|
||||||
public string RootDirectory => _driveInfo.RootDirectory.FullName;
|
public string RootDirectory => _driveInfo.RootDirectory.FullName;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Disk
|
namespace NzbDrone.Common.Disk
|
||||||
@@ -8,6 +9,7 @@ namespace NzbDrone.Common.Disk
|
|||||||
string DriveFormat { get; }
|
string DriveFormat { get; }
|
||||||
DriveType DriveType { get; }
|
DriveType DriveType { get; }
|
||||||
bool IsReady { get; }
|
bool IsReady { get; }
|
||||||
|
MountOptions MountOptions { get; }
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
string RootDirectory { get; }
|
string RootDirectory { get; }
|
||||||
long TotalFreeSpace { get; }
|
long TotalFreeSpace { get; }
|
||||||
|
|||||||
16
src/NzbDrone.Common/Disk/MountOptions.cs
Normal file
16
src/NzbDrone.Common/Disk/MountOptions.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Disk
|
||||||
|
{
|
||||||
|
public class MountOptions
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, string> _options;
|
||||||
|
|
||||||
|
public MountOptions(Dictionary<string, string> options)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsReadOnly => _options.ContainsKey("ro");
|
||||||
|
}
|
||||||
|
}
|
||||||
55
src/NzbDrone.Common/Extensions/ExceptionExtensions.cs
Normal file
55
src/NzbDrone.Common/Extensions/ExceptionExtensions.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Extensions
|
||||||
|
{
|
||||||
|
public static class ExceptionExtensions
|
||||||
|
{
|
||||||
|
public static T WithData<T>(this T ex, string key, string value) where T : Exception
|
||||||
|
{
|
||||||
|
ex.AddData(key, value);
|
||||||
|
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
public static T WithData<T>(this T ex, string key, int value) where T : Exception
|
||||||
|
{
|
||||||
|
ex.AddData(key, value.ToString());
|
||||||
|
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T WithData<T>(this T ex, string key, Http.HttpUri value) where T : Exception
|
||||||
|
{
|
||||||
|
ex.AddData(key, value.ToString());
|
||||||
|
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static T WithData<T>(this T ex, Http.HttpResponse response, int maxSampleLength = 512) where T : Exception
|
||||||
|
{
|
||||||
|
if (response == null || response.Content == null) return ex;
|
||||||
|
|
||||||
|
var contentSample = response.Content.Substring(0, Math.Min(response.Content.Length, 512));
|
||||||
|
|
||||||
|
if (response.Headers != null)
|
||||||
|
{
|
||||||
|
ex.AddData("ContentType", response.Headers.ContentType ?? string.Empty);
|
||||||
|
}
|
||||||
|
ex.AddData("ContentLength", response.Content.Length.ToString());
|
||||||
|
ex.AddData("ContentSample", contentSample);
|
||||||
|
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void AddData(this Exception ex, string key, string value)
|
||||||
|
{
|
||||||
|
if (value.IsNullOrWhiteSpace()) return;
|
||||||
|
|
||||||
|
ex.Data[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,11 +80,11 @@ namespace NzbDrone.Common.Extensions
|
|||||||
|
|
||||||
public static bool IsParentPath(this string parentPath, string childPath)
|
public static bool IsParentPath(this string parentPath, string childPath)
|
||||||
{
|
{
|
||||||
if (parentPath != "/")
|
if (parentPath != "/" && !parentPath.EndsWith(":\\"))
|
||||||
{
|
{
|
||||||
parentPath = parentPath.TrimEnd(Path.DirectorySeparatorChar);
|
parentPath = parentPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||||
}
|
}
|
||||||
if (childPath != "/")
|
if (childPath != "/" && !parentPath.EndsWith(":\\"))
|
||||||
{
|
{
|
||||||
childPath = childPath.TrimEnd(Path.DirectorySeparatorChar);
|
childPath = childPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||||
}
|
}
|
||||||
@@ -276,4 +276,4 @@ namespace NzbDrone.Common.Extensions
|
|||||||
return Path.Combine(appFolderInfo.StartUpFolder, NLOG_CONFIG_FILE);
|
return Path.Combine(appFolderInfo.StartUpFolder, NLOG_CONFIG_FILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
47
src/NzbDrone.Common/Instrumentation/CleansingJsonVisitor.cs
Normal file
47
src/NzbDrone.Common/Instrumentation/CleansingJsonVisitor.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Instrumentation
|
||||||
|
{
|
||||||
|
public class CleansingJsonVisitor : JsonVisitor
|
||||||
|
{
|
||||||
|
public override void Visit(JArray json)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < json.Count; i++)
|
||||||
|
{
|
||||||
|
if (json[i].Type == JTokenType.String)
|
||||||
|
{
|
||||||
|
var text = json[i].Value<string>();
|
||||||
|
json[i] = new JValue(CleanseLogMessage.Cleanse(text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (JToken token in json)
|
||||||
|
{
|
||||||
|
Visit(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Visit(JProperty property)
|
||||||
|
{
|
||||||
|
if (property.Value.Type == JTokenType.String)
|
||||||
|
{
|
||||||
|
property.Value = CleanseValue(property.Value as JValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.Visit(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JValue CleanseValue(JValue value)
|
||||||
|
{
|
||||||
|
var text = value.Value<string>();
|
||||||
|
var cleansed = CleanseLogMessage.Cleanse(text);
|
||||||
|
return new JValue(cleansed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Instrumentation.Sentry
|
||||||
|
{
|
||||||
|
public class SentryPacketCleanser
|
||||||
|
{
|
||||||
|
public void CleansePacket(SonarrSentryPacket packet)
|
||||||
|
{
|
||||||
|
packet.Message = CleanseLogMessage.Cleanse(packet.Message);
|
||||||
|
|
||||||
|
if (packet.Fingerprint != null)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < packet.Fingerprint.Length; i++)
|
||||||
|
{
|
||||||
|
packet.Fingerprint[i] = CleanseLogMessage.Cleanse(packet.Fingerprint[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet.Extra != null)
|
||||||
|
{
|
||||||
|
var target = JObject.FromObject(packet.Extra);
|
||||||
|
new CleansingJsonVisitor().Visit(target);
|
||||||
|
packet.Extra = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -114,7 +114,6 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
|||||||
var extras = logEvent.Properties.ToDictionary(x => x.Key.ToString(), x => x.Value.ToString());
|
var extras = logEvent.Properties.ToDictionary(x => x.Key.ToString(), x => x.Value.ToString());
|
||||||
_client.Logger = logEvent.LoggerName;
|
_client.Logger = logEvent.LoggerName;
|
||||||
|
|
||||||
|
|
||||||
var sentryMessage = new SentryMessage(logEvent.Message, logEvent.Parameters);
|
var sentryMessage = new SentryMessage(logEvent.Message, logEvent.Parameters);
|
||||||
|
|
||||||
var sentryEvent = new SentryEvent(logEvent.Exception)
|
var sentryEvent = new SentryEvent(logEvent.Exception)
|
||||||
|
|||||||
@@ -6,6 +6,13 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
|||||||
{
|
{
|
||||||
public class SonarrJsonPacketFactory : IJsonPacketFactory
|
public class SonarrJsonPacketFactory : IJsonPacketFactory
|
||||||
{
|
{
|
||||||
|
private readonly SentryPacketCleanser _cleanser;
|
||||||
|
|
||||||
|
public SonarrJsonPacketFactory()
|
||||||
|
{
|
||||||
|
_cleanser = new SentryPacketCleanser();
|
||||||
|
}
|
||||||
|
|
||||||
private static string ShortenPath(string path)
|
private static string ShortenPath(string path)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -37,6 +44,8 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
|||||||
frame.Filename = ShortenPath(frame.Filename);
|
frame.Filename = ShortenPath(frame.Filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cleanser.CleansePacket(packet);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@@ -46,7 +55,6 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
|||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Obsolete]
|
[Obsolete]
|
||||||
public JsonPacket Create(string project, SentryMessage message, ErrorLevel level = ErrorLevel.Info, IDictionary<string, string> tags = null,
|
public JsonPacket Create(string project, SentryMessage message, ErrorLevel level = ErrorLevel.Info, IDictionary<string, string> tags = null,
|
||||||
string[] fingerprint = null, object extra = null)
|
string[] fingerprint = null, object extra = null)
|
||||||
@@ -61,4 +69,4 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,16 +46,14 @@
|
|||||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Org.Mentalis, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Org.Mentalis, Version=1.0.0.1, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\DotNet4.SocksProxy.1.3.2.0\lib\net40\Org.Mentalis.dll</HintPath>
|
<HintPath>..\packages\DotNet4.SocksProxy.1.3.4.0\lib\net40\Org.Mentalis.dll</HintPath>
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SharpRaven, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="SharpRaven, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\SharpRaven.2.2.0\lib\net40\SharpRaven.dll</HintPath>
|
<HintPath>..\packages\SharpRaven.2.2.0\lib\net40\SharpRaven.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SocksWebProxy, Version=1.3.2.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="SocksWebProxy, Version=1.3.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\DotNet4.SocksProxy.1.3.2.0\lib\net40\SocksWebProxy.dll</HintPath>
|
<HintPath>..\packages\DotNet4.SocksProxy.1.3.4.0\lib\net40\SocksWebProxy.dll</HintPath>
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Configuration" />
|
<Reference Include="System.Configuration" />
|
||||||
@@ -87,6 +85,7 @@
|
|||||||
<Compile Include="Disk\FileSystemLookupService.cs" />
|
<Compile Include="Disk\FileSystemLookupService.cs" />
|
||||||
<Compile Include="Disk\DriveInfoMount.cs" />
|
<Compile Include="Disk\DriveInfoMount.cs" />
|
||||||
<Compile Include="Disk\IMount.cs" />
|
<Compile Include="Disk\IMount.cs" />
|
||||||
|
<Compile Include="Disk\MountOptions.cs" />
|
||||||
<Compile Include="Disk\RelativeFileSystemModel.cs" />
|
<Compile Include="Disk\RelativeFileSystemModel.cs" />
|
||||||
<Compile Include="Disk\FileSystemModel.cs" />
|
<Compile Include="Disk\FileSystemModel.cs" />
|
||||||
<Compile Include="Disk\FileSystemResult.cs" />
|
<Compile Include="Disk\FileSystemResult.cs" />
|
||||||
@@ -136,6 +135,7 @@
|
|||||||
<Compile Include="Extensions\Base64Extensions.cs" />
|
<Compile Include="Extensions\Base64Extensions.cs" />
|
||||||
<Compile Include="Extensions\DateTimeExtensions.cs" />
|
<Compile Include="Extensions\DateTimeExtensions.cs" />
|
||||||
<Compile Include="Crypto\HashConverter.cs" />
|
<Compile Include="Crypto\HashConverter.cs" />
|
||||||
|
<Compile Include="Extensions\ExceptionExtensions.cs" />
|
||||||
<Compile Include="Extensions\Int64Extensions.cs" />
|
<Compile Include="Extensions\Int64Extensions.cs" />
|
||||||
<Compile Include="Extensions\ObjectExtensions.cs" />
|
<Compile Include="Extensions\ObjectExtensions.cs" />
|
||||||
<Compile Include="Extensions\StreamExtensions.cs" />
|
<Compile Include="Extensions\StreamExtensions.cs" />
|
||||||
@@ -175,12 +175,14 @@
|
|||||||
<Compile Include="Extensions\IEnumerableExtensions.cs" />
|
<Compile Include="Extensions\IEnumerableExtensions.cs" />
|
||||||
<Compile Include="Http\UserAgentBuilder.cs" />
|
<Compile Include="Http\UserAgentBuilder.cs" />
|
||||||
<Compile Include="Instrumentation\CleanseLogMessage.cs" />
|
<Compile Include="Instrumentation\CleanseLogMessage.cs" />
|
||||||
|
<Compile Include="Instrumentation\CleansingJsonVisitor.cs" />
|
||||||
<Compile Include="Instrumentation\Extensions\LoggerProgressExtensions.cs" />
|
<Compile Include="Instrumentation\Extensions\LoggerProgressExtensions.cs" />
|
||||||
<Compile Include="Instrumentation\GlobalExceptionHandlers.cs" />
|
<Compile Include="Instrumentation\GlobalExceptionHandlers.cs" />
|
||||||
<Compile Include="Instrumentation\LogEventExtensions.cs" />
|
<Compile Include="Instrumentation\LogEventExtensions.cs" />
|
||||||
<Compile Include="Instrumentation\NzbDroneFileTarget.cs" />
|
<Compile Include="Instrumentation\NzbDroneFileTarget.cs" />
|
||||||
<Compile Include="Instrumentation\NzbDroneLogger.cs" />
|
<Compile Include="Instrumentation\NzbDroneLogger.cs" />
|
||||||
<Compile Include="Instrumentation\Sentry\SentryDebounce.cs" />
|
<Compile Include="Instrumentation\Sentry\SentryDebounce.cs" />
|
||||||
|
<Compile Include="Instrumentation\Sentry\SentryPacketCleanser.cs" />
|
||||||
<Compile Include="Instrumentation\Sentry\SentryTarget.cs" />
|
<Compile Include="Instrumentation\Sentry\SentryTarget.cs" />
|
||||||
<Compile Include="Instrumentation\Sentry\MachineNameUserFactory.cs" />
|
<Compile Include="Instrumentation\Sentry\MachineNameUserFactory.cs" />
|
||||||
<Compile Include="Instrumentation\Sentry\SonarrJsonPacketFactory.cs" />
|
<Compile Include="Instrumentation\Sentry\SonarrJsonPacketFactory.cs" />
|
||||||
@@ -205,6 +207,7 @@
|
|||||||
<Compile Include="Serializer\HttpUriConverter.cs" />
|
<Compile Include="Serializer\HttpUriConverter.cs" />
|
||||||
<Compile Include="Serializer\IntConverter.cs" />
|
<Compile Include="Serializer\IntConverter.cs" />
|
||||||
<Compile Include="Serializer\Json.cs" />
|
<Compile Include="Serializer\Json.cs" />
|
||||||
|
<Compile Include="Serializer\JsonVisitor.cs" />
|
||||||
<Compile Include="ServiceFactory.cs" />
|
<Compile Include="ServiceFactory.cs" />
|
||||||
<Compile Include="ServiceProvider.cs" />
|
<Compile Include="ServiceProvider.cs" />
|
||||||
<Compile Include="Extensions\StringExtensions.cs" />
|
<Compile Include="Extensions\StringExtensions.cs" />
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Model;
|
using NzbDrone.Common.Model;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Processes
|
namespace NzbDrone.Common.Processes
|
||||||
@@ -129,7 +130,25 @@ namespace NzbDrone.Common.Processes
|
|||||||
{
|
{
|
||||||
foreach (DictionaryEntry environmentVariable in environmentVariables)
|
foreach (DictionaryEntry environmentVariable in environmentVariables)
|
||||||
{
|
{
|
||||||
startInfo.EnvironmentVariables.Add(environmentVariable.Key.ToString(), environmentVariable.Value.ToString());
|
try
|
||||||
|
{
|
||||||
|
_logger.Trace("Setting environment variable '{0}' to '{1}'", environmentVariable.Key, environmentVariable.Value);
|
||||||
|
startInfo.EnvironmentVariables.Add(environmentVariable.Key.ToString(), environmentVariable.Value.ToString());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (environmentVariable.Value == null)
|
||||||
|
{
|
||||||
|
_logger.Error(e, "Unable to set environment variable '{0}', value is null", environmentVariable.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Error(e, "Unable to set environment variable '{0}'", environmentVariable.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
95
src/NzbDrone.Common/Serializer/JsonVisitor.cs
Normal file
95
src/NzbDrone.Common/Serializer/JsonVisitor.cs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Serializer
|
||||||
|
{
|
||||||
|
|
||||||
|
public class JsonVisitor
|
||||||
|
{
|
||||||
|
protected void Dispatch(JToken json)
|
||||||
|
{
|
||||||
|
switch (json.Type)
|
||||||
|
{
|
||||||
|
case JTokenType.Object:
|
||||||
|
Visit(json as JObject);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JTokenType.Array:
|
||||||
|
Visit(json as JArray);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JTokenType.Raw:
|
||||||
|
Visit(json as JRaw);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JTokenType.Constructor:
|
||||||
|
Visit(json as JConstructor);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JTokenType.Property:
|
||||||
|
Visit(json as JProperty);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JTokenType.Comment:
|
||||||
|
case JTokenType.Integer:
|
||||||
|
case JTokenType.Float:
|
||||||
|
case JTokenType.String:
|
||||||
|
case JTokenType.Boolean:
|
||||||
|
case JTokenType.Null:
|
||||||
|
case JTokenType.Undefined:
|
||||||
|
case JTokenType.Date:
|
||||||
|
case JTokenType.Bytes:
|
||||||
|
case JTokenType.Guid:
|
||||||
|
case JTokenType.Uri:
|
||||||
|
case JTokenType.TimeSpan:
|
||||||
|
Visit(json as JValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Visit(JToken json)
|
||||||
|
{
|
||||||
|
Dispatch(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Visit(JContainer json)
|
||||||
|
{
|
||||||
|
Dispatch(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Visit(JArray json)
|
||||||
|
{
|
||||||
|
foreach (JToken token in json)
|
||||||
|
{
|
||||||
|
Visit(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public virtual void Visit(JConstructor json)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Visit(JObject json)
|
||||||
|
{
|
||||||
|
foreach (JProperty property in json.Properties())
|
||||||
|
{
|
||||||
|
Visit(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Visit(JProperty property)
|
||||||
|
{
|
||||||
|
Visit(property.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Visit(JValue value)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="DotNet4.SocksProxy" version="1.3.2.0" targetFramework="net40" />
|
<package id="DotNet4.SocksProxy" version="1.3.4.0" targetFramework="net40" />
|
||||||
<package id="ICSharpCode.SharpZipLib.Patched" version="0.86.5" targetFramework="net40" />
|
<package id="ICSharpCode.SharpZipLib.Patched" version="0.86.5" targetFramework="net40" />
|
||||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net40" />
|
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net40" />
|
||||||
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
||||||
|
|||||||
@@ -20,11 +20,14 @@ namespace NzbDrone.Core.Test.DataAugmentation.Scene
|
|||||||
|
|
||||||
private Mock<ISceneMappingProvider> _provider1;
|
private Mock<ISceneMappingProvider> _provider1;
|
||||||
private Mock<ISceneMappingProvider> _provider2;
|
private Mock<ISceneMappingProvider> _provider2;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_fakeMappings = Builder<SceneMapping>.CreateListOfSize(5).BuildListOfNew();
|
_fakeMappings = Builder<SceneMapping>.CreateListOfSize(5)
|
||||||
|
.All()
|
||||||
|
.With(v => v.FilterRegex = null)
|
||||||
|
.BuildListOfNew();
|
||||||
|
|
||||||
_fakeMappings[0].SearchTerm = "Words";
|
_fakeMappings[0].SearchTerm = "Words";
|
||||||
_fakeMappings[1].SearchTerm = "That";
|
_fakeMappings[1].SearchTerm = "That";
|
||||||
@@ -193,7 +196,7 @@ namespace NzbDrone.Core.Test.DataAugmentation.Scene
|
|||||||
Mocker.GetMock<ISceneMappingRepository>().Setup(c => c.All()).Returns(mappings);
|
Mocker.GetMock<ISceneMappingRepository>().Setup(c => c.All()).Returns(mappings);
|
||||||
|
|
||||||
var tvdbId = Subject.FindTvdbId(parseTitle);
|
var tvdbId = Subject.FindTvdbId(parseTitle);
|
||||||
var seasonNumber = Subject.GetSceneSeasonNumber(parseTitle);
|
var seasonNumber = Subject.GetSceneSeasonNumber(parseTitle, null);
|
||||||
|
|
||||||
tvdbId.Should().Be(100);
|
tvdbId.Should().Be(100);
|
||||||
seasonNumber.Should().Be(expectedSeasonNumber);
|
seasonNumber.Should().Be(expectedSeasonNumber);
|
||||||
@@ -314,6 +317,49 @@ namespace NzbDrone.Core.Test.DataAugmentation.Scene
|
|||||||
Subject.GetSceneNames(100, new List<int> { 4 }, new List<int> { 4 }).Should().BeEmpty();
|
Subject.GetSceneNames(100, new List<int> { 4 }, new List<int> { 4 }).Should().BeEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_filter_by_regex()
|
||||||
|
{
|
||||||
|
var mappings = new List<SceneMapping>
|
||||||
|
{
|
||||||
|
new SceneMapping { Title = "Amareto", ParseTerm = "amareto", SearchTerm = "Amareto", TvdbId = 100 },
|
||||||
|
new SceneMapping { Title = "Amareto", ParseTerm = "amareto", SearchTerm = "Amareto", TvdbId = 101, FilterRegex="-Viva$" }
|
||||||
|
};
|
||||||
|
|
||||||
|
Mocker.GetMock<ISceneMappingRepository>().Setup(c => c.All()).Returns(mappings);
|
||||||
|
|
||||||
|
Subject.FindTvdbId("Amareto", "Amareto.S01E01.720p.WEB-DL-Viva").Should().Be(101);
|
||||||
|
Subject.FindTvdbId("Amareto", "Amareto.S01E01.720p.WEB-DL-DMO").Should().Be(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_throw_if_multiple_mappings()
|
||||||
|
{
|
||||||
|
var mappings = new List<SceneMapping>
|
||||||
|
{
|
||||||
|
new SceneMapping { Title = "Amareto", ParseTerm = "amareto", SearchTerm = "Amareto", TvdbId = 100 },
|
||||||
|
new SceneMapping { Title = "Amareto", ParseTerm = "amareto", SearchTerm = "Amareto", TvdbId = 101 }
|
||||||
|
};
|
||||||
|
|
||||||
|
Mocker.GetMock<ISceneMappingRepository>().Setup(c => c.All()).Returns(mappings);
|
||||||
|
|
||||||
|
Assert.Throws<InvalidSceneMappingException>(() => Subject.FindTvdbId("Amareto", "Amareto.S01E01.720p.WEB-DL-Viva"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_throw_if_multiple_mappings_with_same_tvdbid()
|
||||||
|
{
|
||||||
|
var mappings = new List<SceneMapping>
|
||||||
|
{
|
||||||
|
new SceneMapping { Title = "Amareto", ParseTerm = "amareto", SearchTerm = "Amareto", TvdbId = 100 },
|
||||||
|
new SceneMapping { Title = "Amareto", ParseTerm = "amareto", SearchTerm = "Amareto", TvdbId = 100 }
|
||||||
|
};
|
||||||
|
|
||||||
|
Mocker.GetMock<ISceneMappingRepository>().Setup(c => c.All()).Returns(mappings);
|
||||||
|
|
||||||
|
Subject.FindTvdbId("Amareto", "Amareto.S01E01.720p.WEB-DL-Viva").Should().Be(100);
|
||||||
|
}
|
||||||
|
|
||||||
private void AssertNoUpdate()
|
private void AssertNoUpdate()
|
||||||
{
|
{
|
||||||
_provider1.Verify(c => c.GetSceneMappings(), Times.Once());
|
_provider1.Verify(c => c.GetSceneMappings(), Times.Once());
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||||||
private Mock<IDecisionEngineSpecification> _fail2;
|
private Mock<IDecisionEngineSpecification> _fail2;
|
||||||
private Mock<IDecisionEngineSpecification> _fail3;
|
private Mock<IDecisionEngineSpecification> _fail3;
|
||||||
|
|
||||||
|
private Mock<IDecisionEngineSpecification> _failDelayed1;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
@@ -39,14 +41,19 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||||||
_fail2 = new Mock<IDecisionEngineSpecification>();
|
_fail2 = new Mock<IDecisionEngineSpecification>();
|
||||||
_fail3 = new Mock<IDecisionEngineSpecification>();
|
_fail3 = new Mock<IDecisionEngineSpecification>();
|
||||||
|
|
||||||
|
_failDelayed1 = new Mock<IDecisionEngineSpecification>();
|
||||||
|
|
||||||
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Accept);
|
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Accept);
|
||||||
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Accept);
|
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Accept);
|
||||||
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Accept);
|
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Accept);
|
||||||
|
|
||||||
_fail1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Reject("fail1"));
|
_fail1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Reject("fail1"));
|
||||||
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Reject("fail2"));
|
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Reject("fail2"));
|
||||||
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Reject("fail3"));
|
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Reject("fail3"));
|
||||||
|
|
||||||
|
_failDelayed1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>(), null)).Returns(Decision.Reject("failDelayed1"));
|
||||||
|
_failDelayed1.SetupGet(c => c.Priority).Returns(SpecificationPriority.Disk);
|
||||||
|
|
||||||
_reports = new List<ReleaseInfo> { new ReleaseInfo { Title = "The.Office.S03E115.DVDRip.XviD-OSiTV" } };
|
_reports = new List<ReleaseInfo> { new ReleaseInfo { Title = "The.Office.S03E115.DVDRip.XviD-OSiTV" } };
|
||||||
_remoteEpisode = new RemoteEpisode {
|
_remoteEpisode = new RemoteEpisode {
|
||||||
Series = new Series(),
|
Series = new Series(),
|
||||||
@@ -78,6 +85,25 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||||||
_pass3.Verify(c => c.IsSatisfiedBy(_remoteEpisode, null), Times.Once());
|
_pass3.Verify(c => c.IsSatisfiedBy(_remoteEpisode, null), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_call_delayed_specifications_if_non_delayed_passed()
|
||||||
|
{
|
||||||
|
GivenSpecifications(_pass1, _failDelayed1);
|
||||||
|
|
||||||
|
Subject.GetRssDecision(_reports).ToList();
|
||||||
|
_failDelayed1.Verify(c => c.IsSatisfiedBy(_remoteEpisode, null), Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_call_delayed_specifications_if_non_delayed_failed()
|
||||||
|
{
|
||||||
|
GivenSpecifications(_fail1, _failDelayed1);
|
||||||
|
|
||||||
|
Subject.GetRssDecision(_reports).ToList();
|
||||||
|
|
||||||
|
_failDelayed1.Verify(c => c.IsSatisfiedBy(_remoteEpisode, null), Times.Never());
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_rejected_if_single_specs_fail()
|
public void should_return_rejected_if_single_specs_fail()
|
||||||
{
|
{
|
||||||
@@ -214,10 +240,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||||||
|
|
||||||
var criteria = new SeasonSearchCriteria { Episodes = episodes.Take(1).ToList(), SeasonNumber = 1 };
|
var criteria = new SeasonSearchCriteria { Episodes = episodes.Take(1).ToList(), SeasonNumber = 1 };
|
||||||
|
|
||||||
var reports = episodes.Select(v =>
|
var reports = episodes.Select(v =>
|
||||||
new ReleaseInfo()
|
new ReleaseInfo()
|
||||||
{
|
{
|
||||||
Title = string.Format("{0}.S{1:00}E{2:00}.720p.WEB-DL-DRONE", series.Title, v.SceneSeasonNumber, v.SceneEpisodeNumber)
|
Title = string.Format("{0}.S{1:00}E{2:00}.720p.WEB-DL-DRONE", series.Title, v.SceneSeasonNumber, v.SceneEpisodeNumber)
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
Mocker.GetMock<IParsingService>()
|
Mocker.GetMock<IParsingService>()
|
||||||
@@ -289,4 +315,4 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||||||
ExceptionVerification.ExpectedErrors(1);
|
ExceptionVerification.ExpectedErrors(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,5 +137,17 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||||||
WithFirstEpisodeUnmonitored();
|
WithFirstEpisodeUnmonitored();
|
||||||
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultSingle, new SingleEpisodeSearchCriteria{ MonitoredEpisodesOnly = true}).Accepted.Should().BeFalse();
|
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultSingle, new SingleEpisodeSearchCriteria{ MonitoredEpisodesOnly = true}).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_all_episodes_are_not_monitored_for_season_pack_release()
|
||||||
|
{
|
||||||
|
WithSecondEpisodeUnmonitored();
|
||||||
|
_parseResultMulti.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
|
{
|
||||||
|
FullSeason = true
|
||||||
|
};
|
||||||
|
|
||||||
|
_monitoredEpisodeSpecification.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.DecisionEngine.Specifications.RssSync;
|
||||||
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Profiles;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using Moq;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class DeletedEpisodeFileSpecificationFixture : CoreTest<DeletedEpisodeFileSpecification>
|
||||||
|
{
|
||||||
|
private RemoteEpisode _parseResultMulti;
|
||||||
|
private RemoteEpisode _parseResultSingle;
|
||||||
|
private EpisodeFile _firstFile;
|
||||||
|
private EpisodeFile _secondFile;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_firstFile = new EpisodeFile
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
RelativePath = "My.Series.S01E01.mkv",
|
||||||
|
Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 1)),
|
||||||
|
DateAdded = DateTime.Now
|
||||||
|
};
|
||||||
|
_secondFile = new EpisodeFile
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
RelativePath = "My.Series.S01E02.mkv",
|
||||||
|
Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 1)),
|
||||||
|
DateAdded = DateTime.Now
|
||||||
|
};
|
||||||
|
|
||||||
|
var singleEpisodeList = new List<Episode> { new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 } };
|
||||||
|
var doubleEpisodeList = new List<Episode> {
|
||||||
|
new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 },
|
||||||
|
new Episode { EpisodeFile = _secondFile, EpisodeFileId = 2 }
|
||||||
|
};
|
||||||
|
|
||||||
|
var fakeSeries = Builder<Series>.CreateNew()
|
||||||
|
.With(c => c.Profile = new Profile { Cutoff = Quality.Bluray1080p })
|
||||||
|
.With(c => c.Path = @"C:\Series\My.Series".AsOsAgnostic())
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
_parseResultMulti = new RemoteEpisode
|
||||||
|
{
|
||||||
|
Series = fakeSeries,
|
||||||
|
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, new Revision(version: 2)) },
|
||||||
|
Episodes = doubleEpisodeList
|
||||||
|
};
|
||||||
|
|
||||||
|
_parseResultSingle = new RemoteEpisode
|
||||||
|
{
|
||||||
|
Series = fakeSeries,
|
||||||
|
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, new Revision(version: 2)) },
|
||||||
|
Episodes = singleEpisodeList
|
||||||
|
};
|
||||||
|
|
||||||
|
GivenUnmonitorDeletedEpisodes(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenUnmonitorDeletedEpisodes(bool enabled)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IConfigService>()
|
||||||
|
.SetupGet(v => v.AutoUnmonitorPreviouslyDownloadedEpisodes)
|
||||||
|
.Returns(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WithExistingFile(EpisodeFile episodeFile)
|
||||||
|
{
|
||||||
|
var path = Path.Combine(@"C:\Series\My.Series".AsOsAgnostic(), episodeFile.RelativePath);
|
||||||
|
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Setup(v => v.FileExists(path))
|
||||||
|
.Returns(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_when_unmonitor_deleted_episdes_is_off()
|
||||||
|
{
|
||||||
|
GivenUnmonitorDeletedEpisodes(false);
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_when_searching()
|
||||||
|
{
|
||||||
|
Subject.IsSatisfiedBy(_parseResultSingle, new SeasonSearchCriteria()).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_file_exists()
|
||||||
|
{
|
||||||
|
WithExistingFile(_firstFile);
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_file_is_missing()
|
||||||
|
{
|
||||||
|
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_both_of_multiple_episode_exist()
|
||||||
|
{
|
||||||
|
WithExistingFile(_firstFile);
|
||||||
|
WithExistingFile(_secondFile);
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_one_of_multiple_episode_is_missing()
|
||||||
|
{
|
||||||
|
WithExistingFile(_firstFile);
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_parseResultMulti, null).Accepted.Should().BeFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
@@ -107,6 +107,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
|
|||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyQueued(result);
|
VerifyQueued(result);
|
||||||
|
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -118,6 +121,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
|
|||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyPaused(result);
|
VerifyPaused(result);
|
||||||
|
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -129,6 +135,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
|
|||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyDownloading(result);
|
VerifyDownloading(result);
|
||||||
|
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -152,6 +161,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
|
|||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyFailed(result);
|
VerifyFailed(result);
|
||||||
|
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
@@ -167,6 +167,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
|
|||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyQueued(result);
|
VerifyQueued(result);
|
||||||
|
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -180,6 +183,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
|
|||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyPaused(result);
|
VerifyPaused(result);
|
||||||
|
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -193,6 +199,25 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
|
|||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyDownloading(result);
|
VerifyDownloading(result);
|
||||||
|
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void post_processing_item_should_have_required_properties()
|
||||||
|
{
|
||||||
|
_queued.ActiveDownloads = 1;
|
||||||
|
|
||||||
|
GivenQueue(_queued);
|
||||||
|
GivenHistory(null);
|
||||||
|
|
||||||
|
_queued.RemainingSizeLo = 0;
|
||||||
|
|
||||||
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -89,6 +89,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void GivenHighPriority()
|
||||||
|
{
|
||||||
|
Subject.Definition.Settings.As<QBittorrentSettings>().OlderTvPriority = (int)QBittorrentPriority.First;
|
||||||
|
Subject.Definition.Settings.As<QBittorrentSettings>().RecentTvPriority = (int)QBittorrentPriority.First;
|
||||||
|
}
|
||||||
|
|
||||||
protected void GivenMaxRatio(float maxRatio, bool removeOnMaxRatio = true)
|
protected void GivenMaxRatio(float maxRatio, bool removeOnMaxRatio = true)
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IQBittorrentProxy>()
|
Mocker.GetMock<IQBittorrentProxy>()
|
||||||
@@ -265,6 +271,39 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
id.Should().Be(expectedHash);
|
id.Should().Be(expectedHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Download_should_set_top_priority()
|
||||||
|
{
|
||||||
|
GivenHighPriority();
|
||||||
|
GivenSuccessfulDownload();
|
||||||
|
|
||||||
|
var remoteEpisode = CreateRemoteEpisode();
|
||||||
|
|
||||||
|
var id = Subject.Download(remoteEpisode);
|
||||||
|
|
||||||
|
Mocker.GetMock<IQBittorrentProxy>()
|
||||||
|
.Verify(v => v.MoveTorrentToTopInQueue(It.IsAny<string>(), It.IsAny<QBittorrentSettings>()), Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Download_should_not_fail_if_top_priority_not_available()
|
||||||
|
{
|
||||||
|
GivenHighPriority();
|
||||||
|
GivenSuccessfulDownload();
|
||||||
|
|
||||||
|
Mocker.GetMock<IQBittorrentProxy>()
|
||||||
|
.Setup(v => v.MoveTorrentToTopInQueue(It.IsAny<string>(), It.IsAny<QBittorrentSettings>()))
|
||||||
|
.Throws(new HttpException(new HttpResponse(new HttpRequest("http://me.local/"), new HttpHeader(), new byte[0], System.Net.HttpStatusCode.Forbidden)));
|
||||||
|
|
||||||
|
var remoteEpisode = CreateRemoteEpisode();
|
||||||
|
|
||||||
|
var id = Subject.Download(remoteEpisode);
|
||||||
|
|
||||||
|
id.Should().NotBeNullOrEmpty();
|
||||||
|
|
||||||
|
ExceptionVerification.ExpectedWarns(1);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_status_with_outputdirs()
|
public void should_return_status_with_outputdirs()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
@@ -191,7 +191,10 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyQueued(result);
|
VerifyQueued(result);
|
||||||
|
|
||||||
result.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
result.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(SabnzbdDownloadStatus.Paused)]
|
[TestCase(SabnzbdDownloadStatus.Paused)]
|
||||||
@@ -205,6 +208,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyPaused(result);
|
VerifyPaused(result);
|
||||||
|
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(SabnzbdDownloadStatus.Checking)]
|
[TestCase(SabnzbdDownloadStatus.Checking)]
|
||||||
@@ -227,7 +233,10 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyDownloading(result);
|
VerifyDownloading(result);
|
||||||
|
|
||||||
result.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
result.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -255,6 +264,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyFailed(result);
|
VerifyFailed(result);
|
||||||
|
|
||||||
|
result.CanBeRemoved.Should().BeTrue();
|
||||||
|
result.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -148,8 +148,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
|
|||||||
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
||||||
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
|
||||||
public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
||||||
{
|
{
|
||||||
_queued.Status = apiStatus;
|
_queued.Status = apiStatus;
|
||||||
@@ -163,7 +163,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
|
|||||||
|
|
||||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
||||||
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
|
||||||
public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
||||||
{
|
{
|
||||||
_downloading.Status = apiStatus;
|
_downloading.Status = apiStatus;
|
||||||
|
|||||||
@@ -13,6 +13,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class VuzeFixture : TransmissionFixtureBase<Vuze>
|
public class VuzeFixture : TransmissionFixtureBase<Vuze>
|
||||||
{
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup_Vuze()
|
||||||
|
{
|
||||||
|
// Vuze never sets isFinished.
|
||||||
|
_completed.IsFinished = false;
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void queued_item_should_have_required_properties()
|
public void queued_item_should_have_required_properties()
|
||||||
{
|
{
|
||||||
@@ -150,8 +157,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
||||||
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
|
||||||
public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
||||||
{
|
{
|
||||||
_queued.Status = apiStatus;
|
_queued.Status = apiStatus;
|
||||||
@@ -165,7 +172,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
|
|
||||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
||||||
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
|
||||||
public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
||||||
{
|
{
|
||||||
_downloading.Status = apiStatus;
|
_downloading.Status = apiStatus;
|
||||||
@@ -180,7 +187,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, true)]
|
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, true)]
|
||||||
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, false)]
|
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, false)]
|
||||||
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, false)]
|
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, false)]
|
||||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Completed, false)]
|
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued, false)]
|
||||||
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, false)]
|
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, false)]
|
||||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, false)]
|
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, false)]
|
||||||
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedValue)
|
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedValue)
|
||||||
@@ -298,7 +305,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_have_correct_output_directory()
|
public void should_have_correct_output_directory_for_multifile_torrents()
|
||||||
{
|
{
|
||||||
WindowsOnly();
|
WindowsOnly();
|
||||||
|
|
||||||
@@ -315,5 +322,25 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
items.First().OutputPath.Should().Be(@"C:\Downloads\" + _title);
|
items.First().OutputPath.Should().Be(@"C:\Downloads\" + _title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_have_correct_output_directory_for_singlefile_torrents()
|
||||||
|
{
|
||||||
|
WindowsOnly();
|
||||||
|
|
||||||
|
var fileName = _title + ".mkv";
|
||||||
|
_downloading.Name = fileName;
|
||||||
|
_downloading.DownloadDir = @"C:/Downloads";
|
||||||
|
|
||||||
|
GivenTorrents(new List<TransmissionTorrent>
|
||||||
|
{
|
||||||
|
_downloading
|
||||||
|
});
|
||||||
|
|
||||||
|
var items = Subject.GetItems().ToList();
|
||||||
|
|
||||||
|
items.Should().HaveCount(1);
|
||||||
|
items.First().OutputPath.Should().Be(@"C:\Downloads\" + fileName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@@ -7,6 +8,7 @@ using NzbDrone.Common.Http;
|
|||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Indexers.Newznab;
|
using NzbDrone.Core.Indexers.Newznab;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
||||||
{
|
{
|
||||||
@@ -43,7 +45,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
|||||||
Mocker.GetMock<IHttpClient>()
|
Mocker.GetMock<IHttpClient>()
|
||||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||||
|
|
||||||
var releases = Subject.FetchRecent();
|
var releases = Subject.FetchRecent();
|
||||||
|
|
||||||
releases.Should().HaveCount(100);
|
releases.Should().HaveCount(100);
|
||||||
@@ -69,5 +71,27 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
|||||||
|
|
||||||
Subject.PageSize.Should().Be(25);
|
Subject.PageSize.Should().Be(25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_record_indexer_failure_if_caps_throw()
|
||||||
|
{
|
||||||
|
var request = new HttpRequest("http://my.indexer.com");
|
||||||
|
var response = new HttpResponse(request, new HttpHeader(), new byte[0], (HttpStatusCode)429);
|
||||||
|
response.Headers["Retry-After"] = "300";
|
||||||
|
|
||||||
|
Mocker.GetMock<INewznabCapabilitiesProvider>()
|
||||||
|
.Setup(v => v.GetCapabilities(It.IsAny<NewznabSettings>()))
|
||||||
|
.Throws(new TooManyRequestsException(request, response));
|
||||||
|
|
||||||
|
_caps.MaxPageSize = 30;
|
||||||
|
_caps.DefaultPageSize = 25;
|
||||||
|
|
||||||
|
Subject.FetchRecent().Should().BeEmpty();
|
||||||
|
|
||||||
|
Mocker.GetMock<IIndexerStatusService>()
|
||||||
|
.Verify(v => v.RecordFailure(It.IsAny<int>(), TimeSpan.FromMinutes(5.0)), Times.Once());
|
||||||
|
|
||||||
|
ExceptionVerification.ExpectedWarns(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ using Moq;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Indexers.Exceptions;
|
||||||
using NzbDrone.Core.Indexers.TorrentRss;
|
using NzbDrone.Core.Indexers.TorrentRss;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
|
namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
|
||||||
{
|
{
|
||||||
@@ -48,7 +50,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
|
|||||||
|
|
||||||
releases.Should().HaveCount(50);
|
releases.Should().HaveCount(50);
|
||||||
releases.First().Should().BeOfType<TorrentInfo>();
|
releases.First().Should().BeOfType<TorrentInfo>();
|
||||||
|
|
||||||
var torrentInfo = (TorrentInfo)releases.First();
|
var torrentInfo = (TorrentInfo)releases.First();
|
||||||
|
|
||||||
torrentInfo.Title.Should().Be("Conan.2015.02.05.Jeff.Bridges.720p.HDTV.X264-CROOKS");
|
torrentInfo.Title.Should().Be("Conan.2015.02.05.Jeff.Bridges.720p.HDTV.X264-CROOKS");
|
||||||
@@ -239,7 +241,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
|
|||||||
|
|
||||||
torrentInfo.Title.Should().Be("DAYS - 05 (1280x720 HEVC2 AAC).mkv");
|
torrentInfo.Title.Should().Be("DAYS - 05 (1280x720 HEVC2 AAC).mkv");
|
||||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||||
torrentInfo.DownloadUrl.Should().Be("http://storage.animetosho.org/torrents/4b58360143d59a55cbd922397a3eaa378165f3ff/DAYS%20-%2005%20%281280x720%20HEVC2%20AAC%29.torrent");
|
torrentInfo.DownloadUrl.Should().Be("http://storage.animetosho.org/torrents/4b58360143d59a55cbd922397a3eaa378165f3ff/DAYS%20-%2005%20%281280x720%20HEVC2%20AAC%29.torrent");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -258,5 +260,18 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
|
|||||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||||
torrentInfo.DownloadUrl.Should().Be("https://alpharatio.cc/torrents.php?action=download&authkey=private_auth_key&torrent_pass=private_torrent_pass&id=465831");
|
torrentInfo.DownloadUrl.Should().Be("https://alpharatio.cc/torrents.php?action=download&authkey=private_auth_key&torrent_pass=private_torrent_pass&id=465831");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_record_indexer_failure_if_unsupported_feed()
|
||||||
|
{
|
||||||
|
GivenRecentFeedResponse("TorrentRss/invalid/TorrentDay_NoPubDate.xml");
|
||||||
|
|
||||||
|
Subject.FetchRecent().Should().BeEmpty();
|
||||||
|
|
||||||
|
Mocker.GetMock<IIndexerStatusService>()
|
||||||
|
.Verify(v => v.RecordFailure(It.IsAny<int>(), TimeSpan.Zero), Times.Once());
|
||||||
|
|
||||||
|
ExceptionVerification.ExpectedErrors(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -287,9 +287,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
|
|||||||
|
|
||||||
var ex = Assert.Throws<UnsupportedFeedException>(() => Subject.Detect(_indexerSettings));
|
var ex = Assert.Throws<UnsupportedFeedException>(() => Subject.Detect(_indexerSettings));
|
||||||
|
|
||||||
ex.Message.Should().Contain("Empty feed");
|
ex.Message.Should().Contain("Rss feed must have a pubDate");
|
||||||
|
|
||||||
ExceptionVerification.ExpectedErrors(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("Torrentleech/Torrentleech.xml")]
|
[TestCase("Torrentleech/Torrentleech.xml")]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
@@ -14,6 +14,7 @@ using NzbDrone.Core.Test.Framework;
|
|||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.MediaFiles
|
namespace NzbDrone.Core.Test.MediaFiles
|
||||||
{
|
{
|
||||||
@@ -77,7 +78,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||||||
Subject.ProcessRootFolder(new DirectoryInfo(_droneFactory));
|
Subject.ProcessRootFolder(new DirectoryInfo(_droneFactory));
|
||||||
|
|
||||||
Mocker.GetMock<IMakeImportDecision>()
|
Mocker.GetMock<IMakeImportDecision>()
|
||||||
.Verify(c => c.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), It.IsAny<ParsedEpisodeInfo>(), It.IsAny<bool>()),
|
.Verify(c => c.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), It.IsAny<DownloadClientItem>(), It.IsAny<ParsedEpisodeInfo>(), It.IsAny<bool>()),
|
||||||
Times.Never());
|
Times.Never());
|
||||||
|
|
||||||
VerifyNoImport();
|
VerifyNoImport();
|
||||||
@@ -128,7 +129,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||||||
imported.Add(new ImportDecision(localEpisode));
|
imported.Add(new ImportDecision(localEpisode));
|
||||||
|
|
||||||
Mocker.GetMock<IMakeImportDecision>()
|
Mocker.GetMock<IMakeImportDecision>()
|
||||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), null, true))
|
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), It.IsAny<DownloadClientItem>(), null, true))
|
||||||
.Returns(imported);
|
.Returns(imported);
|
||||||
|
|
||||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||||
@@ -154,7 +155,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||||||
imported.Add(new ImportDecision(localEpisode));
|
imported.Add(new ImportDecision(localEpisode));
|
||||||
|
|
||||||
Mocker.GetMock<IMakeImportDecision>()
|
Mocker.GetMock<IMakeImportDecision>()
|
||||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), null, true))
|
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), It.IsAny<DownloadClientItem>(), null, true))
|
||||||
.Returns(imported);
|
.Returns(imported);
|
||||||
|
|
||||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||||
@@ -226,7 +227,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||||||
imported.Add(new ImportDecision(localEpisode));
|
imported.Add(new ImportDecision(localEpisode));
|
||||||
|
|
||||||
Mocker.GetMock<IMakeImportDecision>()
|
Mocker.GetMock<IMakeImportDecision>()
|
||||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), null, true))
|
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), It.IsAny<DownloadClientItem>(), null, true))
|
||||||
.Returns(imported);
|
.Returns(imported);
|
||||||
|
|
||||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||||
@@ -280,7 +281,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||||||
Subject.ProcessPath(fileName);
|
Subject.ProcessPath(fileName);
|
||||||
|
|
||||||
Mocker.GetMock<IMakeImportDecision>()
|
Mocker.GetMock<IMakeImportDecision>()
|
||||||
.Verify(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), It.Is<ParsedEpisodeInfo>(v => v.AbsoluteEpisodeNumbers.First() == 9), true), Times.Once());
|
.Verify(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), It.IsAny<DownloadClientItem>(), It.Is<ParsedEpisodeInfo>(v => v.AbsoluteEpisodeNumbers.First() == 9), true), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -304,7 +305,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||||||
var result = Subject.ProcessPath(fileName);
|
var result = Subject.ProcessPath(fileName);
|
||||||
|
|
||||||
Mocker.GetMock<IMakeImportDecision>()
|
Mocker.GetMock<IMakeImportDecision>()
|
||||||
.Verify(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), null, true), Times.Once());
|
.Verify(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), It.IsAny<DownloadClientItem>(), null, true), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -337,7 +338,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||||||
imported.Add(new ImportDecision(localEpisode));
|
imported.Add(new ImportDecision(localEpisode));
|
||||||
|
|
||||||
Mocker.GetMock<IMakeImportDecision>()
|
Mocker.GetMock<IMakeImportDecision>()
|
||||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), null, true))
|
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), It.IsAny<DownloadClientItem>(), null, true))
|
||||||
.Returns(imported);
|
.Returns(imported);
|
||||||
|
|
||||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ using NzbDrone.Core.Test.Framework;
|
|||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
{
|
{
|
||||||
@@ -44,13 +45,13 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
_fail2 = new Mock<IImportDecisionEngineSpecification>();
|
_fail2 = new Mock<IImportDecisionEngineSpecification>();
|
||||||
_fail3 = new Mock<IImportDecisionEngineSpecification>();
|
_fail3 = new Mock<IImportDecisionEngineSpecification>();
|
||||||
|
|
||||||
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>())).Returns(Decision.Accept());
|
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Accept());
|
||||||
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>())).Returns(Decision.Accept());
|
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Accept());
|
||||||
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>())).Returns(Decision.Accept());
|
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Accept());
|
||||||
|
|
||||||
_fail1.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>())).Returns(Decision.Reject("_fail1"));
|
_fail1.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Reject("_fail1"));
|
||||||
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>())).Returns(Decision.Reject("_fail2"));
|
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Reject("_fail2"));
|
||||||
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>())).Returns(Decision.Reject("_fail3"));
|
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalEpisode>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Reject("_fail3"));
|
||||||
|
|
||||||
_series = Builder<Series>.CreateNew()
|
_series = Builder<Series>.CreateNew()
|
||||||
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
|
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
@@ -90,16 +91,17 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
[Test]
|
[Test]
|
||||||
public void should_call_all_specifications()
|
public void should_call_all_specifications()
|
||||||
{
|
{
|
||||||
|
var downloadClientItem = Builder<DownloadClientItem>.CreateNew().Build();
|
||||||
GivenSpecifications(_pass1, _pass2, _pass3, _fail1, _fail2, _fail3);
|
GivenSpecifications(_pass1, _pass2, _pass3, _fail1, _fail2, _fail3);
|
||||||
|
|
||||||
Subject.GetImportDecisions(_videoFiles, new Series(), null, false);
|
Subject.GetImportDecisions(_videoFiles, new Series(), downloadClientItem, null, false);
|
||||||
|
|
||||||
_fail1.Verify(c => c.IsSatisfiedBy(_localEpisode), Times.Once());
|
_fail1.Verify(c => c.IsSatisfiedBy(_localEpisode, downloadClientItem), Times.Once());
|
||||||
_fail2.Verify(c => c.IsSatisfiedBy(_localEpisode), Times.Once());
|
_fail2.Verify(c => c.IsSatisfiedBy(_localEpisode, downloadClientItem), Times.Once());
|
||||||
_fail3.Verify(c => c.IsSatisfiedBy(_localEpisode), Times.Once());
|
_fail3.Verify(c => c.IsSatisfiedBy(_localEpisode, downloadClientItem), Times.Once());
|
||||||
_pass1.Verify(c => c.IsSatisfiedBy(_localEpisode), Times.Once());
|
_pass1.Verify(c => c.IsSatisfiedBy(_localEpisode, downloadClientItem), Times.Once());
|
||||||
_pass2.Verify(c => c.IsSatisfiedBy(_localEpisode), Times.Once());
|
_pass2.Verify(c => c.IsSatisfiedBy(_localEpisode, downloadClientItem), Times.Once());
|
||||||
_pass3.Verify(c => c.IsSatisfiedBy(_localEpisode), Times.Once());
|
_pass3.Verify(c => c.IsSatisfiedBy(_localEpisode, downloadClientItem), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -184,7 +186,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||||
var expectedQuality = QualityParser.ParseQuality(_videoFiles.Single());
|
var expectedQuality = QualityParser.ParseQuality(_videoFiles.Single());
|
||||||
|
|
||||||
var result = Subject.GetImportDecisions(_videoFiles, _series, new ParsedEpisodeInfo{Quality = new QualityModel(Quality.SDTV)}, true);
|
var result = Subject.GetImportDecisions(_videoFiles, _series, null, new ParsedEpisodeInfo{Quality = new QualityModel(Quality.SDTV)}, true);
|
||||||
|
|
||||||
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
||||||
}
|
}
|
||||||
@@ -201,7 +203,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
|
|
||||||
var expectedQuality = new QualityModel(Quality.SDTV);
|
var expectedQuality = new QualityModel(Quality.SDTV);
|
||||||
|
|
||||||
var result = Subject.GetImportDecisions(_videoFiles, _series, new ParsedEpisodeInfo { Quality = expectedQuality }, true);
|
var result = Subject.GetImportDecisions(_videoFiles, _series, null, new ParsedEpisodeInfo { Quality = expectedQuality }, true);
|
||||||
|
|
||||||
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
||||||
}
|
}
|
||||||
@@ -217,7 +219,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
|
|
||||||
var expectedQuality = new QualityModel(Quality.Bluray720p);
|
var expectedQuality = new QualityModel(Quality.Bluray720p);
|
||||||
|
|
||||||
var result = Subject.GetImportDecisions(_videoFiles, _series, new ParsedEpisodeInfo { Quality = expectedQuality }, true);
|
var result = Subject.GetImportDecisions(_videoFiles, _series, null, new ParsedEpisodeInfo { Quality = expectedQuality }, true);
|
||||||
|
|
||||||
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
||||||
}
|
}
|
||||||
@@ -264,7 +266,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
|
|
||||||
var folderInfo = Parser.Parser.ParseTitle("Series.Title.S01");
|
var folderInfo = Parser.Parser.ParseTitle("Series.Title.S01");
|
||||||
|
|
||||||
Subject.GetImportDecisions(_videoFiles, _series, folderInfo, true);
|
Subject.GetImportDecisions(_videoFiles, _series, null, folderInfo, true);
|
||||||
|
|
||||||
Mocker.GetMock<IParsingService>()
|
Mocker.GetMock<IParsingService>()
|
||||||
.Verify(c => c.GetLocalEpisode(It.IsAny<string>(), It.IsAny<Series>(), null, true), Times.Exactly(3));
|
.Verify(c => c.GetLocalEpisode(It.IsAny<string>(), It.IsAny<Series>(), null, true), Times.Exactly(3));
|
||||||
@@ -287,7 +289,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
|
|
||||||
var folderInfo = Parser.Parser.ParseTitle("Series.Title.S01E01");
|
var folderInfo = Parser.Parser.ParseTitle("Series.Title.S01E01");
|
||||||
|
|
||||||
Subject.GetImportDecisions(_videoFiles, _series, folderInfo, true);
|
Subject.GetImportDecisions(_videoFiles, _series, null, folderInfo, true);
|
||||||
|
|
||||||
Mocker.GetMock<IParsingService>()
|
Mocker.GetMock<IParsingService>()
|
||||||
.Verify(c => c.GetLocalEpisode(It.IsAny<string>(), It.IsAny<Series>(), null, true), Times.Exactly(2));
|
.Verify(c => c.GetLocalEpisode(It.IsAny<string>(), It.IsAny<Series>(), null, true), Times.Exactly(2));
|
||||||
@@ -309,7 +311,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
|
|
||||||
var folderInfo = Parser.Parser.ParseTitle("Series.Title.S01E01");
|
var folderInfo = Parser.Parser.ParseTitle("Series.Title.S01E01");
|
||||||
|
|
||||||
Subject.GetImportDecisions(_videoFiles, _series, folderInfo, true);
|
Subject.GetImportDecisions(_videoFiles, _series, null, folderInfo, true);
|
||||||
|
|
||||||
Mocker.GetMock<IParsingService>()
|
Mocker.GetMock<IParsingService>()
|
||||||
.Verify(c => c.GetLocalEpisode(It.IsAny<string>(), It.IsAny<Series>(), It.IsAny<ParsedEpisodeInfo>(), true), Times.Exactly(1));
|
.Verify(c => c.GetLocalEpisode(It.IsAny<string>(), It.IsAny<Series>(), It.IsAny<ParsedEpisodeInfo>(), true), Times.Exactly(1));
|
||||||
@@ -336,7 +338,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
|
|
||||||
var folderInfo = Parser.Parser.ParseTitle("Series.Title.S01E01");
|
var folderInfo = Parser.Parser.ParseTitle("Series.Title.S01E01");
|
||||||
|
|
||||||
Subject.GetImportDecisions(_videoFiles, _series, folderInfo, true);
|
Subject.GetImportDecisions(_videoFiles, _series, null, folderInfo, true);
|
||||||
|
|
||||||
Mocker.GetMock<IParsingService>()
|
Mocker.GetMock<IParsingService>()
|
||||||
.Verify(c => c.GetLocalEpisode(It.IsAny<string>(), It.IsAny<Series>(), It.IsAny<ParsedEpisodeInfo>(), true), Times.Exactly(2));
|
.Verify(c => c.GetLocalEpisode(It.IsAny<string>(), It.IsAny<Series>(), It.IsAny<ParsedEpisodeInfo>(), true), Times.Exactly(2));
|
||||||
@@ -358,7 +360,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
|
|
||||||
var folderInfo = Parser.Parser.ParseTitle("Series.Title.S01E01.720p.HDTV-LOL");
|
var folderInfo = Parser.Parser.ParseTitle("Series.Title.S01E01.720p.HDTV-LOL");
|
||||||
|
|
||||||
Subject.GetImportDecisions(_videoFiles, _series, folderInfo, true);
|
Subject.GetImportDecisions(_videoFiles, _series, null, folderInfo, true);
|
||||||
|
|
||||||
Mocker.GetMock<IParsingService>()
|
Mocker.GetMock<IParsingService>()
|
||||||
.Verify(c => c.GetLocalEpisode(It.IsAny<string>(), It.IsAny<Series>(), null, true), Times.Exactly(1));
|
.Verify(c => c.GetLocalEpisode(It.IsAny<string>(), It.IsAny<Series>(), null, true), Times.Exactly(1));
|
||||||
@@ -380,7 +382,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
|
|
||||||
var folderQuality = new QualityModel(Quality.Unknown);
|
var folderQuality = new QualityModel(Quality.Unknown);
|
||||||
|
|
||||||
var result = Subject.GetImportDecisions(_videoFiles, _series, new ParsedEpisodeInfo { Quality = folderQuality}, true);
|
var result = Subject.GetImportDecisions(_videoFiles, _series, null, new ParsedEpisodeInfo { Quality = folderQuality}, true);
|
||||||
|
|
||||||
result.Single().LocalEpisode.Quality.Should().Be(_quality);
|
result.Single().LocalEpisode.Quality.Should().Be(_quality);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,6 +121,24 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
|||||||
ShouldBeFalse();
|
ShouldBeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_runtime_greater_than_anime_short_minimum()
|
||||||
|
{
|
||||||
|
_series.Runtime = 2;
|
||||||
|
GivenRuntime(60);
|
||||||
|
|
||||||
|
ShouldBeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_runtime_less_than_anime_short_minimum()
|
||||||
|
{
|
||||||
|
_series.Runtime = 2;
|
||||||
|
GivenRuntime(10);
|
||||||
|
|
||||||
|
ShouldBeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_fall_back_to_file_size_if_mediainfo_dll_not_found_acceptable_size()
|
public void should_fall_back_to_file_size_if_mediainfo_dll_not_found_acceptable_size()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
GivenFileSize(100.Megabytes());
|
GivenFileSize(100.Megabytes());
|
||||||
GivenFreeSpace(80.Megabytes());
|
GivenFreeSpace(80.Megabytes());
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
ExceptionVerification.ExpectedWarns(1);
|
ExceptionVerification.ExpectedWarns(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
GivenFileSize(100.Megabytes());
|
GivenFileSize(100.Megabytes());
|
||||||
GivenFreeSpace(150.Megabytes());
|
GivenFreeSpace(150.Megabytes());
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
ExceptionVerification.ExpectedWarns(1);
|
ExceptionVerification.ExpectedWarns(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
GivenFileSize(100.Megabytes());
|
GivenFileSize(100.Megabytes());
|
||||||
GivenFreeSpace(1.Gigabytes());
|
GivenFreeSpace(1.Gigabytes());
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -92,7 +92,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
GivenFileSize(100.Megabytes());
|
GivenFileSize(100.Megabytes());
|
||||||
GivenFreeSpace(1.Gigabytes());
|
GivenFreeSpace(1.Gigabytes());
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>()
|
Mocker.GetMock<IDiskProvider>()
|
||||||
.Verify(v => v.GetAvailableSpace(_rootFolder), Times.Once());
|
.Verify(v => v.GetAvailableSpace(_rootFolder), Times.Once());
|
||||||
@@ -104,7 +104,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
GivenFileSize(100.Megabytes());
|
GivenFileSize(100.Megabytes());
|
||||||
GivenFreeSpace(null);
|
GivenFreeSpace(null);
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -116,7 +116,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
.Setup(s => s.GetAvailableSpace(It.IsAny<string>()))
|
.Setup(s => s.GetAvailableSpace(It.IsAny<string>()))
|
||||||
.Throws(new TestException());
|
.Throws(new TestException());
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
ExceptionVerification.ExpectedErrors(1);
|
ExceptionVerification.ExpectedErrors(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
{
|
{
|
||||||
_localEpisode.ExistingFile = true;
|
_localEpisode.ExistingFile = true;
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>()
|
Mocker.GetMock<IDiskProvider>()
|
||||||
.Verify(s => s.GetAvailableSpace(It.IsAny<string>()), Times.Never());
|
.Verify(s => s.GetAvailableSpace(It.IsAny<string>()), Times.Never());
|
||||||
@@ -140,7 +140,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
.Setup(s => s.GetAvailableSpace(It.IsAny<string>()))
|
.Setup(s => s.GetAvailableSpace(It.IsAny<string>()))
|
||||||
.Returns(freeSpace);
|
.Returns(freeSpace);
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -150,7 +150,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
.Setup(s => s.SkipFreeSpaceCheckWhenImporting)
|
.Setup(s => s.SkipFreeSpaceCheckWhenImporting)
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
{
|
{
|
||||||
_localEpisode.ParsedEpisodeInfo.FullSeason = true;
|
_localEpisode.ParsedEpisodeInfo.FullSeason = true;
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_true_when_file_does_not_contain_the_full_season()
|
public void should_return_true_when_file_does_not_contain_the_full_season()
|
||||||
{
|
{
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.History;
|
||||||
|
using NzbDrone.Core.MediaFiles.EpisodeImport.Specifications;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class GrabbedReleaseQualityFixture : CoreTest<GrabbedReleaseQualitySpecification>
|
||||||
|
{
|
||||||
|
private LocalEpisode _localEpisode;
|
||||||
|
private DownloadClientItem _downloadClientItem;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_localEpisode = Builder<LocalEpisode>.CreateNew()
|
||||||
|
.With(l => l.Quality = new QualityModel(Quality.Bluray720p))
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
_downloadClientItem = Builder<DownloadClientItem>.CreateNew()
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenHistory(List<History.History> history)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IHistoryService>()
|
||||||
|
.Setup(s => s.FindByDownloadId(It.IsAny<string>()))
|
||||||
|
.Returns(history);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_accepted_when_downloadClientItem_is_null()
|
||||||
|
{
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_accepted_if_no_history_for_downloadId()
|
||||||
|
{
|
||||||
|
GivenHistory(new List<History.History>());
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_accepted_if_no_grabbed_history_for_downloadId()
|
||||||
|
{
|
||||||
|
var history = Builder<History.History>.CreateListOfSize(1)
|
||||||
|
.All()
|
||||||
|
.With(h => h.EventType = HistoryEventType.Unknown)
|
||||||
|
.BuildList();
|
||||||
|
|
||||||
|
GivenHistory(history);
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_accepted_if_grabbed_history_quality_matches()
|
||||||
|
{
|
||||||
|
var history = Builder<History.History>.CreateListOfSize(1)
|
||||||
|
.All()
|
||||||
|
.With(h => h.EventType = HistoryEventType.Grabbed)
|
||||||
|
.With(h => h.Quality = _localEpisode.Quality)
|
||||||
|
.BuildList();
|
||||||
|
|
||||||
|
GivenHistory(history);
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_rejected_if_grabbed_history_quality_does_not_match()
|
||||||
|
{
|
||||||
|
var history = Builder<History.History>.CreateListOfSize(1)
|
||||||
|
.All()
|
||||||
|
.With(h => h.EventType = HistoryEventType.Grabbed)
|
||||||
|
.With(h => h.Quality = new QualityModel(Quality.HDTV720p))
|
||||||
|
.BuildList();
|
||||||
|
|
||||||
|
GivenHistory(history);
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,7 +31,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
{
|
{
|
||||||
_localEpisode.ExistingFile = true;
|
_localEpisode.ExistingFile = true;
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -39,7 +39,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
{
|
{
|
||||||
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title\S01E01.mkv".AsOsAgnostic();
|
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title\S01E01.mkv".AsOsAgnostic();
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -47,7 +47,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
{
|
{
|
||||||
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title.S01\S01E01.mkv".AsOsAgnostic();
|
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title.S01\S01E01.mkv".AsOsAgnostic();
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -55,7 +55,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
{
|
{
|
||||||
_localEpisode.ParsedEpisodeInfo.EpisodeNumbers = new[] { 1 };
|
_localEpisode.ParsedEpisodeInfo.EpisodeNumbers = new[] { 1 };
|
||||||
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title.S01E01.720p.HDTV-Sonarr\S01E01.mkv".AsOsAgnostic();
|
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title.S01E01.720p.HDTV-Sonarr\S01E01.mkv".AsOsAgnostic();
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -63,14 +63,14 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
{
|
{
|
||||||
_localEpisode.ParsedEpisodeInfo.EpisodeNumbers = new[] { 1 };
|
_localEpisode.ParsedEpisodeInfo.EpisodeNumbers = new[] { 1 };
|
||||||
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title.S01E01E02.720p.HDTV-Sonarr\S01E01.mkv".AsOsAgnostic();
|
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title.S01E01E02.720p.HDTV-Sonarr\S01E01.mkv".AsOsAgnostic();
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_be_rejected_if_file_and_folder_do_not_have_same_episode()
|
public void should_be_rejected_if_file_and_folder_do_not_have_same_episode()
|
||||||
{
|
{
|
||||||
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title.S01E01.720p.HDTV-Sonarr\S01E05.mkv".AsOsAgnostic();
|
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title.S01E01.720p.HDTV-Sonarr\S01E05.mkv".AsOsAgnostic();
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -78,7 +78,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
{
|
{
|
||||||
_localEpisode.ParsedEpisodeInfo.EpisodeNumbers = new[] { 5, 6 };
|
_localEpisode.ParsedEpisodeInfo.EpisodeNumbers = new[] { 5, 6 };
|
||||||
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title.S01E01E02.720p.HDTV-Sonarr\S01E05E06.mkv".AsOsAgnostic();
|
_localEpisode.Path = @"C:\Test\Unsorted\Series.Title.S01E01E02.720p.HDTV-Sonarr\S01E05E06.mkv".AsOsAgnostic();
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
public void should_return_true_for_existing_file()
|
public void should_return_true_for_existing_file()
|
||||||
{
|
{
|
||||||
_localEpisode.ExistingFile = true;
|
_localEpisode.ExistingFile = true;
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
[Test]
|
[Test]
|
||||||
public void should_return_true_if_not_in_working_folder()
|
public void should_return_true_if_not_in_working_folder()
|
||||||
{
|
{
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -59,7 +59,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
GivenInWorkingFolder();
|
GivenInWorkingFolder();
|
||||||
GivenLastWriteTimeUtc(DateTime.UtcNow.AddHours(-1));
|
GivenLastWriteTimeUtc(DateTime.UtcNow.AddHours(-1));
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -68,7 +68,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
GivenInWorkingFolder();
|
GivenInWorkingFolder();
|
||||||
GivenLastWriteTimeUtc(DateTime.UtcNow);
|
GivenLastWriteTimeUtc(DateTime.UtcNow);
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -79,7 +79,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
GivenInWorkingFolder();
|
GivenInWorkingFolder();
|
||||||
GivenLastWriteTimeUtc(DateTime.UtcNow.AddDays(-5));
|
GivenLastWriteTimeUtc(DateTime.UtcNow.AddDays(-5));
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Marr.Data;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.MediaFiles.EpisodeImport.Specifications;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class SameFileSpecificationFixture : CoreTest<SameFileSpecification>
|
||||||
|
{
|
||||||
|
private LocalEpisode _localEpisode;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_localEpisode = Builder<LocalEpisode>.CreateNew()
|
||||||
|
.With(l => l.Size = 150.Megabytes())
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_accepted_if_no_existing_file()
|
||||||
|
{
|
||||||
|
_localEpisode.Episodes = Builder<Episode>.CreateListOfSize(1)
|
||||||
|
.TheFirst(1)
|
||||||
|
.With(e => e.EpisodeFileId = 0)
|
||||||
|
.BuildList();
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_accepted_if_multiple_existing_files()
|
||||||
|
{
|
||||||
|
_localEpisode.Episodes = Builder<Episode>.CreateListOfSize(2)
|
||||||
|
.TheFirst(1)
|
||||||
|
.With(e => e.EpisodeFileId = 1)
|
||||||
|
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(
|
||||||
|
new EpisodeFile
|
||||||
|
{
|
||||||
|
Size = _localEpisode.Size
|
||||||
|
}))
|
||||||
|
.TheNext(1)
|
||||||
|
.With(e => e.EpisodeFileId = 2)
|
||||||
|
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(
|
||||||
|
new EpisodeFile
|
||||||
|
{
|
||||||
|
Size = _localEpisode.Size
|
||||||
|
}))
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_accepted_if_file_size_is_different()
|
||||||
|
{
|
||||||
|
_localEpisode.Episodes = Builder<Episode>.CreateListOfSize(1)
|
||||||
|
.TheFirst(1)
|
||||||
|
.With(e => e.EpisodeFileId = 1)
|
||||||
|
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(
|
||||||
|
new EpisodeFile
|
||||||
|
{
|
||||||
|
Size = _localEpisode.Size + 100.Megabytes()
|
||||||
|
}))
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_reject_if_file_size_is_the_same()
|
||||||
|
{
|
||||||
|
_localEpisode.Episodes = Builder<Episode>.CreateListOfSize(1)
|
||||||
|
.TheFirst(1)
|
||||||
|
.With(e => e.EpisodeFileId = 1)
|
||||||
|
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(
|
||||||
|
new EpisodeFile
|
||||||
|
{
|
||||||
|
Size = _localEpisode.Size
|
||||||
|
}))
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,7 +45,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
.Build()
|
.Build()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -58,7 +58,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
.Build()
|
.Build()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -75,7 +75,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
.Build()
|
.Build()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -92,7 +92,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
.Build()
|
.Build()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -109,7 +109,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
.Build()
|
.Build()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -126,7 +126,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
.Build()
|
.Build()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -150,7 +150,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||||||
.Build()
|
.Build()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_localEpisode).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,121 +1,211 @@
|
|||||||
//using System;
|
using System;
|
||||||
//using System.Collections.Generic;
|
using System.Collections.Concurrent;
|
||||||
//using Moq;
|
using System.Collections.Generic;
|
||||||
//using NUnit.Framework;
|
using System.Threading;
|
||||||
//using NzbDrone.Common;
|
using Moq;
|
||||||
//using NzbDrone.Core.Messaging.Commands;
|
using NUnit.Framework;
|
||||||
//using NzbDrone.Core.Messaging.Commands.Tracking;
|
using NzbDrone.Common;
|
||||||
//using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Lifecycle;
|
||||||
//using NzbDrone.Test.Common;
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
//
|
using NzbDrone.Core.Messaging.Events;
|
||||||
//namespace NzbDrone.Core.Test.Messaging.Commands
|
using NzbDrone.Test.Common;
|
||||||
//{
|
|
||||||
// [TestFixture]
|
namespace NzbDrone.Core.Test.Messaging.Commands
|
||||||
// public class CommandExecutorFixture : TestBase<CommandExecutor>
|
{
|
||||||
// {
|
[TestFixture]
|
||||||
// private Mock<IExecute<CommandA>> _executorA;
|
public class CommandExecutorFixture : TestBase<CommandExecutor>
|
||||||
// private Mock<IExecute<CommandB>> _executorB;
|
{
|
||||||
//
|
private BlockingCollection<CommandModel> _commandQueue;
|
||||||
// [SetUp]
|
private Mock<IExecute<CommandA>> _executorA;
|
||||||
// public void Setup()
|
private Mock<IExecute<CommandB>> _executorB;
|
||||||
// {
|
private bool _commandExecuted = false;
|
||||||
// _executorA = new Mock<IExecute<CommandA>>();
|
|
||||||
// _executorB = new Mock<IExecute<CommandB>>();
|
[SetUp]
|
||||||
//
|
public void Setup()
|
||||||
// Mocker.GetMock<IServiceFactory>()
|
{
|
||||||
// .Setup(c => c.Build(typeof(IExecute<CommandA>)))
|
_executorA = new Mock<IExecute<CommandA>>();
|
||||||
// .Returns(_executorA.Object);
|
_executorB = new Mock<IExecute<CommandB>>();
|
||||||
//
|
|
||||||
// Mocker.GetMock<IServiceFactory>()
|
Mocker.GetMock<IServiceFactory>()
|
||||||
// .Setup(c => c.Build(typeof(IExecute<CommandB>)))
|
.Setup(c => c.Build(typeof(IExecute<CommandA>)))
|
||||||
// .Returns(_executorB.Object);
|
.Returns(_executorA.Object);
|
||||||
//
|
|
||||||
//
|
Mocker.GetMock<IServiceFactory>()
|
||||||
// Mocker.GetMock<ITrackCommands>()
|
.Setup(c => c.Build(typeof(IExecute<CommandB>)))
|
||||||
// .Setup(c => c.FindExisting(It.IsAny<Command>()))
|
.Returns(_executorB.Object);
|
||||||
// .Returns<Command>(null);
|
}
|
||||||
// }
|
|
||||||
//
|
private void GivenCommandQueue()
|
||||||
// [Test]
|
{
|
||||||
// public void should_publish_command_to_executor()
|
_commandQueue = new BlockingCollection<CommandModel>(new CommandQueue());
|
||||||
// {
|
|
||||||
// var commandA = new CommandA();
|
Mocker.GetMock<IManageCommandQueue>()
|
||||||
//
|
.Setup(s => s.Queue(It.IsAny<CancellationToken>()))
|
||||||
// Subject.Push(commandA);
|
.Returns(_commandQueue.GetConsumingEnumerable);
|
||||||
//
|
}
|
||||||
// _executorA.Verify(c => c.Execute(commandA), Times.Once());
|
|
||||||
// }
|
private void WaitForExecution(CommandModel commandModel)
|
||||||
//
|
{
|
||||||
// [Test]
|
Mocker.GetMock<IManageCommandQueue>()
|
||||||
// public void should_publish_command_by_with_optional_arg_using_name()
|
.Setup(s => s.Complete(It.Is<CommandModel>(c => c == commandModel), It.IsAny<string>()))
|
||||||
// {
|
.Callback(() => _commandExecuted = true);
|
||||||
// Mocker.GetMock<IServiceFactory>().Setup(c => c.GetImplementations(typeof(Command)))
|
|
||||||
// .Returns(new List<Type> { typeof(CommandA), typeof(CommandB) });
|
Mocker.GetMock<IManageCommandQueue>()
|
||||||
//
|
.Setup(s => s.Fail(It.Is<CommandModel>(c => c == commandModel), It.IsAny<string>(), It.IsAny<Exception>()))
|
||||||
// Subject.Push(typeof(CommandA).FullName);
|
.Callback(() => _commandExecuted = true);
|
||||||
// _executorA.Verify(c => c.Execute(It.IsAny<CommandA>()), Times.Once());
|
|
||||||
// }
|
while (!_commandExecuted)
|
||||||
//
|
{
|
||||||
//
|
Thread.Sleep(100);
|
||||||
// [Test]
|
}
|
||||||
// public void should_not_publish_to_incompatible_executor()
|
|
||||||
// {
|
var t1 = 1;
|
||||||
// var commandA = new CommandA();
|
}
|
||||||
//
|
|
||||||
// Subject.Push(commandA);
|
[Test]
|
||||||
//
|
public void should_start_executor_threads()
|
||||||
// _executorA.Verify(c => c.Execute(commandA), Times.Once());
|
{
|
||||||
// _executorB.Verify(c => c.Execute(It.IsAny<CommandB>()), Times.Never());
|
Subject.Handle(new ApplicationStartedEvent());
|
||||||
// }
|
|
||||||
//
|
Mocker.GetMock<IManageCommandQueue>()
|
||||||
// [Test]
|
.Verify(v => v.Queue(It.IsAny<CancellationToken>()), Times.AtLeastOnce());
|
||||||
// public void broken_executor_should_throw_the_exception()
|
}
|
||||||
// {
|
|
||||||
// var commandA = new CommandA();
|
[Test]
|
||||||
//
|
public void should_execute_on_executor()
|
||||||
// _executorA.Setup(c => c.Execute(It.IsAny<CommandA>()))
|
{
|
||||||
// .Throws(new NotImplementedException());
|
GivenCommandQueue();
|
||||||
//
|
var commandA = new CommandA();
|
||||||
// Assert.Throws<NotImplementedException>(() => Subject.Push(commandA));
|
var commandModel = new CommandModel
|
||||||
// }
|
{
|
||||||
//
|
Body = commandA
|
||||||
//
|
};
|
||||||
// [Test]
|
|
||||||
// public void broken_executor_should_publish_executed_event()
|
Subject.Handle(new ApplicationStartedEvent());
|
||||||
// {
|
_commandQueue.Add(commandModel);
|
||||||
// var commandA = new CommandA();
|
|
||||||
//
|
WaitForExecution(commandModel);
|
||||||
// _executorA.Setup(c => c.Execute(It.IsAny<CommandA>()))
|
|
||||||
// .Throws(new NotImplementedException());
|
_executorA.Verify(c => c.Execute(commandA), Times.Once());
|
||||||
//
|
}
|
||||||
// Assert.Throws<NotImplementedException>(() => Subject.Push(commandA));
|
|
||||||
//
|
[Test]
|
||||||
// VerifyEventPublished<CommandExecutedEvent>();
|
public void should_not_execute_on_incompatible_executor()
|
||||||
// }
|
{
|
||||||
//
|
GivenCommandQueue();
|
||||||
// [Test]
|
var commandA = new CommandA();
|
||||||
// public void should_publish_executed_event_on_success()
|
var commandModel = new CommandModel
|
||||||
// {
|
{
|
||||||
// var commandA = new CommandA();
|
Body = commandA
|
||||||
// Subject.Push(commandA);
|
};
|
||||||
//
|
|
||||||
// VerifyEventPublished<CommandExecutedEvent>();
|
Subject.Handle(new ApplicationStartedEvent());
|
||||||
// }
|
_commandQueue.Add(commandModel);
|
||||||
// }
|
|
||||||
//
|
WaitForExecution(commandModel);
|
||||||
// public class CommandA : Command
|
|
||||||
// {
|
_executorA.Verify(c => c.Execute(commandA), Times.Once());
|
||||||
// public CommandA(int id = 0)
|
_executorB.Verify(c => c.Execute(It.IsAny<CommandB>()), Times.Never());
|
||||||
// {
|
}
|
||||||
// }
|
|
||||||
// }
|
[Test]
|
||||||
//
|
public void broken_executor_should_publish_executed_event()
|
||||||
// public class CommandB : Command
|
{
|
||||||
// {
|
GivenCommandQueue();
|
||||||
//
|
var commandA = new CommandA();
|
||||||
// public CommandB()
|
var commandModel = new CommandModel
|
||||||
// {
|
{
|
||||||
// }
|
Body = commandA
|
||||||
// }
|
};
|
||||||
//
|
|
||||||
//}
|
_executorA.Setup(s => s.Execute(It.IsAny<CommandA>()))
|
||||||
|
.Throws(new NotImplementedException());
|
||||||
|
|
||||||
|
Subject.Handle(new ApplicationStartedEvent());
|
||||||
|
_commandQueue.Add(commandModel);
|
||||||
|
|
||||||
|
WaitForExecution(commandModel);
|
||||||
|
|
||||||
|
VerifyEventPublished<CommandExecutedEvent>();
|
||||||
|
ExceptionVerification.ExpectedErrors(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_publish_executed_event_on_success()
|
||||||
|
{
|
||||||
|
GivenCommandQueue();
|
||||||
|
var commandA = new CommandA();
|
||||||
|
var commandModel = new CommandModel
|
||||||
|
{
|
||||||
|
Body = commandA
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.Handle(new ApplicationStartedEvent());
|
||||||
|
_commandQueue.Add(commandModel);
|
||||||
|
|
||||||
|
WaitForExecution(commandModel);
|
||||||
|
|
||||||
|
VerifyEventPublished<CommandExecutedEvent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_use_completion_message()
|
||||||
|
{
|
||||||
|
GivenCommandQueue();
|
||||||
|
var commandA = new CommandA();
|
||||||
|
var commandModel = new CommandModel
|
||||||
|
{
|
||||||
|
Body = commandA
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.Handle(new ApplicationStartedEvent());
|
||||||
|
_commandQueue.Add(commandModel);
|
||||||
|
|
||||||
|
WaitForExecution(commandModel);
|
||||||
|
|
||||||
|
Mocker.GetMock<IManageCommandQueue>()
|
||||||
|
.Setup(s => s.Complete(It.Is<CommandModel>(c => c == commandModel), commandA.CompletionMessage))
|
||||||
|
.Callback(() => _commandExecuted = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_use_last_progress_message_if_completion_message_is_null()
|
||||||
|
{
|
||||||
|
GivenCommandQueue();
|
||||||
|
var commandA = new CommandA();
|
||||||
|
var commandModel = new CommandModel
|
||||||
|
{
|
||||||
|
Body = commandA,
|
||||||
|
Message = "Do work"
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.Handle(new ApplicationStartedEvent());
|
||||||
|
_commandQueue.Add(commandModel);
|
||||||
|
|
||||||
|
WaitForExecution(commandModel);
|
||||||
|
|
||||||
|
Mocker.GetMock<IManageCommandQueue>()
|
||||||
|
.Setup(s => s.Complete(It.Is<CommandModel>(c => c == commandModel), commandModel.Message))
|
||||||
|
.Callback(() => _commandExecuted = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommandA : Command
|
||||||
|
{
|
||||||
|
public CommandA(int id = 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommandB : Command
|
||||||
|
{
|
||||||
|
|
||||||
|
public CommandB()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string CompletionMessage => null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -159,6 +159,7 @@
|
|||||||
<Compile Include="DecisionEngineTests\MinimumAgeSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\MinimumAgeSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\RetentionSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\RetentionSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\RssSync\DelaySpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\RssSync\DelaySpecificationFixture.cs" />
|
||||||
|
<Compile Include="DecisionEngineTests\RssSync\DeletedEpisodeFileSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\RssSync\ProperSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\RssSync\ProperSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\Search\SeriesSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\Search\SeriesSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\SameEpisodesSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\SameEpisodesSpecificationFixture.cs" />
|
||||||
@@ -282,6 +283,8 @@
|
|||||||
<Compile Include="MediaFiles\EpisodeImport\SampleServiceFixture.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\SampleServiceFixture.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FreeSpaceSpecificationFixture.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\FreeSpaceSpecificationFixture.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FullSeasonSpecificationFixture.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\FullSeasonSpecificationFixture.cs" />
|
||||||
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\SameFileSpecificationFixture.cs" />
|
||||||
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\GrabbedReleaseQualityFixture.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\MatchesFolderSpecificationFixture.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\MatchesFolderSpecificationFixture.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotSampleSpecificationFixture.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotSampleSpecificationFixture.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotUnpackingSpecificationFixture.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotUnpackingSpecificationFixture.cs" />
|
||||||
@@ -383,6 +386,7 @@
|
|||||||
<Compile Include="TvTests\SeriesServiceTests\UpdateMultipleSeriesFixture.cs" />
|
<Compile Include="TvTests\SeriesServiceTests\UpdateMultipleSeriesFixture.cs" />
|
||||||
<Compile Include="TvTests\SeriesServiceTests\UpdateSeriesFixture.cs" />
|
<Compile Include="TvTests\SeriesServiceTests\UpdateSeriesFixture.cs" />
|
||||||
<Compile Include="TvTests\SeriesTitleNormalizerFixture.cs" />
|
<Compile Include="TvTests\SeriesTitleNormalizerFixture.cs" />
|
||||||
|
<Compile Include="TvTests\SeriesTitleSlugValidatorFixture.cs" />
|
||||||
<Compile Include="TvTests\ShouldRefreshSeriesFixture.cs" />
|
<Compile Include="TvTests\ShouldRefreshSeriesFixture.cs" />
|
||||||
<Compile Include="UpdateTests\UpdatePackageProviderFixture.cs" />
|
<Compile Include="UpdateTests\UpdatePackageProviderFixture.cs" />
|
||||||
<Compile Include="UpdateTests\UpdateServiceFixture.cs" />
|
<Compile Include="UpdateTests\UpdateServiceFixture.cs" />
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
GivenAbsoluteNumberingSeries();
|
GivenAbsoluteNumberingSeries();
|
||||||
|
|
||||||
_parsedEpisodeInfo.Special = true;
|
_parsedEpisodeInfo.Special = true;
|
||||||
|
|
||||||
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
|
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>()
|
Mocker.GetMock<IEpisodeService>()
|
||||||
@@ -210,7 +210,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
GivenAbsoluteNumberingSeries();
|
GivenAbsoluteNumberingSeries();
|
||||||
|
|
||||||
Mocker.GetMock<ISceneMappingService>()
|
Mocker.GetMock<ISceneMappingService>()
|
||||||
.Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle))
|
.Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
|
||||||
.Returns(seasonNumber);
|
.Returns(seasonNumber);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>()
|
Mocker.GetMock<IEpisodeService>()
|
||||||
@@ -234,7 +234,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
GivenAbsoluteNumberingSeries();
|
GivenAbsoluteNumberingSeries();
|
||||||
|
|
||||||
Mocker.GetMock<ISceneMappingService>()
|
Mocker.GetMock<ISceneMappingService>()
|
||||||
.Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle))
|
.Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
|
||||||
.Returns(seasonNumber);
|
.Returns(seasonNumber);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>()
|
Mocker.GetMock<IEpisodeService>()
|
||||||
@@ -258,7 +258,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
GivenAbsoluteNumberingSeries();
|
GivenAbsoluteNumberingSeries();
|
||||||
|
|
||||||
Mocker.GetMock<ISceneMappingService>()
|
Mocker.GetMock<ISceneMappingService>()
|
||||||
.Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle))
|
.Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
|
||||||
.Returns(seasonNumber);
|
.Returns(seasonNumber);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>()
|
Mocker.GetMock<IEpisodeService>()
|
||||||
@@ -280,7 +280,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
const int tvdbSeasonNumber = 5;
|
const int tvdbSeasonNumber = 5;
|
||||||
|
|
||||||
Mocker.GetMock<ISceneMappingService>()
|
Mocker.GetMock<ISceneMappingService>()
|
||||||
.Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle))
|
.Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
|
||||||
.Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber });
|
.Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber });
|
||||||
|
|
||||||
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
|
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
|
||||||
@@ -298,7 +298,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
const int tvdbSeasonNumber = 5;
|
const int tvdbSeasonNumber = 5;
|
||||||
|
|
||||||
Mocker.GetMock<ISceneMappingService>()
|
Mocker.GetMock<ISceneMappingService>()
|
||||||
.Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle))
|
.Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
|
||||||
.Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber + 100 });
|
.Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber + 100 });
|
||||||
|
|
||||||
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
|
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
|
||||||
@@ -330,7 +330,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
const int tvdbSeasonNumber = -1;
|
const int tvdbSeasonNumber = -1;
|
||||||
|
|
||||||
Mocker.GetMock<ISceneMappingService>()
|
Mocker.GetMock<ISceneMappingService>()
|
||||||
.Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle))
|
.Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
|
||||||
.Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber });
|
.Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber });
|
||||||
|
|
||||||
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
|
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
GivenMatchByTvRageId();
|
GivenMatchByTvRageId();
|
||||||
|
|
||||||
Mocker.GetMock<ISceneMappingService>()
|
Mocker.GetMock<ISceneMappingService>()
|
||||||
.Setup(v => v.FindTvdbId(It.IsAny<string>()))
|
.Setup(v => v.FindTvdbId(It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Returns(10);
|
.Returns(10);
|
||||||
|
|
||||||
var result = Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
var result = Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||||
@@ -199,7 +199,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
public void should_use_tvdbid_matching_when_alias_is_found()
|
public void should_use_tvdbid_matching_when_alias_is_found()
|
||||||
{
|
{
|
||||||
Mocker.GetMock<ISceneMappingService>()
|
Mocker.GetMock<ISceneMappingService>()
|
||||||
.Setup(s => s.FindTvdbId(It.IsAny<string>()))
|
.Setup(s => s.FindTvdbId(It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Returns(_series.TvdbId);
|
.Returns(_series.TvdbId);
|
||||||
|
|
||||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||||||
[TestCase("Lost.S04E04.720p.BluRay.x264-xHD-1", "xHD")]
|
[TestCase("Lost.S04E04.720p.BluRay.x264-xHD-1", "xHD")]
|
||||||
[TestCase("Blue.Bloods.S05E11.720p.HDTV.X264-DIMENSION-1", "DIMENSION")]
|
[TestCase("Blue.Bloods.S05E11.720p.HDTV.X264-DIMENSION-1", "DIMENSION")]
|
||||||
[TestCase("saturday.night.live.s40e11.kevin.hart_sia.720p.hdtv.x264-w4f-sample.mkv", "w4f")]
|
[TestCase("saturday.night.live.s40e11.kevin.hart_sia.720p.hdtv.x264-w4f-sample.mkv", "w4f")]
|
||||||
|
[TestCase("The.Sequel.2017.S05E02.1080p.WEB-DL.DD5.1.H264-EVL-Scrambled", "EVL")]
|
||||||
public void should_not_include_repost_in_release_group(string title, string expected)
|
public void should_not_include_repost_in_release_group(string title, string expected)
|
||||||
{
|
{
|
||||||
Parser.Parser.ParseReleaseGroup(title).Should().Be(expected);
|
Parser.Parser.ParseReleaseGroup(title).Should().Be(expected);
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||||||
[TestCase("Jeopardy - S2016E231", "Jeopardy", 2016, 231)]
|
[TestCase("Jeopardy - S2016E231", "Jeopardy", 2016, 231)]
|
||||||
[TestCase("Jeopardy - 2016x231", "Jeopardy", 2016, 231)]
|
[TestCase("Jeopardy - 2016x231", "Jeopardy", 2016, 231)]
|
||||||
[TestCase("Shortland.Street.S26E022.HDTV.x264-FiHTV", "Shortland Street", 26, 22)]
|
[TestCase("Shortland.Street.S26E022.HDTV.x264-FiHTV", "Shortland Street", 26, 22)]
|
||||||
|
[TestCase("Super.Potatoes.S01.Ep06.1080p.BluRay.DTS.x264-MiR", "Super Potatoes", 1, 6)]
|
||||||
//[TestCase("", "", 0, 0)]
|
//[TestCase("", "", 0, 0)]
|
||||||
public void should_parse_single_episode(string postTitle, string title, int seasonNumber, int episodeNumber)
|
public void should_parse_single_episode(string postTitle, string title, int seasonNumber, int episodeNumber)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using FluentValidation.Validators;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.TvTests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class SeriesTitleSlugValidatorFixture : CoreTest<SeriesTitleSlugValidator>
|
||||||
|
{
|
||||||
|
private List<Series> _series;
|
||||||
|
private TestValidator<Series> _validator;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_series = Builder<Series>.CreateListOfSize(1)
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
_validator = new TestValidator<Series>
|
||||||
|
{
|
||||||
|
v => v.RuleFor(s => s.TitleSlug).SetValidator(Subject)
|
||||||
|
};
|
||||||
|
|
||||||
|
Mocker.GetMock<ISeriesService>()
|
||||||
|
.Setup(s => s.GetAllSeries())
|
||||||
|
.Returns(_series);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_be_valid_if_there_is_an_existing_series_with_the_same_title_slug()
|
||||||
|
{
|
||||||
|
var series = Builder<Series>.CreateNew()
|
||||||
|
.With(s => s.Id = 100)
|
||||||
|
.With(s => s.TitleSlug = _series.First().TitleSlug)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
_validator.Validate(series).IsValid.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_valid_if_there_is_not_an_existing_series_with_the_same_title_slug()
|
||||||
|
{
|
||||||
|
var series = Builder<Series>.CreateNew()
|
||||||
|
.With(s => s.TitleSlug = "MyTitleSlug")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
_validator.Validate(series).IsValid.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_valid_if_there_is_an_existing_series_with_a_null_title_slug()
|
||||||
|
{
|
||||||
|
_series.First().TitleSlug = null;
|
||||||
|
|
||||||
|
var series = Builder<Series>.CreateNew()
|
||||||
|
.With(s => s.TitleSlug = "MyTitleSlug")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
_validator.Validate(series).IsValid.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_valid_when_updating_an_existing_series()
|
||||||
|
{
|
||||||
|
_validator.Validate(_series.First().JsonClone()).IsValid.Should().BeTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using NzbDrone.Common.Exceptions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.DataAugmentation.Scene
|
||||||
|
{
|
||||||
|
public class InvalidSceneMappingException : NzbDroneException
|
||||||
|
{
|
||||||
|
public InvalidSceneMappingException(IEnumerable<SceneMapping> mappings)
|
||||||
|
: base(FormatMessage(mappings))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatMessage(IEnumerable<SceneMapping> mappings)
|
||||||
|
{
|
||||||
|
return string.Format("Scene Mappings contains a conflict for tvdbids {0}. Please notify Sonarr developers.", string.Join(",", mappings.Select(v => v.TvdbId.ToString())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,9 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
|||||||
public int? SeasonNumber { get; set; }
|
public int? SeasonNumber { get; set; }
|
||||||
|
|
||||||
public int? SceneSeasonNumber { get; set; }
|
public int? SceneSeasonNumber { get; set; }
|
||||||
|
|
||||||
|
public string FilterRegex { get; set; }
|
||||||
|
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,17 +8,18 @@ using NzbDrone.Core.Messaging.Events;
|
|||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.Tv.Events;
|
using NzbDrone.Core.Tv.Events;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace NzbDrone.Core.DataAugmentation.Scene
|
namespace NzbDrone.Core.DataAugmentation.Scene
|
||||||
{
|
{
|
||||||
public interface ISceneMappingService
|
public interface ISceneMappingService
|
||||||
{
|
{
|
||||||
List<string> GetSceneNames(int tvdbId, List<int> seasonNumbers, List<int> sceneSeasonNumbers);
|
List<string> GetSceneNames(int tvdbId, List<int> seasonNumbers, List<int> sceneSeasonNumbers);
|
||||||
int? FindTvdbId(string title);
|
int? FindTvdbId(string sceneTitle, string releaseTitle);
|
||||||
List<SceneMapping> FindByTvdbId(int tvdbId);
|
List<SceneMapping> FindByTvdbId(int tvdbId);
|
||||||
SceneMapping FindSceneMapping(string title);
|
SceneMapping FindSceneMapping(string sceneTitle, string releaseTitle);
|
||||||
int? GetSceneSeasonNumber(string title);
|
int? GetSceneSeasonNumber(string seriesTitle, string releaseTitle);
|
||||||
int? GetTvdbSeasonNumber(string title);
|
int? GetTvdbSeasonNumber(string seriesTitle, string releaseTitle);
|
||||||
int? GetSceneSeasonNumber(int tvdbId, int seasonNumber);
|
int? GetSceneSeasonNumber(int tvdbId, int seasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,14 +66,14 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
|||||||
return FilterNonEnglish(names);
|
return FilterNonEnglish(names);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int? FindTvdbId(string title)
|
public int? FindTvdbId(string seriesTitle)
|
||||||
{
|
{
|
||||||
var mapping = FindMapping(title);
|
return FindTvdbId(seriesTitle, null);
|
||||||
|
}
|
||||||
|
|
||||||
if (mapping == null)
|
public int? FindTvdbId(string seriesTitle, string releaseTitle)
|
||||||
return null;
|
{
|
||||||
|
return FindSceneMapping(seriesTitle, releaseTitle)?.TvdbId;
|
||||||
return mapping.TvdbId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SceneMapping> FindByTvdbId(int tvdbId)
|
public List<SceneMapping> FindByTvdbId(int tvdbId)
|
||||||
@@ -92,33 +93,33 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
|||||||
return mappings;
|
return mappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SceneMapping FindSceneMapping(string title)
|
public SceneMapping FindSceneMapping(string seriesTitle, string releaseTitle)
|
||||||
{
|
{
|
||||||
return FindMapping(title);
|
var mappings = FindMappings(seriesTitle, releaseTitle);
|
||||||
}
|
|
||||||
|
|
||||||
public int? GetSceneSeasonNumber(string title)
|
if (mappings == null)
|
||||||
{
|
|
||||||
var mapping = FindMapping(title);
|
|
||||||
|
|
||||||
if (mapping == null)
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapping.SceneSeasonNumber;
|
var distinctMappings = mappings.DistinctBy(v => v.TvdbId).ToList();
|
||||||
}
|
|
||||||
|
|
||||||
public int? GetTvdbSeasonNumber(string title)
|
if (distinctMappings.Count <= 1)
|
||||||
{
|
|
||||||
var mapping = FindMapping(title);
|
|
||||||
|
|
||||||
if (mapping == null)
|
|
||||||
{
|
{
|
||||||
return null;
|
return distinctMappings.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapping.SeasonNumber;
|
throw new InvalidSceneMappingException(mappings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int? GetSceneSeasonNumber(string seriesTitle, string releaseTitle)
|
||||||
|
{
|
||||||
|
return FindSceneMapping(seriesTitle, releaseTitle)?.SceneSeasonNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int? GetTvdbSeasonNumber(string seriesTitle, string releaseTitle)
|
||||||
|
{
|
||||||
|
return FindSceneMapping(seriesTitle, releaseTitle)?.SeasonNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int? GetSceneSeasonNumber(int tvdbId, int seasonNumber)
|
public int? GetSceneSeasonNumber(int tvdbId, int seasonNumber)
|
||||||
@@ -184,44 +185,48 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
|||||||
_logger.Error(ex, "Failed to Update Scene Mappings.");
|
_logger.Error(ex, "Failed to Update Scene Mappings.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RefreshCache();
|
RefreshCache();
|
||||||
|
|
||||||
_eventAggregator.PublishEvent(new SceneMappingsUpdatedEvent());
|
_eventAggregator.PublishEvent(new SceneMappingsUpdatedEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SceneMapping FindMapping(string title)
|
private List<SceneMapping> FindMappings(string seriesTitle, string releaseTitle)
|
||||||
{
|
{
|
||||||
if (_getTvdbIdCache.Count == 0)
|
if (_getTvdbIdCache.Count == 0)
|
||||||
{
|
{
|
||||||
RefreshCache();
|
RefreshCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
var candidates = _getTvdbIdCache.Find(title.CleanSeriesTitle());
|
var candidates = _getTvdbIdCache.Find(seriesTitle.CleanSeriesTitle());
|
||||||
|
|
||||||
if (candidates == null)
|
if (candidates == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (candidates.Count == 1)
|
candidates = FilterSceneMappings(candidates, releaseTitle);
|
||||||
|
|
||||||
|
if (candidates.Count <= 1)
|
||||||
{
|
{
|
||||||
return candidates.First();
|
return candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
var exactMatch = candidates.OrderByDescending(v => v.SeasonNumber)
|
var exactMatch = candidates.OrderByDescending(v => v.SeasonNumber)
|
||||||
.FirstOrDefault(v => v.Title == title);
|
.Where(v => v.Title == seriesTitle)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
if (exactMatch != null)
|
if (exactMatch.Any())
|
||||||
{
|
{
|
||||||
return exactMatch;
|
return exactMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
var closestMatch = candidates.OrderBy(v => title.LevenshteinDistance(v.Title, 10, 1, 10))
|
var closestMatch = candidates.OrderBy(v => seriesTitle.LevenshteinDistance(v.Title, 10, 1, 10))
|
||||||
.ThenByDescending(v => v.SeasonNumber)
|
.ThenByDescending(v => v.SeasonNumber)
|
||||||
.First();
|
.First();
|
||||||
|
|
||||||
return closestMatch;
|
|
||||||
|
return candidates.Where(v => v.Title == closestMatch.Title).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshCache()
|
private void RefreshCache()
|
||||||
@@ -232,6 +237,26 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
|||||||
_findByTvdbIdCache.Update(mappings.GroupBy(v => v.TvdbId).ToDictionary(v => v.Key.ToString(), v => v.ToList()));
|
_findByTvdbIdCache.Update(mappings.GroupBy(v => v.TvdbId).ToDictionary(v => v.Key.ToString(), v => v.ToList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<SceneMapping> FilterSceneMappings(List<SceneMapping> candidates, string releaseTitle)
|
||||||
|
{
|
||||||
|
var filteredCandidates = candidates.Where(v => v.FilterRegex.IsNotNullOrWhiteSpace()).ToList();
|
||||||
|
var normalCandidates = candidates.Except(filteredCandidates).ToList();
|
||||||
|
|
||||||
|
if (releaseTitle.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return normalCandidates;
|
||||||
|
}
|
||||||
|
|
||||||
|
filteredCandidates = filteredCandidates.Where(v => Regex.IsMatch(releaseTitle, v.FilterRegex)).ToList();
|
||||||
|
|
||||||
|
if (filteredCandidates.Any())
|
||||||
|
{
|
||||||
|
return filteredCandidates;
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalCandidates;
|
||||||
|
}
|
||||||
|
|
||||||
private List<string> FilterNonEnglish(List<string> titles)
|
private List<string> FilterNonEnglish(List<string> titles)
|
||||||
{
|
{
|
||||||
return titles.Where(title => title.All(c => c <= 255)).ToList();
|
return titles.Where(title => title.All(c => c <= 255)).ToList();
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
// This is a placeholder for migration 102
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
// This is a placeholder for migration 111
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Data;
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(112)]
|
||||||
|
public class added_regex_to_scenemapping : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("SceneMappings").AddColumn("FilterRegex").AsString().Nullable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -122,8 +122,16 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
|
|
||||||
private DownloadDecision GetDecisionForReport(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria = null)
|
private DownloadDecision GetDecisionForReport(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria = null)
|
||||||
{
|
{
|
||||||
var reasons = _specifications.Select(c => EvaluateSpec(c, remoteEpisode, searchCriteria))
|
var reasons = new Rejection[0];
|
||||||
.Where(c => c != null);
|
|
||||||
|
foreach (var specifications in _specifications.GroupBy(v => v.Priority).OrderBy(v => v.Key))
|
||||||
|
{
|
||||||
|
reasons = specifications.Select(c => EvaluateSpec(c, remoteEpisode, searchCriteria))
|
||||||
|
.Where(c => c != null)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
if (reasons.Any()) break;
|
||||||
|
}
|
||||||
|
|
||||||
return new DownloadDecision(remoteEpisode, reasons.ToArray());
|
return new DownloadDecision(remoteEpisode, reasons.ToArray());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
{
|
{
|
||||||
RejectionType Type { get; }
|
RejectionType Type { get; }
|
||||||
|
|
||||||
|
SpecificationPriority Priority { get; }
|
||||||
|
|
||||||
Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria);
|
Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/NzbDrone.Core/DecisionEngine/SpecificationPriority.cs
Normal file
10
src/NzbDrone.Core/DecisionEngine/SpecificationPriority.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace NzbDrone.Core.DecisionEngine
|
||||||
|
{
|
||||||
|
public enum SpecificationPriority
|
||||||
|
{
|
||||||
|
Default = 0,
|
||||||
|
Parsing = 0,
|
||||||
|
Database = 0,
|
||||||
|
Disk = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
{
|
{
|
||||||
if (_blacklistService.Blacklisted(subject.Series.Id, subject.Release))
|
if (_blacklistService.Blacklisted(subject.Series.Id, subject.Release))
|
||||||
{
|
{
|
||||||
_logger.Debug("{0} is blacklisted, rejecting.", subject.Release.Title);
|
_logger.Debug("{0} is blacklisted, rejecting.", subject.Release.Title);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
@@ -29,7 +30,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug("Comparing file quality with report. Existing file is {0}", file.Quality);
|
_logger.Debug("Comparing file quality with report. Existing file is {0}", file.Quality);
|
||||||
|
|
||||||
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Series.Profile, file.Quality, subject.ParsedEpisodeInfo.Quality))
|
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Series.Profile, file.Quality, subject.ParsedEpisodeInfo.Quality))
|
||||||
{
|
{
|
||||||
_logger.Debug("Cutoff already met, rejecting.");
|
_logger.Debug("Cutoff already met, rejecting.");
|
||||||
|
|||||||
@@ -11,14 +11,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
public class FullSeasonSpecification : IDecisionEngineSpecification
|
public class FullSeasonSpecification : IDecisionEngineSpecification
|
||||||
{
|
{
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
private readonly IEpisodeService _episodeService;
|
|
||||||
|
|
||||||
public FullSeasonSpecification(Logger logger, IEpisodeService episodeService)
|
public FullSeasonSpecification(Logger logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_episodeService = episodeService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -13,12 +13,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
{
|
{
|
||||||
var wantedLanguage = subject.Series.Profile.Value.Language;
|
var wantedLanguage = subject.Series.Profile.Value.Language;
|
||||||
|
|
||||||
_logger.Debug("Checking if report meets language requirements. {0}", subject.ParsedEpisodeInfo.Language);
|
_logger.Debug("Checking if report meets language requirements. {0}", subject.ParsedEpisodeInfo.Language);
|
||||||
|
|
||||||
if (subject.ParsedEpisodeInfo.Language != wantedLanguage)
|
if (subject.ParsedEpisodeInfo.Language != wantedLanguage)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Temporary;
|
public RejectionType Type => RejectionType.Temporary;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
{
|
{
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public NotSampleSpecification(Logger logger)
|
public NotSampleSpecification(Logger logger)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||||
public RejectionType Type => RejectionType.Temporary;
|
public RejectionType Type => RejectionType.Temporary;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
|
{
|
||||||
|
public class DeletedEpisodeFileSpecification : IDecisionEngineSpecification
|
||||||
|
{
|
||||||
|
private readonly IDiskProvider _diskProvider;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public DeletedEpisodeFileSpecification(IDiskProvider diskProvider, IConfigService configService, Logger logger)
|
||||||
|
{
|
||||||
|
_diskProvider = diskProvider;
|
||||||
|
_configService = configService;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Disk;
|
||||||
|
public RejectionType Type => RejectionType.Temporary;
|
||||||
|
|
||||||
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
{
|
||||||
|
if (!_configService.AutoUnmonitorPreviouslyDownloadedEpisodes)
|
||||||
|
{
|
||||||
|
return Decision.Accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchCriteria != null)
|
||||||
|
{
|
||||||
|
_logger.Debug("Skipping deleted episodefile check during search");
|
||||||
|
return Decision.Accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
var missingEpisodeFiles = subject.Episodes
|
||||||
|
.Where(v => v.EpisodeFileId != 0)
|
||||||
|
.Select(v => v.EpisodeFile.Value)
|
||||||
|
.DistinctBy(v => v.Id)
|
||||||
|
.Where(v => IsEpisodeFileMissing(subject.Series, v))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
if (missingEpisodeFiles.Any())
|
||||||
|
{
|
||||||
|
foreach (var missingEpisodeFile in missingEpisodeFiles)
|
||||||
|
{
|
||||||
|
_logger.Trace("Episode file {0} is missing from disk.", missingEpisodeFile.RelativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Debug("Files for this episode exist in the database but not on disk, will be unmonitored on next diskscan. skipping.");
|
||||||
|
return Decision.Reject("Series is not monitored");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Decision.Accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsEpisodeFileMissing(Series series, EpisodeFile episodeFile)
|
||||||
|
{
|
||||||
|
var fullPath = Path.Combine(series.Path, episodeFile.RelativePath);
|
||||||
|
|
||||||
|
return !_diskProvider.FileExists(fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
@@ -59,7 +60,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||||||
{
|
{
|
||||||
if (recent)
|
if (recent)
|
||||||
{
|
{
|
||||||
return Decision.Reject("Recent grab event in history already meets cutoff: {0}", mostRecent.Quality);
|
return Decision.Reject("Recent grab event in history already meets cutoff: {0}", mostRecent.Quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Decision.Reject("CDH is disabled and grab event in history already meets cutoff: {0}", mostRecent.Quality);
|
return Decision.Reject("CDH is disabled and grab event in history already meets cutoff: {0}", mostRecent.Quality);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||||||
_episodeService = episodeService;
|
_episodeService = episodeService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
||||||
@@ -40,4 +41,4 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
||||||
@@ -34,4 +35,4 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
||||||
@@ -33,4 +34,4 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
||||||
@@ -47,4 +48,4 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
|
|
||||||
@@ -34,4 +35,4 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
public RejectionType Type => RejectionType.Permanent;
|
public RejectionType Type => RejectionType.Permanent;
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||||||
queueItem.TotalSize = totalSize;
|
queueItem.TotalSize = totalSize;
|
||||||
queueItem.Category = item.Category;
|
queueItem.Category = item.Category;
|
||||||
queueItem.DownloadClient = Definition.Name;
|
queueItem.DownloadClient = Definition.Name;
|
||||||
|
queueItem.CanMoveFiles = true;
|
||||||
|
queueItem.CanBeRemoved = true;
|
||||||
|
|
||||||
if (globalStatus.DownloadPaused || remainingSize == pausedSize && remainingSize != 0)
|
if (globalStatus.DownloadPaused || remainingSize == pausedSize && remainingSize != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,17 +55,31 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
{
|
{
|
||||||
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
|
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
|
||||||
|
|
||||||
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
|
try
|
||||||
{
|
{
|
||||||
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
|
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Warn(ex, "Failed to set the torrent label for {0}.", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
try
|
||||||
|
|
||||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
|
|
||||||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
|
|
||||||
{
|
{
|
||||||
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
|
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||||
|
|
||||||
|
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
|
||||||
|
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
|
||||||
|
{
|
||||||
|
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Warn(ex, "Failed to set the torrent priority for {0}.", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
@@ -177,6 +191,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
{
|
{
|
||||||
failures.AddIfNotNull(TestConnection());
|
failures.AddIfNotNull(TestConnection());
|
||||||
if (failures.Any()) return;
|
if (failures.Any()) return;
|
||||||
|
failures.AddIfNotNull(TestPrioritySupport());
|
||||||
failures.AddIfNotNull(TestGetTorrents());
|
failures.AddIfNotNull(TestGetTorrents());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,6 +268,41 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ValidationFailure TestPrioritySupport()
|
||||||
|
{
|
||||||
|
var recentPriorityDefault = Settings.RecentTvPriority == (int)QBittorrentPriority.Last;
|
||||||
|
var olderPriorityDefault = Settings.OlderTvPriority == (int)QBittorrentPriority.Last;
|
||||||
|
|
||||||
|
if (olderPriorityDefault && recentPriorityDefault)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var config = _proxy.GetConfig(Settings);
|
||||||
|
|
||||||
|
if (!config.QueueingEnabled)
|
||||||
|
{
|
||||||
|
if (!recentPriorityDefault)
|
||||||
|
{
|
||||||
|
return new NzbDroneValidationFailure(nameof(Settings.RecentTvPriority), "Queueing not enabled") { DetailedDescription = "Torrent Queueing is not enabled in your qBittorrent settings. Enable it in qBittorrent or select 'Last' as priority." };
|
||||||
|
}
|
||||||
|
else if (!olderPriorityDefault)
|
||||||
|
{
|
||||||
|
return new NzbDroneValidationFailure(nameof(Settings.OlderTvPriority), "Queueing not enabled") { DetailedDescription = "Torrent Queueing is not enabled in your qBittorrent settings. Enable it in qBittorrent or select 'Last' as priority." };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error(ex);
|
||||||
|
return new NzbDroneValidationFailure(String.Empty, "Unknown exception: " + ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private ValidationFailure TestGetTorrents()
|
private ValidationFailure TestGetTorrents()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -16,5 +16,8 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
|
|
||||||
[JsonProperty(PropertyName = "max_ratio_act")]
|
[JsonProperty(PropertyName = "max_ratio_act")]
|
||||||
public bool RemoveOnMaxRatio { get; set; } // Action performed when a torrent reaches the maximum share ratio. [false = pause, true = remove]
|
public bool RemoveOnMaxRatio { get; set; } // Action performed when a torrent reaches the maximum share ratio. [false = pause, true = remove]
|
||||||
|
|
||||||
|
[JsonProperty(PropertyName = "queueing_enabled")]
|
||||||
|
public bool QueueingEnabled { get; set; } = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
queueItem.TotalSize = (long)(sabQueueItem.Size * 1024 * 1024);
|
queueItem.TotalSize = (long)(sabQueueItem.Size * 1024 * 1024);
|
||||||
queueItem.RemainingSize = (long)(sabQueueItem.Sizeleft * 1024 * 1024);
|
queueItem.RemainingSize = (long)(sabQueueItem.Sizeleft * 1024 * 1024);
|
||||||
queueItem.RemainingTime = sabQueueItem.Timeleft;
|
queueItem.RemainingTime = sabQueueItem.Timeleft;
|
||||||
|
queueItem.CanBeRemoved = true;
|
||||||
|
queueItem.CanMoveFiles = true;
|
||||||
|
|
||||||
if (sabQueue.Paused || sabQueueItem.Status == SabnzbdDownloadStatus.Paused)
|
if (sabQueue.Paused || sabQueueItem.Status == SabnzbdDownloadStatus.Paused)
|
||||||
{
|
{
|
||||||
@@ -142,7 +144,10 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
RemainingSize = 0,
|
RemainingSize = 0,
|
||||||
RemainingTime = TimeSpan.Zero,
|
RemainingTime = TimeSpan.Zero,
|
||||||
|
|
||||||
Message = sabHistoryItem.FailMessage
|
Message = sabHistoryItem.FailMessage,
|
||||||
|
|
||||||
|
CanBeRemoved = true,
|
||||||
|
CanMoveFiles = true
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sabHistoryItem.Status == SabnzbdDownloadStatus.Failed)
|
if (sabHistoryItem.Status == SabnzbdDownloadStatus.Failed)
|
||||||
@@ -160,8 +165,6 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
else if (sabHistoryItem.Status == SabnzbdDownloadStatus.Completed)
|
else if (sabHistoryItem.Status == SabnzbdDownloadStatus.Completed)
|
||||||
{
|
{
|
||||||
historyItem.Status = DownloadItemStatus.Completed;
|
historyItem.Status = DownloadItemStatus.Completed;
|
||||||
historyItem.CanBeRemoved = true;
|
|
||||||
historyItem.CanMoveFiles = true;
|
|
||||||
}
|
}
|
||||||
else // Verifying/Moving etc
|
else // Verifying/Moving etc
|
||||||
{
|
{
|
||||||
@@ -185,6 +188,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
historyItems.Add(historyItem);
|
historyItems.Add(historyItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,8 +86,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
|||||||
item.Status = DownloadItemStatus.Warning;
|
item.Status = DownloadItemStatus.Warning;
|
||||||
item.Message = torrent.ErrorString;
|
item.Message = torrent.ErrorString;
|
||||||
}
|
}
|
||||||
else if (torrent.Status == TransmissionTorrentStatus.Seeding ||
|
else if (torrent.LeftUntilDone == 0 && (torrent.Status == TransmissionTorrentStatus.Stopped ||
|
||||||
torrent.Status == TransmissionTorrentStatus.SeedingWait)
|
torrent.Status == TransmissionTorrentStatus.Seeding ||
|
||||||
|
torrent.Status == TransmissionTorrentStatus.SeedingWait))
|
||||||
{
|
{
|
||||||
item.Status = DownloadItemStatus.Completed;
|
item.Status = DownloadItemStatus.Completed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,19 @@ namespace NzbDrone.Core.Download.Clients.Vuze
|
|||||||
|
|
||||||
protected override OsPath GetOutputPath(OsPath outputPath, TransmissionTorrent torrent)
|
protected override OsPath GetOutputPath(OsPath outputPath, TransmissionTorrent torrent)
|
||||||
{
|
{
|
||||||
_logger.Debug("Vuze output directory: {0}", outputPath);
|
// Vuze has similar behavior as uTorrent:
|
||||||
|
// - A multi-file torrent is downloaded in a job folder and 'outputPath' points to that directory directly.
|
||||||
|
// - A single-file torrent is downloaded in the root folder and 'outputPath' poinst to that root folder.
|
||||||
|
// We have to make sure the return value points to the job folder OR file.
|
||||||
|
if (outputPath == null || outputPath.FileName == torrent.Name)
|
||||||
|
{
|
||||||
|
_logger.Trace("Vuze output directory: {0}", outputPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outputPath = outputPath + torrent.Name;
|
||||||
|
_logger.Trace("Vuze output file: {0}", outputPath);
|
||||||
|
}
|
||||||
|
|
||||||
return outputPath;
|
return outputPath;
|
||||||
}
|
}
|
||||||
@@ -50,4 +62,4 @@ namespace NzbDrone.Core.Download.Clients.Vuze
|
|||||||
|
|
||||||
public override string Name => "Vuze";
|
public override string Name => "Vuze";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ namespace NzbDrone.Core.Extras.Files
|
|||||||
filenameBuilder.Append(fileNameSuffix);
|
filenameBuilder.Append(fileNameSuffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
filenameBuilder.Append(".");
|
|
||||||
filenameBuilder.Append(extraFile.Extension);
|
filenameBuilder.Append(extraFile.Extension);
|
||||||
|
|
||||||
var existingFileName = Path.Combine(series.Path, extraFile.RelativePath);
|
var existingFileName = Path.Combine(series.Path, extraFile.RelativePath);
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
|
|||||||
video.Add(new XElement("framerate", episodeFile.MediaInfo.VideoFps));
|
video.Add(new XElement("framerate", episodeFile.MediaInfo.VideoFps));
|
||||||
video.Add(new XElement("height", episodeFile.MediaInfo.Height));
|
video.Add(new XElement("height", episodeFile.MediaInfo.Height));
|
||||||
video.Add(new XElement("scantype", episodeFile.MediaInfo.ScanType));
|
video.Add(new XElement("scantype", episodeFile.MediaInfo.ScanType));
|
||||||
video.Add(new XElement("width", episodeFile.MediaInfo.Height));
|
video.Add(new XElement("width", episodeFile.MediaInfo.Width));
|
||||||
|
|
||||||
if (episodeFile.MediaInfo.RunTime != null)
|
if (episodeFile.MediaInfo.RunTime != null)
|
||||||
{
|
{
|
||||||
|
|||||||
36
src/NzbDrone.Core/HealthCheck/Checks/MountCheck.cs
Normal file
36
src/NzbDrone.Core/HealthCheck/Checks/MountCheck.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.HealthCheck.Checks
|
||||||
|
{
|
||||||
|
public class MountCheck : HealthCheckBase
|
||||||
|
{
|
||||||
|
private readonly IDiskProvider _diskProvider;
|
||||||
|
private readonly ISeriesService _seriesService;
|
||||||
|
|
||||||
|
public MountCheck(IDiskProvider diskProvider, ISeriesService seriesService)
|
||||||
|
{
|
||||||
|
_diskProvider = diskProvider;
|
||||||
|
_seriesService = seriesService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override HealthCheck Check()
|
||||||
|
{
|
||||||
|
// Not best for optimization but due to possible symlinks and junctions, we get mounts based on series path so internals can handle mount resolution.
|
||||||
|
var mounts = _seriesService.GetAllSeries()
|
||||||
|
.Select(series => _diskProvider.GetMount(series.Path))
|
||||||
|
.Where(m => m != null && m.MountOptions != null && m.MountOptions.IsReadOnly)
|
||||||
|
.DistinctBy(m => m.RootDirectory)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (mounts.Any())
|
||||||
|
{
|
||||||
|
return new HealthCheck(GetType(), HealthCheckResult.Error, "Mount containing a series path is mounted read-only: " + string.Join(",", mounts.Select(m => m.Name)), "#series-mount-ro");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HealthCheck(GetType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -199,7 +199,7 @@ namespace NzbDrone.Core.IndexerSearch
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("AbsoluteEpisodeNumber", "Can not search for an episode without an absolute episode number");
|
throw new ArgumentOutOfRangeException("AbsoluteEpisodeNumber", $"Can not search for {series.Title} - S{episode.SeasonNumber:00}E{episode.EpisodeNumber:00} it does not have an absolute episode number");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec);
|
return Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec);
|
||||||
|
|||||||
@@ -46,9 +46,7 @@ namespace NzbDrone.Core.Indexers
|
|||||||
return new List<ReleaseInfo>();
|
return new List<ReleaseInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var generator = GetRequestGenerator();
|
return FetchReleases(g => g.GetRecentRequests(), true);
|
||||||
|
|
||||||
return FetchReleases(generator.GetRecentRequests(), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IList<ReleaseInfo> Fetch(SingleEpisodeSearchCriteria searchCriteria)
|
public override IList<ReleaseInfo> Fetch(SingleEpisodeSearchCriteria searchCriteria)
|
||||||
@@ -58,9 +56,7 @@ namespace NzbDrone.Core.Indexers
|
|||||||
return new List<ReleaseInfo>();
|
return new List<ReleaseInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var generator = GetRequestGenerator();
|
return FetchReleases(g => g.GetSearchRequests(searchCriteria));
|
||||||
|
|
||||||
return FetchReleases(generator.GetSearchRequests(searchCriteria));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IList<ReleaseInfo> Fetch(SeasonSearchCriteria searchCriteria)
|
public override IList<ReleaseInfo> Fetch(SeasonSearchCriteria searchCriteria)
|
||||||
@@ -70,9 +66,7 @@ namespace NzbDrone.Core.Indexers
|
|||||||
return new List<ReleaseInfo>();
|
return new List<ReleaseInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var generator = GetRequestGenerator();
|
return FetchReleases(g => g.GetSearchRequests(searchCriteria));
|
||||||
|
|
||||||
return FetchReleases(generator.GetSearchRequests(searchCriteria));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IList<ReleaseInfo> Fetch(DailyEpisodeSearchCriteria searchCriteria)
|
public override IList<ReleaseInfo> Fetch(DailyEpisodeSearchCriteria searchCriteria)
|
||||||
@@ -82,9 +76,7 @@ namespace NzbDrone.Core.Indexers
|
|||||||
return new List<ReleaseInfo>();
|
return new List<ReleaseInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var generator = GetRequestGenerator();
|
return FetchReleases(g => g.GetSearchRequests(searchCriteria));
|
||||||
|
|
||||||
return FetchReleases(generator.GetSearchRequests(searchCriteria));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IList<ReleaseInfo> Fetch(AnimeEpisodeSearchCriteria searchCriteria)
|
public override IList<ReleaseInfo> Fetch(AnimeEpisodeSearchCriteria searchCriteria)
|
||||||
@@ -94,9 +86,7 @@ namespace NzbDrone.Core.Indexers
|
|||||||
return new List<ReleaseInfo>();
|
return new List<ReleaseInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var generator = GetRequestGenerator();
|
return FetchReleases(g => g.GetSearchRequests(searchCriteria));
|
||||||
|
|
||||||
return FetchReleases(generator.GetSearchRequests(searchCriteria));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IList<ReleaseInfo> Fetch(SpecialEpisodeSearchCriteria searchCriteria)
|
public override IList<ReleaseInfo> Fetch(SpecialEpisodeSearchCriteria searchCriteria)
|
||||||
@@ -106,20 +96,21 @@ namespace NzbDrone.Core.Indexers
|
|||||||
return new List<ReleaseInfo>();
|
return new List<ReleaseInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var generator = GetRequestGenerator();
|
return FetchReleases(g => g.GetSearchRequests(searchCriteria));
|
||||||
|
|
||||||
return FetchReleases(generator.GetSearchRequests(searchCriteria));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual IList<ReleaseInfo> FetchReleases(IndexerPageableRequestChain pageableRequestChain, bool isRecent = false)
|
protected virtual IList<ReleaseInfo> FetchReleases(Func<IIndexerRequestGenerator, IndexerPageableRequestChain> pageableRequestChainSelector, bool isRecent = false)
|
||||||
{
|
{
|
||||||
var releases = new List<ReleaseInfo>();
|
var releases = new List<ReleaseInfo>();
|
||||||
var url = string.Empty;
|
var url = string.Empty;
|
||||||
|
|
||||||
var parser = GetParser();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var generator = GetRequestGenerator();
|
||||||
|
var parser = GetParser();
|
||||||
|
|
||||||
|
var pageableRequestChain = pageableRequestChainSelector(generator);
|
||||||
|
|
||||||
var fullyUpdated = false;
|
var fullyUpdated = false;
|
||||||
ReleaseInfo lastReleaseInfo = null;
|
ReleaseInfo lastReleaseInfo = null;
|
||||||
if (isRecent)
|
if (isRecent)
|
||||||
@@ -222,18 +213,22 @@ namespace NzbDrone.Core.Indexers
|
|||||||
_logger.Warn("{0} {1} {2}", this, url, webException.Message);
|
_logger.Warn("{0} {1} {2}", this, url, webException.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (HttpException httpException)
|
catch (TooManyRequestsException ex)
|
||||||
{
|
{
|
||||||
if ((int)httpException.Response.StatusCode == 429)
|
if (ex.RetryAfter != TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
_indexerStatusService.RecordFailure(Definition.Id, TimeSpan.FromHours(1));
|
_indexerStatusService.RecordFailure(Definition.Id, ex.RetryAfter);
|
||||||
_logger.Warn("API Request Limit reached for {0}", this);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_indexerStatusService.RecordFailure(Definition.Id);
|
_indexerStatusService.RecordFailure(Definition.Id, TimeSpan.FromHours(1));
|
||||||
_logger.Warn("{0} {1}", this, httpException.Message);
|
|
||||||
}
|
}
|
||||||
|
_logger.Warn("API Request Limit reached for {0}", this);
|
||||||
|
}
|
||||||
|
catch (HttpException ex)
|
||||||
|
{
|
||||||
|
_indexerStatusService.RecordFailure(Definition.Id);
|
||||||
|
_logger.Warn("{0} {1}", this, ex.Message);
|
||||||
}
|
}
|
||||||
catch (RequestLimitReachedException)
|
catch (RequestLimitReachedException)
|
||||||
{
|
{
|
||||||
@@ -248,6 +243,7 @@ namespace NzbDrone.Core.Indexers
|
|||||||
catch (CloudFlareCaptchaException ex)
|
catch (CloudFlareCaptchaException ex)
|
||||||
{
|
{
|
||||||
_indexerStatusService.RecordFailure(Definition.Id);
|
_indexerStatusService.RecordFailure(Definition.Id);
|
||||||
|
ex.WithData("FeedUrl", url);
|
||||||
if (ex.IsExpired)
|
if (ex.IsExpired)
|
||||||
{
|
{
|
||||||
_logger.Error(ex, "Expired CAPTCHA token for {0}, please refresh in indexer settings.", this);
|
_logger.Error(ex, "Expired CAPTCHA token for {0}, please refresh in indexer settings.", this);
|
||||||
@@ -262,11 +258,11 @@ namespace NzbDrone.Core.Indexers
|
|||||||
_indexerStatusService.RecordFailure(Definition.Id);
|
_indexerStatusService.RecordFailure(Definition.Id);
|
||||||
_logger.Warn(ex, "{0}", url);
|
_logger.Warn(ex, "{0}", url);
|
||||||
}
|
}
|
||||||
catch (Exception feedEx)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_indexerStatusService.RecordFailure(Definition.Id);
|
_indexerStatusService.RecordFailure(Definition.Id);
|
||||||
feedEx.Data.Add("FeedUrl", url);
|
ex.WithData("FeedUrl", url);
|
||||||
_logger.Error(feedEx, "An error occurred while processing feed. {0}", url);
|
_logger.Error(ex, "An error occurred while processing feed. {0}", url);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CleanupReleases(releases);
|
return CleanupReleases(releases);
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
catch (XmlException ex)
|
catch (XmlException ex)
|
||||||
{
|
{
|
||||||
_logger.Debug(ex, "Failed to parse newznab api capabilities for {0}.", indexerSettings.Url);
|
_logger.Debug(ex, "Failed to parse newznab api capabilities for {0}.", indexerSettings.Url);
|
||||||
|
|
||||||
|
ex.WithData(response);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -63,9 +63,16 @@ namespace NzbDrone.Core.Indexers
|
|||||||
|
|
||||||
releases.AddIfNotNull(reportInfo);
|
releases.AddIfNotNull(reportInfo);
|
||||||
}
|
}
|
||||||
|
catch (UnsupportedFeedException itemEx)
|
||||||
|
{
|
||||||
|
itemEx.WithData("FeedUrl", indexerResponse.Request.Url);
|
||||||
|
itemEx.WithData("ItemTitle", item.Title());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
catch (Exception itemEx)
|
catch (Exception itemEx)
|
||||||
{
|
{
|
||||||
itemEx.Data.Add("Item", item.Title());
|
itemEx.WithData("FeedUrl", indexerResponse.Request.Url);
|
||||||
|
itemEx.WithData("ItemTitle", item.Title());
|
||||||
_logger.Error(itemEx, "An error occurred while processing feed item from {0}", indexerResponse.Request.Url);
|
_logger.Error(itemEx, "An error occurred while processing feed item from {0}", indexerResponse.Request.Url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,8 +97,7 @@ namespace NzbDrone.Core.Indexers
|
|||||||
var contentSample = indexerResponse.Content.Substring(0, Math.Min(indexerResponse.Content.Length, 512));
|
var contentSample = indexerResponse.Content.Substring(0, Math.Min(indexerResponse.Content.Length, 512));
|
||||||
_logger.Debug("Truncated response content (originally {0} characters): {1}", indexerResponse.Content.Length, contentSample);
|
_logger.Debug("Truncated response content (originally {0} characters): {1}", indexerResponse.Content.Length, contentSample);
|
||||||
|
|
||||||
ex.Data.Add("ContentLength", indexerResponse.Content.Length);
|
ex.WithData(indexerResponse.HttpResponse);
|
||||||
ex.Data.Add("ContentSample", contentSample);
|
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,23 +40,31 @@ namespace NzbDrone.Core.Indexers.TorrentRss
|
|||||||
{
|
{
|
||||||
_logger.Debug("Evaluating TorrentRss feed '{0}'", indexerSettings.BaseUrl);
|
_logger.Debug("Evaluating TorrentRss feed '{0}'", indexerSettings.BaseUrl);
|
||||||
|
|
||||||
var requestGenerator = new TorrentRssIndexerRequestGenerator { Settings = indexerSettings };
|
|
||||||
var request = requestGenerator.GetRecentRequests().GetAllTiers().First().First();
|
|
||||||
|
|
||||||
HttpResponse httpResponse = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
httpResponse = _httpClient.Execute(request.HttpRequest);
|
var requestGenerator = new TorrentRssIndexerRequestGenerator { Settings = indexerSettings };
|
||||||
|
var request = requestGenerator.GetRecentRequests().GetAllTiers().First().First();
|
||||||
|
|
||||||
|
HttpResponse httpResponse = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
httpResponse = _httpClient.Execute(request.HttpRequest);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Warn(ex, string.Format("Unable to connect to indexer {0}: {1}", request.Url, ex.Message));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var indexerResponse = new IndexerResponse(request, httpResponse);
|
||||||
|
return GetParserSettings(indexerResponse, indexerSettings);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Warn(ex, string.Format("Unable to connect to indexer {0}: {1}", request.Url, ex.Message));
|
ex.WithData("FeedUrl", indexerSettings.BaseUrl);
|
||||||
return null;
|
throw;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
var indexerResponse = new IndexerResponse(request, httpResponse);
|
|
||||||
return GetParserSettings(indexerResponse, indexerSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TorrentRssIndexerParserSettings GetParserSettings(IndexerResponse response, TorrentRssIndexerSettings indexerSettings)
|
private TorrentRssIndexerParserSettings GetParserSettings(IndexerResponse response, TorrentRssIndexerSettings indexerSettings)
|
||||||
{
|
{
|
||||||
@@ -140,7 +148,7 @@ namespace NzbDrone.Core.Indexers.TorrentRss
|
|||||||
_logger.Trace("Feed doesn't have Seeders in Description, disabling option.");
|
_logger.Trace("Feed doesn't have Seeders in Description, disabling option.");
|
||||||
parser.ParseSeedersInDescription = settings.ParseSeedersInDescription = false;
|
parser.ParseSeedersInDescription = settings.ParseSeedersInDescription = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!releases.Any(r => r.Size < ValidSizeThreshold))
|
if (!releases.Any(r => r.Size < ValidSizeThreshold))
|
||||||
{
|
{
|
||||||
_logger.Trace("Feed has valid size in enclosure.");
|
_logger.Trace("Feed has valid size in enclosure.");
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), series, folderInfo, true);
|
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), series, downloadClientItem, folderInfo, true);
|
||||||
var importResults = _importApprovedEpisodes.Import(decisions, true, downloadClientItem, importMode);
|
var importResults = _importApprovedEpisodes.Import(decisions, true, downloadClientItem, importMode);
|
||||||
|
|
||||||
if ((downloadClientItem == null || downloadClientItem.CanMoveFiles) &&
|
if ((downloadClientItem == null || downloadClientItem.CanMoveFiles) &&
|
||||||
@@ -236,7 +236,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, series, null, true);
|
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, series, downloadClientItem, null, true);
|
||||||
|
|
||||||
return _importApprovedEpisodes.Import(decisions, true, downloadClientItem, importMode);
|
return _importApprovedEpisodes.Import(decisions, true, downloadClientItem, importMode);
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user