Merge branch 'develop'
This commit is contained in:
commit
dbb499c33c
|
@ -5,6 +5,7 @@ using NzbDrone.Common;
|
|||
using NzbDrone.Common.EnsureThat;
|
||||
using NzbDrone.Common.Reflection;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.ClientSchema
|
||||
{
|
||||
|
@ -55,7 +56,7 @@ namespace NzbDrone.Api.ClientSchema
|
|||
}
|
||||
|
||||
|
||||
public static object ReadFormSchema(List<Field> fields, Type targetType)
|
||||
public static object ReadFormSchema(List<Field> fields, Type targetType, object defaults = null)
|
||||
{
|
||||
Ensure.That(targetType, () => targetType).IsNotNull();
|
||||
|
||||
|
@ -63,6 +64,11 @@ namespace NzbDrone.Api.ClientSchema
|
|||
|
||||
var target = Activator.CreateInstance(targetType);
|
||||
|
||||
if (defaults != null)
|
||||
{
|
||||
target.InjectFrom(defaults);
|
||||
}
|
||||
|
||||
foreach (var propertyInfo in properties)
|
||||
{
|
||||
var fieldAttribute = propertyInfo.GetAttribute<FieldDefinitionAttribute>(false);
|
||||
|
|
|
@ -9,9 +9,12 @@ namespace NzbDrone.Api.Config
|
|||
public String DownloadClientWorkingFolders { get; set; }
|
||||
public Int32 DownloadedEpisodesScanInterval { get; set; }
|
||||
|
||||
public Boolean EnableCompletedDownloadHandling { get; set; }
|
||||
public Boolean RemoveCompletedDownloads { get; set; }
|
||||
|
||||
public Boolean EnableFailedDownloadHandling { get; set; }
|
||||
public Boolean AutoRedownloadFailed { get; set; }
|
||||
public Boolean RemoveFailedDownloads { get; set; }
|
||||
public Boolean EnableFailedDownloadHandling { get; set; }
|
||||
public Int32 BlacklistGracePeriod { get; set; }
|
||||
public Int32 BlacklistRetryInterval { get; set; }
|
||||
public Int32 BlacklistRetryLimit { get; set; }
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
using System;
|
||||
using NzbDrone.Core.Indexers;
|
||||
|
||||
namespace NzbDrone.Api.DownloadClient
|
||||
{
|
||||
public class DownloadClientResource : ProviderResource
|
||||
{
|
||||
public Boolean Enable { get; set; }
|
||||
public Int32 Protocol { get; set; }
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Api.ClientSchema;
|
||||
using NzbDrone.Core.Download;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.DownloadClient
|
||||
{
|
||||
public class DownloadClientSchemaModule : NzbDroneRestModule<DownloadClientResource>
|
||||
{
|
||||
private readonly IDownloadClientFactory _notificationFactory;
|
||||
|
||||
public DownloadClientSchemaModule(IDownloadClientFactory notificationFactory)
|
||||
: base("downloadclient/schema")
|
||||
{
|
||||
_notificationFactory = notificationFactory;
|
||||
GetResourceAll = GetSchema;
|
||||
}
|
||||
|
||||
private List<DownloadClientResource> GetSchema()
|
||||
{
|
||||
var notifications = _notificationFactory.Templates();
|
||||
|
||||
var result = new List<DownloadClientResource>(notifications.Count);
|
||||
|
||||
foreach (var notification in notifications)
|
||||
{
|
||||
var notificationResource = new DownloadClientResource();
|
||||
notificationResource.InjectFrom(notification);
|
||||
notificationResource.Fields = SchemaBuilder.ToSchema(notification.Settings);
|
||||
|
||||
result.Add(notificationResource);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,5 +8,6 @@ namespace NzbDrone.Api.Health
|
|||
{
|
||||
public HealthCheckResult Type { get; set; }
|
||||
public String Message { get; set; }
|
||||
public Uri WikiUrl { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
using System;
|
||||
using NzbDrone.Core.Indexers;
|
||||
|
||||
namespace NzbDrone.Api.Indexers
|
||||
{
|
||||
public class IndexerResource : ProviderResource
|
||||
{
|
||||
public Boolean Enable { get; set; }
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.ClientSchema;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.Indexers
|
||||
{
|
||||
public class IndexerSchemaModule : NzbDroneRestModule<IndexerResource>
|
||||
{
|
||||
private readonly IIndexerFactory _indexerFactory;
|
||||
|
||||
public IndexerSchemaModule(IIndexerFactory indexerFactory)
|
||||
: base("indexer/schema")
|
||||
{
|
||||
_indexerFactory = indexerFactory;
|
||||
GetResourceAll = GetSchema;
|
||||
}
|
||||
|
||||
private List<IndexerResource> GetSchema()
|
||||
{
|
||||
var indexers = _indexerFactory.Templates().Where(c => c.Implementation =="Newznab");
|
||||
|
||||
var result = new List<IndexerResource>(indexers.Count());
|
||||
|
||||
foreach (var indexer in indexers)
|
||||
{
|
||||
var indexerResource = new IndexerResource();
|
||||
indexerResource.InjectFrom(indexer);
|
||||
indexerResource.Fields = SchemaBuilder.ToSchema(indexer.Settings);
|
||||
|
||||
result.Add(indexerResource);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Indexers;
|
||||
|
||||
namespace NzbDrone.Api.Indexers
|
||||
{
|
||||
|
@ -30,5 +31,6 @@ namespace NzbDrone.Api.Indexers
|
|||
public String DownloadUrl { get; set; }
|
||||
public String InfoUrl { get; set; }
|
||||
public Boolean DownloadAllowed { get; set; }
|
||||
public DownloadProtocol DownloadProtocol { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Api.ClientSchema;
|
||||
using NzbDrone.Core.Notifications;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.Notifications
|
||||
{
|
||||
public class NotificationSchemaModule : NzbDroneRestModule<NotificationResource>
|
||||
{
|
||||
private readonly INotificationFactory _notificationFactory;
|
||||
|
||||
public NotificationSchemaModule(INotificationFactory notificationFactory)
|
||||
: base("notification/schema")
|
||||
{
|
||||
_notificationFactory = notificationFactory;
|
||||
GetResourceAll = GetSchema;
|
||||
}
|
||||
|
||||
private List<NotificationResource> GetSchema()
|
||||
{
|
||||
var notifications = _notificationFactory.Templates();
|
||||
|
||||
var result = new List<NotificationResource>(notifications.Count);
|
||||
|
||||
foreach (var notification in notifications)
|
||||
{
|
||||
var notificationResource = new NotificationResource();
|
||||
notificationResource.InjectFrom(notification);
|
||||
notificationResource.Fields = SchemaBuilder.ToSchema(notification.Settings);
|
||||
|
||||
result.Add(notificationResource);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -144,11 +144,9 @@
|
|||
<Compile Include="MediaCovers\MediaCoverModule.cs" />
|
||||
<Compile Include="Metadata\MetadataResource.cs" />
|
||||
<Compile Include="Metadata\MetadataModule.cs" />
|
||||
<Compile Include="Notifications\NotificationSchemaModule.cs" />
|
||||
<Compile Include="NzbDroneFeedModule.cs" />
|
||||
<Compile Include="ProviderResource.cs" />
|
||||
<Compile Include="ProviderModuleBase.cs" />
|
||||
<Compile Include="Indexers\IndexerSchemaModule.cs" />
|
||||
<Compile Include="Indexers\IndexerModule.cs" />
|
||||
<Compile Include="Indexers\IndexerResource.cs" />
|
||||
<Compile Include="Indexers\ReleaseModule.cs" />
|
||||
|
@ -172,7 +170,6 @@
|
|||
<Compile Include="Queue\QueueModule.cs" />
|
||||
<Compile Include="Queue\QueueResource.cs" />
|
||||
<Compile Include="ResourceChangeMessage.cs" />
|
||||
<Compile Include="DownloadClient\DownloadClientSchemaModule.cs" />
|
||||
<Compile Include="Notifications\NotificationModule.cs" />
|
||||
<Compile Include="Notifications\NotificationResource.cs" />
|
||||
<Compile Include="NzbDroneRestModule.cs" />
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using Nancy;
|
||||
|
@ -22,7 +23,7 @@ namespace NzbDrone.Api
|
|||
: base(resource)
|
||||
{
|
||||
_providerFactory = providerFactory;
|
||||
Get["templates"] = x => GetTemplates();
|
||||
Get["schema"] = x => GetTemplates();
|
||||
GetResourceAll = GetAll;
|
||||
GetResourceById = GetProviderById;
|
||||
CreateResource = CreateProvider;
|
||||
|
@ -30,10 +31,11 @@ namespace NzbDrone.Api
|
|||
DeleteResource = DeleteProvider;
|
||||
|
||||
SharedValidator.RuleFor(c => c.Name).NotEmpty();
|
||||
SharedValidator.RuleFor(c => c.Name).Must((v,c) => !_providerFactory.All().Any(p => p.Name == c && p.Id != v.Id)).WithMessage("Should be unique");
|
||||
SharedValidator.RuleFor(c => c.Implementation).NotEmpty();
|
||||
SharedValidator.RuleFor(c => c.ConfigContract).NotEmpty();
|
||||
|
||||
PostValidator.RuleFor(c => c.Fields).NotEmpty();
|
||||
PostValidator.RuleFor(c => c.Fields).NotNull();
|
||||
}
|
||||
|
||||
private TProviderResource GetProviderById(int id)
|
||||
|
@ -81,8 +83,13 @@ namespace NzbDrone.Api
|
|||
|
||||
definition.InjectFrom(providerResource);
|
||||
|
||||
var preset = _providerFactory.GetPresetDefinitions(definition)
|
||||
.Where(v => v.Name == definition.Name)
|
||||
.Select(v => v.Settings)
|
||||
.FirstOrDefault();
|
||||
|
||||
var configContract = ReflectionExtensions.CoreAssembly.FindTypeByName(definition.ConfigContract);
|
||||
definition.Settings = (IProviderConfig)SchemaBuilder.ReadFormSchema(providerResource.Fields, configContract);
|
||||
definition.Settings = (IProviderConfig)SchemaBuilder.ReadFormSchema(providerResource.Fields, configContract, preset);
|
||||
|
||||
Validate(definition);
|
||||
|
||||
|
@ -96,15 +103,29 @@ namespace NzbDrone.Api
|
|||
|
||||
private Response GetTemplates()
|
||||
{
|
||||
var templates = _providerFactory.Templates();
|
||||
var defaultDefinitions = _providerFactory.GetDefaultDefinitions();
|
||||
|
||||
var result = new List<TProviderResource>(templates.Count());
|
||||
var result = new List<TProviderResource>(defaultDefinitions.Count());
|
||||
|
||||
foreach (var providerDefinition in templates)
|
||||
foreach (var providerDefinition in defaultDefinitions)
|
||||
{
|
||||
var providerResource = new TProviderResource();
|
||||
providerResource.InjectFrom(providerDefinition);
|
||||
providerResource.Fields = SchemaBuilder.ToSchema(providerDefinition.Settings);
|
||||
providerResource.InfoLink = String.Format("https://github.com/NzbDrone/NzbDrone/wiki/Supported-{0}#{1}",
|
||||
typeof(TProviderResource).Name.Replace("Resource", "s"),
|
||||
providerDefinition.Implementation.ToLower());
|
||||
|
||||
var presetDefinitions = _providerFactory.GetPresetDefinitions(providerDefinition);
|
||||
|
||||
providerResource.Presets = presetDefinitions.Select(v =>
|
||||
{
|
||||
var presetResource = new TProviderResource();
|
||||
presetResource.InjectFrom(v);
|
||||
presetResource.Fields = SchemaBuilder.ToSchema(v.Settings);
|
||||
|
||||
return presetResource as ProviderResource;
|
||||
}).ToList();
|
||||
|
||||
result.Add(providerResource);
|
||||
}
|
||||
|
|
|
@ -11,5 +11,8 @@ namespace NzbDrone.Api
|
|||
public List<Field> Fields { get; set; }
|
||||
public String Implementation { get; set; }
|
||||
public String ConfigContract { get; set; }
|
||||
public String InfoLink { get; set; }
|
||||
|
||||
public List<ProviderResource> Presets { get; set; }
|
||||
}
|
||||
}
|
|
@ -2,18 +2,20 @@
|
|||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Api.Episodes;
|
||||
|
||||
namespace NzbDrone.Api.Queue
|
||||
{
|
||||
public class QueueResource : RestResource
|
||||
{
|
||||
public Core.Tv.Series Series { get; set; }
|
||||
public Episode Episode { get; set; }
|
||||
public SeriesResource Series { get; set; }
|
||||
public EpisodeResource Episode { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public Decimal Size { get; set; }
|
||||
public String Title { get; set; }
|
||||
public Decimal Sizeleft { get; set; }
|
||||
public TimeSpan Timeleft { get; set; }
|
||||
public TimeSpan? Timeleft { get; set; }
|
||||
public String Status { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
|
@ -40,7 +41,8 @@ namespace NzbDrone.Api.Series
|
|||
PathExistsValidator pathExistsValidator,
|
||||
SeriesPathValidator seriesPathValidator,
|
||||
SeriesExistsValidator seriesExistsValidator,
|
||||
DroneFactoryValidator droneFactoryValidator
|
||||
DroneFactoryValidator droneFactoryValidator,
|
||||
SeriesAncestorValidator seriesAncestorValidator
|
||||
)
|
||||
: base(commandExecutor)
|
||||
{
|
||||
|
@ -59,17 +61,21 @@ namespace NzbDrone.Api.Series
|
|||
|
||||
SharedValidator.RuleFor(s => s.QualityProfileId).ValidId();
|
||||
|
||||
PutValidator.RuleFor(s => s.Path)
|
||||
.Cascade(CascadeMode.StopOnFirstFailure)
|
||||
.IsValidPath()
|
||||
.SetValidator(rootFolderValidator)
|
||||
.SetValidator(seriesPathValidator)
|
||||
.SetValidator(droneFactoryValidator);
|
||||
SharedValidator.RuleFor(s => s.Path)
|
||||
.Cascade(CascadeMode.StopOnFirstFailure)
|
||||
.IsValidPath()
|
||||
.SetValidator(rootFolderValidator)
|
||||
.SetValidator(seriesPathValidator)
|
||||
.SetValidator(droneFactoryValidator)
|
||||
.SetValidator(seriesAncestorValidator)
|
||||
.When(s => !s.Path.IsNullOrWhiteSpace());
|
||||
|
||||
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => String.IsNullOrEmpty(s.RootFolderPath));
|
||||
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => String.IsNullOrEmpty(s.Path));
|
||||
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => s.Path.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.Title).NotEmpty();
|
||||
PostValidator.RuleFor(s => s.TvdbId).GreaterThan(0).SetValidator(seriesExistsValidator);
|
||||
|
||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||
}
|
||||
|
||||
private void PopulateAlternativeTitles(List<SeriesResource> resources)
|
||||
|
|
|
@ -137,7 +137,7 @@ namespace NzbDrone.Common.Test.DiskProviderTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void move_read_only_file()
|
||||
public void should_be_able_to_move_read_only_file()
|
||||
{
|
||||
var source = GetTempFilePath();
|
||||
var destination = GetTempFilePath();
|
||||
|
@ -151,6 +151,23 @@ namespace NzbDrone.Common.Test.DiskProviderTests
|
|||
Subject.MoveFile(source, destination);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_delete_directory_with_read_only_file()
|
||||
{
|
||||
var sourceDir = GetTempFilePath();
|
||||
var source = Path.Combine(sourceDir, "test.txt");
|
||||
|
||||
Directory.CreateDirectory(sourceDir);
|
||||
|
||||
Subject.WriteAllText(source, "SourceFile");
|
||||
|
||||
File.SetAttributes(source, FileAttributes.ReadOnly);
|
||||
|
||||
Subject.DeleteFolder(sourceDir, true);
|
||||
|
||||
Directory.Exists(sourceDir).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void empty_folder_should_return_folder_modified_date()
|
||||
{
|
||||
|
|
|
@ -5,32 +5,7 @@ using NzbDrone.Test.Common;
|
|||
|
||||
namespace NzbDrone.Common.Test.DiskProviderTests
|
||||
{
|
||||
public class IsParentFixture : TestBase
|
||||
public class IsParentPathFixture : TestBase
|
||||
{
|
||||
private string _parent = @"C:\Test".AsOsAgnostic();
|
||||
|
||||
[Test]
|
||||
public void should_return_false_when_not_a_child()
|
||||
{
|
||||
var path = @"C:\Another Folder".AsOsAgnostic();
|
||||
|
||||
DiskProviderBase.IsParent(_parent, path).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_folder_is_parent_of_another_folder()
|
||||
{
|
||||
var path = @"C:\Test\TV".AsOsAgnostic();
|
||||
|
||||
DiskProviderBase.IsParent(_parent, path).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_folder_is_parent_of_a_file()
|
||||
{
|
||||
var path = @"C:\Test\30.Rock.S01E01.Pilot.avi".AsOsAgnostic();
|
||||
|
||||
DiskProviderBase.IsParent(_parent, path).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Common.Test
|
||||
{
|
||||
[TestFixture]
|
||||
public class LevenshteinDistanceFixture : TestBase
|
||||
{
|
||||
[TestCase("", "", 0)]
|
||||
[TestCase("abc", "abc", 0)]
|
||||
[TestCase("abc", "abcd", 1)]
|
||||
[TestCase("abcd", "abc", 1)]
|
||||
[TestCase("abc", "abd", 1)]
|
||||
[TestCase("abc", "adc", 1)]
|
||||
[TestCase("abcdefgh", "abcghdef", 4)]
|
||||
[TestCase("a.b.c.", "abc", 3)]
|
||||
[TestCase("Agents Of SHIELD", "Marvel's Agents Of S.H.I.E.L.D.", 15)]
|
||||
[TestCase("Agents of cracked", "Agents of shield", 6)]
|
||||
[TestCase("ABCxxx", "ABC1xx", 1)]
|
||||
[TestCase("ABC1xx", "ABCxxx", 1)]
|
||||
public void LevenshteinDistance(String text, String other, Int32 expected)
|
||||
{
|
||||
text.LevenshteinDistance(other).Should().Be(expected);
|
||||
}
|
||||
|
||||
[TestCase("", "", 0)]
|
||||
[TestCase("abc", "abc", 0)]
|
||||
[TestCase("abc", "abcd", 1)]
|
||||
[TestCase("abcd", "abc", 3)]
|
||||
[TestCase("abc", "abd", 3)]
|
||||
[TestCase("abc", "adc", 3)]
|
||||
[TestCase("abcdefgh", "abcghdef", 8)]
|
||||
[TestCase("a.b.c.", "abc", 0)]
|
||||
[TestCase("Agents of shield", "Marvel's Agents Of S.H.I.E.L.D.", 9)]
|
||||
[TestCase("Agents of shield", "Agents of cracked", 14)]
|
||||
[TestCase("Agents of shield", "the shield", 24)]
|
||||
[TestCase("ABCxxx", "ABC1xx", 3)]
|
||||
[TestCase("ABC1xx", "ABCxxx", 3)]
|
||||
public void LevenshteinDistanceClean(String text, String other, Int32 expected)
|
||||
{
|
||||
text.ToLower().LevenshteinDistanceClean(other.ToLower()).Should().Be(expected);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -67,6 +67,7 @@
|
|||
<Compile Include="EnsureTest\PathExtensionFixture.cs" />
|
||||
<Compile Include="EnvironmentTests\StartupArgumentsFixture.cs" />
|
||||
<Compile Include="EnvironmentTests\EnvironmentProviderTest.cs" />
|
||||
<Compile Include="LevenshteinDistanceFixture.cs" />
|
||||
<Compile Include="ReflectionExtensions.cs" />
|
||||
<Compile Include="PathExtensionFixture.cs" />
|
||||
<Compile Include="DiskProviderTests\DiskProviderFixtureBase.cs" />
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace NzbDrone.Common.Test
|
|||
[TestFixture]
|
||||
public class PathExtensionFixture : TestBase
|
||||
{
|
||||
private string _parent = @"C:\Test".AsOsAgnostic();
|
||||
|
||||
private IAppFolderInfo GetIAppDirectoryInfo()
|
||||
{
|
||||
|
@ -85,6 +86,64 @@ namespace NzbDrone.Common.Test
|
|||
{
|
||||
first.AsOsAgnostic().PathEquals(second.AsOsAgnostic()).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_false_when_not_a_child()
|
||||
{
|
||||
var path = @"C:\Another Folder".AsOsAgnostic();
|
||||
|
||||
_parent.IsParentPath(path).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_folder_is_parent_of_another_folder()
|
||||
{
|
||||
var path = @"C:\Test\TV".AsOsAgnostic();
|
||||
|
||||
_parent.IsParentPath(path).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_folder_is_parent_of_a_file()
|
||||
{
|
||||
var path = @"C:\Test\30.Rock.S01E01.Pilot.avi".AsOsAgnostic();
|
||||
|
||||
_parent.IsParentPath(path).Should().BeTrue();
|
||||
}
|
||||
[TestCase(@"C:\Test\", @"C:\Test\mydir")]
|
||||
[TestCase(@"C:\Test\", @"C:\Test\mydir\")]
|
||||
[TestCase(@"C:\Test", @"C:\Test\30.Rock.S01E01.Pilot.avi")]
|
||||
public void path_should_be_parent(string parentPath, string childPath)
|
||||
{
|
||||
parentPath.AsOsAgnostic().IsParentPath(childPath.AsOsAgnostic()).Should().BeTrue();
|
||||
}
|
||||
|
||||
[TestCase(@"C:\Test2\", @"C:\Test")]
|
||||
[TestCase(@"C:\Test\Test\", @"C:\Test\")]
|
||||
[TestCase(@"C:\Test\", @"C:\Test")]
|
||||
[TestCase(@"C:\Test\", @"C:\Test\")]
|
||||
public void path_should_not_be_parent(string parentPath, string childPath)
|
||||
{
|
||||
parentPath.AsOsAgnostic().IsParentPath(childPath.AsOsAgnostic()).Should().BeFalse();
|
||||
}
|
||||
|
||||
[TestCase(@"C:\test\", @"C:\Test\mydir")]
|
||||
[TestCase(@"C:\test", @"C:\Test\mydir\")]
|
||||
public void path_should_be_parent_on_windows_only(string parentPath, string childPath)
|
||||
{
|
||||
var expectedResult = OsInfo.IsWindows;
|
||||
|
||||
parentPath.IsParentPath(childPath).Should().Be(expectedResult);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
public void should_not_be_parent_when_it_is_grandparent()
|
||||
{
|
||||
var path = Path.Combine(_parent, "parent", "child");
|
||||
|
||||
_parent.IsParentPath(path).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void normalize_path_exception_empty()
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Common
|
||||
{
|
||||
public static class ConvertBase32
|
||||
{
|
||||
private static string ValidChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
public static byte[] FromBase32String(string str)
|
||||
{
|
||||
int numBytes = str.Length * 5 / 8;
|
||||
byte[] bytes = new Byte[numBytes];
|
||||
|
||||
// all UPPERCASE chars
|
||||
str = str.ToUpper();
|
||||
|
||||
int bitBuffer = 0;
|
||||
int bitBufferCount = 0;
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < str.Length;i++ )
|
||||
{
|
||||
bitBuffer = (bitBuffer << 5) | ValidChars.IndexOf(str[i]);
|
||||
bitBufferCount += 5;
|
||||
|
||||
if (bitBufferCount >= 8)
|
||||
{
|
||||
bitBufferCount -= 8;
|
||||
bytes[index++] = (byte)(bitBuffer >> bitBufferCount);
|
||||
}
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,45 +25,17 @@ namespace NzbDrone.Common.Disk
|
|||
public abstract void SetPermissions(string path, string mask, string user, string group);
|
||||
public abstract long? GetTotalSize(string path);
|
||||
|
||||
public static string GetRelativePath(string parentPath, string childPath)
|
||||
|
||||
public DateTime FolderGetCreationTimeUtc(string path)
|
||||
{
|
||||
if (!IsParent(parentPath, childPath))
|
||||
{
|
||||
throw new NotParentException("{0} is not a child of {1}", childPath, parentPath);
|
||||
}
|
||||
CheckFolderExists(path);
|
||||
|
||||
return childPath.Substring(parentPath.Length).Trim(Path.DirectorySeparatorChar);
|
||||
}
|
||||
|
||||
public static bool IsParent(string parentPath, string childPath)
|
||||
{
|
||||
parentPath = parentPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||
childPath = childPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||
|
||||
var parent = new DirectoryInfo(parentPath);
|
||||
var child = new DirectoryInfo(childPath);
|
||||
|
||||
while (child.Parent != null)
|
||||
{
|
||||
if (child.Parent.FullName == parent.FullName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
child = child.Parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
return new DirectoryInfo(path).CreationTimeUtc;
|
||||
}
|
||||
|
||||
public DateTime FolderGetLastWrite(string path)
|
||||
{
|
||||
Ensure.That(path, () => path).IsValidPath();
|
||||
|
||||
if (!FolderExists(path))
|
||||
{
|
||||
throw new DirectoryNotFoundException("Directory doesn't exist. " + path);
|
||||
}
|
||||
CheckFolderExists(path);
|
||||
|
||||
var dirFiles = GetFiles(path, SearchOption.AllDirectories).ToList();
|
||||
|
||||
|
@ -76,21 +48,38 @@ namespace NzbDrone.Common.Disk
|
|||
.Max(c => c.LastWriteTimeUtc);
|
||||
}
|
||||
|
||||
public DateTime FileGetCreationTimeUtc(string path)
|
||||
{
|
||||
CheckFileExists(path);
|
||||
|
||||
return new FileInfo(path).CreationTimeUtc;
|
||||
}
|
||||
|
||||
public DateTime FileGetLastWrite(string path)
|
||||
{
|
||||
PathEnsureFileExists(path);
|
||||
CheckFileExists(path);
|
||||
|
||||
return new FileInfo(path).LastWriteTime;
|
||||
}
|
||||
|
||||
public DateTime FileGetLastWriteUtc(string path)
|
||||
{
|
||||
PathEnsureFileExists(path);
|
||||
CheckFileExists(path);
|
||||
|
||||
return new FileInfo(path).LastWriteTimeUtc;
|
||||
}
|
||||
|
||||
private void PathEnsureFileExists(string path)
|
||||
private void CheckFolderExists(string path)
|
||||
{
|
||||
Ensure.That(path, () => path).IsValidPath();
|
||||
|
||||
if (!FolderExists(path))
|
||||
{
|
||||
throw new DirectoryNotFoundException("Directory doesn't exist. " + path);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckFileExists(string path)
|
||||
{
|
||||
Ensure.That(path, () => path).IsValidPath();
|
||||
|
||||
|
@ -286,6 +275,9 @@ namespace NzbDrone.Common.Disk
|
|||
{
|
||||
Ensure.That(path, () => path).IsValidPath();
|
||||
|
||||
var files = Directory.GetFiles(path, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
|
||||
Array.ForEach(files, RemoveReadOnly);
|
||||
|
||||
Directory.Delete(path, recursive);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,9 @@ namespace NzbDrone.Common.Disk
|
|||
void InheritFolderPermissions(string filename);
|
||||
void SetPermissions(string path, string mask, string user, string group);
|
||||
long? GetTotalSize(string path);
|
||||
DateTime FolderGetCreationTimeUtc(string path);
|
||||
DateTime FolderGetLastWrite(string path);
|
||||
DateTime FileGetCreationTimeUtc(string path);
|
||||
DateTime FileGetLastWrite(string path);
|
||||
DateTime FileGetLastWriteUtc(string path);
|
||||
void EnsureFolder(string path);
|
||||
|
|
|
@ -24,11 +24,14 @@ namespace NzbDrone.Common.EnvironmentInfo
|
|||
if (!IsMono)
|
||||
{
|
||||
Os = Os.Windows;
|
||||
}
|
||||
|
||||
PathStringComparison = StringComparison.OrdinalIgnoreCase;
|
||||
}
|
||||
else
|
||||
{
|
||||
Os = IsOsx ? Os.Osx : Os.Linux;
|
||||
|
||||
PathStringComparison = StringComparison.Ordinal;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +43,7 @@ namespace NzbDrone.Common.EnvironmentInfo
|
|||
public static bool IsWindows { get; private set; }
|
||||
public static Os Os { get; private set; }
|
||||
public static DayOfWeek FirstDayOfWeek { get; private set; }
|
||||
public static StringComparison PathStringComparison { get; private set; }
|
||||
|
||||
//Borrowed from: https://github.com/jpobst/Pinta/blob/master/Pinta.Core/Managers/SystemManager.cs
|
||||
//From Managed.Windows.Forms/XplatUI
|
||||
|
|
|
@ -84,6 +84,7 @@ namespace NzbDrone.Common.Http
|
|||
public Stream DownloadStream(string url, NetworkCredential credential = null)
|
||||
{
|
||||
var request = (HttpWebRequest)WebRequest.Create(url);
|
||||
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
|
||||
request.UserAgent = _userAgent;
|
||||
request.Timeout = 20 * 1000;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace NzbDrone.Common.Http
|
|||
if (request is HttpWebRequest)
|
||||
{
|
||||
((HttpWebRequest)request).KeepAlive = false;
|
||||
((HttpWebRequest)request).ServicePoint.Expect100Continue = false;
|
||||
}
|
||||
|
||||
return request;
|
||||
|
|
|
@ -22,7 +22,8 @@ namespace NzbDrone.Common.Instrumentation
|
|||
RegisterDebugger();
|
||||
}
|
||||
|
||||
RegisterExceptron();
|
||||
//Disabling for now - until its fixed or we yank it out
|
||||
//RegisterExceptron();
|
||||
|
||||
if (updateApp)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
|
||||
namespace NzbDrone.Common
|
||||
{
|
||||
public static class LevenstheinExtensions
|
||||
{
|
||||
public static Int32 LevenshteinDistance(this String text, String other, Int32 costInsert = 1, Int32 costDelete = 1, Int32 costSubstitute = 1)
|
||||
{
|
||||
if (text == other) return 0;
|
||||
if (text.Length == 0) return other.Length * costInsert;
|
||||
if (other.Length == 0) return text.Length * costDelete;
|
||||
|
||||
Int32[] matrix = new Int32[other.Length + 1];
|
||||
|
||||
for (var i = 1; i < matrix.Length; i++)
|
||||
{
|
||||
matrix[i] = i * costInsert;
|
||||
}
|
||||
|
||||
for (var i = 0; i < text.Length; i++)
|
||||
{
|
||||
Int32 topLeft = matrix[0];
|
||||
matrix[0] = matrix[0] + costDelete;
|
||||
|
||||
for (var j = 0; j < other.Length; j++)
|
||||
{
|
||||
Int32 top = matrix[j];
|
||||
Int32 left = matrix[j + 1];
|
||||
|
||||
var sumIns = top + costInsert;
|
||||
var sumDel = left + costDelete;
|
||||
var sumSub = topLeft + (text[i] == other[j] ? 0 : costSubstitute);
|
||||
|
||||
topLeft = matrix[j + 1];
|
||||
matrix[j + 1] = Math.Min(Math.Min(sumIns, sumDel), sumSub);
|
||||
}
|
||||
}
|
||||
|
||||
return matrix[other.Length];
|
||||
}
|
||||
|
||||
public static Int32 LevenshteinDistanceClean(this String expected, String other)
|
||||
{
|
||||
expected = expected.ToLower().Replace(".", "");
|
||||
other = other.ToLower().Replace(".", "");
|
||||
|
||||
return expected.LevenshteinDistance(other, 1, 3, 3);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,6 +60,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ArchiveProvider.cs" />
|
||||
<Compile Include="ConvertBase32.cs" />
|
||||
<Compile Include="Cache\Cached.cs" />
|
||||
<Compile Include="Cache\CacheManager.cs" />
|
||||
<Compile Include="Cache\ICached.cs" />
|
||||
|
@ -113,6 +114,7 @@
|
|||
<Compile Include="Serializer\IntConverter.cs" />
|
||||
<Compile Include="Services.cs" />
|
||||
<Compile Include="Extensions\StreamExtensions.cs" />
|
||||
<Compile Include="LevenstheinExtensions.cs" />
|
||||
<Compile Include="TPL\LimitedConcurrencyLevelTaskScheduler.cs" />
|
||||
<Compile Include="Security\IgnoreCertErrorPolicy.cs" />
|
||||
<Compile Include="StringExtensions.cs" />
|
||||
|
|
|
@ -39,14 +39,39 @@ namespace NzbDrone.Common
|
|||
|
||||
public static bool PathEquals(this string firstPath, string secondPath)
|
||||
{
|
||||
if (OsInfo.IsMono)
|
||||
if (firstPath.Equals(secondPath, OsInfo.PathStringComparison)) return true;
|
||||
return String.Equals(firstPath.CleanFilePath(), secondPath.CleanFilePath(), OsInfo.PathStringComparison);
|
||||
}
|
||||
|
||||
public static string GetRelativePath(this string parentPath, string childPath)
|
||||
{
|
||||
if (!parentPath.IsParentPath(childPath))
|
||||
{
|
||||
if (firstPath.Equals(secondPath)) return true;
|
||||
return String.Equals(firstPath.CleanFilePath(), secondPath.CleanFilePath());
|
||||
throw new Exceptions.NotParentException("{0} is not a child of {1}", childPath, parentPath);
|
||||
}
|
||||
|
||||
if (firstPath.Equals(secondPath, StringComparison.OrdinalIgnoreCase)) return true;
|
||||
return String.Equals(firstPath.CleanFilePath(), secondPath.CleanFilePath(), StringComparison.OrdinalIgnoreCase);
|
||||
return childPath.Substring(parentPath.Length).Trim(Path.DirectorySeparatorChar);
|
||||
}
|
||||
|
||||
public static bool IsParentPath(this string parentPath, string childPath)
|
||||
{
|
||||
parentPath = parentPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||
childPath = childPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||
|
||||
var parent = new DirectoryInfo(parentPath);
|
||||
var child = new DirectoryInfo(childPath);
|
||||
|
||||
while (child.Parent != null)
|
||||
{
|
||||
if (child.Parent.FullName.Equals(parent.FullName, OsInfo.PathStringComparison))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
child = child.Parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static readonly Regex WindowsPathWithDriveRegex = new Regex(@"^[a-zA-Z]:\\", RegexOptions.Compiled);
|
||||
|
|
|
@ -14,6 +14,8 @@ namespace NzbDrone.Core.Test.Configuration
|
|||
public void SetUp()
|
||||
{
|
||||
Mocker.SetConstant<IConfigRepository>(Mocker.Resolve<ConfigRepository>());
|
||||
|
||||
Db.All<Config>().ForEach(Db.Delete);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -67,7 +67,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Mocker.GetMock<IHistoryService>().Setup(c => c.GetBestQualityInHistory(It.IsAny<QualityProfile>(), 3)).Returns<QualityModel>(null);
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(c => c.GetDownloadClient()).Returns(Mocker.GetMock<IDownloadClient>().Object);
|
||||
.Setup(c => c.GetDownloadClients())
|
||||
.Returns(new IDownloadClient[] { Mocker.GetMock<IDownloadClient>().Object });
|
||||
}
|
||||
|
||||
private void WithFirstReportUpgradable()
|
||||
|
@ -83,7 +84,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
private void GivenSabnzbdDownloadClient()
|
||||
{
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(c => c.GetDownloadClient()).Returns(Mocker.Resolve<Sabnzbd>());
|
||||
.Setup(c => c.GetDownloadClients())
|
||||
.Returns(new IDownloadClient[] { Mocker.Resolve<Sabnzbd>() });
|
||||
}
|
||||
|
||||
private void GivenMostRecentForEpisode(HistoryEventType eventType)
|
||||
|
|
|
@ -9,6 +9,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Queue;
|
||||
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
|
@ -18,7 +19,6 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
private Series _series;
|
||||
private Episode _episode;
|
||||
private RemoteEpisode _remoteEpisode;
|
||||
private Mock<IDownloadClient> _downloadClient;
|
||||
|
||||
private Series _otherSeries;
|
||||
private Episode _otherEpisode;
|
||||
|
@ -50,34 +50,30 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
.With(r => r.Episodes = new List<Episode> { _episode })
|
||||
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD)})
|
||||
.Build();
|
||||
|
||||
_downloadClient = Mocker.GetMock<IDownloadClient>();
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClient())
|
||||
.Returns(_downloadClient.Object);
|
||||
}
|
||||
|
||||
private void GivenEmptyQueue()
|
||||
{
|
||||
_downloadClient.Setup(s => s.GetQueue())
|
||||
.Returns(new List<QueueItem>());
|
||||
Mocker.GetMock<IQueueService>()
|
||||
.Setup(s => s.GetQueue())
|
||||
.Returns(new List<Queue.Queue>());
|
||||
}
|
||||
|
||||
private void GivenQueue(IEnumerable<RemoteEpisode> remoteEpisodes)
|
||||
{
|
||||
var queue = new List<QueueItem>();
|
||||
var queue = new List<Queue.Queue>();
|
||||
|
||||
foreach (var remoteEpisode in remoteEpisodes)
|
||||
{
|
||||
queue.Add(new QueueItem
|
||||
{
|
||||
RemoteEpisode = remoteEpisode
|
||||
queue.Add(new Queue.Queue
|
||||
{
|
||||
RemoteEpisode = remoteEpisode
|
||||
});
|
||||
}
|
||||
|
||||
_downloadClient.Setup(s => s.GetQueue())
|
||||
.Returns(queue);
|
||||
Mocker.GetMock<IQueueService>()
|
||||
.Setup(s => s.GetQueue())
|
||||
.Returns(queue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -0,0 +1,439 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using FizzWare.NBuilder;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download
|
||||
{
|
||||
[TestFixture]
|
||||
public class CompletedDownloadServiceFixture : CoreTest<DownloadTrackingService>
|
||||
{
|
||||
private List<DownloadClientItem> _completed;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_completed = Builder<DownloadClientItem>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(h => h.Status = DownloadItemStatus.Completed)
|
||||
.With(h => h.OutputPath = @"C:\DropFolder\MyDownload".AsOsAgnostic())
|
||||
.With(h => h.RemoteEpisode = new RemoteEpisode
|
||||
{
|
||||
Episodes = new List<Episode> { new Episode { Id = 1 } }
|
||||
})
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(c => c.GetDownloadClients())
|
||||
.Returns( new IDownloadClient[] { Mocker.GetMock<IDownloadClient>().Object });
|
||||
|
||||
Mocker.GetMock<IDownloadClient>()
|
||||
.SetupGet(c => c.Definition)
|
||||
.Returns(new Core.Download.DownloadClientDefinition { Id = 1, Name = "testClient" });
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.EnableCompletedDownloadHandling)
|
||||
.Returns(true);
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.RemoveCompletedDownloads)
|
||||
.Returns(true);
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.Failed())
|
||||
.Returns(new List<History.History>());
|
||||
|
||||
Mocker.SetConstant<ICompletedDownloadService>(Mocker.Resolve<CompletedDownloadService>());
|
||||
}
|
||||
|
||||
private void GivenNoGrabbedHistory()
|
||||
{
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.Grabbed())
|
||||
.Returns(new List<History.History>());
|
||||
}
|
||||
|
||||
private void GivenGrabbedHistory(List<History.History> history)
|
||||
{
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.Grabbed())
|
||||
.Returns(history);
|
||||
}
|
||||
|
||||
private void GivenNoImportedHistory()
|
||||
{
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.Imported())
|
||||
.Returns(new List<History.History>());
|
||||
}
|
||||
|
||||
private void GivenImportedHistory(List<History.History> importedHistory)
|
||||
{
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.Imported())
|
||||
.Returns(importedHistory);
|
||||
}
|
||||
|
||||
private void GivenCompletedDownloadClientHistory(bool hasStorage = true)
|
||||
{
|
||||
Mocker.GetMock<IDownloadClient>()
|
||||
.Setup(s => s.GetItems())
|
||||
.Returns(_completed);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.FolderExists(It.IsAny<string>()))
|
||||
.Returns(hasStorage);
|
||||
}
|
||||
|
||||
private void GivenCompletedImport()
|
||||
{
|
||||
Mocker.GetMock<IDownloadedEpisodesImportService>()
|
||||
.Setup(v => v.ProcessFolder(It.IsAny<DirectoryInfo>(), It.IsAny<DownloadClientItem>()))
|
||||
.Returns(new List<Core.MediaFiles.EpisodeImport.ImportDecision>() { new Core.MediaFiles.EpisodeImport.ImportDecision(null) });
|
||||
}
|
||||
|
||||
private void GivenFailedImport()
|
||||
{
|
||||
Mocker.GetMock<IDownloadedEpisodesImportService>()
|
||||
.Setup(v => v.ProcessFolder(It.IsAny<DirectoryInfo>(), It.IsAny<DownloadClientItem>()))
|
||||
.Returns(new List<Core.MediaFiles.EpisodeImport.ImportDecision>());
|
||||
}
|
||||
|
||||
private void VerifyNoImports()
|
||||
{
|
||||
Mocker.GetMock<IDownloadedEpisodesImportService>()
|
||||
.Verify(v => v.ProcessFolder(It.IsAny<DirectoryInfo>(), It.IsAny<DownloadClientItem>()), Times.Never());
|
||||
}
|
||||
|
||||
private void VerifyImports()
|
||||
{
|
||||
Mocker.GetMock<IDownloadedEpisodesImportService>()
|
||||
.Verify(v => v.ProcessFolder(It.IsAny<DirectoryInfo>(), It.IsAny<DownloadClientItem>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_process_if_matching_history_is_not_found_but_category_specified()
|
||||
{
|
||||
_completed.First().Category = "tv";
|
||||
|
||||
GivenCompletedDownloadClientHistory();
|
||||
GivenNoGrabbedHistory();
|
||||
GivenNoImportedHistory();
|
||||
GivenCompletedImport();
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyImports();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_process_if_matching_history_is_not_found_and_no_category_specified()
|
||||
{
|
||||
_completed.First().Category = null;
|
||||
|
||||
GivenCompletedDownloadClientHistory();
|
||||
GivenNoGrabbedHistory();
|
||||
GivenNoImportedHistory();
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoImports();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_process_if_grabbed_history_contains_null_downloadclient_id()
|
||||
{
|
||||
_completed.First().Category = null;
|
||||
|
||||
GivenCompletedDownloadClientHistory();
|
||||
|
||||
var historyGrabbed = Builder<History.History>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
historyGrabbed.First().Data.Add("downloadClientId", null);
|
||||
|
||||
GivenGrabbedHistory(historyGrabbed);
|
||||
GivenNoImportedHistory();
|
||||
GivenFailedImport();
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoImports();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_process_if_failed_history_contains_null_downloadclient_id()
|
||||
{
|
||||
GivenCompletedDownloadClientHistory();
|
||||
|
||||
var historyGrabbed = Builder<History.History>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
historyGrabbed.First().Data.Add("downloadClientId", _completed.First().DownloadClientId);
|
||||
|
||||
GivenGrabbedHistory(historyGrabbed);
|
||||
|
||||
var historyImported = Builder<History.History>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
historyImported.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
historyImported.First().Data.Add("downloadClientId", null);
|
||||
|
||||
GivenImportedHistory(historyImported);
|
||||
GivenCompletedImport();
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyImports();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_process_if_already_added_to_history_as_imported()
|
||||
{
|
||||
GivenCompletedDownloadClientHistory();
|
||||
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
GivenGrabbedHistory(history);
|
||||
GivenImportedHistory(history);
|
||||
|
||||
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId);
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoImports();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_process_if_not_already_in_imported_history()
|
||||
{
|
||||
GivenCompletedDownloadClientHistory();
|
||||
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
GivenGrabbedHistory(history);
|
||||
GivenNoImportedHistory();
|
||||
GivenCompletedImport();
|
||||
|
||||
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId);
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyImports();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_process_if_storage_directory_does_not_exist()
|
||||
{
|
||||
GivenCompletedDownloadClientHistory(false);
|
||||
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
GivenGrabbedHistory(history);
|
||||
GivenNoImportedHistory();
|
||||
|
||||
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId);
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoImports();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_process_if_storage_directory_in_drone_factory()
|
||||
{
|
||||
GivenCompletedDownloadClientHistory(true);
|
||||
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
GivenGrabbedHistory(history);
|
||||
GivenNoImportedHistory();
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(v => v.DownloadedEpisodesFolder)
|
||||
.Returns(@"C:\DropFolder".AsOsAgnostic());
|
||||
|
||||
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId);
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoImports();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_process_as_already_imported_if_drone_factory_import_history_exists()
|
||||
{
|
||||
GivenCompletedDownloadClientHistory(false);
|
||||
|
||||
_completed.Clear();
|
||||
_completed.AddRange(Builder<DownloadClientItem>.CreateListOfSize(2)
|
||||
.All()
|
||||
.With(h => h.Status = DownloadItemStatus.Completed)
|
||||
.With(h => h.OutputPath = @"C:\DropFolder\MyDownload".AsOsAgnostic())
|
||||
.With(h => h.RemoteEpisode = new RemoteEpisode
|
||||
{
|
||||
Episodes = new List<Episode> { new Episode { Id = 1 } }
|
||||
})
|
||||
.Build());
|
||||
|
||||
var grabbedHistory = Builder<History.History>.CreateListOfSize(2)
|
||||
.All()
|
||||
.With(d => d.Data["downloadClient"] = "SabnzbdClient")
|
||||
.TheFirst(1)
|
||||
.With(d => d.Data["downloadClientId"] = _completed.First().DownloadClientId)
|
||||
.With(d => d.SourceTitle = "Droned.S01E01.720p-LAZY")
|
||||
.TheLast(1)
|
||||
.With(d => d.Data["downloadClientId"] = _completed.Last().DownloadClientId)
|
||||
.With(d => d.SourceTitle = "Droned.S01E01.Proper.720p-LAZY")
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
var importedHistory = Builder<History.History>.CreateListOfSize(2)
|
||||
.All()
|
||||
.With(d => d.EpisodeId = 1)
|
||||
.TheFirst(1)
|
||||
.With(d => d.Data["droppedPath"] = @"C:\mydownload\Droned.S01E01.720p-LAZY\lzy-dr101.mkv".AsOsAgnostic())
|
||||
.TheLast(1)
|
||||
.With(d => d.Data["droppedPath"] = @"C:\mydownload\Droned.S01E01.Proper.720p-LAZY\lzy-dr101.mkv".AsOsAgnostic())
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
GivenGrabbedHistory(grabbedHistory);
|
||||
GivenImportedHistory(importedHistory);
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoImports();
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Verify(v => v.UpdateHistoryData(It.IsAny<int>(), It.IsAny<Dictionary<String, String>>()), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_remove_if_config_disabled()
|
||||
{
|
||||
GivenCompletedDownloadClientHistory();
|
||||
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
GivenGrabbedHistory(history);
|
||||
GivenNoImportedHistory();
|
||||
GivenCompletedImport();
|
||||
|
||||
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId);
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.RemoveCompletedDownloads)
|
||||
.Returns(false);
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(c => c.DeleteFolder(It.IsAny<string>(), true), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_remove_while_readonly()
|
||||
{
|
||||
GivenCompletedDownloadClientHistory();
|
||||
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
GivenGrabbedHistory(history);
|
||||
GivenNoImportedHistory();
|
||||
GivenCompletedImport();
|
||||
|
||||
_completed.First().IsReadOnly = true;
|
||||
|
||||
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId);
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(c => c.DeleteFolder(It.IsAny<string>(), true), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_remove_if_imported_failed()
|
||||
{
|
||||
GivenCompletedDownloadClientHistory();
|
||||
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
GivenGrabbedHistory(history);
|
||||
GivenNoImportedHistory();
|
||||
GivenFailedImport();
|
||||
|
||||
_completed.First().IsReadOnly = true;
|
||||
|
||||
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId);
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(c => c.DeleteFolder(It.IsAny<string>(), true), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_remove_if_imported()
|
||||
{
|
||||
GivenCompletedDownloadClientHistory();
|
||||
|
||||
var history = Builder<History.History>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
GivenGrabbedHistory(history);
|
||||
GivenNoImportedHistory();
|
||||
GivenCompletedImport();
|
||||
|
||||
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId);
|
||||
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(c => c.DeleteFolder(It.IsAny<string>(), true), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using FluentAssertions;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.Clients;
|
||||
using NzbDrone.Core.Download.Clients.UsenetBlackhole;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class UsenetBlackholeFixture : DownloadClientFixtureBase<UsenetBlackhole>
|
||||
{
|
||||
protected string _completedDownloadFolder;
|
||||
protected string _blackholeFolder;
|
||||
protected string _filePath;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_completedDownloadFolder = @"c:\blackhole\completed".AsOsAgnostic();
|
||||
_blackholeFolder = @"c:\blackhole\nzb".AsOsAgnostic();
|
||||
_filePath = (@"c:\blackhole\nzb\" + _title + ".nzb").AsOsAgnostic();
|
||||
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new UsenetBlackholeSettings
|
||||
{
|
||||
NzbFolder = _blackholeFolder,
|
||||
WatchFolder = _completedDownloadFolder
|
||||
};
|
||||
}
|
||||
|
||||
protected void WithSuccessfulDownload()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected void WithFailedDownload()
|
||||
{
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Throws(new WebException());
|
||||
}
|
||||
|
||||
protected void GivenCompletedItem()
|
||||
{
|
||||
var targetDir = Path.Combine(_completedDownloadFolder, _title);
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetDirectories(_completedDownloadFolder))
|
||||
.Returns(new[] { targetDir });
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
|
||||
.Returns(new[] { Path.Combine(_completedDownloadFolder, "somefile.mkv") });
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetFileSize(It.IsAny<string>()))
|
||||
.Returns(1000000);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void completed_download_should_have_required_properties()
|
||||
{
|
||||
GivenCompletedItem();
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyCompleted(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Download_should_download_file_if_it_doesnt_exist()
|
||||
{
|
||||
var remoteEpisode = CreateRemoteEpisode();
|
||||
|
||||
Subject.Download(remoteEpisode);
|
||||
|
||||
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(_downloadUrl, _filePath), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Download_should_replace_illegal_characters_in_title()
|
||||
{
|
||||
var illegalTitle = "Saturday Night Live - S38E08 - Jeremy Renner/Maroon 5 [SDTV]";
|
||||
var expectedFilename = Path.Combine(_blackholeFolder, "Saturday Night Live - S38E08 - Jeremy Renner+Maroon 5 [SDTV]" + Path.GetExtension(_filePath));
|
||||
|
||||
var remoteEpisode = CreateRemoteEpisode();
|
||||
remoteEpisode.Release.Title = illegalTitle;
|
||||
|
||||
Subject.Download(remoteEpisode);
|
||||
|
||||
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(It.IsAny<string>(), expectedFilename), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_considered_locked_files_downloading()
|
||||
{
|
||||
GivenCompletedItem();
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.IsFileLocked(It.IsAny<string>()))
|
||||
.Returns(true);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
result.Status.Should().Be(DownloadItemStatus.Downloading);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
using System.IO;
|
||||
using System.Net;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.Clients;
|
||||
using NzbDrone.Core.Download.Clients.Blackhole;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class BlackholeProviderFixture : CoreTest<Blackhole>
|
||||
{
|
||||
private const string _nzbUrl = "http://www.nzbs.com/url";
|
||||
private const string _title = "some_nzb_title";
|
||||
private string _blackHoleFolder;
|
||||
private string _nzbPath;
|
||||
private RemoteEpisode _remoteEpisode;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_blackHoleFolder = @"c:\nzb\blackhole\".AsOsAgnostic();
|
||||
_nzbPath = @"c:\nzb\blackhole\some_nzb_title.nzb".AsOsAgnostic();
|
||||
|
||||
_remoteEpisode = new RemoteEpisode();
|
||||
_remoteEpisode.Release = new ReleaseInfo();
|
||||
_remoteEpisode.Release.Title = _title;
|
||||
_remoteEpisode.Release.DownloadUrl = _nzbUrl;
|
||||
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new FolderSettings
|
||||
{
|
||||
Folder = _blackHoleFolder
|
||||
};
|
||||
}
|
||||
|
||||
private void WithExistingFile()
|
||||
{
|
||||
Mocker.GetMock<IDiskProvider>().Setup(c => c.FileExists(_nzbPath)).Returns(true);
|
||||
}
|
||||
|
||||
private void WithFailedDownload()
|
||||
{
|
||||
Mocker.GetMock<IHttpProvider>().Setup(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>())).Throws(new WebException());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DownloadNzb_should_download_file_if_it_doesnt_exist()
|
||||
{
|
||||
Subject.DownloadNzb(_remoteEpisode);
|
||||
|
||||
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(_nzbUrl, _nzbPath), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_replace_illegal_characters_in_title()
|
||||
{
|
||||
var illegalTitle = "Saturday Night Live - S38E08 - Jeremy Renner/Maroon 5 [SDTV]";
|
||||
var expectedFilename = Path.Combine(_blackHoleFolder, "Saturday Night Live - S38E08 - Jeremy Renner+Maroon 5 [SDTV].nzb");
|
||||
_remoteEpisode.Release.Title = illegalTitle;
|
||||
|
||||
Subject.DownloadNzb(_remoteEpisode);
|
||||
|
||||
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(It.IsAny<string>(), expectedFilename), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using FluentAssertions;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests
|
||||
{
|
||||
public abstract class DownloadClientFixtureBase<TSubject> : CoreTest<TSubject>
|
||||
where TSubject : class, IDownloadClient
|
||||
{
|
||||
protected readonly string _title = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE";
|
||||
protected readonly string _downloadUrl = "http://somewhere.com/Droned.S01E01.Pilot.1080p.WEB-DL-DRONE.ext";
|
||||
|
||||
[SetUp]
|
||||
public void SetupBase()
|
||||
{
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.DownloadClientHistoryLimit)
|
||||
.Returns(30);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), null))
|
||||
.Returns(CreateRemoteEpisode());
|
||||
}
|
||||
|
||||
protected virtual RemoteEpisode CreateRemoteEpisode()
|
||||
{
|
||||
var remoteEpisode = new RemoteEpisode();
|
||||
remoteEpisode.Release = new ReleaseInfo();
|
||||
remoteEpisode.Release.Title = _title;
|
||||
remoteEpisode.Release.DownloadUrl = _downloadUrl;
|
||||
remoteEpisode.Release.DownloadProtocol = Subject.Protocol;
|
||||
|
||||
remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
|
||||
remoteEpisode.ParsedEpisodeInfo.FullSeason = false;
|
||||
|
||||
remoteEpisode.Episodes = new List<Episode>();
|
||||
|
||||
remoteEpisode.Series = new Series();
|
||||
|
||||
return remoteEpisode;
|
||||
}
|
||||
|
||||
protected void VerifyIdentifiable(DownloadClientItem downloadClientItem)
|
||||
{
|
||||
downloadClientItem.DownloadClient.Should().Be(Subject.Definition.Name);
|
||||
downloadClientItem.DownloadClientId.Should().NotBeNullOrEmpty();
|
||||
|
||||
downloadClientItem.Title.Should().NotBeNullOrEmpty();
|
||||
|
||||
downloadClientItem.RemoteEpisode.Should().NotBeNull();
|
||||
|
||||
}
|
||||
|
||||
protected void VerifyQueued(DownloadClientItem downloadClientItem)
|
||||
{
|
||||
VerifyIdentifiable(downloadClientItem);
|
||||
downloadClientItem.RemainingSize.Should().NotBe(0);
|
||||
//downloadClientItem.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||
//downloadClientItem.OutputPath.Should().NotBeNullOrEmpty();
|
||||
downloadClientItem.Status.Should().Be(DownloadItemStatus.Queued);
|
||||
}
|
||||
|
||||
protected void VerifyPaused(DownloadClientItem downloadClientItem)
|
||||
{
|
||||
VerifyIdentifiable(downloadClientItem);
|
||||
|
||||
downloadClientItem.RemainingSize.Should().NotBe(0);
|
||||
//downloadClientItem.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||
//downloadClientItem.OutputPath.Should().NotBeNullOrEmpty();
|
||||
downloadClientItem.Status.Should().Be(DownloadItemStatus.Paused);
|
||||
}
|
||||
|
||||
protected void VerifyDownloading(DownloadClientItem downloadClientItem)
|
||||
{
|
||||
VerifyIdentifiable(downloadClientItem);
|
||||
|
||||
downloadClientItem.RemainingSize.Should().NotBe(0);
|
||||
//downloadClientItem.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||
//downloadClientItem.OutputPath.Should().NotBeNullOrEmpty();
|
||||
downloadClientItem.Status.Should().Be(DownloadItemStatus.Downloading);
|
||||
}
|
||||
|
||||
protected void VerifyCompleted(DownloadClientItem downloadClientItem)
|
||||
{
|
||||
VerifyIdentifiable(downloadClientItem);
|
||||
|
||||
downloadClientItem.Title.Should().NotBeNullOrEmpty();
|
||||
downloadClientItem.RemainingSize.Should().Be(0);
|
||||
downloadClientItem.RemainingTime.Should().Be(TimeSpan.Zero);
|
||||
//downloadClientItem.OutputPath.Should().NotBeNullOrEmpty();
|
||||
downloadClientItem.Status.Should().Be(DownloadItemStatus.Completed);
|
||||
}
|
||||
|
||||
protected void VerifyFailed(DownloadClientItem downloadClientItem)
|
||||
{
|
||||
VerifyIdentifiable(downloadClientItem);
|
||||
|
||||
downloadClientItem.Status.Should().Be(DownloadItemStatus.Failed);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.Clients.Nzbget;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
|
||||
{
|
||||
public class DownloadNzbFixture : CoreTest<Nzbget>
|
||||
{
|
||||
private const string _url = "http://www.nzbdrone.com";
|
||||
private const string _title = "30.Rock.S01E01.Pilot.720p.hdtv";
|
||||
private RemoteEpisode _remoteEpisode;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_remoteEpisode = new RemoteEpisode();
|
||||
_remoteEpisode.Release = new ReleaseInfo();
|
||||
_remoteEpisode.Release.Title = _title;
|
||||
_remoteEpisode.Release.DownloadUrl = _url;
|
||||
|
||||
_remoteEpisode.Episodes = Builder<Episode>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(e => e.AirDate = DateTime.Today.ToString(Episode.AIR_DATE_FORMAT))
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new NzbgetSettings
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6789,
|
||||
Username = "nzbget",
|
||||
Password = "pass",
|
||||
TvCategory = "tv",
|
||||
RecentTvPriority = (int)NzbgetPriority.High
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_add_item_to_queue()
|
||||
{
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), It.IsAny<Int32>(), It.IsAny<NzbgetSettings>()))
|
||||
.Returns("id");
|
||||
|
||||
Subject.DownloadNzb(_remoteEpisode);
|
||||
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Verify(v => v.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), It.IsAny<Int32>(), It.IsAny<NzbgetSettings>()), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.Clients.Nzbget;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class NzbgetFixture : DownloadClientFixtureBase<Nzbget>
|
||||
{
|
||||
private NzbgetQueueItem _queued;
|
||||
private NzbgetHistoryItem _failed;
|
||||
private NzbgetHistoryItem _completed;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new NzbgetSettings
|
||||
{
|
||||
Host = "192.168.5.55",
|
||||
Port = 2222,
|
||||
Username = "admin",
|
||||
Password = "pass",
|
||||
TvCategory = "tv",
|
||||
RecentTvPriority = (int)NzbgetPriority.High
|
||||
};
|
||||
|
||||
_queued = new NzbgetQueueItem
|
||||
{
|
||||
FileSizeLo = 1000,
|
||||
RemainingSizeLo = 10,
|
||||
Category = "tv",
|
||||
NzbName = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
|
||||
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } }
|
||||
};
|
||||
|
||||
_failed = new NzbgetHistoryItem
|
||||
{
|
||||
FileSizeLo = 1000,
|
||||
Category = "tv",
|
||||
Name = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
|
||||
DestDir = "somedirectory",
|
||||
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } },
|
||||
ParStatus = "Some Error",
|
||||
UnpackStatus = "NONE",
|
||||
MoveStatus = "NONE",
|
||||
ScriptStatus = "NONE",
|
||||
DeleteStatus = "NONE",
|
||||
MarkStatus = "NONE"
|
||||
};
|
||||
|
||||
_completed = new NzbgetHistoryItem
|
||||
{
|
||||
FileSizeLo = 1000,
|
||||
Category = "tv",
|
||||
Name = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
|
||||
DestDir = "somedirectory",
|
||||
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } },
|
||||
ParStatus = "SUCCESS",
|
||||
UnpackStatus = "NONE",
|
||||
MoveStatus = "SUCCESS",
|
||||
ScriptStatus = "NONE",
|
||||
DeleteStatus = "NONE",
|
||||
MarkStatus = "NONE"
|
||||
};
|
||||
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.GetGlobalStatus(It.IsAny<NzbgetSettings>()))
|
||||
.Returns(new NzbgetGlobalStatus
|
||||
{
|
||||
DownloadRate = 7000000
|
||||
});
|
||||
}
|
||||
|
||||
protected void WithFailedDownload()
|
||||
{
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<NzbgetSettings>()))
|
||||
.Returns((String)null);
|
||||
}
|
||||
|
||||
protected void WithSuccessfulDownload()
|
||||
{
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<NzbgetSettings>()))
|
||||
.Returns(Guid.NewGuid().ToString().Replace("-", ""));
|
||||
}
|
||||
|
||||
protected virtual void WithQueue(NzbgetQueueItem queue)
|
||||
{
|
||||
var list = new List<NzbgetQueueItem>();
|
||||
|
||||
if (queue != null)
|
||||
{
|
||||
list.Add(queue);
|
||||
}
|
||||
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.GetQueue(It.IsAny<NzbgetSettings>()))
|
||||
.Returns(list);
|
||||
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.GetPostQueue(It.IsAny<NzbgetSettings>()))
|
||||
.Returns(new List<NzbgetPostQueueItem>());
|
||||
}
|
||||
|
||||
protected virtual void WithHistory(NzbgetHistoryItem history)
|
||||
{
|
||||
var list = new List<NzbgetHistoryItem>();
|
||||
|
||||
if (history != null)
|
||||
{
|
||||
list.Add(history);
|
||||
}
|
||||
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.GetHistory(It.IsAny<NzbgetSettings>()))
|
||||
.Returns(list);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_return_no_items_when_queue_is_empty()
|
||||
{
|
||||
WithQueue(null);
|
||||
WithHistory(null);
|
||||
|
||||
Subject.GetItems().Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void queued_item_should_have_required_properties()
|
||||
{
|
||||
_queued.ActiveDownloads = 0;
|
||||
|
||||
WithQueue(_queued);
|
||||
WithHistory(null);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyQueued(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void paused_item_should_have_required_properties()
|
||||
{
|
||||
_queued.PausedSizeLo = _queued.RemainingSizeLo;
|
||||
|
||||
WithQueue(_queued);
|
||||
WithHistory(null);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyPaused(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void downloading_item_should_have_required_properties()
|
||||
{
|
||||
_queued.ActiveDownloads = 1;
|
||||
|
||||
WithQueue(_queued);
|
||||
WithHistory(null);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyDownloading(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void completed_download_should_have_required_properties()
|
||||
{
|
||||
WithQueue(null);
|
||||
WithHistory(_completed);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyCompleted(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void failed_item_should_have_required_properties()
|
||||
{
|
||||
WithQueue(null);
|
||||
WithHistory(_failed);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyFailed(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Download_should_return_unique_id()
|
||||
{
|
||||
WithSuccessfulDownload();
|
||||
|
||||
var remoteEpisode = CreateRemoteEpisode();
|
||||
|
||||
var id = Subject.Download(remoteEpisode);
|
||||
|
||||
id.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_ignore_downloads_from_other_categories()
|
||||
{
|
||||
_completed.Category = "mycat";
|
||||
|
||||
WithQueue(null);
|
||||
WithHistory(_completed);
|
||||
|
||||
var items = Subject.GetItems();
|
||||
|
||||
items.Should().BeEmpty();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.Clients.Nzbget;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
|
||||
{
|
||||
public class QueueFixture : CoreTest<Nzbget>
|
||||
{
|
||||
private List<NzbgetQueueItem> _queue;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_queue = Builder<NzbgetQueueItem>.CreateListOfSize(5)
|
||||
.All()
|
||||
.With(q => q.NzbName = "30.Rock.S01E01.Pilot.720p.hdtv.nzb")
|
||||
.With(q => q.Parameters = new List<NzbgetParameter>
|
||||
{
|
||||
new NzbgetParameter { Name = "drone", Value = "id" }
|
||||
})
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new NzbgetSettings
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6789,
|
||||
Username = "nzbget",
|
||||
Password = "pass",
|
||||
TvCategory = "tv",
|
||||
RecentTvPriority = (int)NzbgetPriority.High
|
||||
};
|
||||
}
|
||||
|
||||
private void WithFullQueue()
|
||||
{
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.GetQueue(It.IsAny<NzbgetSettings>()))
|
||||
.Returns(_queue);
|
||||
}
|
||||
|
||||
private void WithEmptyQueue()
|
||||
{
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.GetQueue(It.IsAny<NzbgetSettings>()))
|
||||
.Returns(new List<NzbgetQueueItem>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_no_items_when_queue_is_empty()
|
||||
{
|
||||
WithEmptyQueue();
|
||||
|
||||
Subject.GetQueue()
|
||||
.Should()
|
||||
.BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_item_when_queue_has_item()
|
||||
{
|
||||
WithFullQueue();
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), 0, null))
|
||||
.Returns(new RemoteEpisode {Series = new Series()});
|
||||
|
||||
Subject.GetQueue()
|
||||
.Should()
|
||||
.HaveCount(_queue.Count);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,9 +45,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
|
|||
_remoteEpisode.ParsedEpisodeInfo.FullSeason = false;
|
||||
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new FolderSettings
|
||||
Subject.Definition.Settings = new PneumaticSettings
|
||||
{
|
||||
Folder = _pneumaticFolder
|
||||
NzbFolder = _pneumaticFolder
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
|
|||
[Test]
|
||||
public void should_download_file_if_it_doesnt_exist()
|
||||
{
|
||||
Subject.DownloadNzb(_remoteEpisode);
|
||||
Subject.Download(_remoteEpisode);
|
||||
|
||||
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(_nzbUrl, _nzbPath), Times.Once());
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
|
|||
{
|
||||
WithFailedDownload();
|
||||
|
||||
Assert.Throws<WebException>(() => Subject.DownloadNzb(_remoteEpisode));
|
||||
Assert.Throws<WebException>(() => Subject.Download(_remoteEpisode));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -84,7 +84,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
|
|||
_remoteEpisode.Release.Title = "30 Rock - Season 1";
|
||||
_remoteEpisode.ParsedEpisodeInfo.FullSeason = true;
|
||||
|
||||
Assert.Throws<NotImplementedException>(() => Subject.DownloadNzb(_remoteEpisode));
|
||||
Assert.Throws<NotSupportedException>(() => Subject.Download(_remoteEpisode));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_throw_item_is_removed()
|
||||
{
|
||||
Assert.Throws<NotSupportedException>(() => Subject.RemoveItem(""));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -94,7 +100,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
|
|||
var expectedFilename = Path.Combine(_pneumaticFolder, "Saturday Night Live - S38E08 - Jeremy Renner+Maroon 5 [SDTV].nzb");
|
||||
_remoteEpisode.Release.Title = illegalTitle;
|
||||
|
||||
Subject.DownloadNzb(_remoteEpisode);
|
||||
Subject.Download(_remoteEpisode);
|
||||
|
||||
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(It.IsAny<string>(), expectedFilename), Times.Once());
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
|
@ -12,30 +13,20 @@ using NzbDrone.Core.Download.Clients.Sabnzbd.Responses;
|
|||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class SabnzbdFixture : CoreTest<Sabnzbd>
|
||||
public class SabnzbdFixture : DownloadClientFixtureBase<Sabnzbd>
|
||||
{
|
||||
private const string URL = "http://www.nzbclub.com/nzb_download.aspx?mid=1950232";
|
||||
private const string TITLE = "My Series Name - 5x2-5x3 - My title [Bluray720p] [Proper]";
|
||||
private RemoteEpisode _remoteEpisode;
|
||||
private SabnzbdQueue _queued;
|
||||
private SabnzbdHistory _failed;
|
||||
private SabnzbdHistory _completed;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_remoteEpisode = new RemoteEpisode();
|
||||
_remoteEpisode.Release = new ReleaseInfo();
|
||||
_remoteEpisode.Release.Title = TITLE;
|
||||
_remoteEpisode.Release.DownloadUrl = URL;
|
||||
|
||||
_remoteEpisode.Episodes = Builder<Episode>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(e => e.AirDate = DateTime.Today.ToString(Episode.AIR_DATE_FORMAT))
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new SabnzbdSettings
|
||||
{
|
||||
|
@ -47,19 +38,248 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||
TvCategory = "tv",
|
||||
RecentTvPriority = (int)SabnzbdPriority.High
|
||||
};
|
||||
_queued = new SabnzbdQueue
|
||||
{
|
||||
Paused = false,
|
||||
Items = new List<SabnzbdQueueItem>()
|
||||
{
|
||||
new SabnzbdQueueItem
|
||||
{
|
||||
Status = SabnzbdDownloadStatus.Downloading,
|
||||
Size = 1000,
|
||||
Sizeleft = 10,
|
||||
Timeleft = TimeSpan.FromSeconds(10),
|
||||
Category = "tv",
|
||||
Id = "sabnzbd_nzb12345",
|
||||
Title = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_failed = new SabnzbdHistory
|
||||
{
|
||||
Items = new List<SabnzbdHistoryItem>()
|
||||
{
|
||||
new SabnzbdHistoryItem
|
||||
{
|
||||
Status = SabnzbdDownloadStatus.Failed,
|
||||
Size = 1000,
|
||||
Category = "tv",
|
||||
Id = "sabnzbd_nzb12345",
|
||||
Title = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_completed = new SabnzbdHistory
|
||||
{
|
||||
Items = new List<SabnzbdHistoryItem>()
|
||||
{
|
||||
new SabnzbdHistoryItem
|
||||
{
|
||||
Status = SabnzbdDownloadStatus.Completed,
|
||||
Size = 1000,
|
||||
Category = "tv",
|
||||
Id = "sabnzbd_nzb12345",
|
||||
Title = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
|
||||
Storage = "somedirectory"
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected void WithFailedDownload()
|
||||
{
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<SabnzbdSettings>()))
|
||||
.Returns((SabnzbdAddResponse)null);
|
||||
}
|
||||
|
||||
protected void WithSuccessfulDownload()
|
||||
{
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), It.IsAny<int>(), It.IsAny<SabnzbdSettings>()))
|
||||
.Returns(new SabnzbdAddResponse()
|
||||
{
|
||||
Status = true,
|
||||
Ids = new List<string> { "sabznbd_nzo12345" }
|
||||
});
|
||||
}
|
||||
|
||||
protected virtual void WithQueue(SabnzbdQueue queue)
|
||||
{
|
||||
if (queue == null)
|
||||
{
|
||||
queue = new SabnzbdQueue() { Items = new List<SabnzbdQueueItem>() };
|
||||
}
|
||||
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Setup(s => s.GetQueue(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SabnzbdSettings>()))
|
||||
.Returns(queue);
|
||||
}
|
||||
|
||||
protected virtual void WithHistory(SabnzbdHistory history)
|
||||
{
|
||||
if (history == null)
|
||||
history = new SabnzbdHistory() { Items = new List<SabnzbdHistoryItem>() };
|
||||
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Setup(s => s.GetHistory(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SabnzbdSettings>()))
|
||||
.Returns(history);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void downloadNzb_should_use_sabRecentTvPriority_when_recentEpisode_is_true()
|
||||
public void GetItems_should_return_no_items_when_queue_is_empty()
|
||||
{
|
||||
WithQueue(null);
|
||||
WithHistory(null);
|
||||
|
||||
Subject.GetItems().Should().BeEmpty();
|
||||
}
|
||||
|
||||
[TestCase(SabnzbdDownloadStatus.Grabbing)]
|
||||
[TestCase(SabnzbdDownloadStatus.Queued)]
|
||||
public void queued_item_should_have_required_properties(SabnzbdDownloadStatus status)
|
||||
{
|
||||
_queued.Items.First().Status = status;
|
||||
|
||||
WithQueue(_queued);
|
||||
WithHistory(null);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyQueued(result);
|
||||
result.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||
}
|
||||
|
||||
[TestCase(SabnzbdDownloadStatus.Paused)]
|
||||
public void paused_item_should_have_required_properties(SabnzbdDownloadStatus status)
|
||||
{
|
||||
_queued.Items.First().Status = status;
|
||||
|
||||
WithQueue(_queued);
|
||||
WithHistory(null);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyPaused(result);
|
||||
}
|
||||
|
||||
[TestCase(SabnzbdDownloadStatus.Checking)]
|
||||
[TestCase(SabnzbdDownloadStatus.Downloading)]
|
||||
[TestCase(SabnzbdDownloadStatus.QuickCheck)]
|
||||
[TestCase(SabnzbdDownloadStatus.Verifying)]
|
||||
[TestCase(SabnzbdDownloadStatus.Repairing)]
|
||||
[TestCase(SabnzbdDownloadStatus.Fetching)]
|
||||
[TestCase(SabnzbdDownloadStatus.Extracting)]
|
||||
[TestCase(SabnzbdDownloadStatus.Moving)]
|
||||
[TestCase(SabnzbdDownloadStatus.Running)]
|
||||
public void downloading_item_should_have_required_properties(SabnzbdDownloadStatus status)
|
||||
{
|
||||
_queued.Items.First().Status = status;
|
||||
|
||||
WithQueue(_queued);
|
||||
WithHistory(null);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyDownloading(result);
|
||||
result.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void completed_download_should_have_required_properties()
|
||||
{
|
||||
WithQueue(null);
|
||||
WithHistory(_completed);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyCompleted(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void failed_item_should_have_required_properties()
|
||||
{
|
||||
_completed.Items.First().Status = SabnzbdDownloadStatus.Failed;
|
||||
|
||||
WithQueue(null);
|
||||
WithHistory(_completed);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyFailed(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Download_should_return_unique_id()
|
||||
{
|
||||
WithSuccessfulDownload();
|
||||
|
||||
var remoteEpisode = CreateRemoteEpisode();
|
||||
|
||||
var id = Subject.Download(remoteEpisode);
|
||||
|
||||
id.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_ignore_downloads_from_other_categories()
|
||||
{
|
||||
_completed.Items.First().Category = "myowncat";
|
||||
|
||||
WithQueue(null);
|
||||
WithHistory(_completed);
|
||||
|
||||
var items = Subject.GetItems();
|
||||
|
||||
items.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Download_should_use_sabRecentTvPriority_when_recentEpisode_is_true()
|
||||
{
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), (int)SabnzbdPriority.High, It.IsAny<SabnzbdSettings>()))
|
||||
.Returns(new SabnzbdAddResponse());
|
||||
|
||||
Subject.DownloadNzb(_remoteEpisode);
|
||||
var remoteEpisode = CreateRemoteEpisode();
|
||||
remoteEpisode.Episodes = Builder<Episode>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(e => e.AirDate = DateTime.Today.ToString(Episode.AIR_DATE_FORMAT))
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Subject.Download(remoteEpisode);
|
||||
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
.Verify(v => v.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), (int)SabnzbdPriority.High, It.IsAny<SabnzbdSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_path_to_folder_instead_of_file()
|
||||
{
|
||||
_completed.Items.First().Storage = @"C:\sorted\Droned.S01E01.Pilot.1080p.WEB-DL-DRONE\Droned.S01E01_Pilot_1080p_WEB-DL-DRONE.mkv".AsOsAgnostic();
|
||||
|
||||
WithQueue(null);
|
||||
WithHistory(_completed);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
result.OutputPath.Should().Be(@"C:\sorted\Droned.S01E01.Pilot.1080p.WEB-DL-DRONE".AsOsAgnostic());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_blow_up_if_storage_is_drive_root()
|
||||
{
|
||||
_completed.Items.First().Storage = @"C:\".AsOsAgnostic();
|
||||
|
||||
WithQueue(null);
|
||||
WithHistory(_completed);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
result.OutputPath.Should().Be(@"C:\".AsOsAgnostic());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Test.Common;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download
|
||||
{
|
||||
|
@ -16,12 +17,19 @@ namespace NzbDrone.Core.Test.Download
|
|||
public class DownloadServiceFixture : CoreTest<DownloadService>
|
||||
{
|
||||
private RemoteEpisode _parseResult;
|
||||
|
||||
private List<IDownloadClient> _downloadClients;
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_downloadClients = new List<IDownloadClient>();
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(c => c.GetDownloadClient()).Returns(Mocker.GetMock<IDownloadClient>().Object);
|
||||
.Setup(v => v.GetDownloadClients())
|
||||
.Returns(_downloadClients);
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(v => v.GetDownloadClient(It.IsAny<Indexers.DownloadProtocol>()))
|
||||
.Returns<Indexers.DownloadProtocol>(v => _downloadClients.FirstOrDefault(d => d.Protocol == v));
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(2)
|
||||
.TheFirst(1).With(s => s.Id = 12)
|
||||
|
@ -29,31 +37,43 @@ namespace NzbDrone.Core.Test.Download
|
|||
.All().With(s => s.SeriesId = 5)
|
||||
.Build().ToList();
|
||||
|
||||
var releaseInfo = Builder<ReleaseInfo>.CreateNew()
|
||||
.With(v => v.DownloadProtocol = Indexers.DownloadProtocol.Usenet)
|
||||
.Build();
|
||||
|
||||
_parseResult = Builder<RemoteEpisode>.CreateNew()
|
||||
.With(c => c.Series = Builder<Series>.CreateNew().Build())
|
||||
.With(c => c.Release = Builder<ReleaseInfo>.CreateNew().Build())
|
||||
.With(c => c.Release = releaseInfo)
|
||||
.With(c => c.Episodes = episodes)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private void WithSuccessfulAdd()
|
||||
private Mock<IDownloadClient> WithUsenetClient()
|
||||
{
|
||||
Mocker.GetMock<IDownloadClient>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<RemoteEpisode>()));
|
||||
var mock = new Mock<IDownloadClient>(Moq.MockBehavior.Default);
|
||||
_downloadClients.Add(mock.Object);
|
||||
|
||||
mock.SetupGet(v => v.Protocol).Returns(Indexers.DownloadProtocol.Usenet);
|
||||
|
||||
return mock;
|
||||
}
|
||||
|
||||
private void WithFailedAdd()
|
||||
private Mock<IDownloadClient> WithTorrentClient()
|
||||
{
|
||||
Mocker.GetMock<IDownloadClient>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<RemoteEpisode>()))
|
||||
.Throws(new WebException());
|
||||
var mock = new Mock<IDownloadClient>(Moq.MockBehavior.Default);
|
||||
_downloadClients.Add(mock.Object);
|
||||
|
||||
mock.SetupGet(v => v.Protocol).Returns(Indexers.DownloadProtocol.Torrent);
|
||||
|
||||
return mock;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Download_report_should_publish_on_grab_event()
|
||||
{
|
||||
WithSuccessfulAdd();
|
||||
|
||||
var mock = WithUsenetClient();
|
||||
mock.Setup(s => s.Download(It.IsAny<RemoteEpisode>()));
|
||||
|
||||
Subject.DownloadReport(_parseResult);
|
||||
|
||||
VerifyEventPublished<EpisodeGrabbedEvent>();
|
||||
|
@ -62,18 +82,20 @@ namespace NzbDrone.Core.Test.Download
|
|||
[Test]
|
||||
public void Download_report_should_grab_using_client()
|
||||
{
|
||||
WithSuccessfulAdd();
|
||||
|
||||
var mock = WithUsenetClient();
|
||||
mock.Setup(s => s.Download(It.IsAny<RemoteEpisode>()));
|
||||
|
||||
Subject.DownloadReport(_parseResult);
|
||||
|
||||
Mocker.GetMock<IDownloadClient>()
|
||||
.Verify(s => s.DownloadNzb(It.IsAny<RemoteEpisode>()), Times.Once());
|
||||
mock.Verify(s => s.Download(It.IsAny<RemoteEpisode>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Download_report_should_not_publish_on_failed_grab_event()
|
||||
{
|
||||
WithFailedAdd();
|
||||
var mock = WithUsenetClient();
|
||||
mock.Setup(s => s.Download(It.IsAny<RemoteEpisode>()))
|
||||
.Throws(new WebException());
|
||||
|
||||
Assert.Throws<WebException>(() => Subject.DownloadReport(_parseResult));
|
||||
|
||||
|
@ -83,15 +105,38 @@ namespace NzbDrone.Core.Test.Download
|
|||
[Test]
|
||||
public void should_not_attempt_download_if_client_isnt_configure()
|
||||
{
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(c => c.GetDownloadClient()).Returns((IDownloadClient)null);
|
||||
|
||||
Subject.DownloadReport(_parseResult);
|
||||
|
||||
Mocker.GetMock<IDownloadClient>().Verify(c => c.DownloadNzb(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||
Mocker.GetMock<IDownloadClient>().Verify(c => c.Download(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||
VerifyEventNotPublished<EpisodeGrabbedEvent>();
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_send_download_to_correct_usenet_client()
|
||||
{
|
||||
var mockTorrent = WithTorrentClient();
|
||||
var mockUsenet = WithUsenetClient();
|
||||
|
||||
Subject.DownloadReport(_parseResult);
|
||||
|
||||
mockTorrent.Verify(c => c.Download(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||
mockUsenet.Verify(c => c.Download(It.IsAny<RemoteEpisode>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_send_download_to_correct_torrent_client()
|
||||
{
|
||||
var mockTorrent = WithTorrentClient();
|
||||
var mockUsenet = WithUsenetClient();
|
||||
|
||||
_parseResult.Release.DownloadProtocol = Indexers.DownloadProtocol.Torrent;
|
||||
|
||||
Subject.DownloadReport(_parseResult);
|
||||
|
||||
mockTorrent.Verify(c => c.Download(It.IsAny<RemoteEpisode>()), Times.Once());
|
||||
mockUsenet.Verify(c => c.Download(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,32 +13,43 @@ using NzbDrone.Core.Test.Framework;
|
|||
namespace NzbDrone.Core.Test.Download
|
||||
{
|
||||
[TestFixture]
|
||||
public class FailedDownloadServiceFixture : CoreTest<FailedDownloadService>
|
||||
public class FailedDownloadServiceFixture : CoreTest<DownloadTrackingService>
|
||||
{
|
||||
private List<HistoryItem> _completed;
|
||||
private List<HistoryItem> _failed;
|
||||
private List<DownloadClientItem> _completed;
|
||||
private List<DownloadClientItem> _failed;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_completed = Builder<HistoryItem>.CreateListOfSize(5)
|
||||
_completed = Builder<DownloadClientItem>.CreateListOfSize(5)
|
||||
.All()
|
||||
.With(h => h.Status = HistoryStatus.Completed)
|
||||
.With(h => h.Status = DownloadItemStatus.Completed)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
_failed = Builder<HistoryItem>.CreateListOfSize(1)
|
||||
_failed = Builder<DownloadClientItem>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(h => h.Status = HistoryStatus.Failed)
|
||||
.With(h => h.Status = DownloadItemStatus.Failed)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(c => c.GetDownloadClient()).Returns(Mocker.GetMock<IDownloadClient>().Object);
|
||||
.Setup(c => c.GetDownloadClients())
|
||||
.Returns( new IDownloadClient[] { Mocker.GetMock<IDownloadClient>().Object });
|
||||
|
||||
Mocker.GetMock<IDownloadClient>()
|
||||
.SetupGet(c => c.Definition)
|
||||
.Returns(new Core.Download.DownloadClientDefinition { Id = 1, Name = "testClient" });
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.EnableFailedDownloadHandling)
|
||||
.Returns(true);
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.Imported())
|
||||
.Returns(new List<History.History>());
|
||||
|
||||
Mocker.SetConstant<IFailedDownloadService>(Mocker.Resolve<FailedDownloadService>());
|
||||
}
|
||||
|
||||
private void GivenNoGrabbedHistory()
|
||||
|
@ -72,7 +83,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
private void GivenFailedDownloadClientHistory()
|
||||
{
|
||||
Mocker.GetMock<IDownloadClient>()
|
||||
.Setup(s => s.GetHistory(0, 20))
|
||||
.Setup(s => s.GetItems())
|
||||
.Returns(_failed);
|
||||
}
|
||||
|
||||
|
@ -102,10 +113,10 @@ namespace NzbDrone.Core.Test.Download
|
|||
public void should_not_process_if_no_download_client_history()
|
||||
{
|
||||
Mocker.GetMock<IDownloadClient>()
|
||||
.Setup(s => s.GetHistory(0, 20))
|
||||
.Returns(new List<HistoryItem>());
|
||||
.Setup(s => s.GetItems())
|
||||
.Returns(new List<DownloadClientItem>());
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Verify(s => s.BetweenDates(It.IsAny<DateTime>(), It.IsAny<DateTime>(), HistoryEventType.Grabbed),
|
||||
|
@ -117,11 +128,14 @@ namespace NzbDrone.Core.Test.Download
|
|||
[Test]
|
||||
public void should_not_process_if_no_failed_items_in_download_client_history()
|
||||
{
|
||||
GivenNoGrabbedHistory();
|
||||
GivenNoFailedHistory();
|
||||
|
||||
Mocker.GetMock<IDownloadClient>()
|
||||
.Setup(s => s.GetHistory(0, 20))
|
||||
.Setup(s => s.GetItems())
|
||||
.Returns(_completed);
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Verify(s => s.BetweenDates(It.IsAny<DateTime>(), It.IsAny<DateTime>(), HistoryEventType.Grabbed),
|
||||
|
@ -136,7 +150,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
GivenNoGrabbedHistory();
|
||||
GivenFailedDownloadClientHistory();
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoFailedDownloads();
|
||||
}
|
||||
|
@ -156,7 +170,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
GivenGrabbedHistory(historyGrabbed);
|
||||
GivenNoFailedHistory();
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoFailedDownloads();
|
||||
}
|
||||
|
@ -171,7 +185,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
.ToList();
|
||||
|
||||
historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().Id);
|
||||
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().DownloadClientId);
|
||||
|
||||
GivenGrabbedHistory(historyGrabbed);
|
||||
|
||||
|
@ -184,7 +198,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
|
||||
GivenFailedHistory(historyFailed);
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyFailedDownloads();
|
||||
}
|
||||
|
@ -202,9 +216,9 @@ namespace NzbDrone.Core.Test.Download
|
|||
GivenFailedHistory(history);
|
||||
|
||||
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
history.First().Data.Add("downloadClientId", _failed.First().Id);
|
||||
history.First().Data.Add("downloadClientId", _failed.First().DownloadClientId);
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoFailedDownloads();
|
||||
}
|
||||
|
@ -222,9 +236,9 @@ namespace NzbDrone.Core.Test.Download
|
|||
GivenNoFailedHistory();
|
||||
|
||||
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
history.First().Data.Add("downloadClientId", _failed.First().Id);
|
||||
history.First().Data.Add("downloadClientId", _failed.First().DownloadClientId);
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyFailedDownloads();
|
||||
}
|
||||
|
@ -244,10 +258,10 @@ namespace NzbDrone.Core.Test.Download
|
|||
history.ForEach(h =>
|
||||
{
|
||||
h.Data.Add("downloadClient", "SabnzbdClient");
|
||||
h.Data.Add("downloadClientId", _failed.First().Id);
|
||||
h.Data.Add("downloadClientId", _failed.First().DownloadClientId);
|
||||
});
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyFailedDownloads(2);
|
||||
}
|
||||
|
@ -259,7 +273,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
.SetupGet(s => s.EnableFailedDownloadHandling)
|
||||
.Returns(false);
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoFailedDownloads();
|
||||
}
|
||||
|
@ -276,7 +290,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
|
||||
_failed.First().Message = "Unpacking failed, write error or disk is full?";
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoFailedDownloads();
|
||||
}
|
||||
|
@ -291,12 +305,12 @@ namespace NzbDrone.Core.Test.Download
|
|||
.ToList();
|
||||
|
||||
historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().Id);
|
||||
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().DownloadClientId);
|
||||
|
||||
GivenGrabbedHistory(historyGrabbed);
|
||||
GivenNoFailedHistory();
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyFailedDownloads();
|
||||
}
|
||||
|
@ -311,13 +325,13 @@ namespace NzbDrone.Core.Test.Download
|
|||
.ToList();
|
||||
|
||||
historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().Id);
|
||||
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().DownloadClientId);
|
||||
historyGrabbed.First().Data.Add("ageHours", "48");
|
||||
|
||||
GivenGrabbedHistory(historyGrabbed);
|
||||
GivenNoFailedHistory();
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyFailedDownloads();
|
||||
}
|
||||
|
@ -332,14 +346,14 @@ namespace NzbDrone.Core.Test.Download
|
|||
.ToList();
|
||||
|
||||
historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().Id);
|
||||
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().DownloadClientId);
|
||||
historyGrabbed.First().Data.Add("ageHours", "48");
|
||||
|
||||
GivenGrabbedHistory(historyGrabbed);
|
||||
GivenNoFailedHistory();
|
||||
GivenGracePeriod(6);
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyFailedDownloads();
|
||||
}
|
||||
|
@ -354,7 +368,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
.ToList();
|
||||
|
||||
historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().Id);
|
||||
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().DownloadClientId);
|
||||
historyGrabbed.First().Data.Add("ageHours", "1");
|
||||
|
||||
GivenGrabbedHistory(historyGrabbed);
|
||||
|
@ -362,7 +376,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
GivenGracePeriod(6);
|
||||
GivenRetryLimit(1);
|
||||
|
||||
Subject.Execute(new CheckForFailedDownloadCommand());
|
||||
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||
|
||||
VerifyNoFailedDownloads();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
using NUnit.Framework;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.HealthCheck.Checks;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
{
|
||||
[TestFixture]
|
||||
public class AppDataLocationFixture : CoreTest<AppDataLocationCheck>
|
||||
{
|
||||
[Test]
|
||||
public void should_return_warning_when_app_data_is_child_of_startup_folder()
|
||||
{
|
||||
Mocker.GetMock<IAppFolderInfo>()
|
||||
.Setup(s => s.StartUpFolder)
|
||||
.Returns(@"C:\NzbDrone".AsOsAgnostic());
|
||||
|
||||
Mocker.GetMock<IAppFolderInfo>()
|
||||
.Setup(s => s.AppDataFolder)
|
||||
.Returns(@"C:\NzbDrone\AppData".AsOsAgnostic());
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_when_app_data_is_same_as_startup_folder()
|
||||
{
|
||||
Mocker.GetMock<IAppFolderInfo>()
|
||||
.Setup(s => s.StartUpFolder)
|
||||
.Returns(@"C:\NzbDrone".AsOsAgnostic());
|
||||
|
||||
Mocker.GetMock<IAppFolderInfo>()
|
||||
.Setup(s => s.AppDataFolder)
|
||||
.Returns(@"C:\NzbDrone".AsOsAgnostic());
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_ok_when_no_conflict()
|
||||
{
|
||||
Mocker.GetMock<IAppFolderInfo>()
|
||||
.Setup(s => s.StartUpFolder)
|
||||
.Returns(@"C:\NzbDrone".AsOsAgnostic());
|
||||
|
||||
Mocker.GetMock<IAppFolderInfo>()
|
||||
.Setup(s => s.AppDataFolder)
|
||||
.Returns(@"C:\ProgramData\NzbDrone".AsOsAgnostic());
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,8 +15,8 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
public void should_return_warning_when_download_client_has_not_been_configured()
|
||||
{
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClient())
|
||||
.Returns((IDownloadClient)null);
|
||||
.Setup(s => s.GetDownloadClients())
|
||||
.Returns(new IDownloadClient[0]);
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
@ -26,12 +26,12 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
{
|
||||
var downloadClient = Mocker.GetMock<IDownloadClient>();
|
||||
|
||||
downloadClient.Setup(s => s.GetQueue())
|
||||
downloadClient.Setup(s => s.GetItems())
|
||||
.Throws<Exception>();
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClient())
|
||||
.Returns(downloadClient.Object);
|
||||
.Setup(s => s.GetDownloadClients())
|
||||
.Returns(new IDownloadClient[] { downloadClient.Object });
|
||||
|
||||
Subject.Check().ShouldBeError();
|
||||
}
|
||||
|
@ -41,12 +41,12 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
{
|
||||
var downloadClient = Mocker.GetMock<IDownloadClient>();
|
||||
|
||||
downloadClient.Setup(s => s.GetQueue())
|
||||
.Returns(new List<QueueItem>());
|
||||
downloadClient.Setup(s => s.GetItems())
|
||||
.Returns(new List<DownloadClientItem>());
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClient())
|
||||
.Returns(downloadClient.Object);
|
||||
.Setup(s => s.GetDownloadClients())
|
||||
.Returns(new IDownloadClient[] { downloadClient.Object });
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
|
|
|
@ -25,17 +25,7 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
.Setup(s => s.FolderExists(DRONE_FACTORY_FOLDER))
|
||||
.Returns(exists);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_when_drone_factory_folder_is_not_configured()
|
||||
{
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.DownloadedEpisodesFolder)
|
||||
.Returns("");
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_return_error_when_drone_factory_folder_does_not_exist()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using FizzWare.NBuilder;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.HealthCheck.Checks;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Download;
|
||||
|
||||
namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
{
|
||||
[TestFixture]
|
||||
public class ImportMechanismCheckFixture : CoreTest<ImportMechanismCheck>
|
||||
{
|
||||
private const string DRONE_FACTORY_FOLDER = @"C:\Test\Unsorted";
|
||||
|
||||
private IList<TrackedDownload> _completed;
|
||||
|
||||
private void GivenCompletedDownloadHandling(bool? enabled = null)
|
||||
{
|
||||
if (enabled.HasValue)
|
||||
{
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.Setup(s => s.IsDefined("EnableCompletedDownloadHandling"))
|
||||
.Returns(true);
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.EnableCompletedDownloadHandling)
|
||||
.Returns(enabled.Value);
|
||||
}
|
||||
|
||||
_completed = Builder<TrackedDownload>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(v => v.State == TrackedDownloadState.Downloading)
|
||||
.With(v => v.DownloadItem = new DownloadClientItem())
|
||||
.With(v => v.DownloadItem.Status = DownloadItemStatus.Completed)
|
||||
.With(v => v.DownloadItem.OutputPath = @"C:\Test\DropFolder\myfile.mkv".AsOsAgnostic())
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<IDownloadTrackingService>()
|
||||
.Setup(v => v.GetCompletedDownloads())
|
||||
.Returns(_completed.ToArray());
|
||||
}
|
||||
|
||||
private void GivenDroneFactoryFolder(bool exists = false)
|
||||
{
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.SetupGet(s => s.DownloadedEpisodesFolder)
|
||||
.Returns(DRONE_FACTORY_FOLDER.AsOsAgnostic());
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.FolderExists(DRONE_FACTORY_FOLDER.AsOsAgnostic()))
|
||||
.Returns(exists);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_when_completed_download_handling_not_configured()
|
||||
{
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_when_both_completeddownloadhandling_and_dronefactory_are_not_configured()
|
||||
{
|
||||
GivenCompletedDownloadHandling(false);
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_warning_when_downloadclient_drops_in_dronefactory_folder()
|
||||
{
|
||||
GivenCompletedDownloadHandling(true);
|
||||
GivenDroneFactoryFolder(true);
|
||||
|
||||
_completed.First().DownloadItem.OutputPath = (DRONE_FACTORY_FOLDER + @"\myfile.mkv").AsOsAgnostic();
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_ok_when_no_issues_found()
|
||||
{
|
||||
GivenCompletedDownloadHandling(true);
|
||||
GivenDroneFactoryFolder(true);
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
using System;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.HealthCheck;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.HealthCheck.Checks;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
|
@ -28,5 +27,25 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
|
||||
Subject.Check().ShouldBeError();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_error_when_app_folder_is_write_protected_and_update_automatically_is_enabled()
|
||||
{
|
||||
MonoOnly();
|
||||
|
||||
Mocker.GetMock<IConfigFileProvider>()
|
||||
.Setup(s => s.UpdateAutomatically)
|
||||
.Returns(true);
|
||||
|
||||
Mocker.GetMock<IAppFolderInfo>()
|
||||
.Setup(s => s.StartUpFolder)
|
||||
.Returns(@"/opt/nzbdrone");
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.WriteAllText(It.IsAny<String>(), It.IsAny<String>()))
|
||||
.Throws<Exception>();
|
||||
|
||||
Subject.Check().ShouldBeError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,37 +29,6 @@ namespace NzbDrone.Core.Test.IndexerTests
|
|||
Mocker.SetConstant<IEnumerable<IIndexer>>(_indexers);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_create_default_indexer_on_startup()
|
||||
{
|
||||
IList<IndexerDefinition> storedIndexers = null;
|
||||
|
||||
Mocker.GetMock<IIndexerRepository>()
|
||||
.Setup(c => c.InsertMany(It.IsAny<IList<IndexerDefinition>>()))
|
||||
.Callback<IList<IndexerDefinition>>(indexers => storedIndexers = indexers);
|
||||
|
||||
Subject.Handle(new ApplicationStartedEvent());
|
||||
|
||||
storedIndexers.Should().NotBeEmpty();
|
||||
storedIndexers.Select(c => c.Name).Should().OnlyHaveUniqueItems();
|
||||
storedIndexers.Select(c => c.Enable).Should().NotBeEmpty();
|
||||
storedIndexers.Select(c => c.Implementation).Should().NotContainNulls();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void getting_list_of_indexers()
|
||||
{
|
||||
Mocker.SetConstant<IIndexerRepository>(Mocker.Resolve<IndexerRepository>());
|
||||
|
||||
Subject.Handle(new ApplicationStartedEvent());
|
||||
|
||||
var indexers = Subject.All().ToList();
|
||||
indexers.Should().NotBeEmpty();
|
||||
indexers.Should().NotContain(c => c.Settings == null);
|
||||
indexers.Should().NotContain(c => c.Name == null);
|
||||
indexers.Select(c => c.Name).Should().OnlyHaveUniqueItems();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_remove_missing_indexers_on_startup()
|
||||
{
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using FluentAssertions;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.Eztv;
|
||||
using NzbDrone.Core.Indexers.Newznab;
|
||||
using NzbDrone.Core.Indexers.Wombles;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
@ -37,39 +36,6 @@ namespace NzbDrone.Core.Test.IndexerTests.IntegrationTests
|
|||
|
||||
ValidateResult(result, skipSize: true, skipInfo: true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void extv_rss()
|
||||
{
|
||||
var indexer = new Eztv();
|
||||
indexer.Definition = new IndexerDefinition
|
||||
{
|
||||
Name = "Eztv",
|
||||
Settings = NullConfig.Instance
|
||||
};
|
||||
|
||||
var result = Subject.FetchRss(indexer);
|
||||
|
||||
ValidateTorrentResult(result, skipSize: false, skipInfo: true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void nzbsorg_rss()
|
||||
{
|
||||
var indexer = new Newznab();
|
||||
|
||||
indexer.Definition = new IndexerDefinition();
|
||||
indexer.Definition.Name = "nzbs.org";
|
||||
indexer.Definition.Settings = new NewznabSettings
|
||||
{
|
||||
ApiKey = "64d61d3cfd4b75e51d01cbc7c6a78275",
|
||||
Url = "http://nzbs.org"
|
||||
};
|
||||
|
||||
var result = Subject.FetchRss(indexer);
|
||||
|
||||
ValidateResult(result);
|
||||
}
|
||||
|
||||
private void ValidateResult(IList<ReleaseInfo> reports, bool skipSize = false, bool skipInfo = false)
|
||||
{
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace NzbDrone.Core.Test.IndexerTests
|
|||
indexer.Setup(s => s.GetSeasonSearchUrls(It.IsAny<String>(), It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
|
||||
.Returns(new List<string> { "http://www.nzbdrone.com" });
|
||||
|
||||
indexer.SetupGet(s => s.SupportsPaging).Returns(paging);
|
||||
indexer.SetupGet(s => s.SupportedPageSize).Returns(paging ? 100 : 0);
|
||||
|
||||
var definition = new IndexerDefinition();
|
||||
definition.Name = "Test";
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
.Returns("c:\\drop\\".AsOsAgnostic());
|
||||
|
||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true))
|
||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null))
|
||||
.Returns(new List<ImportDecision>());
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,8 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
[Test]
|
||||
public void should_skip_if_file_is_in_use_by_another_process()
|
||||
{
|
||||
GivenValidSeries();
|
||||
|
||||
Mocker.GetMock<IDiskProvider>().Setup(c => c.IsFileLocked(It.IsAny<string>()))
|
||||
.Returns(true);
|
||||
|
||||
|
@ -122,7 +124,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
public void should_not_delete_folder_if_no_files_were_imported()
|
||||
{
|
||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), false))
|
||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), false, null))
|
||||
.Returns(new List<ImportDecision>());
|
||||
|
||||
Subject.Execute(new DownloadedEpisodesScanCommand());
|
||||
|
@ -132,7 +134,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void should_delete_folder_if_files_were_imported_and_video_files_remain()
|
||||
public void should_not_delete_folder_if_files_were_imported_and_video_files_remain()
|
||||
{
|
||||
GivenValidSeries();
|
||||
|
||||
|
@ -146,7 +148,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
.Returns(imported);
|
||||
|
||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true))
|
||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null))
|
||||
.Returns(imported);
|
||||
|
||||
Subject.Execute(new DownloadedEpisodesScanCommand());
|
||||
|
@ -172,7 +174,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
.Returns(imported);
|
||||
|
||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true))
|
||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null))
|
||||
.Returns(imported);
|
||||
|
||||
Mocker.GetMock<ISampleService>()
|
||||
|
@ -211,13 +213,13 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
|
||||
private void VerifyNoImport()
|
||||
{
|
||||
Mocker.GetMock<IImportApprovedEpisodes>().Verify(c => c.Import(It.IsAny<List<ImportDecision>>(), true),
|
||||
Mocker.GetMock<IImportApprovedEpisodes>().Verify(c => c.Import(It.IsAny<List<ImportDecision>>(), true, null),
|
||||
Times.Never());
|
||||
}
|
||||
|
||||
private void VerifyImport()
|
||||
{
|
||||
Mocker.GetMock<IImportApprovedEpisodes>().Verify(c => c.Import(It.IsAny<List<ImportDecision>>(), true),
|
||||
Mocker.GetMock<IImportApprovedEpisodes>().Verify(c => c.Import(It.IsAny<List<ImportDecision>>(), true, null),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport.Specifications;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||
{
|
||||
[TestFixture]
|
||||
public class NotInUseSpecificationFixture : CoreTest<NotInUseSpecification>
|
||||
{
|
||||
private LocalEpisode _localEpisode;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_localEpisode = new LocalEpisode
|
||||
{
|
||||
Path = @"C:\Test\30 Rock\30.rock.s01e01.avi".AsOsAgnostic(),
|
||||
Size = 100,
|
||||
Series = Builder<Series>.CreateNew().Build()
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenChildOfSeries()
|
||||
{
|
||||
_localEpisode.ExistingFile = true;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_if_file_is_under_series_folder()
|
||||
{
|
||||
GivenChildOfSeries();
|
||||
|
||||
Subject.IsSatisfiedBy(_localEpisode).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_check_for_file_in_use_if_child_of_series_folder()
|
||||
{
|
||||
GivenChildOfSeries();
|
||||
|
||||
Subject.IsSatisfiedBy(_localEpisode);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(v => v.IsFileLocked(It.IsAny<string>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_false_if_file_is_in_use()
|
||||
{
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.IsFileLocked(It.IsAny<string>()))
|
||||
.Returns(true);
|
||||
|
||||
Subject.IsSatisfiedBy(_localEpisode).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_if_file_is_not_in_use()
|
||||
{
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.IsFileLocked(It.IsAny<string>()))
|
||||
.Returns(false);
|
||||
|
||||
Subject.IsSatisfiedBy(_localEpisode).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
|||
|
||||
private void GivenInWorkingFolder()
|
||||
{
|
||||
_localEpisode.Path = @"C:\Test\Unsorted TV\_UNPACK_30.rock\30.rock.s01e01.avi".AsOsAgnostic();
|
||||
_localEpisode.Path = @"C:\Test\Unsorted TV\_UNPACK_30.rock\someSubFolder\30.rock.s01e01.avi".AsOsAgnostic();
|
||||
}
|
||||
|
||||
private void GivenLastWriteTimeUtc(DateTime time)
|
||||
|
|
|
@ -57,20 +57,20 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
}
|
||||
|
||||
Mocker.GetMock<IUpgradeMediaFiles>()
|
||||
.Setup(s => s.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), It.IsAny<LocalEpisode>()))
|
||||
.Setup(s => s.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), It.IsAny<LocalEpisode>(), false))
|
||||
.Returns(new EpisodeFileMoveResult());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_empty_list_if_there_are_no_approved_decisions()
|
||||
{
|
||||
Subject.Import(_rejectedDecisions).Should().BeEmpty();
|
||||
Subject.Import(_rejectedDecisions, false).Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_import_each_approved()
|
||||
{
|
||||
Subject.Import(_approvedDecisions).Should().HaveCount(5);
|
||||
Subject.Import(_approvedDecisions, false).Should().HaveCount(5);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
all.AddRange(_rejectedDecisions);
|
||||
all.AddRange(_approvedDecisions);
|
||||
|
||||
Subject.Import(all).Should().HaveCount(5);
|
||||
Subject.Import(all, false).Should().HaveCount(5);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -90,7 +90,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
all.AddRange(_approvedDecisions);
|
||||
all.Add(new ImportDecision(_approvedDecisions.First().LocalEpisode));
|
||||
|
||||
Subject.Import(all).Should().HaveCount(5);
|
||||
Subject.Import(all, false).Should().HaveCount(5);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -99,7 +99,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
Subject.Import(new List<ImportDecision> {_approvedDecisions.First()}, true);
|
||||
|
||||
Mocker.GetMock<IUpgradeMediaFiles>()
|
||||
.Verify(v => v.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), _approvedDecisions.First().LocalEpisode),
|
||||
.Verify(v => v.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), _approvedDecisions.First().LocalEpisode, false),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
|
@ -115,10 +115,10 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
[Test]
|
||||
public void should_not_move_existing_files()
|
||||
{
|
||||
Subject.Import(new List<ImportDecision> { _approvedDecisions.First() });
|
||||
Subject.Import(new List<ImportDecision> { _approvedDecisions.First() }, false);
|
||||
|
||||
Mocker.GetMock<IUpgradeMediaFiles>()
|
||||
.Verify(v => v.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), _approvedDecisions.First().LocalEpisode),
|
||||
.Verify(v => v.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), _approvedDecisions.First().LocalEpisode, false),
|
||||
Times.Never());
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
|||
all.Add(fileDecision);
|
||||
all.Add(sampleDecision);
|
||||
|
||||
var results = Subject.Import(all);
|
||||
var results = Subject.Import(all, false);
|
||||
|
||||
results.Should().HaveCount(1);
|
||||
results.Should().ContainSingle(d => d.LocalEpisode.Size == fileDecision.LocalEpisode.Size);
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
using System.IO;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Metadata;
|
||||
using NzbDrone.Core.Metadata.Consumers.Roksbox;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.Metadata.Consumers.Roksbox
|
||||
{
|
||||
[TestFixture]
|
||||
public class FindMetadataFileFixture : CoreTest<RoksboxMetadata>
|
||||
{
|
||||
private Series _series;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_series = Builder<Series>.CreateNew()
|
||||
.With(s => s.Path = @"C:\Test\TV\The.Series".AsOsAgnostic())
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_null_if_filename_is_not_handled()
|
||||
{
|
||||
var path = Path.Combine(_series.Path, "file.jpg");
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Should().BeNull();
|
||||
}
|
||||
|
||||
[TestCase("Specials")]
|
||||
[TestCase("specials")]
|
||||
[TestCase("Season 1")]
|
||||
public void should_return_season_image(string folder)
|
||||
{
|
||||
var path = Path.Combine(_series.Path, folder, folder + ".jpg");
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Type.Should().Be(MetadataType.SeasonImage);
|
||||
}
|
||||
|
||||
[TestCase(".xml", MetadataType.EpisodeMetadata)]
|
||||
[TestCase(".jpg", MetadataType.EpisodeImage)]
|
||||
public void should_return_metadata_for_episode_if_valid_file_for_episode(string extension, MetadataType type)
|
||||
{
|
||||
var path = Path.Combine(_series.Path, "the.series.s01e01.episode" + extension);
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Type.Should().Be(type);
|
||||
}
|
||||
|
||||
[TestCase(".xml")]
|
||||
[TestCase(".jpg")]
|
||||
public void should_return_null_if_not_valid_file_for_episode(string extension)
|
||||
{
|
||||
var path = Path.Combine(_series.Path, "the.series.episode" + extension);
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_return_metadata_if_image_file_is_a_thumb()
|
||||
{
|
||||
var path = Path.Combine(_series.Path, "the.series.s01e01.episode-thumb.jpg");
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_series_image_for_folder_jpg_in_series_folder()
|
||||
{
|
||||
var path = Path.Combine(_series.Path, new DirectoryInfo(_series.Path).Name + ".jpg");
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Type.Should().Be(MetadataType.SeriesImage);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Metadata;
|
||||
using NzbDrone.Core.Metadata.Consumers.Wdtv;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.Metadata.Consumers.Wdtv
|
||||
{
|
||||
[TestFixture]
|
||||
public class FindMetadataFileFixture : CoreTest<WdtvMetadata>
|
||||
{
|
||||
private Series _series;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_series = Builder<Series>.CreateNew()
|
||||
.With(s => s.Path = @"C:\Test\TV\The.Series".AsOsAgnostic())
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_null_if_filename_is_not_handled()
|
||||
{
|
||||
var path = Path.Combine(_series.Path, "file.jpg");
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Should().BeNull();
|
||||
}
|
||||
|
||||
[TestCase("Specials")]
|
||||
[TestCase("specials")]
|
||||
[TestCase("Season 1")]
|
||||
public void should_return_season_image(string folder)
|
||||
{
|
||||
var path = Path.Combine(_series.Path, folder, "folder.jpg");
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Type.Should().Be(MetadataType.SeasonImage);
|
||||
}
|
||||
|
||||
[TestCase(".xml", MetadataType.EpisodeMetadata)]
|
||||
[TestCase(".metathumb", MetadataType.EpisodeImage)]
|
||||
public void should_return_metadata_for_episode_if_valid_file_for_episode(string extension, MetadataType type)
|
||||
{
|
||||
var path = Path.Combine(_series.Path, "the.series.s01e01.episode" + extension);
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Type.Should().Be(type);
|
||||
}
|
||||
|
||||
[TestCase(".xml")]
|
||||
[TestCase(".metathumb")]
|
||||
public void should_return_null_if_not_valid_file_for_episode(string extension)
|
||||
{
|
||||
var path = Path.Combine(_series.Path, "the.series.episode" + extension);
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_series_image_for_folder_jpg_in_series_folder()
|
||||
{
|
||||
var path = Path.Combine(_series.Path, "folder.jpg");
|
||||
|
||||
Subject.FindMetadataFile(_series, path).Type.Should().Be(MetadataType.SeriesImage);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -115,18 +115,21 @@
|
|||
<Compile Include="DecisionEngineTests\Search\SeriesSpecificationFixture.cs" />
|
||||
<Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" />
|
||||
<Compile Include="Download\DownloadApprovedReportsTests\GetQualifiedReportsFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\BlackholeProviderFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\NzbgetTests\DownloadNzbFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\NzbgetTests\QueueFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\Blackhole\UsenetBlackholeFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\DownloadClientFixtureBase.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\NzbgetTests\NzbgetFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\PneumaticProviderFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\SabnzbdTests\SabnzbdFixture.cs" />
|
||||
<Compile Include="Download\DownloadServiceFixture.cs" />
|
||||
<Compile Include="Download\CompletedDownloadServiceFixture.cs" />
|
||||
<Compile Include="Download\FailedDownloadServiceFixture.cs" />
|
||||
<Compile Include="Framework\CoreTest.cs" />
|
||||
<Compile Include="Framework\DbTest.cs" />
|
||||
<Compile Include="Framework\NBuilderExtensions.cs" />
|
||||
<Compile Include="HealthCheck\Checks\AppDataLocationFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\RootFolderCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\DownloadClientCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\ImportMechanismCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\UpdateCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\IndexerCheckFixture.cs" />
|
||||
<Compile Include="HealthCheck\Checks\DroneFactoryCheckFixture.cs" />
|
||||
|
@ -156,7 +159,6 @@
|
|||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FullSeasonSpecificationFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FreeSpaceSpecificationFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\ImportDecisionMakerFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotInUseSpecificationFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\SampleServiceFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotSampleSpecificationFixture.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotUnpackingSpecificationFixture.cs" />
|
||||
|
@ -172,6 +174,8 @@
|
|||
<Compile Include="Messaging\Commands\CommandFixture.cs" />
|
||||
<Compile Include="Messaging\Events\EventAggregatorFixture.cs" />
|
||||
<Compile Include="MetadataSourceTests\TraktProxyFixture.cs" />
|
||||
<Compile Include="Metadata\Consumers\Roksbox\FindMetadataFileFixture.cs" />
|
||||
<Compile Include="Metadata\Consumers\Wdtv\FindMetadataFileFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\GetJsonVersionFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Http\ActivePlayersFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Http\CheckForErrorFixture.cs" />
|
||||
|
|
|
@ -33,13 +33,14 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
[TestCase("[ACX]Hack Sign 01 Role Play [Kosaka] [9C57891E].mkv", "Hack Sign", 1, 0, 0)]
|
||||
[TestCase("[SFW-sage] Bakuman S3 - 12 [720p][D07C91FC]", "Bakuman S3", 12, 0, 0)]
|
||||
[TestCase("ducktales_e66_time_is_money_part_one_marking_time", "DuckTales", 66, 0, 0)]
|
||||
[TestCase("[Underwater-FFF] No Game No Life - 01 (720p) [27AAA0A0].mkv", "No Game No Life", 1, 0, 0)]
|
||||
public void should_parse_absolute_numbers(string postTitle, string title, int absoluteEpisodeNumber, int seasonNumber, int episodeNumber)
|
||||
{
|
||||
var result = Parser.Parser.ParseTitle(postTitle);
|
||||
result.Should().NotBeNull();
|
||||
result.AbsoluteEpisodeNumbers.First().Should().Be(absoluteEpisodeNumber);
|
||||
result.AbsoluteEpisodeNumbers.Single().Should().Be(absoluteEpisodeNumber);
|
||||
result.SeasonNumber.Should().Be(seasonNumber);
|
||||
result.EpisodeNumbers.FirstOrDefault().Should().Be(episodeNumber);
|
||||
result.EpisodeNumbers.SingleOrDefault().Should().Be(episodeNumber);
|
||||
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
|
||||
result.FullSeason.Should().BeFalse();
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
[TestCase("Shield,.The.1x13.Tueurs.De.Flics.FR.DVDRip.XviD", Language.French)]
|
||||
[TestCase("True.Detective.S01E01.1080p.WEB-DL.Rus.Eng.TVKlondike", Language.Russian)]
|
||||
[TestCase("The.Trip.To.Italy.S02E01.720p.HDTV.x264-TLA", Language.English)]
|
||||
[TestCase("Revolution S01E03 No Quarter 2012 WEB-DL 720p Nordic-philipo mkv", Language.Norwegian)]
|
||||
public void should_parse_language(string postTitle, Language language)
|
||||
{
|
||||
var result = Parser.Parser.ParseTitle(postTitle);
|
||||
|
|
|
@ -16,12 +16,26 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
new object[] { Quality.DVD },
|
||||
new object[] { Quality.WEBDL480p },
|
||||
new object[] { Quality.HDTV720p },
|
||||
new object[] { Quality.HDTV1080p },
|
||||
new object[] { Quality.WEBDL720p },
|
||||
new object[] { Quality.WEBDL1080p },
|
||||
new object[] { Quality.Bluray720p },
|
||||
new object[] { Quality.Bluray1080p }
|
||||
};
|
||||
|
||||
public static object[] OtherSourceQualityParserCases =
|
||||
{
|
||||
new object[] { "SD TV", Quality.SDTV },
|
||||
new object[] { "SD DVD", Quality.DVD },
|
||||
new object[] { "480p WEB-DL", Quality.WEBDL480p },
|
||||
new object[] { "HD TV", Quality.HDTV720p },
|
||||
new object[] { "1080p HD TV", Quality.HDTV1080p },
|
||||
new object[] { "720p WEB-DL", Quality.WEBDL720p },
|
||||
new object[] { "1080p WEB-DL", Quality.WEBDL1080p },
|
||||
new object[] { "720p BluRay", Quality.Bluray720p },
|
||||
new object[] { "1080p BluRay", Quality.Bluray1080p }
|
||||
};
|
||||
|
||||
[TestCase("S07E23 .avi ", false)]
|
||||
[TestCase("The.Shield.S01E13.x264-CtrlSD", false)]
|
||||
[TestCase("Nikita S02E01 HDTV XviD 2HD", false)]
|
||||
|
@ -64,7 +78,8 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
|
||||
[TestCase("Elementary.S01E10.The.Leviathan.480p.WEB-DL.x264-mSD", false)]
|
||||
[TestCase("Glee.S04E10.Glee.Actually.480p.WEB-DL.x264-mSD", false)]
|
||||
[TestCase("The.Big.Bang.Theory.S06E11.The.Santa.Simulation.480p.WEB-DL.x264-mSD", false)]
|
||||
[TestCase("The.Big.Bang.Theory.S06E11.The.Santa.Simulation.480p.WEB-DL.x264-mSD", false)]
|
||||
[TestCase("Da.Vincis.Demons.S02E04.480p.WEB.DL.nSD.x264-NhaNc3", false)]
|
||||
public void should_parse_webdl480p_quality(string title, bool proper)
|
||||
{
|
||||
ParseAndVerifyQuality(title, Quality.WEBDL480p, proper);
|
||||
|
@ -105,6 +120,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
[TestCase("S07E23 - [WEBDL].mkv ", false)]
|
||||
[TestCase("Fringe S04E22 720p WEB-DL DD5.1 H264-EbP.mkv", false)]
|
||||
[TestCase("House.S04.720p.Web-Dl.Dd5.1.h264-P2PACK", false)]
|
||||
[TestCase("Da.Vincis.Demons.S02E04.720p.WEB.DL.nSD.x264-NhaNc3", false)]
|
||||
public void should_parse_webdl720p_quality(string title, bool proper)
|
||||
{
|
||||
ParseAndVerifyQuality(title, Quality.WEBDL720p, proper);
|
||||
|
@ -144,6 +160,9 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
[TestCase("POI S02E11 1080i HDTV DD5.1 MPEG2-TrollHD", false)]
|
||||
[TestCase("How I Met Your Mother S01E18 Nothing Good Happens After 2 A.M. 720p HDTV DD5.1 MPEG2-TrollHD", false)]
|
||||
[TestCase("The Voice S01E11 The Finals 1080i HDTV DD5.1 MPEG2-TrollHD", false)]
|
||||
[TestCase("Californication.S07E11.1080i.HDTV.DD5.1.MPEG2-NTb.ts", false)]
|
||||
[TestCase("Game of Thrones S04E10 1080i HDTV MPEG2 DD5.1-CtrlHD.ts", false)]
|
||||
[TestCase("VICE.S02E05.1080i.HDTV.DD2.0.MPEG2-NTb.ts", false)]
|
||||
public void should_parse_raw_quality(string title, bool proper)
|
||||
{
|
||||
ParseAndVerifyQuality(title, Quality.RAWHD, proper);
|
||||
|
@ -164,6 +183,18 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
result.Quality.Should().Be(quality);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("OtherSourceQualityParserCases")]
|
||||
public void should_parse_quality_from_other_source(string qualityString, Quality quality)
|
||||
{
|
||||
foreach (var c in new char[] { '-', '.', ' ', '_' })
|
||||
{
|
||||
var title = String.Format("My series S01E01 {0}", qualityString.Replace(' ', c));
|
||||
|
||||
ParseAndVerifyQuality(title, quality, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ParseAndVerifyQuality(string title, Quality quality, bool proper)
|
||||
{
|
||||
var result = Parser.QualityParser.ParseQuality(title);
|
||||
|
|
|
@ -4,7 +4,6 @@ using NzbDrone.Core.Test.Framework;
|
|||
|
||||
namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class ReleaseGroupParserFixture : CoreTest
|
||||
{
|
||||
|
@ -19,6 +18,11 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
[TestCase("The Office - S01E01 - Pilot [HTDV-1080p]", "DRONE")]
|
||||
[TestCase("The.Walking.Dead.S04E13.720p.WEB-DL.AAC2.0.H.264-Cyphanix", "Cyphanix")]
|
||||
[TestCase("Arrow.S02E01.720p.WEB-DL.DD5.1.H.264.mkv", "DRONE")]
|
||||
[TestCase("Series Title S01E01 Episode Title", "DRONE")]
|
||||
[TestCase("The Colbert Report - 2014-06-02 - Thomas Piketty.mkv", "DRONE")]
|
||||
[TestCase("Real Time with Bill Maher S12E17 May 23, 2014.mp4", "DRONE")]
|
||||
[TestCase("Reizen Waes - S01E08 - Transistrië, Zuid-Ossetië en Abchazië SDTV.avi", "DRONE")]
|
||||
[TestCase("Simpsons 10x11 - Wild Barts Cant Be Broken [rl].avi", "DRONE")]
|
||||
public void should_parse_release_group(string title, string expected)
|
||||
{
|
||||
Parser.Parser.ParseReleaseGroup(title).Should().Be(expected);
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -49,6 +49,9 @@ namespace NzbDrone.Core.Test.UpdateTests
|
|||
}
|
||||
|
||||
Mocker.GetMock<IAppFolderInfo>().SetupGet(c => c.TempFolder).Returns(TempFolder);
|
||||
Mocker.GetMock<IAppFolderInfo>().SetupGet(c => c.StartUpFolder).Returns(@"C:\NzbDrone".AsOsAgnostic);
|
||||
Mocker.GetMock<IAppFolderInfo>().SetupGet(c => c.AppDataFolder).Returns(@"C:\ProgramData\NzbDrone".AsOsAgnostic);
|
||||
|
||||
Mocker.GetMock<ICheckUpdateService>().Setup(c => c.AvailableUpdate()).Returns(_updatePackage);
|
||||
Mocker.GetMock<IVerifyUpdates>().Setup(c => c.Verify(It.IsAny<UpdatePackage>(), It.IsAny<String>())).Returns(true);
|
||||
|
||||
|
@ -101,7 +104,6 @@ namespace NzbDrone.Core.Test.UpdateTests
|
|||
|
||||
Subject.Execute(new ApplicationUpdateCommand());
|
||||
|
||||
|
||||
Mocker.GetMock<IHttpProvider>().Verify(c => c.DownloadFile(_updatePackage.Url, updateArchive));
|
||||
}
|
||||
|
||||
|
@ -112,7 +114,6 @@ namespace NzbDrone.Core.Test.UpdateTests
|
|||
|
||||
Subject.Execute(new ApplicationUpdateCommand());
|
||||
|
||||
|
||||
Mocker.GetMock<IArchiveService>().Verify(c => c.Extract(updateArchive, _sandboxFolder));
|
||||
}
|
||||
|
||||
|
@ -239,6 +240,26 @@ namespace NzbDrone.Core.Test.UpdateTests
|
|||
updateSubFolder.GetFiles().Should().NotBeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_log_error_when_app_data_is_child_of_startup_folder()
|
||||
{
|
||||
Mocker.GetMock<IAppFolderInfo>().SetupGet(c => c.StartUpFolder).Returns(@"C:\NzbDrone".AsOsAgnostic);
|
||||
Mocker.GetMock<IAppFolderInfo>().SetupGet(c => c.AppDataFolder).Returns(@"C:\NzbDrone\AppData".AsOsAgnostic);
|
||||
|
||||
Subject.Execute(new ApplicationUpdateCommand());
|
||||
ExceptionVerification.ExpectedErrors(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_log_error_when_app_data_is_same_as_startup_folder()
|
||||
{
|
||||
Mocker.GetMock<IAppFolderInfo>().SetupGet(c => c.StartUpFolder).Returns(@"C:\NzbDrone".AsOsAgnostic);
|
||||
Mocker.GetMock<IAppFolderInfo>().SetupGet(c => c.AppDataFolder).Returns(@"C:\NzbDrone".AsOsAgnostic);
|
||||
|
||||
Subject.Execute(new ApplicationUpdateCommand());
|
||||
ExceptionVerification.ExpectedErrors(1);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration />
|
|
@ -72,6 +72,11 @@ namespace NzbDrone.Core.Configuration
|
|||
_eventAggregator.PublishEvent(new ConfigSavedEvent());
|
||||
}
|
||||
|
||||
public Boolean IsDefined(String key)
|
||||
{
|
||||
return _repository.Get(key.ToLower()) != null;
|
||||
}
|
||||
|
||||
public String DownloadedEpisodesFolder
|
||||
{
|
||||
get { return GetValue(ConfigKey.DownloadedEpisodesFolder.ToString()); }
|
||||
|
@ -117,6 +122,27 @@ namespace NzbDrone.Core.Configuration
|
|||
set { SetValue("AutoDownloadPropers", value); }
|
||||
}
|
||||
|
||||
public Boolean EnableCompletedDownloadHandling
|
||||
{
|
||||
get { return GetValueBoolean("EnableCompletedDownloadHandling", false); }
|
||||
|
||||
set { SetValue("EnableCompletedDownloadHandling", value); }
|
||||
}
|
||||
|
||||
public Boolean RemoveCompletedDownloads
|
||||
{
|
||||
get { return GetValueBoolean("RemoveCompletedDownloads", false); }
|
||||
|
||||
set { SetValue("RemoveCompletedDownloads", value); }
|
||||
}
|
||||
|
||||
public Boolean EnableFailedDownloadHandling
|
||||
{
|
||||
get { return GetValueBoolean("EnableFailedDownloadHandling", true); }
|
||||
|
||||
set { SetValue("EnableFailedDownloadHandling", value); }
|
||||
}
|
||||
|
||||
public Boolean AutoRedownloadFailed
|
||||
{
|
||||
get { return GetValueBoolean("AutoRedownloadFailed", true); }
|
||||
|
@ -152,13 +178,6 @@ namespace NzbDrone.Core.Configuration
|
|||
set { SetValue("BlacklistRetryLimit", value); }
|
||||
}
|
||||
|
||||
public Boolean EnableFailedDownloadHandling
|
||||
{
|
||||
get { return GetValueBoolean("EnableFailedDownloadHandling", true); }
|
||||
|
||||
set { SetValue("EnableFailedDownloadHandling", value); }
|
||||
}
|
||||
|
||||
public Boolean CreateEmptySeriesFolders
|
||||
{
|
||||
get { return GetValueBoolean("CreateEmptySeriesFolders", false); }
|
||||
|
@ -186,6 +205,13 @@ namespace NzbDrone.Core.Configuration
|
|||
set { SetValue("DownloadedEpisodesScanInterval", value); }
|
||||
}
|
||||
|
||||
public Int32 DownloadClientHistoryLimit
|
||||
{
|
||||
get { return GetValueInt("DownloadClientHistoryLimit", 30); }
|
||||
|
||||
set { SetValue("DownloadClientHistoryLimit", value); }
|
||||
}
|
||||
|
||||
public Boolean SkipFreeSpaceCheckWhenImporting
|
||||
{
|
||||
get { return GetValueBoolean("SkipFreeSpaceCheckWhenImporting", false); }
|
||||
|
|
|
@ -11,15 +11,21 @@ namespace NzbDrone.Core.Configuration
|
|||
Dictionary<String, Object> AllWithDefaults();
|
||||
void SaveConfigDictionary(Dictionary<string, object> configValues);
|
||||
|
||||
Boolean IsDefined(String key);
|
||||
|
||||
//Download Client
|
||||
String DownloadedEpisodesFolder { get; set; }
|
||||
String DownloadClientWorkingFolders { get; set; }
|
||||
Int32 DownloadedEpisodesScanInterval { get; set; }
|
||||
Int32 DownloadClientHistoryLimit { get; set; }
|
||||
|
||||
//Failed Download Handling (Download client)
|
||||
//Completed/Failed Download Handling (Download client)
|
||||
Boolean EnableCompletedDownloadHandling { get; set; }
|
||||
Boolean RemoveCompletedDownloads { get; set; }
|
||||
|
||||
Boolean EnableFailedDownloadHandling { get; set; }
|
||||
Boolean AutoRedownloadFailed { get; set; }
|
||||
Boolean RemoveFailedDownloads { get; set; }
|
||||
Boolean EnableFailedDownloadHandling { get; set; }
|
||||
Int32 BlacklistGracePeriod { get; set; }
|
||||
Int32 BlacklistRetryInterval { get; set; }
|
||||
Int32 BlacklistRetryLimit { get; set; }
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
using System;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using FluentMigrator;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.IO;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(51)]
|
||||
public class download_client_import : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.WithConnection(EnableCompletedDownloadHandlingForNewUsers);
|
||||
|
||||
Execute.WithConnection(ConvertFolderSettings);
|
||||
|
||||
Execute.WithConnection(AssociateImportedHistoryItems);
|
||||
}
|
||||
|
||||
private void EnableCompletedDownloadHandlingForNewUsers(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
using (IDbCommand cmd = conn.CreateCommand())
|
||||
{
|
||||
cmd.Transaction = tran;
|
||||
cmd.CommandText = @"SELECT Value FROM Config WHERE Key = 'downloadedepisodesfolder'";
|
||||
|
||||
var result = cmd.ExecuteScalar();
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
cmd.CommandText = @"INSERT INTO Config (Key, Value) VALUES ('enablecompleteddownloadhandling', 'True')";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ConvertFolderSettings(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
using (IDbCommand downloadClientsCmd = conn.CreateCommand())
|
||||
{
|
||||
downloadClientsCmd.Transaction = tran;
|
||||
downloadClientsCmd.CommandText = @"SELECT Value FROM Config WHERE Key = 'downloadedepisodesfolder'";
|
||||
var downloadedEpisodesFolder = downloadClientsCmd.ExecuteScalar() as String;
|
||||
|
||||
downloadClientsCmd.Transaction = tran;
|
||||
downloadClientsCmd.CommandText = @"SELECT Id, Implementation, Settings, ConfigContract FROM DownloadClients WHERE ConfigContract = 'FolderSettings'";
|
||||
using (IDataReader downloadClientReader = downloadClientsCmd.ExecuteReader())
|
||||
{
|
||||
while (downloadClientReader.Read())
|
||||
{
|
||||
var id = downloadClientReader.GetInt32(0);
|
||||
var implementation = downloadClientReader.GetString(1);
|
||||
var settings = downloadClientReader.GetString(2);
|
||||
var configContract = downloadClientReader.GetString(3);
|
||||
|
||||
var settingsJson = JsonConvert.DeserializeObject(settings) as Newtonsoft.Json.Linq.JObject;
|
||||
|
||||
if (implementation == "Blackhole")
|
||||
{
|
||||
var newSettings = new
|
||||
{
|
||||
NzbFolder = settingsJson.Value<String>("folder"),
|
||||
WatchFolder = downloadedEpisodesFolder
|
||||
}.ToJson();
|
||||
|
||||
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||
{
|
||||
updateCmd.Transaction = tran;
|
||||
updateCmd.CommandText = "UPDATE DownloadClients SET Implementation = ?, Settings = ?, ConfigContract = ? WHERE Id = ?";
|
||||
updateCmd.AddParameter("UsenetBlackhole");
|
||||
updateCmd.AddParameter(newSettings);
|
||||
updateCmd.AddParameter("UsenetBlackholeSettings");
|
||||
updateCmd.AddParameter(id);
|
||||
|
||||
updateCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
else if (implementation == "Pneumatic")
|
||||
{
|
||||
var newSettings = new
|
||||
{
|
||||
NzbFolder = settingsJson.Value<String>("folder")
|
||||
}.ToJson();
|
||||
|
||||
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||
{
|
||||
updateCmd.Transaction = tran;
|
||||
updateCmd.CommandText = "UPDATE DownloadClients SET Settings = ?, ConfigContract = ? WHERE Id = ?";
|
||||
updateCmd.AddParameter(newSettings);
|
||||
updateCmd.AddParameter("PneumaticSettings");
|
||||
updateCmd.AddParameter(id);
|
||||
|
||||
updateCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||
{
|
||||
updateCmd.Transaction = tran;
|
||||
updateCmd.CommandText = "DELETE FROM DownloadClients WHERE Id = ?";
|
||||
updateCmd.AddParameter(id);
|
||||
|
||||
updateCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class MigrationHistoryItem
|
||||
{
|
||||
public Int32 Id { get; set; }
|
||||
public Int32 EpisodeId { get; set; }
|
||||
public Int32 SeriesId { get; set; }
|
||||
public String SourceTitle { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
public Dictionary<String, String> Data { get; set; }
|
||||
public MigrationHistoryEventType EventType { get; set; }
|
||||
}
|
||||
|
||||
private enum MigrationHistoryEventType
|
||||
{
|
||||
Unknown = 0,
|
||||
Grabbed = 1,
|
||||
SeriesFolderImported = 2,
|
||||
DownloadFolderImported = 3,
|
||||
DownloadFailed = 4
|
||||
}
|
||||
|
||||
private void AssociateImportedHistoryItems(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
var historyItems = new List<MigrationHistoryItem>();
|
||||
|
||||
using (IDbCommand historyCmd = conn.CreateCommand())
|
||||
{
|
||||
historyCmd.Transaction = tran;
|
||||
historyCmd.CommandText = @"SELECT Id, EpisodeId, SeriesId, SourceTitle, Date, Data, EventType FROM History WHERE EventType NOT NULL";
|
||||
using (IDataReader historyRead = historyCmd.ExecuteReader())
|
||||
{
|
||||
while (historyRead.Read())
|
||||
{
|
||||
historyItems.Add(new MigrationHistoryItem
|
||||
{
|
||||
Id = historyRead.GetInt32(0),
|
||||
EpisodeId = historyRead.GetInt32(1),
|
||||
SeriesId = historyRead.GetInt32(2),
|
||||
SourceTitle = historyRead.GetString(3),
|
||||
Date = historyRead.GetDateTime(4),
|
||||
Data = Json.Deserialize<Dictionary<String, String>>(historyRead.GetString(5)),
|
||||
EventType = (MigrationHistoryEventType)historyRead.GetInt32(6)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var numHistoryItemsNotAssociated = historyItems.Count(v => v.EventType == MigrationHistoryEventType.DownloadFolderImported &&
|
||||
v.Data.GetValueOrDefault("downloadClientId") == null);
|
||||
|
||||
if (numHistoryItemsNotAssociated == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var historyItemsToAssociate = new Dictionary<MigrationHistoryItem, MigrationHistoryItem>();
|
||||
|
||||
var historyItemsLookup = historyItems.ToLookup(v => v.EpisodeId);
|
||||
|
||||
foreach (var historyItemGroup in historyItemsLookup)
|
||||
{
|
||||
var list = historyItemGroup.ToList();
|
||||
|
||||
for (int i = 0; i < list.Count - 1; i++)
|
||||
{
|
||||
var grabbedEvent = list[i];
|
||||
if (grabbedEvent.EventType != MigrationHistoryEventType.Grabbed) continue;
|
||||
if (grabbedEvent.Data.GetValueOrDefault("downloadClient") == null || grabbedEvent.Data.GetValueOrDefault("downloadClientId") == null) continue;
|
||||
|
||||
// Check if it is already associated with a failed/imported event.
|
||||
int j;
|
||||
for (j = i + 1; j < list.Count;j++)
|
||||
{
|
||||
if (list[j].EventType != MigrationHistoryEventType.DownloadFolderImported &&
|
||||
list[j].EventType != MigrationHistoryEventType.DownloadFailed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (list[j].Data.ContainsKey("downloadClient") && list[j].Data["downloadClient"] == grabbedEvent.Data["downloadClient"] &&
|
||||
list[j].Data.ContainsKey("downloadClientId") && list[j].Data["downloadClientId"] == grabbedEvent.Data["downloadClientId"])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j != list.Count)
|
||||
{
|
||||
list.RemoveAt(j);
|
||||
list.RemoveAt(i--);
|
||||
continue;
|
||||
}
|
||||
|
||||
var importedEvent = list[i + 1];
|
||||
if (importedEvent.EventType != MigrationHistoryEventType.DownloadFolderImported) continue;
|
||||
|
||||
var droppedPath = importedEvent.Data.GetValueOrDefault("droppedPath");
|
||||
if (droppedPath != null && new FileInfo(droppedPath).Directory.Name == grabbedEvent.SourceTitle)
|
||||
{
|
||||
historyItemsToAssociate[importedEvent] = grabbedEvent;
|
||||
|
||||
list.RemoveAt(i + 1);
|
||||
list.RemoveAt(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var pair in historyItemsToAssociate)
|
||||
{
|
||||
using (IDbCommand updateHistoryCmd = conn.CreateCommand())
|
||||
{
|
||||
pair.Key.Data["downloadClient"] = pair.Value.Data["downloadClient"];
|
||||
pair.Key.Data["downloadClientId"] = pair.Value.Data["downloadClientId"];
|
||||
|
||||
updateHistoryCmd.Transaction = tran;
|
||||
updateHistoryCmd.CommandText = "UPDATE History SET Data = ? WHERE Id = ?";
|
||||
updateHistoryCmd.AddParameter(pair.Key.Data.ToJson());
|
||||
updateHistoryCmd.AddParameter(pair.Key.Id);
|
||||
|
||||
updateHistoryCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Info("Updated old History items. {0}/{1} old ImportedEvents were associated with GrabbedEvents.", historyItemsToAssociate.Count, numHistoryItemsNotAssociated);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,11 +6,11 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
|||
{
|
||||
public abstract class NzbDroneMigrationBase : FluentMigrator.Migration
|
||||
{
|
||||
private Logger _logger;
|
||||
protected readonly Logger _logger;
|
||||
|
||||
protected NzbDroneMigrationBase()
|
||||
{
|
||||
_logger = NzbDroneLogger.GetLogger();
|
||||
_logger = NzbDroneLogger.GetLogger(this);
|
||||
}
|
||||
|
||||
protected virtual void MainDbUpgrade()
|
||||
|
|
|
@ -37,7 +37,8 @@ namespace NzbDrone.Core.Datastore
|
|||
Mapper.Entity<Config>().RegisterModel("Config");
|
||||
Mapper.Entity<RootFolder>().RegisterModel("RootFolders").Ignore(r => r.FreeSpace);
|
||||
|
||||
Mapper.Entity<IndexerDefinition>().RegisterModel("Indexers");
|
||||
Mapper.Entity<IndexerDefinition>().RegisterModel("Indexers")
|
||||
.Ignore(s => s.Protocol);
|
||||
Mapper.Entity<ScheduledTask>().RegisterModel("ScheduledTasks");
|
||||
Mapper.Entity<NotificationDefinition>().RegisterModel("Notifications");
|
||||
Mapper.Entity<MetadataDefinition>().RegisterModel("Metadata");
|
||||
|
|
|
@ -5,17 +5,18 @@ using NzbDrone.Core.Download;
|
|||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Queue;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class NotInQueueSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly IProvideDownloadClient _downloadClientProvider;
|
||||
private readonly IQueueService _queueService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public NotInQueueSpecification(IProvideDownloadClient downloadClientProvider, Logger logger)
|
||||
public NotInQueueSpecification(IQueueService queueService, Logger logger)
|
||||
{
|
||||
_downloadClientProvider = downloadClientProvider;
|
||||
_queueService = queueService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -29,15 +30,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
|
||||
public bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var downloadClient = _downloadClientProvider.GetDownloadClient();
|
||||
|
||||
if (downloadClient == null)
|
||||
{
|
||||
_logger.Warn("Download client isn't configured yet.");
|
||||
return true;
|
||||
}
|
||||
|
||||
var queue = downloadClient.GetQueue().Select(q => q.RemoteEpisode);
|
||||
var queue = _queueService.GetQueue().Select(q => q.RemoteEpisode);
|
||||
|
||||
if (IsInQueue(subject, queue))
|
||||
{
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.Clients.Sabnzbd;
|
||||
|
@ -41,9 +42,9 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
return true;
|
||||
}
|
||||
|
||||
var downloadClient = _downloadClientProvider.GetDownloadClient();
|
||||
var downloadClients = _downloadClientProvider.GetDownloadClients();
|
||||
|
||||
if (downloadClient != null && downloadClient.GetType() == typeof (Sabnzbd))
|
||||
foreach (var downloadClient in downloadClients.OfType<Sabnzbd>())
|
||||
{
|
||||
_logger.Debug("Performing history status check on report");
|
||||
foreach (var episode in subject.Episodes)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
public class CheckForFailedDownloadCommand : Command
|
||||
public class CheckForFinishedDownloadCommand : Command
|
||||
{
|
||||
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
{
|
||||
public class Blackhole : DownloadClientBase<FolderSettings>, IExecute<TestBlackholeCommand>
|
||||
{
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public Blackhole(IDiskProvider diskProvider, IHttpProvider httpProvider, Logger logger)
|
||||
{
|
||||
_diskProvider = diskProvider;
|
||||
_httpProvider = httpProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override string DownloadNzb(RemoteEpisode remoteEpisode)
|
||||
{
|
||||
var url = remoteEpisode.Release.DownloadUrl;
|
||||
var title = remoteEpisode.Release.Title;
|
||||
|
||||
title = FileNameBuilder.CleanFilename(title);
|
||||
|
||||
var filename = Path.Combine(Settings.Folder, title + ".nzb");
|
||||
|
||||
|
||||
_logger.Debug("Downloading NZB from: {0} to: {1}", url, filename);
|
||||
_httpProvider.DownloadFile(url, filename);
|
||||
_logger.Debug("NZB Download succeeded, saved to: {0}", filename);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override IEnumerable<QueueItem> GetQueue()
|
||||
{
|
||||
return new QueueItem[0];
|
||||
}
|
||||
|
||||
public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10)
|
||||
{
|
||||
return new HistoryItem[0];
|
||||
}
|
||||
|
||||
public override void RemoveFromQueue(string id)
|
||||
{
|
||||
}
|
||||
|
||||
public override void RemoveFromHistory(string id)
|
||||
{
|
||||
}
|
||||
|
||||
public override void RetryDownload(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Test()
|
||||
{
|
||||
PerformTest(Settings.Folder);
|
||||
}
|
||||
|
||||
private void PerformTest(string folder)
|
||||
{
|
||||
var testPath = Path.Combine(folder, "drone_test.txt");
|
||||
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
|
||||
_diskProvider.DeleteFile(testPath);
|
||||
}
|
||||
|
||||
public void Execute(TestBlackholeCommand message)
|
||||
{
|
||||
PerformTest(message.Folder);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
using System;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients
|
||||
{
|
||||
public class FolderSettingsValidator : AbstractValidator<FolderSettings>
|
||||
{
|
||||
public FolderSettingsValidator()
|
||||
{
|
||||
//Todo: Validate that the path actually exists
|
||||
RuleFor(c => c.Folder).IsValidPath();
|
||||
}
|
||||
}
|
||||
|
||||
public class FolderSettings : IProviderConfig
|
||||
{
|
||||
private static readonly FolderSettingsValidator Validator = new FolderSettingsValidator();
|
||||
|
||||
[FieldDefinition(0, Label = "Folder", Type = FieldType.Path)]
|
||||
public String Folder { get; set; }
|
||||
|
||||
public ValidationResult Validate()
|
||||
{
|
||||
return Validator.Validate(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,15 +5,20 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
{
|
||||
public class NzbgetQueueItem
|
||||
{
|
||||
private string _nzbName;
|
||||
public Int32 NzbId { get; set; }
|
||||
public Int32 FirstId { get; set; }
|
||||
public Int32 LastId { get; set; }
|
||||
public string NzbName { get; set; }
|
||||
public String NzbName { get; set; }
|
||||
public String Category { get; set; }
|
||||
public Int32 FileSizeMb { get; set; }
|
||||
public Int32 RemainingSizeMb { get; set; }
|
||||
public Int32 PausedSizeMb { get; set; }
|
||||
public UInt32 FileSizeLo { get; set; }
|
||||
public UInt32 FileSizeHi { get; set; }
|
||||
public UInt32 RemainingSizeLo { get; set; }
|
||||
public UInt32 RemainingSizeHi { get; set; }
|
||||
public UInt32 PausedSizeLo { get; set; }
|
||||
public UInt32 PausedSizeHi { get; set; }
|
||||
public Int32 MinPriority { get; set; }
|
||||
public Int32 MaxPriority { get; set; }
|
||||
public Int32 ActiveDownloads { get; set; }
|
||||
public List<NzbgetParameter> Parameters { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
@ -14,22 +17,28 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
public class Nzbget : DownloadClientBase<NzbgetSettings>, IExecute<TestNzbgetCommand>
|
||||
{
|
||||
private readonly INzbgetProxy _proxy;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public Nzbget(INzbgetProxy proxy,
|
||||
IConfigService configService,
|
||||
IParsingService parsingService,
|
||||
IHttpProvider httpProvider,
|
||||
Logger logger)
|
||||
: base(configService, parsingService, logger)
|
||||
{
|
||||
_proxy = proxy;
|
||||
_parsingService = parsingService;
|
||||
_httpProvider = httpProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override string DownloadNzb(RemoteEpisode remoteEpisode)
|
||||
public override DownloadProtocol Protocol
|
||||
{
|
||||
get
|
||||
{
|
||||
return DownloadProtocol.Usenet;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Download(RemoteEpisode remoteEpisode)
|
||||
{
|
||||
var url = remoteEpisode.Release.DownloadUrl;
|
||||
var title = remoteEpisode.Release.Title + ".nzb";
|
||||
|
@ -48,80 +57,129 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<QueueItem> GetQueue()
|
||||
private IEnumerable<DownloadClientItem> GetQueue()
|
||||
{
|
||||
NzbgetGlobalStatus globalStatus;
|
||||
List<NzbgetQueueItem> queue;
|
||||
Dictionary<Int32, NzbgetPostQueueItem> postQueue;
|
||||
|
||||
try
|
||||
{
|
||||
globalStatus = _proxy.GetGlobalStatus(Settings);
|
||||
queue = _proxy.GetQueue(Settings);
|
||||
postQueue = _proxy.GetPostQueue(Settings).ToDictionary(v => v.NzbId);
|
||||
}
|
||||
catch (DownloadClientException ex)
|
||||
{
|
||||
_logger.ErrorException(ex.Message, ex);
|
||||
return Enumerable.Empty<QueueItem>();
|
||||
return Enumerable.Empty<DownloadClientItem>();
|
||||
}
|
||||
|
||||
var queueItems = new List<QueueItem>();
|
||||
var queueItems = new List<DownloadClientItem>();
|
||||
|
||||
Int64 totalRemainingSize = 0;
|
||||
|
||||
foreach (var item in queue)
|
||||
{
|
||||
var postQueueItem = postQueue.GetValueOrDefault(item.NzbId);
|
||||
|
||||
var totalSize = MakeInt64(item.FileSizeHi, item.FileSizeLo);
|
||||
var pausedSize = MakeInt64(item.PausedSizeHi, item.PausedSizeLo);
|
||||
var remainingSize = MakeInt64(item.RemainingSizeHi, item.RemainingSizeLo);
|
||||
|
||||
var droneParameter = item.Parameters.SingleOrDefault(p => p.Name == "drone");
|
||||
|
||||
var queueItem = new QueueItem();
|
||||
queueItem.Id = droneParameter == null ? item.NzbId.ToString() : droneParameter.Value.ToString();
|
||||
var queueItem = new DownloadClientItem();
|
||||
queueItem.DownloadClientId = droneParameter == null ? item.NzbId.ToString() : droneParameter.Value.ToString();
|
||||
queueItem.Title = item.NzbName;
|
||||
queueItem.Size = item.FileSizeMb;
|
||||
queueItem.Sizeleft = item.RemainingSizeMb;
|
||||
queueItem.Status = item.FileSizeMb == item.PausedSizeMb ? "paused" : "queued";
|
||||
queueItem.TotalSize = totalSize;
|
||||
queueItem.Category = item.Category;
|
||||
|
||||
var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title);
|
||||
if (parsedEpisodeInfo == null) continue;
|
||||
if (postQueueItem != null)
|
||||
{
|
||||
queueItem.Status = DownloadItemStatus.Downloading;
|
||||
queueItem.Message = postQueueItem.ProgressLabel;
|
||||
|
||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0);
|
||||
if (remoteEpisode.Series == null) continue;
|
||||
if (postQueueItem.StageProgress != 0)
|
||||
{
|
||||
queueItem.RemainingTime = TimeSpan.FromSeconds(postQueueItem.StageTimeSec * 1000 / postQueueItem.StageProgress - postQueueItem.StageTimeSec);
|
||||
}
|
||||
}
|
||||
else if (globalStatus.DownloadPaused || remainingSize == pausedSize)
|
||||
{
|
||||
queueItem.Status = DownloadItemStatus.Paused;
|
||||
queueItem.RemainingSize = remainingSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.ActiveDownloads == 0 && remainingSize != 0)
|
||||
{
|
||||
queueItem.Status = DownloadItemStatus.Queued;
|
||||
}
|
||||
else
|
||||
{
|
||||
queueItem.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
|
||||
queueItem.RemainingSize = remainingSize - pausedSize;
|
||||
|
||||
if (globalStatus.DownloadRate != 0)
|
||||
{
|
||||
queueItem.RemainingTime = TimeSpan.FromSeconds((totalRemainingSize + queueItem.RemainingSize) / globalStatus.DownloadRate);
|
||||
totalRemainingSize += queueItem.RemainingSize;
|
||||
}
|
||||
}
|
||||
|
||||
queueItem.RemoteEpisode = remoteEpisode;
|
||||
queueItems.Add(queueItem);
|
||||
}
|
||||
|
||||
return queueItems;
|
||||
}
|
||||
|
||||
public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10)
|
||||
private IEnumerable<DownloadClientItem> GetHistory()
|
||||
{
|
||||
List<NzbgetHistoryItem> history;
|
||||
|
||||
try
|
||||
{
|
||||
history = _proxy.GetHistory(Settings);
|
||||
history = _proxy.GetHistory(Settings).Take(_configService.DownloadClientHistoryLimit).ToList();
|
||||
}
|
||||
catch (DownloadClientException ex)
|
||||
{
|
||||
_logger.ErrorException(ex.Message, ex);
|
||||
return Enumerable.Empty<HistoryItem>();
|
||||
return Enumerable.Empty<DownloadClientItem>();
|
||||
}
|
||||
|
||||
var historyItems = new List<HistoryItem>();
|
||||
var successStatues = new[] {"SUCCESS", "NONE"};
|
||||
var historyItems = new List<DownloadClientItem>();
|
||||
var successStatus = new[] {"SUCCESS", "NONE"};
|
||||
|
||||
foreach (var item in history)
|
||||
{
|
||||
var droneParameter = item.Parameters.SingleOrDefault(p => p.Name == "drone");
|
||||
var status = successStatues.Contains(item.ParStatus) &&
|
||||
successStatues.Contains(item.ScriptStatus)
|
||||
? HistoryStatus.Completed
|
||||
: HistoryStatus.Failed;
|
||||
|
||||
var historyItem = new HistoryItem();
|
||||
historyItem.Id = droneParameter == null ? item.Id.ToString() : droneParameter.Value.ToString();
|
||||
var historyItem = new DownloadClientItem();
|
||||
historyItem.DownloadClient = Definition.Name;
|
||||
historyItem.DownloadClientId = droneParameter == null ? item.Id.ToString() : droneParameter.Value.ToString();
|
||||
historyItem.Title = item.Name;
|
||||
historyItem.Size = item.FileSizeMb.ToString(); //Why is this a string?
|
||||
historyItem.DownloadTime = 0;
|
||||
historyItem.Storage = item.DestDir;
|
||||
historyItem.TotalSize = MakeInt64(item.FileSizeHi, item.FileSizeLo);
|
||||
historyItem.OutputPath = item.DestDir;
|
||||
historyItem.Category = item.Category;
|
||||
historyItem.Message = String.Format("PAR Status: {0} - Script Status: {1}", item.ParStatus, item.ScriptStatus);
|
||||
historyItem.Status = status;
|
||||
historyItem.Message = String.Format("PAR Status: {0} - Unpack Status: {1} - Move Status: {2} - Script Status: {3} - Delete Status: {4} - Mark Status: {5}", item.ParStatus, item.UnpackStatus, item.MoveStatus, item.ScriptStatus, item.DeleteStatus, item.MarkStatus);
|
||||
historyItem.Status = DownloadItemStatus.Completed;
|
||||
historyItem.RemainingTime = TimeSpan.Zero;
|
||||
|
||||
if (item.DeleteStatus == "MANUAL")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!successStatus.Contains(item.ParStatus) ||
|
||||
!successStatus.Contains(item.UnpackStatus) ||
|
||||
!successStatus.Contains(item.MoveStatus) ||
|
||||
!successStatus.Contains(item.ScriptStatus))
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Failed;
|
||||
}
|
||||
|
||||
historyItems.Add(historyItem);
|
||||
}
|
||||
|
@ -129,12 +187,20 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
return historyItems;
|
||||
}
|
||||
|
||||
public override void RemoveFromQueue(string id)
|
||||
public override IEnumerable<DownloadClientItem> GetItems()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
foreach (var downloadClientItem in GetQueue().Concat(GetHistory()))
|
||||
{
|
||||
if (downloadClientItem.Category != Settings.TvCategory) continue;
|
||||
|
||||
downloadClientItem.RemoteEpisode = GetRemoteEpisode(downloadClientItem.Title);
|
||||
if (downloadClientItem.RemoteEpisode == null) continue;
|
||||
|
||||
yield return downloadClientItem;
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoveFromHistory(string id)
|
||||
public override void RemoveItem(string id)
|
||||
{
|
||||
_proxy.RemoveFromHistory(id, Settings);
|
||||
}
|
||||
|
@ -144,22 +210,94 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
_proxy.RetryDownload(id, Settings);
|
||||
}
|
||||
|
||||
public override void Test()
|
||||
public override DownloadClientStatus GetStatus()
|
||||
{
|
||||
_proxy.GetVersion(Settings);
|
||||
var config = _proxy.GetConfig(Settings);
|
||||
|
||||
var category = GetCategories(config).FirstOrDefault(v => v.Name == Settings.TvCategory);
|
||||
|
||||
var status = new DownloadClientStatus
|
||||
{
|
||||
IsLocalhost = Settings.Host == "127.0.0.1" || Settings.Host == "localhost"
|
||||
};
|
||||
|
||||
if (category != null)
|
||||
{
|
||||
status.OutputRootFolders = new List<string> { category.DestDir };
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
private VersionResponse GetVersion(string host = null, int port = 0, string username = null, string password = null)
|
||||
protected IEnumerable<NzbgetCategory> GetCategories(Dictionary<String, String> config)
|
||||
{
|
||||
for (int i = 1; i < 100; i++)
|
||||
{
|
||||
var name = config.GetValueOrDefault("Category" + i + ".Name");
|
||||
|
||||
if (name == null) yield break;
|
||||
|
||||
var destDir = config.GetValueOrDefault("Category" + i + ".DestDir");
|
||||
|
||||
if (destDir.IsNullOrWhiteSpace())
|
||||
{
|
||||
var mainDir = config.GetValueOrDefault("MainDir");
|
||||
destDir = config.GetValueOrDefault("DestDir", String.Empty).Replace("${MainDir}", mainDir);
|
||||
|
||||
if (config.GetValueOrDefault("AppendCategoryDir", "yes") == "yes")
|
||||
{
|
||||
destDir = Path.Combine(destDir, name);
|
||||
}
|
||||
}
|
||||
|
||||
yield return new NzbgetCategory
|
||||
{
|
||||
Name = name,
|
||||
DestDir = destDir,
|
||||
Unpack = config.GetValueOrDefault("Category" + i + ".Unpack") == "yes",
|
||||
DefScript = config.GetValueOrDefault("Category" + i + ".DefScript"),
|
||||
Aliases = config.GetValueOrDefault("Category" + i + ".Aliases"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private String GetVersion(string host = null, int port = 0, string username = null, string password = null)
|
||||
{
|
||||
return _proxy.GetVersion(Settings);
|
||||
}
|
||||
|
||||
public override void Test(NzbgetSettings settings)
|
||||
{
|
||||
_proxy.GetVersion(settings);
|
||||
|
||||
var config = _proxy.GetConfig(settings);
|
||||
|
||||
var categories = GetCategories(config);
|
||||
|
||||
if (!categories.Any(v => v.Name == settings.TvCategory))
|
||||
{
|
||||
throw new ApplicationException("Category does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
public void Execute(TestNzbgetCommand message)
|
||||
{
|
||||
var settings = new NzbgetSettings();
|
||||
settings.InjectFrom(message);
|
||||
|
||||
_proxy.GetVersion(settings);
|
||||
Test(settings);
|
||||
}
|
||||
|
||||
// Javascript doesn't support 64 bit integers natively so json officially doesn't either.
|
||||
// NzbGet api thus sends it in two 32 bit chunks. Here we join the two chunks back together.
|
||||
// Simplified decimal example: "42" splits into "4" and "2". To join them I shift (<<) the "4" 1 digit to the left = "40". combine it with "2". which becomes "42" again.
|
||||
private Int64 MakeInt64(UInt32 high, UInt32 low)
|
||||
{
|
||||
Int64 result = high;
|
||||
|
||||
result = (result << 32) | (Int64)low;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
{
|
||||
public class NzbgetBooleanResponse
|
||||
{
|
||||
public String Version { get; set; }
|
||||
public Boolean Result { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
{
|
||||
public class NzbgetCategory
|
||||
{
|
||||
public String Name { get; set; }
|
||||
public String DestDir { get; set; }
|
||||
public Boolean Unpack { get; set; }
|
||||
public String DefScript { get; set; }
|
||||
public String Aliases { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
{
|
||||
public class NzbgetConfigItem
|
||||
{
|
||||
public String Name { get; set; }
|
||||
public String Value { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
{
|
||||
public class NzbgetGlobalStatus
|
||||
{
|
||||
public UInt32 RemainingSizeLo { get; set; }
|
||||
public UInt32 RemainingSizeHi { get; set; }
|
||||
public UInt32 DownloadedSizeLo { get; set; }
|
||||
public UInt32 DownloadedSizeHi { get; set; }
|
||||
public UInt32 DownloadRate { get; set; }
|
||||
public UInt32 AverageDownloadRate { get; set; }
|
||||
public UInt32 DownloadLimit { get; set; }
|
||||
public Boolean DownloadPaused { get; set; }
|
||||
}
|
||||
}
|
|
@ -5,13 +5,17 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
{
|
||||
public class NzbgetHistoryItem
|
||||
{
|
||||
private string _nzbName;
|
||||
public Int32 Id { get; set; }
|
||||
public String Name { get; set; }
|
||||
public String Category { get; set; }
|
||||
public Int32 FileSizeMb { get; set; }
|
||||
public UInt32 FileSizeLo { get; set; }
|
||||
public UInt32 FileSizeHi { get; set; }
|
||||
public String ParStatus { get; set; }
|
||||
public String UnpackStatus { get; set; }
|
||||
public String MoveStatus { get; set; }
|
||||
public String ScriptStatus { get; set; }
|
||||
public String DeleteStatus { get; set; }
|
||||
public String MarkStatus { get; set; }
|
||||
public String DestDir { get; set; }
|
||||
public List<NzbgetParameter> Parameters { get; set; }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
{
|
||||
public class NzbgetPostQueueItem
|
||||
{
|
||||
public Int32 NzbId { get; set; }
|
||||
public String NzbName { get; set; }
|
||||
public String Stage { get; set; }
|
||||
public String ProgressLabel { get; set; }
|
||||
public Int32 FileProgress { get; set; }
|
||||
public Int32 StageProgress { get; set; }
|
||||
public Int32 TotalTimeSec { get; set; }
|
||||
public Int32 StageTimeSec { get; set; }
|
||||
}
|
||||
}
|
|
@ -13,9 +13,12 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
public interface INzbgetProxy
|
||||
{
|
||||
string DownloadNzb(Stream nzb, string title, string category, int priority, NzbgetSettings settings);
|
||||
NzbgetGlobalStatus GetGlobalStatus(NzbgetSettings settings);
|
||||
List<NzbgetQueueItem> GetQueue(NzbgetSettings settings);
|
||||
List<NzbgetPostQueueItem> GetPostQueue(NzbgetSettings settings);
|
||||
List<NzbgetHistoryItem> GetHistory(NzbgetSettings settings);
|
||||
VersionResponse GetVersion(NzbgetSettings settings);
|
||||
String GetVersion(NzbgetSettings settings);
|
||||
Dictionary<String, String> GetConfig(NzbgetSettings settings);
|
||||
void RemoveFromHistory(string id, NzbgetSettings settings);
|
||||
void RetryDownload(string id, NzbgetSettings settings);
|
||||
}
|
||||
|
@ -34,8 +37,8 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
var parameters = new object[] { title, category, priority, false, Convert.ToBase64String(nzb.ToBytes()) };
|
||||
var request = BuildRequest(new JsonRequest("append", parameters));
|
||||
|
||||
var response = Json.Deserialize<NzbgetBooleanResponse>(ProcessRequest(request, settings));
|
||||
_logger.Debug("Queue Response: [{0}]", response.Result);
|
||||
var response = Json.Deserialize<NzbgetResponse<Boolean>>(ProcessRequest(request, settings));
|
||||
_logger.Trace("Response: [{0}]", response.Result);
|
||||
|
||||
if (!response.Result)
|
||||
{
|
||||
|
@ -61,31 +64,53 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
return droneId;
|
||||
}
|
||||
|
||||
public NzbgetGlobalStatus GetGlobalStatus(NzbgetSettings settings)
|
||||
{
|
||||
var request = BuildRequest(new JsonRequest("status"));
|
||||
|
||||
return Json.Deserialize<NzbgetResponse<NzbgetGlobalStatus>>(ProcessRequest(request, settings)).Result;
|
||||
}
|
||||
|
||||
public List<NzbgetQueueItem> GetQueue(NzbgetSettings settings)
|
||||
{
|
||||
var request = BuildRequest(new JsonRequest("listgroups"));
|
||||
|
||||
return Json.Deserialize<NzbgetListResponse<NzbgetQueueItem>>(ProcessRequest(request, settings)).QueueItems;
|
||||
return Json.Deserialize<NzbgetResponse<List<NzbgetQueueItem>>>(ProcessRequest(request, settings)).Result;
|
||||
}
|
||||
|
||||
public List<NzbgetPostQueueItem> GetPostQueue(NzbgetSettings settings)
|
||||
{
|
||||
var request = BuildRequest(new JsonRequest("postqueue"));
|
||||
|
||||
return Json.Deserialize<NzbgetResponse<List<NzbgetPostQueueItem>>>(ProcessRequest(request, settings)).Result;
|
||||
}
|
||||
|
||||
public List<NzbgetHistoryItem> GetHistory(NzbgetSettings settings)
|
||||
{
|
||||
var request = BuildRequest(new JsonRequest("history"));
|
||||
|
||||
return Json.Deserialize<NzbgetListResponse<NzbgetHistoryItem>>(ProcessRequest(request, settings)).QueueItems;
|
||||
return Json.Deserialize<NzbgetResponse<List<NzbgetHistoryItem>>>(ProcessRequest(request, settings)).Result;
|
||||
}
|
||||
|
||||
public VersionResponse GetVersion(NzbgetSettings settings)
|
||||
public String GetVersion(NzbgetSettings settings)
|
||||
{
|
||||
var request = BuildRequest(new JsonRequest("version"));
|
||||
|
||||
return Json.Deserialize<VersionResponse>(ProcessRequest(request, settings));
|
||||
return Json.Deserialize<NzbgetResponse<String>>(ProcessRequest(request, settings)).Version;
|
||||
}
|
||||
|
||||
public Dictionary<String, String> GetConfig(NzbgetSettings settings)
|
||||
{
|
||||
var request = BuildRequest(new JsonRequest("config"));
|
||||
|
||||
return Json.Deserialize<NzbgetResponse<List<NzbgetConfigItem>>>(ProcessRequest(request, settings)).Result.ToDictionary(v => v.Name, v => v.Value);
|
||||
}
|
||||
|
||||
|
||||
public void RemoveFromHistory(string id, NzbgetSettings settings)
|
||||
{
|
||||
var history = GetHistory(settings);
|
||||
var item = history.SingleOrDefault(h => h.Parameters.SingleOrDefault(p => p.Name == "drone") != null);
|
||||
var item = history.SingleOrDefault(h => h.Parameters.Any(p => p.Name == "drone" && id == (p.Value as string)));
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
|
@ -120,7 +145,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
{
|
||||
var parameters = new object[] { command, offset, editText, id };
|
||||
var request = BuildRequest(new JsonRequest("editqueue", parameters));
|
||||
var response = Json.Deserialize<NzbgetBooleanResponse>(ProcessRequest(request, settings));
|
||||
var response = Json.Deserialize<NzbgetResponse<Boolean>>(ProcessRequest(request, settings));
|
||||
|
||||
return response.Result;
|
||||
}
|
||||
|
@ -129,7 +154,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
{
|
||||
var client = BuildClient(settings);
|
||||
var response = client.Execute(restRequest);
|
||||
_logger.Debug("Response: {0}", response.Content);
|
||||
_logger.Trace("Response: {0}", response.Content);
|
||||
|
||||
CheckForError(response);
|
||||
|
||||
|
@ -145,6 +170,8 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
settings.Host,
|
||||
settings.Port);
|
||||
|
||||
_logger.Debug("Url: " + url);
|
||||
|
||||
var client = new RestClient(url);
|
||||
client.Authenticator = new HttpBasicAuthenticator(settings.Username, settings.Password);
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ using Newtonsoft.Json;
|
|||
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
{
|
||||
public class NzbgetListResponse<T>
|
||||
public class NzbgetResponse<T>
|
||||
{
|
||||
public String Version { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "result")]
|
||||
public List<T> QueueItems { get; set; }
|
||||
public T Result { get; set; }
|
||||
|
||||
}
|
||||
}
|
|
@ -13,9 +13,14 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public String Host { get; set; }
|
||||
public Int32 Port { get; set; }
|
||||
public String Username { get; set; }
|
||||
public String Password { get; set; }
|
||||
public String TvCategory { get; set; }
|
||||
public Int32 RecentTvPriority { get; set; }
|
||||
public Int32 OlderTvPriority { get; set; }
|
||||
public Boolean UseSsl { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
{
|
||||
public class VersionResponse
|
||||
{
|
||||
public String Version { get; set; }
|
||||
public String Result { get; set; }
|
||||
}
|
||||
}
|
|
@ -7,42 +7,55 @@ using NzbDrone.Common.Disk;
|
|||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Common.Instrumentation;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Pneumatic
|
||||
{
|
||||
public class Pneumatic : DownloadClientBase<FolderSettings>, IExecute<TestPneumaticCommand>
|
||||
public class Pneumatic : DownloadClientBase<PneumaticSettings>, IExecute<TestPneumaticCommand>
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
|
||||
private static readonly Logger logger = NzbDroneLogger.GetLogger();
|
||||
|
||||
public Pneumatic(IConfigService configService, IHttpProvider httpProvider,
|
||||
IDiskProvider diskProvider)
|
||||
public Pneumatic(IHttpProvider httpProvider,
|
||||
IDiskProvider diskProvider,
|
||||
IConfigService configService,
|
||||
IParsingService parsingService,
|
||||
Logger logger)
|
||||
: base(configService, parsingService, logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_httpProvider = httpProvider;
|
||||
_diskProvider = diskProvider;
|
||||
}
|
||||
|
||||
public override string DownloadNzb(RemoteEpisode remoteEpisode)
|
||||
public override DownloadProtocol Protocol
|
||||
{
|
||||
get
|
||||
{
|
||||
return DownloadProtocol.Usenet;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Download(RemoteEpisode remoteEpisode)
|
||||
{
|
||||
var url = remoteEpisode.Release.DownloadUrl;
|
||||
var title = remoteEpisode.Release.Title;
|
||||
|
||||
if (remoteEpisode.ParsedEpisodeInfo.FullSeason)
|
||||
{
|
||||
throw new NotImplementedException("Full season releases are not supported with Pneumatic.");
|
||||
throw new NotSupportedException("Full season releases are not supported with Pneumatic.");
|
||||
}
|
||||
|
||||
title = FileNameBuilder.CleanFilename(title);
|
||||
|
||||
//Save to the Pneumatic directory (The user will need to ensure its accessible by XBMC)
|
||||
var filename = Path.Combine(Settings.Folder, title + ".nzb");
|
||||
var filename = Path.Combine(Settings.NzbFolder, title + ".nzb");
|
||||
|
||||
logger.Debug("Downloading NZB from: {0} to: {1}", url, filename);
|
||||
_httpProvider.DownloadFile(url, filename);
|
||||
|
@ -59,39 +72,41 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
|
|||
{
|
||||
get
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(Settings.Folder);
|
||||
return !string.IsNullOrWhiteSpace(Settings.NzbFolder);
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<QueueItem> GetQueue()
|
||||
public override IEnumerable<DownloadClientItem> GetItems()
|
||||
{
|
||||
return new QueueItem[0];
|
||||
return new DownloadClientItem[0];
|
||||
}
|
||||
|
||||
public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10)
|
||||
{
|
||||
return new HistoryItem[0];
|
||||
}
|
||||
|
||||
public override void RemoveFromQueue(string id)
|
||||
{
|
||||
}
|
||||
|
||||
public override void RemoveFromHistory(string id)
|
||||
|
||||
public override void RemoveItem(string id)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void RetryDownload(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Test()
|
||||
public override DownloadClientStatus GetStatus()
|
||||
{
|
||||
PerformTest(Settings.Folder);
|
||||
var status = new DownloadClientStatus
|
||||
{
|
||||
IsLocalhost = true
|
||||
};
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
private void PerformTest(string folder)
|
||||
public override void Test(PneumaticSettings settings)
|
||||
{
|
||||
PerformWriteTest(settings.NzbFolder);
|
||||
}
|
||||
|
||||
private void PerformWriteTest(string folder)
|
||||
{
|
||||
var testPath = Path.Combine(folder, "drone_test.txt");
|
||||
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
|
||||
|
@ -100,7 +115,10 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
|
|||
|
||||
public void Execute(TestPneumaticCommand message)
|
||||
{
|
||||
PerformTest(message.Folder);
|
||||
var settings = new PneumaticSettings();
|
||||
settings.InjectFrom(message);
|
||||
|
||||
Test(settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Pneumatic
|
||||
{
|
||||
public class PneumaticSettingsValidator : AbstractValidator<PneumaticSettings>
|
||||
{
|
||||
public PneumaticSettingsValidator()
|
||||
{
|
||||
//Todo: Validate that the path actually exists
|
||||
RuleFor(c => c.NzbFolder).IsValidPath();
|
||||
}
|
||||
}
|
||||
|
||||
public class PneumaticSettings : IProviderConfig
|
||||
{
|
||||
private static readonly PneumaticSettingsValidator Validator = new PneumaticSettingsValidator();
|
||||
|
||||
[FieldDefinition(0, Label = "Nzb Folder", Type = FieldType.Path)]
|
||||
public String NzbFolder { get; set; }
|
||||
|
||||
public ValidationResult Validate()
|
||||
{
|
||||
return Validator.Validate(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
@ -15,25 +17,28 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
public class Sabnzbd : DownloadClientBase<SabnzbdSettings>, IExecute<TestSabnzbdCommand>
|
||||
{
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly ISabnzbdProxy _proxy;
|
||||
private readonly ICached<IEnumerable<QueueItem>> _queueCache;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public Sabnzbd(IHttpProvider httpProvider,
|
||||
ICacheManager cacheManager,
|
||||
IParsingService parsingService,
|
||||
ISabnzbdProxy proxy,
|
||||
IConfigService configService,
|
||||
IParsingService parsingService,
|
||||
Logger logger)
|
||||
: base(configService, parsingService, logger)
|
||||
{
|
||||
_httpProvider = httpProvider;
|
||||
_parsingService = parsingService;
|
||||
_proxy = proxy;
|
||||
_queueCache = cacheManager.GetCache<IEnumerable<QueueItem>>(GetType(), "queue");
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override string DownloadNzb(RemoteEpisode remoteEpisode)
|
||||
public override DownloadProtocol Protocol
|
||||
{
|
||||
get
|
||||
{
|
||||
return DownloadProtocol.Usenet;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Download(RemoteEpisode remoteEpisode)
|
||||
{
|
||||
var url = remoteEpisode.Release.DownloadUrl;
|
||||
var title = remoteEpisode.Release.Title;
|
||||
|
@ -54,76 +59,118 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<QueueItem> GetQueue()
|
||||
private IEnumerable<DownloadClientItem> GetQueue()
|
||||
{
|
||||
return _queueCache.Get("queue", () =>
|
||||
SabnzbdQueue sabQueue;
|
||||
|
||||
try
|
||||
{
|
||||
SabnzbdQueue sabQueue;
|
||||
sabQueue = _proxy.GetQueue(0, 0, Settings);
|
||||
}
|
||||
catch (DownloadClientException ex)
|
||||
{
|
||||
_logger.ErrorException(ex.Message, ex);
|
||||
return Enumerable.Empty<DownloadClientItem>();
|
||||
}
|
||||
|
||||
try
|
||||
var queueItems = new List<DownloadClientItem>();
|
||||
|
||||
foreach (var sabQueueItem in sabQueue.Items)
|
||||
{
|
||||
var queueItem = new DownloadClientItem();
|
||||
queueItem.DownloadClient = Definition.Name;
|
||||
queueItem.DownloadClientId = sabQueueItem.Id;
|
||||
queueItem.Category = sabQueueItem.Category;
|
||||
queueItem.Title = sabQueueItem.Title;
|
||||
queueItem.TotalSize = (long)(sabQueueItem.Size * 1024 * 1024);
|
||||
queueItem.RemainingSize = (long)(sabQueueItem.Sizeleft * 1024 * 1024);
|
||||
queueItem.RemainingTime = sabQueueItem.Timeleft;
|
||||
|
||||
if (sabQueue.Paused || sabQueueItem.Status == SabnzbdDownloadStatus.Paused)
|
||||
{
|
||||
sabQueue = _proxy.GetQueue(0, 0, Settings);
|
||||
queueItem.Status = DownloadItemStatus.Paused;
|
||||
|
||||
queueItem.RemainingTime = null;
|
||||
}
|
||||
catch (DownloadClientException ex)
|
||||
else if (sabQueueItem.Status == SabnzbdDownloadStatus.Queued || sabQueueItem.Status == SabnzbdDownloadStatus.Grabbing)
|
||||
{
|
||||
_logger.ErrorException(ex.Message, ex);
|
||||
return Enumerable.Empty<QueueItem>();
|
||||
queueItem.Status = DownloadItemStatus.Queued;
|
||||
}
|
||||
else
|
||||
{
|
||||
queueItem.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
|
||||
var queueItems = new List<QueueItem>();
|
||||
|
||||
foreach (var sabQueueItem in sabQueue.Items)
|
||||
if (queueItem.Title.StartsWith("ENCRYPTED /"))
|
||||
{
|
||||
var queueItem = new QueueItem();
|
||||
queueItem.Id = sabQueueItem.Id;
|
||||
queueItem.Title = sabQueueItem.Title;
|
||||
queueItem.Size = sabQueueItem.Size;
|
||||
queueItem.Sizeleft = sabQueueItem.Sizeleft;
|
||||
queueItem.Timeleft = sabQueueItem.Timeleft;
|
||||
queueItem.Status = sabQueueItem.Status;
|
||||
|
||||
var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title.Replace("ENCRYPTED / ", ""));
|
||||
if (parsedEpisodeInfo == null) continue;
|
||||
|
||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0);
|
||||
if (remoteEpisode.Series == null) continue;
|
||||
|
||||
queueItem.RemoteEpisode = remoteEpisode;
|
||||
|
||||
queueItems.Add(queueItem);
|
||||
queueItem.Title = queueItem.Title.Substring(11);
|
||||
queueItem.IsEncrypted = true;
|
||||
}
|
||||
|
||||
return queueItems;
|
||||
}, TimeSpan.FromSeconds(10));
|
||||
queueItems.Add(queueItem);
|
||||
}
|
||||
|
||||
return queueItems;
|
||||
}
|
||||
|
||||
public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10)
|
||||
private IEnumerable<DownloadClientItem> GetHistory()
|
||||
{
|
||||
SabnzbdHistory sabHistory;
|
||||
|
||||
try
|
||||
{
|
||||
sabHistory = _proxy.GetHistory(start, limit, Settings);
|
||||
sabHistory = _proxy.GetHistory(0, _configService.DownloadClientHistoryLimit, Settings);
|
||||
}
|
||||
catch (DownloadClientException ex)
|
||||
{
|
||||
_logger.ErrorException(ex.Message, ex);
|
||||
return Enumerable.Empty<HistoryItem>();
|
||||
return Enumerable.Empty<DownloadClientItem>();
|
||||
}
|
||||
|
||||
var historyItems = new List<HistoryItem>();
|
||||
var historyItems = new List<DownloadClientItem>();
|
||||
|
||||
foreach (var sabHistoryItem in sabHistory.Items)
|
||||
{
|
||||
var historyItem = new HistoryItem();
|
||||
historyItem.Id = sabHistoryItem.Id;
|
||||
historyItem.Title = sabHistoryItem.Title;
|
||||
historyItem.Size = sabHistoryItem.Size;
|
||||
historyItem.DownloadTime = sabHistoryItem.DownloadTime;
|
||||
historyItem.Storage = sabHistoryItem.Storage;
|
||||
historyItem.Category = sabHistoryItem.Category;
|
||||
historyItem.Message = sabHistoryItem.FailMessage;
|
||||
historyItem.Status = sabHistoryItem.Status == "Failed" ? HistoryStatus.Failed : HistoryStatus.Completed;
|
||||
var historyItem = new DownloadClientItem
|
||||
{
|
||||
DownloadClient = Definition.Name,
|
||||
DownloadClientId = sabHistoryItem.Id,
|
||||
Category = sabHistoryItem.Category,
|
||||
Title = sabHistoryItem.Title,
|
||||
|
||||
TotalSize = sabHistoryItem.Size,
|
||||
RemainingSize = 0,
|
||||
DownloadTime = TimeSpan.FromSeconds(sabHistoryItem.DownloadTime),
|
||||
RemainingTime = TimeSpan.Zero,
|
||||
|
||||
Message = sabHistoryItem.FailMessage
|
||||
};
|
||||
|
||||
if (sabHistoryItem.Status == SabnzbdDownloadStatus.Failed)
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Failed;
|
||||
}
|
||||
else if (sabHistoryItem.Status == SabnzbdDownloadStatus.Completed)
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Completed;
|
||||
}
|
||||
else // Verifying/Moving etc
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
|
||||
if (!sabHistoryItem.Storage.IsNullOrWhiteSpace())
|
||||
{
|
||||
var parent = Directory.GetParent(sabHistoryItem.Storage);
|
||||
if (parent != null && parent.Name == sabHistoryItem.Title)
|
||||
{
|
||||
historyItem.OutputPath = parent.FullName;
|
||||
}
|
||||
else
|
||||
{
|
||||
historyItem.OutputPath = sabHistoryItem.Storage;
|
||||
}
|
||||
}
|
||||
|
||||
historyItems.Add(historyItem);
|
||||
}
|
||||
|
@ -131,14 +178,29 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
return historyItems;
|
||||
}
|
||||
|
||||
public override void RemoveFromQueue(string id)
|
||||
public override IEnumerable<DownloadClientItem> GetItems()
|
||||
{
|
||||
_proxy.RemoveFrom("queue", id, Settings);
|
||||
foreach (var downloadClientItem in GetQueue().Concat(GetHistory()))
|
||||
{
|
||||
if (downloadClientItem.Category != Settings.TvCategory) continue;
|
||||
|
||||
downloadClientItem.RemoteEpisode = GetRemoteEpisode(downloadClientItem.Title);
|
||||
if (downloadClientItem.RemoteEpisode == null) continue;
|
||||
|
||||
yield return downloadClientItem;
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoveFromHistory(string id)
|
||||
public override void RemoveItem(string id)
|
||||
{
|
||||
_proxy.RemoveFrom("history", id, Settings);
|
||||
if (GetQueue().Any(v => v.DownloadClientId == id))
|
||||
{
|
||||
_proxy.RemoveFrom("queue", id, Settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
_proxy.RemoveFrom("history", id, Settings);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RetryDownload(string id)
|
||||
|
@ -146,9 +208,24 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
_proxy.RetryDownload(id, Settings);
|
||||
}
|
||||
|
||||
public override void Test()
|
||||
public override DownloadClientStatus GetStatus()
|
||||
{
|
||||
_proxy.GetCategories(Settings);
|
||||
var status = new DownloadClientStatus
|
||||
{
|
||||
IsLocalhost = Settings.Host == "127.0.0.1" || Settings.Host == "localhost"
|
||||
};
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
public override void Test(SabnzbdSettings settings)
|
||||
{
|
||||
var categories = _proxy.GetCategories(settings);
|
||||
|
||||
if (!categories.Any(v => v == settings.TvCategory))
|
||||
{
|
||||
throw new ApplicationException("Category does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
public void Execute(TestSabnzbdCommand message)
|
||||
|
@ -156,7 +233,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
var settings = new SabnzbdSettings();
|
||||
settings.InjectFrom(message);
|
||||
|
||||
_proxy.GetCategories(settings);
|
||||
Test(settings);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
public enum SabnzbdDownloadStatus
|
||||
{
|
||||
Grabbing,
|
||||
Queued,
|
||||
Paused,
|
||||
Checking,
|
||||
Downloading,
|
||||
QuickCheck,
|
||||
Verifying,
|
||||
Repairing,
|
||||
Fetching, // Fetching additional blocks
|
||||
Extracting,
|
||||
Moving,
|
||||
Running, // Running PP Script
|
||||
Completed,
|
||||
Failed
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
|
@ -7,7 +8,8 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
[JsonProperty(PropertyName = "fail_message")]
|
||||
public string FailMessage { get; set; }
|
||||
|
||||
public string Size { get; set; }
|
||||
[JsonProperty(PropertyName = "bytes")]
|
||||
public Int64 Size { get; set; }
|
||||
public string Category { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "nzb_name")]
|
||||
|
@ -17,7 +19,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
public int DownloadTime { get; set; }
|
||||
|
||||
public string Storage { get; set; }
|
||||
public string Status { get; set; }
|
||||
public SabnzbdDownloadStatus Status { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "nzo_id")]
|
||||
public string Id { get; set; }
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Download.Clients.Sabnzbd.Responses;
|
||||
using NzbDrone.Core.Instrumentation.Extensions;
|
||||
using RestSharp;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
|
@ -17,7 +18,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
void RemoveFrom(string source, string id, SabnzbdSettings settings);
|
||||
string ProcessRequest(IRestRequest restRequest, string action, SabnzbdSettings settings);
|
||||
SabnzbdVersionResponse GetVersion(SabnzbdSettings settings);
|
||||
SabnzbdCategoryResponse GetCategories(SabnzbdSettings settings);
|
||||
List<String> GetCategories(SabnzbdSettings settings);
|
||||
SabnzbdQueue GetQueue(int start, int limit, SabnzbdSettings settings);
|
||||
SabnzbdHistory GetHistory(int start, int limit, SabnzbdSettings settings);
|
||||
void RetryDownload(string id, SabnzbdSettings settings);
|
||||
|
@ -84,12 +85,12 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
return response;
|
||||
}
|
||||
|
||||
public SabnzbdCategoryResponse GetCategories(SabnzbdSettings settings)
|
||||
public List<String> GetCategories(SabnzbdSettings settings)
|
||||
{
|
||||
var request = new RestRequest();
|
||||
var action = "mode=get_cats";
|
||||
|
||||
var response = Json.Deserialize<SabnzbdCategoryResponse>(ProcessRequest(request, action, settings));
|
||||
var response = Json.Deserialize<SabnzbdCategoryResponse>(ProcessRequest(request, action, settings)).Categories;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
@ -135,7 +136,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
action,
|
||||
authentication);
|
||||
|
||||
_logger.Debug(url);
|
||||
_logger.Debug("Url: " + url);
|
||||
|
||||
return new RestClient(url);
|
||||
}
|
||||
|
@ -167,7 +168,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
|
||||
result.Error = response.Content.Replace("error: ", "");
|
||||
}
|
||||
|
||||
|
||||
if (result.Failed)
|
||||
throw new DownloadClientException("Error response received from SABnzbd: {0}", result.Error);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
{
|
||||
public class SabnzbdQueueItem
|
||||
{
|
||||
public string Status { get; set; }
|
||||
public SabnzbdDownloadStatus Status { get; set; }
|
||||
public int Index { get; set; }
|
||||
|
||||
[JsonConverter(typeof(SabnzbdQueueTimeConverter))]
|
||||
|
@ -15,8 +15,6 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
[JsonProperty(PropertyName = "mb")]
|
||||
public decimal Size { get; set; }
|
||||
|
||||
private string _title;
|
||||
|
||||
[JsonProperty(PropertyName = "filename")]
|
||||
public string Title { get; set; }
|
||||
|
||||
|
|
|
@ -13,11 +13,15 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public String Host { get; set; }
|
||||
public Int32 Port { get; set; }
|
||||
public String ApiKey { get; set; }
|
||||
public String Username { get; set; }
|
||||
public String Password { get; set; }
|
||||
public String TvCategory { get; set; }
|
||||
public Int32 RecentTvPriority { get; set; }
|
||||
public Int32 OlderTvPriority { get; set; }
|
||||
public Boolean UseSsl { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using System;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
|
||||
{
|
||||
public class TestBlackholeCommand : Command
|
||||
public class TestUsenetBlackholeCommand : Command
|
||||
{
|
||||
public override bool SendUpdatesToClient
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
|||
}
|
||||
}
|
||||
|
||||
public String Folder { get; set; }
|
||||
public String NzbFolder { get; set; }
|
||||
public String WatchFolder { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
|
||||
{
|
||||
public class UsenetBlackhole : DownloadClientBase<UsenetBlackholeSettings>, IExecute<TestUsenetBlackholeCommand>
|
||||
{
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IDiskScanService _diskScanService;
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
|
||||
public UsenetBlackhole(IDiskProvider diskProvider,
|
||||
IDiskScanService diskScanService,
|
||||
IHttpProvider httpProvider,
|
||||
IConfigService configService,
|
||||
IParsingService parsingService,
|
||||
Logger logger)
|
||||
: base(configService, parsingService, logger)
|
||||
{
|
||||
_diskProvider = diskProvider;
|
||||
_diskScanService = diskScanService;
|
||||
_httpProvider = httpProvider;
|
||||
}
|
||||
|
||||
public override DownloadProtocol Protocol
|
||||
{
|
||||
get
|
||||
{
|
||||
return DownloadProtocol.Usenet;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Download(RemoteEpisode remoteEpisode)
|
||||
{
|
||||
var url = remoteEpisode.Release.DownloadUrl;
|
||||
var title = remoteEpisode.Release.Title;
|
||||
|
||||
title = FileNameBuilder.CleanFilename(title);
|
||||
|
||||
var filename = Path.Combine(Settings.NzbFolder, title + ".nzb");
|
||||
|
||||
_logger.Debug("Downloading NZB from: {0} to: {1}", url, filename);
|
||||
_httpProvider.DownloadFile(url, filename);
|
||||
_logger.Debug("NZB Download succeeded, saved to: {0}", filename);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override IEnumerable<DownloadClientItem> GetItems()
|
||||
{
|
||||
foreach (var folder in _diskProvider.GetDirectories(Settings.WatchFolder))
|
||||
{
|
||||
var title = FileNameBuilder.CleanFilename(Path.GetFileName(folder));
|
||||
|
||||
var files = _diskProvider.GetFiles(folder, SearchOption.AllDirectories);
|
||||
|
||||
var historyItem = new DownloadClientItem
|
||||
{
|
||||
DownloadClient = Definition.Name,
|
||||
DownloadClientId = Definition.Name + "_" + Path.GetFileName(folder) + "_" + _diskProvider.FolderGetCreationTimeUtc(folder).Ticks,
|
||||
Title = title,
|
||||
|
||||
TotalSize = files.Select(_diskProvider.GetFileSize).Sum(),
|
||||
|
||||
OutputPath = folder
|
||||
};
|
||||
|
||||
if (files.Any(_diskProvider.IsFileLocked))
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
else
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Completed;
|
||||
|
||||
historyItem.RemainingTime = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
historyItem.RemoteEpisode = GetRemoteEpisode(historyItem.Title);
|
||||
if (historyItem.RemoteEpisode == null) continue;
|
||||
|
||||
yield return historyItem;
|
||||
}
|
||||
|
||||
foreach (var videoFile in _diskScanService.GetVideoFiles(Settings.WatchFolder, false))
|
||||
{
|
||||
var title = FileNameBuilder.CleanFilename(Path.GetFileName(videoFile));
|
||||
|
||||
var historyItem = new DownloadClientItem
|
||||
{
|
||||
DownloadClient = Definition.Name,
|
||||
DownloadClientId = Definition.Name + "_" + Path.GetFileName(videoFile) + "_" + _diskProvider.FileGetLastWriteUtc(videoFile).Ticks,
|
||||
Title = title,
|
||||
|
||||
TotalSize = _diskProvider.GetFileSize(videoFile),
|
||||
|
||||
OutputPath = videoFile
|
||||
};
|
||||
|
||||
if (_diskProvider.IsFileLocked(videoFile))
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
else
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Completed;
|
||||
}
|
||||
|
||||
historyItem.RemoteEpisode = GetRemoteEpisode(historyItem.Title);
|
||||
if (historyItem.RemoteEpisode == null) continue;
|
||||
|
||||
yield return historyItem;
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoveItem(string id)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void RetryDownload(string id)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override DownloadClientStatus GetStatus()
|
||||
{
|
||||
return new DownloadClientStatus
|
||||
{
|
||||
IsLocalhost = true,
|
||||
OutputRootFolders = new List<string> { Settings.WatchFolder }
|
||||
};
|
||||
}
|
||||
|
||||
public override void Test(UsenetBlackholeSettings settings)
|
||||
{
|
||||
PerformWriteTest(settings.NzbFolder);
|
||||
PerformWriteTest(settings.WatchFolder);
|
||||
}
|
||||
|
||||
private void PerformWriteTest(string folder)
|
||||
{
|
||||
var testPath = Path.Combine(folder, "drone_test.txt");
|
||||
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
|
||||
_diskProvider.DeleteFile(testPath);
|
||||
}
|
||||
|
||||
public void Execute(TestUsenetBlackholeCommand message)
|
||||
{
|
||||
var settings = new UsenetBlackholeSettings();
|
||||
settings.InjectFrom(message);
|
||||
|
||||
Test(settings);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue