Merge branch 'develop'

This commit is contained in:
Mark McDowall 2014-02-23 14:57:02 -08:00
commit e7c2eda995
249 changed files with 4351 additions and 3175 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

View File

@ -0,0 +1,21 @@
using System;
using FluentValidation;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Validation.Paths;
namespace NzbDrone.Api.Config
{
public class DownloadClientConfigModule : NzbDroneConfigModule<DownloadClientConfigResource>
{
public DownloadClientConfigModule(IConfigService configService, RootFolderValidator rootFolderValidator, PathExistsValidator pathExistsValidator)
: base(configService)
{
SharedValidator.RuleFor(c => c.DownloadedEpisodesFolder)
.Cascade(CascadeMode.StopOnFirstFailure)
.IsValidPath()
.SetValidator(rootFolderValidator)
.SetValidator(pathExistsValidator)
.When(c => !String.IsNullOrWhiteSpace(c.DownloadedEpisodesFolder));
}
}
}

View File

@ -0,0 +1,15 @@
using System;
using NzbDrone.Api.REST;
namespace NzbDrone.Api.Config
{
public class DownloadClientConfigResource : RestResource
{
public String DownloadedEpisodesFolder { get; set; }
public String DownloadClientWorkingFolders { get; set; }
public Boolean AutoRedownloadFailed { get; set; }
public Boolean RemoveFailedDownloads { get; set; }
public Boolean EnableFailedDownloadHandling { get; set; }
}
}

View File

@ -0,0 +1,55 @@
using System.Linq;
using System.Reflection;
using FluentValidation;
using NzbDrone.Core.Configuration;
using Omu.ValueInjecter;
namespace NzbDrone.Api.Config
{
public class HostConfigModule : NzbDroneRestModule<HostConfigResource>
{
private readonly IConfigFileProvider _configFileProvider;
public HostConfigModule(ConfigFileProvider configFileProvider)
: base("/config/host")
{
_configFileProvider = configFileProvider;
GetResourceSingle = GetHostConfig;
GetResourceById = GetHostConfig;
UpdateResource = SaveHostConfig;
SharedValidator.RuleFor(c => c.Branch).NotEmpty().WithMessage("Branch name is required, 'master' is the default");
SharedValidator.RuleFor(c => c.Port).InclusiveBetween(1, 65535);
SharedValidator.RuleFor(c => c.Username).NotEmpty().When(c => c.AuthenticationEnabled);
SharedValidator.RuleFor(c => c.Password).NotEmpty().When(c => c.AuthenticationEnabled);
SharedValidator.RuleFor(c => c.SslPort).InclusiveBetween(1, 65535).When(c => c.EnableSsl);
SharedValidator.RuleFor(c => c.SslCertHash).NotEmpty().When(c => c.EnableSsl);
}
private HostConfigResource GetHostConfig()
{
var resource = new HostConfigResource();
resource.InjectFrom(_configFileProvider);
resource.Id = 1;
return resource;
}
private HostConfigResource GetHostConfig(int id)
{
return GetHostConfig();
}
private void SaveHostConfig(HostConfigResource resource)
{
var dictionary = resource.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.ToDictionary(prop => prop.Name, prop => prop.GetValue(resource, null));
_configFileProvider.SaveConfigDictionary(dictionary);
}
}
}

View File

@ -0,0 +1,22 @@
using System;
using NzbDrone.Api.REST;
namespace NzbDrone.Api.Config
{
public class HostConfigResource : RestResource
{
public Int32 Port { get; set; }
public Int32 SslPort { get; set; }
public Boolean EnableSsl { get; set; }
public Boolean LaunchBrowser { get; set; }
public Boolean AuthenticationEnabled { get; set; }
public String Username { get; set; }
public String Password { get; set; }
public String LogLevel { get; set; }
public String Branch { get; set; }
public String ApiKey { get; set; }
public Boolean Torrent { get; set; }
public String SslCertHash { get; set; }
public String UrlBase { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using FluentValidation;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Api.Config
{
public class IndexerConfigModule : NzbDroneConfigModule<IndexerConfigResource>
{
public IndexerConfigModule(IConfigService configService)
: base(configService)
{
SharedValidator.RuleFor(c => c.RssSyncInterval).InclusiveBetween(10, 120);
}
}
}

View File

@ -0,0 +1,12 @@
using System;
using NzbDrone.Api.REST;
namespace NzbDrone.Api.Config
{
public class IndexerConfigResource : RestResource
{
public Int32 Retention { get; set; }
public Int32 RssSyncInterval { get; set; }
public String ReleaseRestrictions { get; set; }
}
}

View File

@ -0,0 +1,18 @@
using System;
using FluentValidation;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Validation.Paths;
namespace NzbDrone.Api.Config
{
public class MediaManagementConfigModule : NzbDroneConfigModule<MediaManagementConfigResource>
{
public MediaManagementConfigModule(IConfigService configService, PathExistsValidator pathExistsValidator)
: base(configService)
{
SharedValidator.RuleFor(c => c.FileChmod).NotEmpty();
SharedValidator.RuleFor(c => c.FolderChmod).NotEmpty();
SharedValidator.RuleFor(c => c.RecycleBin).IsValidPath().SetValidator(pathExistsValidator).When(c => !String.IsNullOrWhiteSpace(c.RecycleBin));
}
}
}

View File

@ -0,0 +1,19 @@
using System;
using NzbDrone.Api.REST;
namespace NzbDrone.Api.Config
{
public class MediaManagementConfigResource : RestResource
{
public Boolean AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; }
public String RecycleBin { get; set; }
public Boolean AutoDownloadPropers { get; set; }
public Boolean CreateEmptySeriesFolders { get; set; }
public Boolean SetPermissionsLinux { get; set; }
public String FileChmod { get; set; }
public String FolderChmod { get; set; }
public String ChownUser { get; set; }
public String ChownGroup { get; set; }
}
}

View File

@ -12,14 +12,14 @@ using Omu.ValueInjecter;
namespace NzbDrone.Api.Config namespace NzbDrone.Api.Config
{ {
public class NamingModule : NzbDroneRestModule<NamingConfigResource> public class NamingConfigModule : NzbDroneRestModule<NamingConfigResource>
{ {
private readonly INamingConfigService _namingConfigService; private readonly INamingConfigService _namingConfigService;
private readonly IFilenameSampleService _filenameSampleService; private readonly IFilenameSampleService _filenameSampleService;
private readonly IFilenameValidationService _filenameValidationService; private readonly IFilenameValidationService _filenameValidationService;
private readonly IBuildFileNames _filenameBuilder; private readonly IBuildFileNames _filenameBuilder;
public NamingModule(INamingConfigService namingConfigService, public NamingConfigModule(INamingConfigService namingConfigService,
IFilenameSampleService filenameSampleService, IFilenameSampleService filenameSampleService,
IFilenameValidationService filenameValidationService, IFilenameValidationService filenameValidationService,
IBuildFileNames filenameBuilder) IBuildFileNames filenameBuilder)

View File

@ -0,0 +1,51 @@
using System.Linq;
using System.Reflection;
using NzbDrone.Api.REST;
using NzbDrone.Core.Configuration;
using Omu.ValueInjecter;
namespace NzbDrone.Api.Config
{
public abstract class NzbDroneConfigModule<TResource> : NzbDroneRestModule<TResource> where TResource : RestResource, new()
{
private readonly IConfigService _configService;
protected NzbDroneConfigModule(IConfigService configService)
: this(new TResource().ResourceName.Replace("config", ""), configService)
{
}
protected NzbDroneConfigModule(string resource, IConfigService configService) :
base("config/" + resource.Trim('/'))
{
_configService = configService;
GetResourceSingle = GetConfig;
GetResourceById = GetConfig;
UpdateResource = SaveConfig;
}
private TResource GetConfig()
{
var resource = new TResource();
resource.InjectFrom(_configService);
resource.Id = 1;
return resource;
}
private TResource GetConfig(int id)
{
return GetConfig();
}
private void SaveConfig(TResource resource)
{
var dictionary = resource.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.ToDictionary(prop => prop.Name, prop => prop.GetValue(resource, null));
_configService.SaveConfigDictionary(dictionary);
}
}
}

View File

@ -1,71 +0,0 @@
using System;
using System.Collections.Generic;
using Nancy;
using NzbDrone.Api.Extensions;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Api.Config
{
public class SettingsModule : NzbDroneApiModule
{
private readonly IConfigService _configService;
private readonly IConfigFileProvider _configFileProvider;
public SettingsModule(IConfigService configService, IConfigFileProvider configFileProvider)
: base("/settings")
{
_configService = configService;
_configFileProvider = configFileProvider;
Get["/"] = x => GetGeneralSettings();
Post["/"] = x => SaveGeneralSettings();
Get["/host"] = x => GetHostSettings();
Post["/host"] = x => SaveHostSettings();
Get["/log"] = x => GetLogSettings();
Post["/log"] = x => SaveLogSettings();
}
private Response SaveLogSettings()
{
throw new NotImplementedException();
}
private Response GetLogSettings()
{
throw new NotImplementedException();
}
private Response SaveHostSettings()
{
var request = Request.Body.FromJson<Dictionary<string, object>>();
_configFileProvider.SaveConfigDictionary(request);
return GetHostSettings();
}
private Response GetHostSettings()
{
return _configFileProvider.GetConfigDictionary().AsResponse();
}
private Response GetGeneralSettings()
{
var collection = Request.Query.Collection;
if (collection.HasValue && Boolean.Parse(collection.Value))
return _configService.All().AsResponse();
return _configService.AllWithDefaults().AsResponse();
}
private Response SaveGeneralSettings()
{
var request = Request.Body.FromJson<Dictionary<string, object>>();
_configService.SaveValues(request);
return request.AsResponse();
}
}
}

View File

@ -0,0 +1,18 @@
using NzbDrone.Core.Download;
namespace NzbDrone.Api.DownloadClient
{
public class DownloadClientModule : ProviderModuleBase<DownloadClientResource, IDownloadClient, DownloadClientDefinition>
{
public DownloadClientModule(IDownloadClientFactory downloadClientFactory)
: base(downloadClientFactory, "downloadclient")
{
}
protected override void Validate(DownloadClientDefinition definition)
{
if (!definition.Enable) return;
base.Validate(definition);
}
}
}

View File

@ -0,0 +1,10 @@
using System;
namespace NzbDrone.Api.DownloadClient
{
public class DownloadClientResource : ProviderResource
{
public Boolean Enable { get; set; }
public Int32 Protocol { get; set; }
}
}

View File

@ -0,0 +1,37 @@
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;
}
}
}

View File

@ -92,8 +92,19 @@
<Compile Include="ClientSchema\SelectOption.cs" /> <Compile Include="ClientSchema\SelectOption.cs" />
<Compile Include="Commands\CommandModule.cs" /> <Compile Include="Commands\CommandModule.cs" />
<Compile Include="Commands\CommandResource.cs" /> <Compile Include="Commands\CommandResource.cs" />
<Compile Include="Config\IndexerConfigModule.cs" />
<Compile Include="Config\MediaManagementConfigModule.cs" />
<Compile Include="Config\MediaManagementConfigResource.cs" />
<Compile Include="Config\NzbDroneConfigModule.cs" />
<Compile Include="Config\DownloadClientConfigModule.cs" />
<Compile Include="Config\DownloadClientConfigResource.cs" />
<Compile Include="Config\HostConfigModule.cs" />
<Compile Include="Config\HostConfigResource.cs" />
<Compile Include="Config\NamingConfigResource.cs" /> <Compile Include="Config\NamingConfigResource.cs" />
<Compile Include="Config\NamingModule.cs" /> <Compile Include="Config\NamingConfigModule.cs" />
<Compile Include="Config\IndexerConfigResource.cs" />
<Compile Include="DownloadClient\DownloadClientModule.cs" />
<Compile Include="DownloadClient\DownloadClientResource.cs" />
<Compile Include="DiskSpace\DiskSpaceModule.cs" /> <Compile Include="DiskSpace\DiskSpaceModule.cs" />
<Compile Include="DiskSpace\DiskSpaceResource.cs" /> <Compile Include="DiskSpace\DiskSpaceResource.cs" />
<Compile Include="EpisodeFiles\EpisodeFileModule.cs" /> <Compile Include="EpisodeFiles\EpisodeFileModule.cs" />
@ -122,6 +133,7 @@
<Compile Include="History\HistoryModule.cs" /> <Compile Include="History\HistoryModule.cs" />
<Compile Include="Metadata\MetadataResource.cs" /> <Compile Include="Metadata\MetadataResource.cs" />
<Compile Include="Metadata\MetadataModule.cs" /> <Compile Include="Metadata\MetadataModule.cs" />
<Compile Include="Notifications\NotificationSchemaModule.cs" />
<Compile Include="ProviderResource.cs" /> <Compile Include="ProviderResource.cs" />
<Compile Include="ProviderModuleBase.cs" /> <Compile Include="ProviderModuleBase.cs" />
<Compile Include="Indexers\IndexerSchemaModule.cs" /> <Compile Include="Indexers\IndexerSchemaModule.cs" />
@ -145,7 +157,7 @@
<Compile Include="Queue\QueueModule.cs" /> <Compile Include="Queue\QueueModule.cs" />
<Compile Include="Queue\QueueResource.cs" /> <Compile Include="Queue\QueueResource.cs" />
<Compile Include="ResourceChangeMessage.cs" /> <Compile Include="ResourceChangeMessage.cs" />
<Compile Include="Notifications\NotificationSchemaModule.cs" /> <Compile Include="DownloadClient\DownloadClientSchemaModule.cs" />
<Compile Include="Notifications\NotificationModule.cs" /> <Compile Include="Notifications\NotificationModule.cs" />
<Compile Include="Notifications\NotificationResource.cs" /> <Compile Include="Notifications\NotificationResource.cs" />
<Compile Include="NzbDroneRestModule.cs" /> <Compile Include="NzbDroneRestModule.cs" />
@ -174,11 +186,9 @@
<Compile Include="Qualities\QualityDefinitionResource.cs" /> <Compile Include="Qualities\QualityDefinitionResource.cs" />
<Compile Include="Qualities\QualityDefinitionModule.cs" /> <Compile Include="Qualities\QualityDefinitionModule.cs" />
<Compile Include="Extensions\ReqResExtensions.cs" /> <Compile Include="Extensions\ReqResExtensions.cs" />
<Compile Include="Config\SettingsModule.cs" />
<Compile Include="System\SystemModule.cs" /> <Compile Include="System\SystemModule.cs" />
<Compile Include="TinyIoCNancyBootstrapper.cs" /> <Compile Include="TinyIoCNancyBootstrapper.cs" />
<Compile Include="Update\UpdateModule.cs" /> <Compile Include="Update\UpdateModule.cs" />
<Compile Include="Validation\PathValidator.cs" />
<Compile Include="Validation\RuleBuilderExtensions.cs" /> <Compile Include="Validation\RuleBuilderExtensions.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -5,7 +5,7 @@ using FluentValidation.Results;
using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.RootFolders; using NzbDrone.Core.RootFolders;
using NzbDrone.Api.Mapping; using NzbDrone.Api.Mapping;
using NzbDrone.Api.Validation; using NzbDrone.Core.Validation.Paths;
namespace NzbDrone.Api.RootFolders namespace NzbDrone.Api.RootFolders
{ {
@ -13,7 +13,11 @@ namespace NzbDrone.Api.RootFolders
{ {
private readonly IRootFolderService _rootFolderService; private readonly IRootFolderService _rootFolderService;
public RootFolderModule(IRootFolderService rootFolderService, ICommandExecutor commandExecutor) public RootFolderModule(IRootFolderService rootFolderService,
ICommandExecutor commandExecutor,
RootFolderValidator rootFolderValidator,
PathExistsValidator pathExistsValidator,
DroneFactoryValidator droneFactoryValidator)
: base(commandExecutor) : base(commandExecutor)
{ {
_rootFolderService = rootFolderService; _rootFolderService = rootFolderService;
@ -23,7 +27,12 @@ namespace NzbDrone.Api.RootFolders
CreateResource = CreateRootFolder; CreateResource = CreateRootFolder;
DeleteResource = DeleteFolder; DeleteResource = DeleteFolder;
SharedValidator.RuleFor(c => c.Path).IsValidPath(); SharedValidator.RuleFor(c => c.Path)
.Cascade(CascadeMode.StopOnFirstFailure)
.IsValidPath()
.SetValidator(rootFolderValidator)
.SetValidator(pathExistsValidator)
.SetValidator(droneFactoryValidator);
} }
private RootFolderResource GetRootFolder(int id) private RootFolderResource GetRootFolder(int id)
@ -33,15 +42,7 @@ namespace NzbDrone.Api.RootFolders
private int CreateRootFolder(RootFolderResource rootFolderResource) private int CreateRootFolder(RootFolderResource rootFolderResource)
{ {
try return GetNewId<RootFolder>(_rootFolderService.Add, rootFolderResource);
{
return GetNewId<RootFolder>(_rootFolderService.Add, rootFolderResource);
}
catch (Exception ex)
{
throw new ValidationException(new [] { new ValidationFailure("Path", ex.Message) });
}
} }
private List<RootFolderResource> GetRootFolders() private List<RootFolderResource> GetRootFolders()

View File

@ -12,6 +12,7 @@ using NzbDrone.Core.Tv;
using NzbDrone.Api.Validation; using NzbDrone.Api.Validation;
using NzbDrone.Api.Mapping; using NzbDrone.Api.Mapping;
using NzbDrone.Core.Tv.Events; using NzbDrone.Core.Tv.Events;
using NzbDrone.Core.Validation.Paths;
namespace NzbDrone.Api.Series namespace NzbDrone.Api.Series
{ {

View File

@ -1,6 +1,7 @@
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using FluentValidation; using FluentValidation;
using FluentValidation.Validators; using FluentValidation.Validators;
using NzbDrone.Core.Validation.Paths;
namespace NzbDrone.Api.Validation namespace NzbDrone.Api.Validation
{ {
@ -21,11 +22,6 @@ namespace NzbDrone.Api.Validation
return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(s)?://", RegexOptions.IgnoreCase)).WithMessage("must start with http:// or https://"); return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(s)?://", RegexOptions.IgnoreCase)).WithMessage("must start with http:// or https://");
} }
public static IRuleBuilderOptions<T, string> IsValidPath<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return ruleBuilder.SetValidator(new PathValidator());
}
public static IRuleBuilderOptions<T, string> NotBlank<T>(this IRuleBuilder<T, string> ruleBuilder) public static IRuleBuilderOptions<T, string> NotBlank<T>(this IRuleBuilder<T, string> ruleBuilder)
{ {
return ruleBuilder.SetValidator(new NotNullValidator()).SetValidator(new NotEmptyValidator("")); return ruleBuilder.SetValidator(new NotNullValidator()).SetValidator(new NotEmptyValidator(""));

View File

@ -71,7 +71,6 @@ namespace NzbDrone.Common
return false; return false;
} }
public static bool ContainsInvalidPathChars(this string text) public static bool ContainsInvalidPathChars(this string text)
{ {
return text.IndexOfAny(Path.GetInvalidPathChars()) >= 0; return text.IndexOfAny(Path.GetInvalidPathChars()) >= 0;

View File

@ -179,9 +179,7 @@ namespace NzbDrone.Common.Processes
public ProcessOutput StartAndCapture(string path, string args = null) public ProcessOutput StartAndCapture(string path, string args = null)
{ {
var output = new ProcessOutput(); var output = new ProcessOutput();
var process = Start(path, args, s => output.Standard.Add(s), error => output.Error.Add(error)); Start(path, args, s => output.Standard.Add(s), error => output.Error.Add(error)).WaitForExit();
WaitForExit(process);
return output; return output;
} }
@ -190,10 +188,7 @@ namespace NzbDrone.Common.Processes
{ {
Logger.Trace("Waiting for process {0} to exit.", process.ProcessName); Logger.Trace("Waiting for process {0} to exit.", process.ProcessName);
if (!process.HasExited) process.WaitForExit();
{
process.WaitForExit();
}
} }
public void SetPriority(int processId, ProcessPriorityClass priority) public void SetPriority(int processId, ProcessPriorityClass priority)

View File

@ -105,16 +105,6 @@ namespace NzbDrone.Core.Test.Configuration
Subject.GetValue(key, value2).Should().Be(value2); Subject.GetValue(key, value2).Should().Be(value2);
} }
[Test]
public void updating_a_vakye_should_update_its_value()
{
Subject.SabHost = "Test";
Subject.SabHost.Should().Be("Test");
Subject.SabHost = "Test2";
Subject.SabHost.Should().Be("Test2");
}
[Test] [Test]
[Description("This test will use reflection to ensure each config property read/writes to a unique key")] [Description("This test will use reflection to ensure each config property read/writes to a unique key")]
public void config_properties_should_write_and_read_using_same_key() public void config_properties_should_write_and_read_using_same_key()

View File

@ -15,340 +15,166 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public class AcceptableSizeSpecificationFixture : CoreTest<AcceptableSizeSpecification> public class AcceptableSizeSpecificationFixture : CoreTest<AcceptableSizeSpecification>
{ {
private RemoteEpisode parseResultMultiSet;
private RemoteEpisode parseResultMulti; private RemoteEpisode parseResultMulti;
private RemoteEpisode parseResultSingle; private RemoteEpisode parseResultSingle;
private Series series30minutes; private Series series;
private Series series60minutes;
private QualityDefinition qualityType; private QualityDefinition qualityType;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
series = Builder<Series>.CreateNew()
.Build();
parseResultMultiSet = new RemoteEpisode
{
Series = series,
Release = new ReleaseInfo(),
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.SDTV, true) },
Episodes = new List<Episode> { new Episode(), new Episode(), new Episode(), new Episode(), new Episode(), new Episode() }
};
parseResultMulti = new RemoteEpisode parseResultMulti = new RemoteEpisode
{ {
Release = new ReleaseInfo(), Series = series,
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.SDTV, true) }, Release = new ReleaseInfo(),
Episodes = new List<Episode> { new Episode(), new Episode() } ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.SDTV, true) },
}; Episodes = new List<Episode> { new Episode(), new Episode() }
};
parseResultSingle = new RemoteEpisode parseResultSingle = new RemoteEpisode
{ {
Series = series,
Release = new ReleaseInfo(), Release = new ReleaseInfo(),
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.SDTV, true) }, ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.SDTV, true) },
Episodes = new List<Episode> { new Episode() } Episodes = new List<Episode> { new Episode() }
}; };
series30minutes = Builder<Series>.CreateNew()
.With(c => c.Runtime = 30)
.Build();
series60minutes = Builder<Series>.CreateNew()
.With(c => c.Runtime = 60)
.Build();
qualityType = Builder<QualityDefinition>.CreateNew() qualityType = Builder<QualityDefinition>.CreateNew()
.With(q => q.MinSize = 0) .With(q => q.MinSize = 2)
.With(q => q.MaxSize = 10) .With(q => q.MaxSize = 10)
.With(q => q.Quality = Quality.SDTV) .With(q => q.Quality = Quality.SDTV)
.Build(); .Build();
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
} }
[Test] private void GivenLastEpisode()
public void IsAcceptableSize_true_single_episode_not_first_or_last_30_minute()
{ {
parseResultSingle.Series = series30minutes;
parseResultSingle.Release.Size = 184572800;
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(false);
bool result = Subject.IsSatisfiedBy(parseResultSingle, null);
result.Should().BeTrue();
}
[Test]
public void IsAcceptableSize_true_single_episode_not_first_or_last_60_minute()
{
parseResultSingle.Series = series60minutes;
parseResultSingle.Release.Size = 368572800;
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(false);
bool result = Subject.IsSatisfiedBy(parseResultSingle, null);
result.Should().BeTrue();
}
[Test]
public void IsAcceptableSize_false_single_episode_not_first_or_last_30_minute()
{
parseResultSingle.Series = series30minutes;
parseResultSingle.Release.Size = 1.Gigabytes();
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(false);
bool result = Subject.IsSatisfiedBy(parseResultSingle, null);
result.Should().BeFalse();
}
[Test]
public void IsAcceptableSize_false_single_episode_not_first_or_last_60_minute()
{
parseResultSingle.Series = series60minutes;
parseResultSingle.Release.Size = 1.Gigabytes();
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(false);
bool result = Subject.IsSatisfiedBy(parseResultSingle, null);
result.Should().BeFalse();
}
[Test]
public void IsAcceptableSize_true_multi_episode_not_first_or_last_30_minute()
{
parseResultMulti.Series = series30minutes;
parseResultMulti.Release.Size = 184572800;
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(false);
bool result = Subject.IsSatisfiedBy(parseResultMulti, null);
result.Should().BeTrue();
}
[Test]
public void IsAcceptableSize_true_multi_episode_not_first_or_last_60_minute()
{
parseResultMulti.Series = series60minutes;
parseResultMulti.Release.Size = 368572800;
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(false);
bool result = Subject.IsSatisfiedBy(parseResultMulti, null);
result.Should().BeTrue();
}
[Test]
public void IsAcceptableSize_false_multi_episode_not_first_or_last_30_minute()
{
parseResultMulti.Series = series30minutes;
parseResultMulti.Release.Size = 1.Gigabytes();
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(false);
bool result = Subject.IsSatisfiedBy(parseResultMulti, null);
result.Should().BeFalse();
}
[Test]
public void IsAcceptableSize_false_multi_episode_not_first_or_last_60_minute()
{
parseResultMulti.Series = series60minutes;
parseResultMulti.Release.Size = 10.Gigabytes();
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(false);
bool result = Subject.IsSatisfiedBy(parseResultMulti, null);
result.Should().BeFalse();
}
[Test]
public void IsAcceptableSize_true_single_episode_first_30_minute()
{
parseResultSingle.Series = series30minutes;
parseResultSingle.Release.Size = 184572800;
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup( Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>())) s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(true); .Returns(true);
bool result = Subject.IsSatisfiedBy(parseResultSingle, null);
result.Should().BeTrue();
} }
[Test] [TestCase(30, 50, false)]
public void IsAcceptableSize_true_single_episode_first_60_minute() [TestCase(30, 250, true)]
{ [TestCase(30, 500, false)]
parseResultSingle.Series = series60minutes; [TestCase(60, 100, false)]
parseResultSingle.Release.Size = 368572800; [TestCase(60, 500, true)]
[TestCase(60, 1000, false)]
public void single_episode(int runtime, int sizeInMegaBytes, bool expectedResult)
{
series.Runtime = runtime;
parseResultSingle.Series = series;
parseResultSingle.Release.Size = sizeInMegaBytes.Megabytes();
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType); Subject.IsSatisfiedBy(parseResultSingle, null).Should().Be(expectedResult);
}
[TestCase(30, 500, true)]
[TestCase(30, 1000, false)]
[TestCase(60, 1000, true)]
[TestCase(60, 2000, false)]
public void single_episode_first_or_last(int runtime, int sizeInMegaBytes, bool expectedResult)
{
GivenLastEpisode();
series.Runtime = runtime;
parseResultSingle.Series = series;
parseResultSingle.Release.Size = sizeInMegaBytes.Megabytes();
Subject.IsSatisfiedBy(parseResultSingle, null).Should().Be(expectedResult);
}
[TestCase(30, 50 * 2, false)]
[TestCase(30, 250 * 2, true)]
[TestCase(30, 500 * 2, false)]
[TestCase(60, 100 * 2, false)]
[TestCase(60, 500 * 2, true)]
[TestCase(60, 1000 * 2, false)]
public void multi_episode(int runtime, int sizeInMegaBytes, bool expectedResult)
{
series.Runtime = runtime;
parseResultMulti.Series = series;
parseResultMulti.Release.Size = sizeInMegaBytes.Megabytes();
Mocker.GetMock<IEpisodeService>().Setup( Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>())) s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(true); .Returns(false);
Subject.IsSatisfiedBy(parseResultMulti, null).Should().Be(expectedResult);
bool result = Subject.IsSatisfiedBy(parseResultSingle, null);
result.Should().BeTrue();
} }
[Test] [TestCase(30, 50 * 6, false)]
public void IsAcceptableSize_false_single_episode_first_30_minute() [TestCase(30, 250 * 6, true)]
[TestCase(30, 500 * 6, false)]
[TestCase(60, 100 * 6, false)]
[TestCase(60, 500 * 6, true)]
[TestCase(60, 1000 * 6, false)]
public void multiset_episode(int runtime, int sizeInMegaBytes, bool expectedResult)
{ {
parseResultSingle.Series = series30minutes; series.Runtime = runtime;
parseResultSingle.Release.Size = 1.Gigabytes(); parseResultMultiSet.Series = series;
parseResultMultiSet.Release.Size = sizeInMegaBytes.Megabytes();
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup( Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>())) s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(true); .Returns(false);
Subject.IsSatisfiedBy(parseResultMultiSet, null).Should().Be(expectedResult);
bool result = Subject.IsSatisfiedBy(parseResultSingle, null);
result.Should().BeFalse();
} }
[Test] [Test]
public void IsAcceptableSize_false_single_episode_first_60_minute() public void should_return_true_if_unlimited_30_minute()
{ {
GivenLastEpisode();
series.Runtime = 30;
parseResultSingle.Series = series60minutes; parseResultSingle.Series = series;
parseResultSingle.Release.Size = 10.Gigabytes();
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(true);
bool result = Subject.IsSatisfiedBy(parseResultSingle, null);
result.Should().BeFalse();
}
[Test]
public void IsAcceptableSize_true_unlimited_30_minute()
{
parseResultSingle.Series = series30minutes;
parseResultSingle.Release.Size = 18457280000; parseResultSingle.Release.Size = 18457280000;
qualityType.MaxSize = 0; qualityType.MaxSize = 0;
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType); Subject.IsSatisfiedBy(parseResultSingle, null).Should().BeTrue();
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(true);
bool result = Subject.IsSatisfiedBy(parseResultSingle, null);
result.Should().BeTrue();
} }
[Test] [Test]
public void IsAcceptableSize_true_unlimited_60_minute() public void should_return_true_if_unlimited_60_minute()
{ {
GivenLastEpisode();
series.Runtime = 60;
parseResultSingle.Series = series60minutes; parseResultSingle.Series = series;
parseResultSingle.Release.Size = 36857280000; parseResultSingle.Release.Size = 36857280000;
qualityType.MaxSize = 0; qualityType.MaxSize = 0;
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType); Subject.IsSatisfiedBy(parseResultSingle, null).Should().BeTrue();;
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(true);
bool result = Subject.IsSatisfiedBy(parseResultSingle, null);
result.Should().BeTrue();
} }
[Test] [Test]
public void IsAcceptableSize_should_treat_daily_series_as_single_episode() public void should_treat_daily_series_as_single_episode()
{ {
GivenLastEpisode();
parseResultSingle.Series = series60minutes; series.Runtime = 60;
parseResultSingle.Series = series;
parseResultSingle.Series.SeriesType = SeriesTypes.Daily; parseResultSingle.Series.SeriesType = SeriesTypes.Daily;
parseResultSingle.Release.Size = 300.Megabytes(); parseResultSingle.Release.Size = 300.Megabytes();
qualityType.MaxSize = (int)600.Megabytes(); qualityType.MaxSize = 10;
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType); Subject.IsSatisfiedBy(parseResultSingle, null).Should().BeTrue();
Mocker.GetMock<IEpisodeService>().Setup(
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
.Returns(true);
bool result = Subject.IsSatisfiedBy(parseResultSingle, null);
result.Should().BeTrue();
} }
[Test] [Test]
@ -362,9 +188,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Subject.IsSatisfiedBy(parseResult, null).Should().BeTrue(); Subject.IsSatisfiedBy(parseResult, null).Should().BeTrue();
} }
[Test] [Test]
public void should_always_return_false_if_unknow() public void should_always_return_false_if_unknown()
{ {
var parseResult = new RemoteEpisode var parseResult = new RemoteEpisode
{ {
@ -373,7 +198,6 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Subject.IsSatisfiedBy(parseResult, null).Should().BeFalse(); Subject.IsSatisfiedBy(parseResult, null).Should().BeFalse();
Mocker.GetMock<IQualityDefinitionService>().Verify(c => c.Get(It.IsAny<Quality>()), Times.Never()); Mocker.GetMock<IQualityDefinitionService>().Verify(c => c.Get(It.IsAny<Quality>()), Times.Never());
} }
} }

View File

@ -67,7 +67,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
private void GivenSpecifications(params Mock<IDecisionEngineSpecification>[] mocks) private void GivenSpecifications(params Mock<IDecisionEngineSpecification>[] mocks)
{ {
Mocker.SetConstant<IEnumerable<IRejectWithReason>>(mocks.Select(c => c.Object)); Mocker.SetConstant<IEnumerable<IDecisionEngineSpecification>>(mocks.Select(c => c.Object));
} }
[Test] [Test]

View File

@ -83,7 +83,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
private void GivenSabnzbdDownloadClient() private void GivenSabnzbdDownloadClient()
{ {
Mocker.GetMock<IProvideDownloadClient>() Mocker.GetMock<IProvideDownloadClient>()
.Setup(c => c.GetDownloadClient()).Returns(Mocker.Resolve<SabnzbdClient>()); .Setup(c => c.GetDownloadClient()).Returns(Mocker.Resolve<Sabnzbd>());
} }
private void GivenMostRecentForEpisode(HistoryEventType eventType) private void GivenMostRecentForEpisode(HistoryEventType eventType)

View File

@ -56,9 +56,6 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Mocker.GetMock<IProvideDownloadClient>() Mocker.GetMock<IProvideDownloadClient>()
.Setup(s => s.GetDownloadClient()) .Setup(s => s.GetDownloadClient())
.Returns(_downloadClient.Object); .Returns(_downloadClient.Object);
_downloadClient.SetupGet(s => s.IsConfigured)
.Returns(true);
} }
private void GivenEmptyQueue() private void GivenEmptyQueue()

View File

@ -20,65 +20,62 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{ {
parseResult = new RemoteEpisode parseResult = new RemoteEpisode
{ {
Release = new ReleaseInfo Release = new ReleaseInfo()
{
PublishDate = DateTime.Now.AddDays(-100)
}
}; };
} }
private void WithUnlimitedRetention() private void WithRetention(int days)
{ {
Mocker.GetMock<IConfigService>().SetupGet(c => c.Retention).Returns(0); Mocker.GetMock<IConfigService>().SetupGet(c => c.Retention).Returns(days);
} }
private void WithLongRetention() private void WithAge(int days)
{ {
Mocker.GetMock<IConfigService>().SetupGet(c => c.Retention).Returns(1000); parseResult.Release.PublishDate = DateTime.Now.AddDays(-days);
}
private void WithShortRetention()
{
Mocker.GetMock<IConfigService>().SetupGet(c => c.Retention).Returns(10);
}
private void WithEqualRetention()
{
Mocker.GetMock<IConfigService>().SetupGet(c => c.Retention).Returns(100);
} }
[Test] [Test]
public void unlimited_retention_should_return_true() public void should_return_true_when_retention_is_set_to_zero()
{ {
WithUnlimitedRetention(); WithRetention(0);
WithAge(100);
Subject.IsSatisfiedBy(parseResult, null).Should().BeTrue(); Subject.IsSatisfiedBy(parseResult, null).Should().BeTrue();
} }
[Test] [Test]
public void longer_retention_should_return_true() public void should_return_true_when_release_if_younger_than_retention()
{ {
WithLongRetention(); WithRetention(1000);
WithAge(100);
Subject.IsSatisfiedBy(parseResult, null).Should().BeTrue(); Subject.IsSatisfiedBy(parseResult, null).Should().BeTrue();
} }
[Test] [Test]
public void equal_retention_should_return_true() public void should_return_true_when_release_and_retention_are_the_same()
{ {
WithEqualRetention(); WithRetention(100);
WithAge(100);
Subject.IsSatisfiedBy(parseResult, null).Should().BeTrue(); Subject.IsSatisfiedBy(parseResult, null).Should().BeTrue();
} }
[Test] [Test]
public void shorter_retention_should_return_false() public void should_return_false_when_old_than_retention()
{ {
WithShortRetention(); WithRetention(10);
WithAge(100);
Subject.IsSatisfiedBy(parseResult, null).Should().BeFalse(); Subject.IsSatisfiedBy(parseResult, null).Should().BeFalse();
} }
[Test] [Test]
public void zeroDay_report_should_return_true() public void should_return_true_if_release_came_out_today_and_retention_is_zero()
{ {
WithUnlimitedRetention(); WithRetention(0);
WithAge(100);
Subject.IsSatisfiedBy(parseResult, null).Should().BeTrue(); Subject.IsSatisfiedBy(parseResult, null).Should().BeTrue();
} }
} }

View File

@ -4,8 +4,9 @@ using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients; using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Download.Clients.Blackhole;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
@ -13,7 +14,7 @@ using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.Download.DownloadClientTests namespace NzbDrone.Core.Test.Download.DownloadClientTests
{ {
[TestFixture] [TestFixture]
public class BlackholeProviderFixture : CoreTest<BlackholeProvider> public class BlackholeProviderFixture : CoreTest<Blackhole>
{ {
private const string _nzbUrl = "http://www.nzbs.com/url"; private const string _nzbUrl = "http://www.nzbs.com/url";
private const string _title = "some_nzb_title"; private const string _title = "some_nzb_title";
@ -27,13 +28,16 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
_blackHoleFolder = @"c:\nzb\blackhole\".AsOsAgnostic(); _blackHoleFolder = @"c:\nzb\blackhole\".AsOsAgnostic();
_nzbPath = @"c:\nzb\blackhole\some_nzb_title.nzb".AsOsAgnostic(); _nzbPath = @"c:\nzb\blackhole\some_nzb_title.nzb".AsOsAgnostic();
Mocker.GetMock<IConfigService>().SetupGet(c => c.BlackholeFolder).Returns(_blackHoleFolder);
_remoteEpisode = new RemoteEpisode(); _remoteEpisode = new RemoteEpisode();
_remoteEpisode.Release = new ReleaseInfo(); _remoteEpisode.Release = new ReleaseInfo();
_remoteEpisode.Release.Title = _title; _remoteEpisode.Release.Title = _title;
_remoteEpisode.Release.DownloadUrl = _nzbUrl; _remoteEpisode.Release.DownloadUrl = _nzbUrl;
Subject.Definition = new DownloadClientDefinition();
Subject.Definition.Settings = new FolderSettings
{
Folder = _blackHoleFolder
};
} }
private void WithExistingFile() private void WithExistingFile()

View File

@ -3,17 +3,15 @@ using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common; using NzbDrone.Core.Download;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download.Clients.Nzbget; using NzbDrone.Core.Download.Clients.Nzbget;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetProviderTests namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
{ {
public class DownloadNzbFixture : CoreTest public class DownloadNzbFixture : CoreTest<Nzbget>
{ {
private const string _url = "http://www.nzbdrone.com"; private const string _url = "http://www.nzbdrone.com";
private const string _title = "30.Rock.S01E01.Pilot.720p.hdtv"; private const string _title = "30.Rock.S01E01.Pilot.720p.hdtv";
@ -32,6 +30,17 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetProviderTests
.With(e => e.AirDate = DateTime.Today.ToString(Episode.AIR_DATE_FORMAT)) .With(e => e.AirDate = DateTime.Today.ToString(Episode.AIR_DATE_FORMAT))
.Build() .Build()
.ToList(); .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] [Test]
@ -39,14 +48,14 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetProviderTests
{ {
var p = new object[] {"30.Rock.S01E01.Pilot.720p.hdtv.nzb", "TV", 50, false, "http://www.nzbdrone.com"}; var p = new object[] {"30.Rock.S01E01.Pilot.720p.hdtv.nzb", "TV", 50, false, "http://www.nzbdrone.com"};
Mocker.GetMock<INzbGetCommunicationProxy>() Mocker.GetMock<INzbgetProxy>()
.Setup(s => s.AddNzb(p)) .Setup(s => s.AddNzb(It.IsAny<NzbgetSettings>(), p))
.Returns(true); .Returns(true);
Mocker.Resolve<NzbgetClient>().DownloadNzb(_remoteEpisode); Subject.DownloadNzb(_remoteEpisode);
Mocker.GetMock<INzbGetCommunicationProxy>() Mocker.GetMock<INzbgetProxy>()
.Verify(v => v.AddNzb(It.IsAny<object []>()), Times.Once()); .Verify(v => v.AddNzb(It.IsAny<NzbgetSettings>(), It.IsAny<object []>()), Times.Once());
} }
} }
} }

View File

@ -5,40 +5,52 @@ using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Nzbget; using NzbDrone.Core.Download.Clients.Nzbget;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetProviderTests namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
{ {
public class QueueFixture : CoreTest<NzbgetClient> public class QueueFixture : CoreTest<Nzbget>
{ {
private List<NzbGetQueueItem> _queue; private List<NzbgetQueueItem> _queue;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_queue = Builder<NzbGetQueueItem>.CreateListOfSize(5) _queue = Builder<NzbgetQueueItem>.CreateListOfSize(5)
.All() .All()
.With(q => q.NzbName = "30.Rock.S01E01.Pilot.720p.hdtv.nzb") .With(q => q.NzbName = "30.Rock.S01E01.Pilot.720p.hdtv.nzb")
.Build() .Build()
.ToList(); .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() private void WithFullQueue()
{ {
Mocker.GetMock<INzbGetCommunicationProxy>() Mocker.GetMock<INzbgetProxy>()
.Setup(s => s.GetQueue()) .Setup(s => s.GetQueue(It.IsAny<NzbgetSettings>()))
.Returns(_queue); .Returns(_queue);
} }
private void WithEmptyQueue() private void WithEmptyQueue()
{ {
Mocker.GetMock<INzbGetCommunicationProxy>() Mocker.GetMock<INzbgetProxy>()
.Setup(s => s.GetQueue()) .Setup(s => s.GetQueue(It.IsAny<NzbgetSettings>()))
.Returns(new List<NzbGetQueueItem>()); .Returns(new List<NzbgetQueueItem>());
} }
[Test] [Test]

View File

@ -6,7 +6,9 @@ using NUnit.Framework;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients; using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Download.Clients.Pneumatic;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
@ -14,7 +16,7 @@ using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.Download.DownloadClientTests namespace NzbDrone.Core.Test.Download.DownloadClientTests
{ {
[TestFixture] [TestFixture]
public class PneumaticProviderFixture : CoreTest<PneumaticClient> public class PneumaticProviderFixture : CoreTest<Pneumatic>
{ {
private const string _nzbUrl = "http://www.nzbs.com/url"; private const string _nzbUrl = "http://www.nzbs.com/url";
private const string _title = "30.Rock.S01E05.hdtv.xvid-LoL"; private const string _title = "30.Rock.S01E05.hdtv.xvid-LoL";
@ -31,7 +33,6 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
_nzbPath = Path.Combine(_pneumaticFolder, _title + ".nzb").AsOsAgnostic(); _nzbPath = Path.Combine(_pneumaticFolder, _title + ".nzb").AsOsAgnostic();
_sabDrop = @"d:\unsorted tv\".AsOsAgnostic(); _sabDrop = @"d:\unsorted tv\".AsOsAgnostic();
Mocker.GetMock<IConfigService>().SetupGet(c => c.PneumaticFolder).Returns(_pneumaticFolder);
Mocker.GetMock<IConfigService>().SetupGet(c => c.DownloadedEpisodesFolder).Returns(_sabDrop); Mocker.GetMock<IConfigService>().SetupGet(c => c.DownloadedEpisodesFolder).Returns(_sabDrop);
_remoteEpisode = new RemoteEpisode(); _remoteEpisode = new RemoteEpisode();
@ -41,6 +42,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
_remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo(); _remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
_remoteEpisode.ParsedEpisodeInfo.FullSeason = false; _remoteEpisode.ParsedEpisodeInfo.FullSeason = false;
Subject.Definition = new DownloadClientDefinition();
Subject.Definition.Settings = new FolderSettings
{
Folder = _pneumaticFolder
};
} }
private void WithExistingFile() private void WithExistingFile()

View File

@ -1,191 +0,0 @@
using System;
using System.IO;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download.Clients.Sabnzbd;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabProviderTests
{
[TestFixture]
public class SabProviderFixture : CoreTest<SabnzbdClient>
{
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;
[SetUp]
public void Setup()
{
var fakeConfig = Mocker.GetMock<IConfigService>();
fakeConfig.SetupGet(c => c.SabHost).Returns("192.168.5.55");
fakeConfig.SetupGet(c => c.SabPort).Returns(2222);
fakeConfig.SetupGet(c => c.SabApiKey).Returns("5c770e3197e4fe763423ee7c392c25d1");
fakeConfig.SetupGet(c => c.SabUsername).Returns("admin");
fakeConfig.SetupGet(c => c.SabPassword).Returns("pass");
fakeConfig.SetupGet(c => c.SabTvCategory).Returns("tv");
_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();
}
[Test]
public void should_be_able_to_get_categories_when_config_is_passed_in()
{
const string host = "192.168.5.22";
const int port = 1111;
const string apikey = "5c770e3197e4fe763423ee7c392c25d2";
const string username = "admin2";
const string password = "pass2";
Mocker.GetMock<IHttpProvider>(MockBehavior.Strict)
.Setup(s => s.DownloadString("http://192.168.5.22:1111/api?mode=get_cats&output=json&apikey=5c770e3197e4fe763423ee7c392c25d2&ma_username=admin2&ma_password=pass2"))
.Returns(ReadAllText("Files", "Categories_json.txt"));
var result = Subject.GetCategories(host, port, apikey, username, password);
result.Should().NotBeNull();
result.categories.Should().NotBeEmpty();
}
[Test]
public void should_be_able_to_get_categories_using_config()
{
Mocker.GetMock<IHttpProvider>(MockBehavior.Strict)
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=get_cats&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
.Returns(ReadAllText("Files", "Categories_json.txt"));
var result = Subject.GetCategories();
result.Should().NotBeNull();
result.categories.Should().NotBeEmpty();
}
[Test]
public void GetHistory_should_return_a_list_with_items_when_the_history_has_items()
{
Mocker.GetMock<IHttpProvider>()
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
.Returns(ReadAllText("Files", "History.txt"));
var result = Subject.GetHistory();
result.Should().HaveCount(1);
}
[Test]
public void GetHistory_should_return_an_empty_list_when_the_queue_is_empty()
{
Mocker.GetMock<IHttpProvider>()
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
.Returns(ReadAllText("Files", "HistoryEmpty.txt"));
var result = Subject.GetHistory();
result.Should().BeEmpty();
}
[Test]
public void GetHistory_should_return_an_empty_list_when_there_is_an_error_getting_the_queue()
{
Mocker.GetMock<IHttpProvider>()
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
.Returns(ReadAllText("Files", "JsonError.txt"));
Assert.Throws<ApplicationException>(() => Subject.GetHistory(), "API Key Incorrect");
}
[Test]
public void GetVersion_should_return_the_version_using_passed_in_values()
{
var response = "{ \"version\": \"0.6.9\" }";
Mocker.GetMock<IHttpProvider>()
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=version&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
.Returns(response);
var result = Subject.GetVersion("192.168.5.55", 2222, "5c770e3197e4fe763423ee7c392c25d1", "admin", "pass");
result.Should().NotBeNull();
result.Version.Should().Be("0.6.9");
}
[Test]
public void GetVersion_should_return_the_version_using_saved_values()
{
var response = "{ \"version\": \"0.6.9\" }";
Mocker.GetMock<IHttpProvider>()
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=version&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
.Returns(response);
var result = Subject.GetVersion();
result.Should().NotBeNull();
result.Version.Should().Be("0.6.9");
}
[Test]
public void Test_should_return_version_as_a_string()
{
const string response = "{ \"version\": \"0.6.9\" }";
Mocker.GetMock<IHttpProvider>()
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=version&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
.Returns(response);
var result = Subject.Test("192.168.5.55", 2222, "5c770e3197e4fe763423ee7c392c25d1", "admin", "pass");
result.Should().Be("0.6.9");
}
[Test]
public void downloadNzb_should_use_sabRecentTvPriority_when_recentEpisode_is_true()
{
Mocker.GetMock<IConfigService>()
.SetupGet(s => s.SabRecentTvPriority)
.Returns(SabPriorityType.High);
Mocker.GetMock<ISabCommunicationProxy>()
.Setup(s => s.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), (int)SabPriorityType.High))
.Returns(new SabAddResponse());
Subject.DownloadNzb(_remoteEpisode);
Mocker.GetMock<ISabCommunicationProxy>()
.Verify(v => v.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), (int)SabPriorityType.High), Times.Once());
}
}
}

View File

@ -0,0 +1,65 @@
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.Sabnzbd;
using NzbDrone.Core.Download.Clients.Sabnzbd.Responses;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
{
[TestFixture]
public class SabnzbdFixture : CoreTest<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;
[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
{
Host = "192.168.5.55",
Port = 2222,
ApiKey = "5c770e3197e4fe763423ee7c392c25d1",
Username = "admin",
Password = "pass",
TvCategory = "tv",
RecentTvPriority = (int)SabnzbdPriority.High
};
}
[Test]
public void downloadNzb_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);
Mocker.GetMock<ISabnzbdProxy>()
.Verify(v => v.DownloadNzb(It.IsAny<Stream>(), It.IsAny<String>(), It.IsAny<String>(), (int)SabnzbdPriority.High, It.IsAny<SabnzbdSettings>()), Times.Once());
}
}
}

View File

@ -1,3 +1,4 @@
using System;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using FizzWare.NBuilder; using FizzWare.NBuilder;
@ -33,9 +34,6 @@ namespace NzbDrone.Core.Test.Download
.With(c => c.Release = Builder<ReleaseInfo>.CreateNew().Build()) .With(c => c.Release = Builder<ReleaseInfo>.CreateNew().Build())
.With(c => c.Episodes = episodes) .With(c => c.Episodes = episodes)
.Build(); .Build();
Mocker.GetMock<IDownloadClient>().Setup(c => c.IsConfigured).Returns(true);
} }
private void WithSuccessfulAdd() private void WithSuccessfulAdd()
@ -85,7 +83,8 @@ namespace NzbDrone.Core.Test.Download
[Test] [Test]
public void should_not_attempt_download_if_client_isnt_configure() public void should_not_attempt_download_if_client_isnt_configure()
{ {
Mocker.GetMock<IDownloadClient>().Setup(c => c.IsConfigured).Returns(false); Mocker.GetMock<IProvideDownloadClient>()
.Setup(c => c.GetDownloadClient()).Returns((IDownloadClient)null);
Subject.DownloadReport(_parseResult); Subject.DownloadReport(_parseResult);

View File

@ -1,25 +0,0 @@
{
"categories":[
"*",
"anime",
"apps",
"books",
"consoles",
"ds-games",
"emulation",
"games",
"misc",
"movies",
"music",
"pda",
"resources",
"test",
"tv",
"tv-dvd",
"unknown",
"wii-games",
"xbox-dlc",
"xbox-xbla",
"xxx"
]
}

View File

@ -1,99 +0,0 @@
{
"history":{
"active_lang":"en",
"paused":false,
"session":"5c770e3197e4fe763423ee7c392c25d1",
"restart_req":false,
"power_options":true,
"slots":[
{
"action_line":"",
"show_details":"True",
"script_log":"",
"meta":null,
"fail_message":"",
"loaded":false,
"id":9858,
"size":"970 MB",
"category":"tv",
"pp":"D",
"retry":0,
"completeness":0,
"script":"None",
"nzb_name":"The.Mentalist.S04E12.720p.HDTV.x264-IMMERSE.nzb",
"download_time":524,
"storage":"C:\\ServerPool\\ServerFolders\\Unsorted TV\\The Mentalist - 4x12 - My Bloody Valentine [HDTV-720p]",
"status":"Completed",
"script_line":"",
"completed":1327033479,
"nzo_id":"SABnzbd_nzo_0crgis",
"downloaded":1016942445,
"report":"",
"path":"D:\\SABnzbd\\downloading\\The Mentalist - 4x12 - My Bloody Valentine [HDTV-720p]",
"postproc_time":24,
"name":"The Mentalist - 4x12 - My Bloody Valentine [HDTV-720p]",
"url":"",
"bytes":1016942445,
"url_info":"",
"stage_log":[
{
"name":"Download",
"actions":[
"Downloaded in 8 minutes 44 seconds at an average of 1.8 MB/s"
]
},
{
"name":"Repair",
"actions":[
"[the.mentalist.s04e12.720p.hdtv.x264-immerse] Quick Check OK"
]
},
{
"name":"Unpack",
"actions":[
"[the.mentalist.s04e12.720p.hdtv.x264-immerse] Unpacked 1 files/folders in 23 seconds"
]
}
]
}
],
"speed":"0 ",
"helpuri":"http://wiki.sabnzbd.org/",
"size":"0 B",
"uptime":"1d",
"total_size":"10.2 T",
"month_size":"445.7 G",
"week_size":"46.6 G",
"version":"0.6.9",
"new_rel_url":"http://sourceforge.net/projects/sabnzbdplus/files/sabnzbdplus/sabnzbd-0.6.14",
"diskspacetotal2":"9314.57",
"color_scheme":"gold",
"diskspacetotal1":"871.41",
"nt":true,
"status":"Idle",
"last_warning":"2012-01-19 23:58:01,736\nWARNING:\nAPI Key incorrect, Use the api key from Config->General in your 3rd party program:",
"have_warnings":"3",
"cache_art":"0",
"sizeleft":"0 B",
"finishaction":null,
"paused_all":false,
"cache_size":"0 B",
"new_release":"0.6.14",
"pause_int":"0",
"mbleft":"0.00",
"diskspace1":"869.82",
"darwin":false,
"timeleft":"0:00:00",
"mb":"0.00",
"noofslots":9724,
"day_size":"0 ",
"eta":"unknown",
"nzb_quota":"",
"loadavg":"",
"cache_max":"-1",
"kbpersec":"0.00",
"speedlimit":"",
"webdir":"D:\\SABnzbd\\SABnzbd\\interfaces\\Plush\\templates",
"diskspace2":"1084.96"
}
}

View File

@ -1,50 +0,0 @@
{
"history":{
"active_lang":"en",
"paused":false,
"session":"5c770e3197e4fe763423ee7c392c25d1",
"restart_req":false,
"power_options":true,
"slots":[
],
"speed":"0 ",
"helpuri":"http://wiki.sabnzbd.org/",
"size":"0 B",
"uptime":"1d",
"total_size":"10.2 T",
"month_size":"445.7 G",
"week_size":"46.6 G",
"version":"0.6.9",
"new_rel_url":"http://sourceforge.net/projects/sabnzbdplus/files/sabnzbdplus/sabnzbd-0.6.14",
"diskspacetotal2":"9314.57",
"color_scheme":"gold",
"diskspacetotal1":"871.41",
"nt":true,
"status":"Idle",
"last_warning":"2012-01-19 23:58:01,736\nWARNING:\nAPI Key incorrect, Use the api key from Config->General in your 3rd party program:",
"have_warnings":"3",
"cache_art":"0",
"sizeleft":"0 B",
"finishaction":null,
"paused_all":false,
"cache_size":"0 B",
"new_release":"0.6.14",
"pause_int":"0",
"mbleft":"0.00",
"diskspace1":"869.82",
"darwin":false,
"timeleft":"0:00:00",
"mb":"0.00",
"noofslots":9724,
"day_size":"0 ",
"eta":"unknown",
"nzb_quota":"",
"loadavg":"",
"cache_max":"-1",
"kbpersec":"0.00",
"speedlimit":"",
"webdir":"D:\\SABnzbd\\SABnzbd\\interfaces\\Plush\\templates",
"diskspace2":"1084.96"
}
}

View File

@ -1,4 +0,0 @@
{
"status": false,
"error": "API Key Incorrect"
}

View File

@ -77,7 +77,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
}; };
Mocker.GetMock<IParsingService>() Mocker.GetMock<IParsingService>()
.Setup(c => c.GetEpisodes(It.IsAny<String>(), It.IsAny<Series>(), It.IsAny<Boolean>())) .Setup(c => c.GetLocalEpisode(It.IsAny<String>(), It.IsAny<Series>(), It.IsAny<Boolean>()))
.Returns(_localEpisode); .Returns(_localEpisode);
@ -150,7 +150,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
{ {
GivenSpecifications(_pass1); GivenSpecifications(_pass1);
Mocker.GetMock<IParsingService>().Setup(c => c.GetEpisodes(It.IsAny<String>(), It.IsAny<Series>(), It.IsAny<Boolean>())) Mocker.GetMock<IParsingService>().Setup(c => c.GetLocalEpisode(It.IsAny<String>(), It.IsAny<Series>(), It.IsAny<Boolean>()))
.Throws<TestException>(); .Throws<TestException>();
_videoFiles = new List<String> _videoFiles = new List<String>
@ -168,7 +168,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
Subject.GetImportDecisions(_videoFiles, _series, false); Subject.GetImportDecisions(_videoFiles, _series, false);
Mocker.GetMock<IParsingService>() Mocker.GetMock<IParsingService>()
.Verify(c => c.GetEpisodes(It.IsAny<String>(), It.IsAny<Series>(), It.IsAny<Boolean>()), Times.Exactly(_videoFiles.Count)); .Verify(c => c.GetLocalEpisode(It.IsAny<String>(), It.IsAny<Series>(), It.IsAny<Boolean>()), Times.Exactly(_videoFiles.Count));
ExceptionVerification.ExpectedErrors(3); ExceptionVerification.ExpectedErrors(3);
} }

View File

@ -21,6 +21,7 @@ namespace NzbDrone.Core.Test.MetadataSourceTests
[TestCase("Franklin & Bash", "Franklin & Bash")] [TestCase("Franklin & Bash", "Franklin & Bash")]
[TestCase("Mr. D", "Mr. D")] [TestCase("Mr. D", "Mr. D")]
[TestCase("Rob & Big", "Rob and Big")] [TestCase("Rob & Big", "Rob and Big")]
[TestCase("M*A*S*H", "M*A*S*H")]
public void successful_search(string title, string expected) public void successful_search(string title, string expected)
{ {
var result = Subject.SearchForNewSeries(title); var result = Subject.SearchForNewSeries(title);
@ -38,7 +39,7 @@ namespace NzbDrone.Core.Test.MetadataSourceTests
} }
[TestCase(75978)] [TestCase(75978)]
[TestCase(79349)] [TestCase(83462)]
public void should_be_able_to_get_series_detail(int tvdbId) public void should_be_able_to_get_series_detail(int tvdbId)
{ {
var details = Subject.GetSeriesInfo(tvdbId); var details = Subject.GetSeriesInfo(tvdbId);

View File

@ -122,10 +122,10 @@
<Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" /> <Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" />
<Compile Include="Download\DownloadApprovedReportsTests\GetQualifiedReportsFixture.cs" /> <Compile Include="Download\DownloadApprovedReportsTests\GetQualifiedReportsFixture.cs" />
<Compile Include="Download\DownloadClientTests\BlackholeProviderFixture.cs" /> <Compile Include="Download\DownloadClientTests\BlackholeProviderFixture.cs" />
<Compile Include="Download\DownloadClientTests\NzbgetProviderTests\DownloadNzbFixture.cs" /> <Compile Include="Download\DownloadClientTests\NzbgetTests\DownloadNzbFixture.cs" />
<Compile Include="Download\DownloadClientTests\NzbgetProviderTests\QueueFixture.cs" /> <Compile Include="Download\DownloadClientTests\NzbgetTests\QueueFixture.cs" />
<Compile Include="Download\DownloadClientTests\PneumaticProviderFixture.cs" /> <Compile Include="Download\DownloadClientTests\PneumaticProviderFixture.cs" />
<Compile Include="Download\DownloadClientTests\SabProviderTests\SabProviderFixture.cs" /> <Compile Include="Download\DownloadClientTests\SabnzbdTests\SabnzbdFixture.cs" />
<Compile Include="Download\DownloadServiceFixture.cs" /> <Compile Include="Download\DownloadServiceFixture.cs" />
<Compile Include="Download\FailedDownloadServiceFixture.cs" /> <Compile Include="Download\FailedDownloadServiceFixture.cs" />
<Compile Include="Framework\CoreTest.cs" /> <Compile Include="Framework\CoreTest.cs" />
@ -180,6 +180,17 @@
<Compile Include="NotificationTests\Xbmc\OnDownloadFixture.cs" /> <Compile Include="NotificationTests\Xbmc\OnDownloadFixture.cs" />
<Compile Include="OrganizerTests\BuildFilePathFixture.cs" /> <Compile Include="OrganizerTests\BuildFilePathFixture.cs" />
<Compile Include="OrganizerTests\GetSeriesFolderFixture.cs" /> <Compile Include="OrganizerTests\GetSeriesFolderFixture.cs" />
<Compile Include="ParserTests\AbsoluteEpisodeNumberParserFixture.cs" />
<Compile Include="ParserTests\IsPossibleSpecialEpisodeFixture.cs" />
<Compile Include="ParserTests\ReleaseGroupParserFixture.cs" />
<Compile Include="ParserTests\LanguageParserFixture.cs" />
<Compile Include="ParserTests\SeasonParserFixture.cs" />
<Compile Include="ParserTests\NormalizeTitleFixture.cs" />
<Compile Include="ParserTests\CrapParserFixture.cs" />
<Compile Include="ParserTests\DailyEpisodeParserFixture.cs" />
<Compile Include="ParserTests\SingleEpisodeParserFixture.cs" />
<Compile Include="ParserTests\PathParserFixture.cs" />
<Compile Include="ParserTests\MultiEpisodeParserFixture.cs" />
<Compile Include="ParserTests\ParsingServiceTests\GetEpisodesFixture.cs" /> <Compile Include="ParserTests\ParsingServiceTests\GetEpisodesFixture.cs" />
<Compile Include="ParserTests\ParsingServiceTests\GetSeriesFixture.cs" /> <Compile Include="ParserTests\ParsingServiceTests\GetSeriesFixture.cs" />
<Compile Include="ParserTests\ParsingServiceTests\MapFixture.cs" /> <Compile Include="ParserTests\ParsingServiceTests\MapFixture.cs" />
@ -287,18 +298,9 @@
<Content Include="Files\LongOverview.txt"> <Content Include="Files\LongOverview.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Files\HistoryEmpty.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\Queue.txt"> <Content Include="Files\Queue.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Files\History.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\JsonError.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<None Include="..\NzbDrone.Test.Common\App.config"> <None Include="..\NzbDrone.Test.Common\App.config">
<Link>App.config</Link> <Link>App.config</Link>
</None> </None>
@ -330,9 +332,6 @@
<Content Include="Files\RSS\newznab.xml"> <Content Include="Files\RSS\newznab.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Files\Categories_json.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\RSS\SizeParsing\newznab.xml"> <Content Include="Files\RSS\SizeParsing\newznab.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>

View File

@ -0,0 +1,47 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class AbsoluteEpisodeNumberParserFixture : CoreTest
{
[TestCase("[SubDESU]_High_School_DxD_07_(1280x720_x264-AAC)_[6B7FD717]", "High School DxD", 7, 0, 0)]
[TestCase("[Chihiro]_Working!!_-_06_[848x480_H.264_AAC][859EEAFA]", "Working!!", 6, 0, 0)]
[TestCase("[Commie]_Senki_Zesshou_Symphogear_-_11_[65F220B4]", "Senki_Zesshou_Symphogear", 11, 0, 0)]
[TestCase("[Underwater]_Rinne_no_Lagrange_-_12_(720p)_[5C7BC4F9]", "Rinne_no_Lagrange", 12, 0, 0)]
[TestCase("[Commie]_Rinne_no_Lagrange_-_15_[E76552EA]", "Rinne_no_Lagrange", 15, 0, 0)]
[TestCase("[HorribleSubs]_Hunter_X_Hunter_-_33_[720p]", "Hunter_X_Hunter", 33, 0, 0)]
[TestCase("[HorribleSubs]_Fairy_Tail_-_145_[720p]", "Fairy_Tail", 145, 0, 0)]
[TestCase("[HorribleSubs] Tonari no Kaibutsu-kun - 13 [1080p].mkv", "Tonari no Kaibutsu-kun", 13, 0, 0)]
[TestCase("[Doremi].Yes.Pretty.Cure.5.Go.Go!.31.[1280x720].[C65D4B1F].mkv", "Yes.Pretty.Cure.5.Go.Go!", 31, 0, 0)]
[TestCase("[K-F] One Piece 214", "One Piece", 214, 0, 0)]
[TestCase("[K-F] One Piece S10E14 214", "One Piece", 214, 10, 14)]
[TestCase("[K-F] One Piece 10x14 214", "One Piece", 214, 10, 14)]
[TestCase("[K-F] One Piece 214 10x14", "One Piece", 214, 10, 14)]
// [TestCase("One Piece S10E14 214", "One Piece", 214, 10, 14)]
// [TestCase("One Piece 10x14 214", "One Piece", 214, 10, 14)]
// [TestCase("One Piece 214 10x14", "One Piece", 214, 10, 14)]
// [TestCase("214 One Piece 10x14", "One Piece", 214, 10, 14)]
[TestCase("Bleach - 031 - The Resolution to Kill [Lunar].avi", "Bleach", 31, 0, 0)]
[TestCase("Bleach - 031 - The Resolution to Kill [Lunar]", "Bleach", 31, 0, 0)]
[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)]
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.SeasonNumber.Should().Be(seasonNumber);
result.EpisodeNumbers.FirstOrDefault().Should().Be(episodeNumber);
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
result.FullSeason.Should().BeFalse();
}
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Expansive;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class CrapParserFixture : CoreTest
{
[TestCase("76El6LcgLzqb426WoVFg1vVVVGx4uCYopQkfjmLe")]
[TestCase("Vrq6e1Aba3U amCjuEgV5R2QvdsLEGYF3YQAQkw8")]
[TestCase("TDAsqTea7k4o6iofVx3MQGuDK116FSjPobMuh8oB")]
[TestCase("yp4nFodAAzoeoRc467HRh1mzuT17qeekmuJ3zFnL")]
[TestCase("oxXo8S2272KE1 lfppvxo3iwEJBrBmhlQVK1gqGc")]
[TestCase("dPBAtu681Ycy3A4NpJDH6kNVQooLxqtnsW1Umfiv")]
[TestCase("password - \"bdc435cb-93c4-4902-97ea-ca00568c3887.337\" yEnc")]
[TestCase("185d86a343e39f3341e35c4dad3f9959")]
[TestCase("ba27283b17c00d01193eacc02a8ba98eeb523a76")]
[TestCase("45a55debe3856da318cc35882ad07e43cd32fd15")]
[TestCase("86420f8ee425340d8894bf3bc636b66404b95f18")]
[TestCase("ce39afb7da6cf7c04eba3090f0a309f609883862")]
[TestCase("THIS SHOULD NEVER PARSE")]
public void should_not_parse_crap(string title)
{
Parser.Parser.ParseTitle(title).Should().BeNull();
ExceptionVerification.IgnoreWarns();
}
}
}

View File

@ -0,0 +1,76 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Expansive;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class DailyEpisodeParserFixture : CoreTest
{
[TestCase("Conan 2011 04 18 Emma Roberts HDTV XviD BFF", "Conan", 2011, 04, 18)]
[TestCase("The Tonight Show With Jay Leno 2011 04 15 1080i HDTV DD5 1 MPEG2 TrollHD", "The Tonight Show With Jay Leno", 2011, 04, 15)]
[TestCase("The.Daily.Show.2010.10.11.Johnny.Knoxville.iTouch-MW", "The.Daily.Show", 2010, 10, 11)]
[TestCase("The Daily Show - 2011-04-12 - Gov. Deval Patrick", "The.Daily.Show", 2011, 04, 12)]
[TestCase("2011.01.10 - Denis Leary - HD TV.mkv", "", 2011, 1, 10)]
[TestCase("2011.03.13 - Denis Leary - HD TV.mkv", "", 2011, 3, 13)]
[TestCase("The Tonight Show with Jay Leno - 2011-06-16 - Larry David, \"Bachelorette\" Ashley Hebert, Pitbull with Ne-Yo", "The Tonight Show with Jay Leno", 2011, 6, 16)]
[TestCase("2020.NZ.2012.16.02.PDTV.XviD-C4TV", "2020nz", 2012, 2, 16)]
[TestCase("2020.NZ.2012.13.02.PDTV.XviD-C4TV", "2020nz", 2012, 2, 13)]
[TestCase("2020.NZ.2011.12.02.PDTV.XviD-C4TV", "2020nz", 2011, 12, 2)]
public void should_parse_daily_episode(string postTitle, string title, int year, int month, int day)
{
var result = Parser.Parser.ParseTitle(postTitle);
var airDate = new DateTime(year, month, day);
result.Should().NotBeNull();
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
result.AirDate.Should().Be(airDate.ToString(Episode.AIR_DATE_FORMAT));
result.EpisodeNumbers.Should().BeEmpty();
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeFalse();
}
[TestCase("Conan {year} {month} {day} Emma Roberts HDTV XviD BFF")]
[TestCase("The Tonight Show With Jay Leno {year} {month} {day} 1080i HDTV DD5 1 MPEG2 TrollHD")]
[TestCase("The.Daily.Show.{year}.{month}.{day}.Johnny.Knoxville.iTouch-MW")]
[TestCase("The Daily Show - {year}-{month}-{day} - Gov. Deval Patrick")]
[TestCase("{year}.{month}.{day} - Denis Leary - HD TV.mkv")]
[TestCase("The Tonight Show with Jay Leno - {year}-{month}-{day} - Larry David, \"Bachelorette\" Ashley Hebert, Pitbull with Ne-Yo")]
[TestCase("2020.NZ.{year}.{month}.{day}.PDTV.XviD-C4TV")]
public void should_not_accept_ancient_daily_series(string title)
{
var yearTooLow = title.Expand(new { year = 1950, month = 10, day = 14 });
Parser.Parser.ParseTitle(yearTooLow).Should().BeNull();
}
[TestCase("Conan {year} {month} {day} Emma Roberts HDTV XviD BFF")]
[TestCase("The Tonight Show With Jay Leno {year} {month} {day} 1080i HDTV DD5 1 MPEG2 TrollHD")]
[TestCase("The.Daily.Show.{year}.{month}.{day}.Johnny.Knoxville.iTouch-MW")]
[TestCase("The Daily Show - {year}-{month}-{day} - Gov. Deval Patrick")]
[TestCase("{year}.{month}.{day} - Denis Leary - HD TV.mkv")]
[TestCase("The Tonight Show with Jay Leno - {year}-{month}-{day} - Larry David, \"Bachelorette\" Ashley Hebert, Pitbull with Ne-Yo")]
[TestCase("2020.NZ.{year}.{month}.{day}.PDTV.XviD-C4TV")]
public void should_not_accept_future_dates(string title)
{
var twoDaysFromNow = DateTime.Now.AddDays(2);
var validDate = title.Expand(new { year = twoDaysFromNow.Year, month = twoDaysFromNow.Month.ToString("00"), day = twoDaysFromNow.Day.ToString("00") });
Parser.Parser.ParseTitle(validDate).Should().BeNull();
}
[Test]
public void should_fail_if_episode_is_far_in_future()
{
var title = string.Format("{0:yyyy.MM.dd} - Denis Leary - HD TV.mkv", DateTime.Now.AddDays(2));
Parser.Parser.ParseTitle(title).Should().BeNull();
}
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class IsPossibleSpecialEpisodeFixture
{
[Test]
public void should_not_treat_files_without_a_series_title_as_a_special()
{
var parsedEpisodeInfo = new ParsedEpisodeInfo
{
EpisodeNumbers = new[]{ 7 },
SeasonNumber = 1,
SeriesTitle = ""
};
parsedEpisodeInfo.IsPossibleSpecialEpisode().Should().BeFalse();
}
[Test]
public void should_return_true_when_episode_numbers_is_empty()
{
var parsedEpisodeInfo = new ParsedEpisodeInfo
{
SeasonNumber = 1,
SeriesTitle = ""
};
parsedEpisodeInfo.IsPossibleSpecialEpisode().Should().BeTrue();
}
}
}

View File

@ -0,0 +1,48 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class LanguageParserFixture : CoreTest
{
[TestCase("Castle.2009.S01E14.English.HDTV.XviD-LOL", Language.English)]
[TestCase("Castle.2009.S01E14.French.HDTV.XviD-LOL", Language.French)]
[TestCase("Castle.2009.S01E14.Spanish.HDTV.XviD-LOL", Language.Spanish)]
[TestCase("Castle.2009.S01E14.German.HDTV.XviD-LOL", Language.German)]
[TestCase("Castle.2009.S01E14.Germany.HDTV.XviD-LOL", Language.English)]
[TestCase("Castle.2009.S01E14.Italian.HDTV.XviD-LOL", Language.Italian)]
[TestCase("Castle.2009.S01E14.Danish.HDTV.XviD-LOL", Language.Danish)]
[TestCase("Castle.2009.S01E14.Dutch.HDTV.XviD-LOL", Language.Dutch)]
[TestCase("Castle.2009.S01E14.Japanese.HDTV.XviD-LOL", Language.Japanese)]
[TestCase("Castle.2009.S01E14.Cantonese.HDTV.XviD-LOL", Language.Cantonese)]
[TestCase("Castle.2009.S01E14.Mandarin.HDTV.XviD-LOL", Language.Mandarin)]
[TestCase("Castle.2009.S01E14.Korean.HDTV.XviD-LOL", Language.Korean)]
[TestCase("Castle.2009.S01E14.Russian.HDTV.XviD-LOL", Language.Russian)]
[TestCase("Castle.2009.S01E14.Polish.HDTV.XviD-LOL", Language.Polish)]
[TestCase("Castle.2009.S01E14.Vietnamese.HDTV.XviD-LOL", Language.Vietnamese)]
[TestCase("Castle.2009.S01E14.Swedish.HDTV.XviD-LOL", Language.Swedish)]
[TestCase("Castle.2009.S01E14.Norwegian.HDTV.XviD-LOL", Language.Norwegian)]
[TestCase("Castle.2009.S01E14.Finnish.HDTV.XviD-LOL", Language.Finnish)]
[TestCase("Castle.2009.S01E14.Turkish.HDTV.XviD-LOL", Language.Turkish)]
[TestCase("Castle.2009.S01E14.Portuguese.HDTV.XviD-LOL", Language.Portuguese)]
[TestCase("Castle.2009.S01E14.HDTV.XviD-LOL", Language.English)]
[TestCase("person.of.interest.1x19.ita.720p.bdmux.x264-novarip", Language.Italian)]
[TestCase("Salamander.S01E01.FLEMISH.HDTV.x264-BRiGAND", Language.Flemish)]
[TestCase("H.Polukatoikia.S03E13.Greek.PDTV.XviD-Ouzo", Language.Greek)]
[TestCase("Burn.Notice.S04E15.Brotherly.Love.GERMAN.DUBBED.WS.WEBRiP.XviD.REPACK-TVP", Language.German)]
[TestCase("Ray Donovan - S01E01.720p.HDtv.x264-Evolve (NLsub)", Language.Norwegian)]
[TestCase("Shield,.The.1x13.Tueurs.De.Flics.FR.DVDRip.XviD", Language.French)]
[TestCase("True.Detective.S01E01.1080p.WEB-DL.Rus.Eng.TVKlondike", Language.Russian)]
public void should_parse_language(string postTitle, Language language)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.Language.Should().Be(language);
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Expansive;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class MultiEpisodeParserFixture : CoreTest
{
[TestCase("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", "WEEDS", 3, new[] { 1, 2, 3, 4, 5, 6 })]
[TestCase("Two.and.a.Half.Men.103.104.720p.HDTV.X264-DIMENSION", "Two.and.a.Half.Men", 1, new[] { 3, 4 })]
[TestCase("Weeds.S03E01.S03E02.720p.HDTV.X264-DIMENSION", "Weeds", 3, new[] { 1, 2 })]
[TestCase("The Borgias S01e01 e02 ShoHD On Demand 1080i DD5 1 ALANiS", "The Borgias", 1, new[] { 1, 2 })]
[TestCase("White.Collar.2x04.2x05.720p.BluRay-FUTV", "White.Collar", 2, new[] { 4, 5 })]
[TestCase("Desperate.Housewives.S07E22E23.720p.HDTV.X264-DIMENSION", "Desperate.Housewives", 7, new[] { 22, 23 })]
[TestCase("Desparate Housewives - S07E22 - S07E23 - And Lots of Security.. [HDTV-720p].mkv", "Desparate Housewives", 7, new[] { 22, 23 })]
[TestCase("S03E01.S03E02.720p.HDTV.X264-DIMENSION", "", 3, new[] { 1, 2 })]
[TestCase("Desparate Housewives - S07E22 - 7x23 - And Lots of Security.. [HDTV-720p].mkv", "Desparate Housewives", 7, new[] { 22, 23 })]
[TestCase("S07E22 - 7x23 - And Lots of Security.. [HDTV-720p].mkv", "", 7, new[] { 22, 23 })]
[TestCase("2x04x05.720p.BluRay-FUTV", "", 2, new[] { 4, 5 })]
[TestCase("S02E04E05.720p.BluRay-FUTV", "", 2, new[] { 4, 5 })]
[TestCase("S02E03-04-05.720p.BluRay-FUTV", "", 2, new[] { 3, 4, 5 })]
[TestCase("Breakout.Kings.S02E09-E10.HDTV.x264-ASAP", "Breakout Kings", 2, new[] { 9, 10 })]
[TestCase("Breakout Kings - 2x9-2x10 - Served Cold [SDTV] ", "Breakout Kings", 2, new[] { 9, 10 })]
[TestCase("Breakout Kings - 2x09-2x10 - Served Cold [SDTV] ", "Breakout Kings", 2, new[] { 9, 10 })]
[TestCase("Hell on Wheels S02E09 E10 HDTV x264 EVOLVE", "Hell on Wheels", 2, new[] { 9, 10 })]
[TestCase("Hell.on.Wheels.S02E09-E10.720p.HDTV.x264-EVOLVE", "Hell on Wheels", 2, new[] { 9, 10 })]
[TestCase("Grey's Anatomy - 8x01_02 - Free Falling", "Grey's Anatomy", 8, new [] { 1,2 })]
[TestCase("8x01_02 - Free Falling", "", 8, new[] { 1, 2 })]
[TestCase("Kaamelott.S01E91-E100", "Kaamelott", 1, new[] { 91, 92, 93, 94, 95, 96, 97, 98, 99, 100 })]
[TestCase("Neighbours.S29E161-E165.PDTV.x264-FQM", "Neighbours", 29, new[] { 161, 162, 163, 164, 165 })]
[TestCase("Shortland.Street.S22E5363-E5366.HDTV.x264-FiHTV", "Shortland Street", 22, new[] { 5363, 5364, 5365, 5366 })]
public void should_parse_multiple_episodes(string postTitle, string title, int season, int[] episodes)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.SeasonNumber.Should().Be(season);
result.EpisodeNumbers.Should().BeEquivalentTo(episodes);
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeFalse();
}
}
}

View File

@ -0,0 +1,96 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Expansive;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class NormalizeTitleFixture : CoreTest
{
[TestCase("Conan", "conan")]
[TestCase("The Tonight Show With Jay Leno", "tonightshowwithjayleno")]
[TestCase("The.Daily.Show", "dailyshow")]
[TestCase("Castle (2009)", "castle2009")]
[TestCase("Parenthood.2010", "parenthood2010")]
[TestCase("Law_and_Order_SVU", "lawordersvu")]
public void should_normalize_series_title(string parsedSeriesName, string seriesName)
{
var result = parsedSeriesName.CleanSeriesTitle();
result.Should().Be(seriesName);
}
[TestCase("CaPitAl", "capital")]
[TestCase("peri.od", "period")]
[TestCase("this.^&%^**$%@#$!That", "thisthat")]
[TestCase("test/test", "testtest")]
[TestCase("90210", "90210")]
[TestCase("24", "24")]
public void should_remove_special_characters_and_casing(string dirty, string clean)
{
var result = dirty.CleanSeriesTitle();
result.Should().Be(clean);
}
[TestCase("the")]
[TestCase("and")]
[TestCase("or")]
[TestCase("a")]
[TestCase("an")]
[TestCase("of")]
public void should_remove_common_words(string word)
{
var dirtyFormat = new[]
{
"word.{0}.word",
"word {0} word",
"word-{0}-word",
"{0}.word.word",
"{0}-word-word",
"{0} word word",
"word.word.{0}",
"word-word-{0}",
"word-word {0}",
};
foreach (var s in dirtyFormat)
{
var dirty = String.Format(s, word);
dirty.CleanSeriesTitle().Should().Be("wordword");
}
}
[TestCase("the")]
[TestCase("and")]
[TestCase("or")]
[TestCase("a")]
[TestCase("an")]
[TestCase("of")]
public void should_not_remove_common_words_in_the_middle_of_word(string word)
{
var dirtyFormat = new[]
{
"word.{0}word",
"word {0}word",
"word-{0}word",
"word{0}.word",
"word{0}-word",
"word{0}-word",
};
foreach (var s in dirtyFormat)
{
var dirty = String.Format(s, word);
dirty.CleanSeriesTitle().Should().Be(("word" + word.ToLower() + "word"));
}
}
}
}

View File

@ -2,11 +2,8 @@ using System;
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Expansive;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ParserTests namespace NzbDrone.Core.Test.ParserTests
{ {
@ -26,179 +23,6 @@ namespace NzbDrone.Core.Test.ParserTests
* Superman.-.The.Man.of.Steel.1994-05.33.hybrid.DreamGirl-Novus-HD * Superman.-.The.Man.of.Steel.1994-05.33.hybrid.DreamGirl-Novus-HD
*/ */
[TestCase("Sonny.With.a.Chance.S02E15", "Sonny.With.a.Chance", 2, 15)]
[TestCase("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", "Two.and.a.Half.Me", 1, 3)]
[TestCase("Two.and.a.Half.Me.113.720p.HDTV.X264-DIMENSION", "Two.and.a.Half.Me", 1, 13)]
[TestCase("Two.and.a.Half.Me.1013.720p.HDTV.X264-DIMENSION", "Two.and.a.Half.Me", 10, 13)]
[TestCase("Chuck.4x05.HDTV.XviD-LOL", "Chuck", 4, 5)]
[TestCase("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", "The.Girls.Next.Door", 3, 6)]
[TestCase("Degrassi.S10E27.WS.DSR.XviD-2HD", "Degrassi", 10, 27)]
[TestCase("Parenthood.2010.S02E14.HDTV.XviD-LOL", "Parenthood 2010", 2, 14)]
[TestCase("Hawaii Five 0 S01E19 720p WEB DL DD5 1 H 264 NT", "Hawaii Five 0", 1, 19)]
[TestCase("The Event S01E14 A Message Back 720p WEB DL DD5 1 H264 SURFER", "The Event", 1, 14)]
[TestCase("Adam Hills In Gordon St Tonight S01E07 WS PDTV XviD FUtV", "Adam Hills In Gordon St Tonight", 1, 7)]
[TestCase("Adam Hills In Gordon St Tonight S01E07 WS PDTV XviD FUtV", "Adam Hills In Gordon St Tonight", 1, 7)]
[TestCase("Adventure.Inc.S03E19.DVDRip.XviD-OSiTV", "Adventure.Inc", 3, 19)]
[TestCase("S03E09 WS PDTV XviD FUtV", "", 3, 9)]
[TestCase("5x10 WS PDTV XviD FUtV", "", 5, 10)]
[TestCase("Castle.2009.S01E14.HDTV.XviD-LOL", "Castle 2009", 1, 14)]
[TestCase("Pride.and.Prejudice.1995.S03E20.HDTV.XviD-LOL", "Pride and Prejudice 1995", 3, 20)]
[TestCase("The.Office.S03E115.DVDRip.XviD-OSiTV", "The.Office", 3, 115)]
[TestCase(@"Parks and Recreation - S02E21 - 94 Meetings - 720p TV.mkv", "Parks and Recreation", 2, 21)]
[TestCase(@"24-7 Penguins-Capitals- Road to the NHL Winter Classic - S01E03 - Episode 3.mkv", "24-7 Penguins-Capitals- Road to the NHL Winter Classic", 1, 3)]
[TestCase("Adventure.Inc.S03E19.DVDRip.\"XviD\"-OSiTV", "Adventure.Inc", 3, 19)]
[TestCase("Hawaii Five-0 (2010) - 1x05 - Nalowale (Forgotten/Missing)", "Hawaii Five-0 (2010)", 1, 5)]
[TestCase("Hawaii Five-0 (2010) - 1x05 - Title", "Hawaii Five-0 (2010)", 1, 5)]
[TestCase("House - S06E13 - 5 to 9 [DVD]", "House", 6, 13)]
[TestCase("The Mentalist - S02E21 - 18-5-4", "The Mentalist", 2, 21)]
[TestCase("Breaking.In.S01E07.21.0.Jump.Street.720p.WEB-DL.DD5.1.h.264-KiNGS", "Breaking In", 1, 7)]
[TestCase("CSI.525", "CSI", 5, 25)]
[TestCase("King of the Hill - 10x12 - 24 Hour Propane People [SDTV]", "King of the Hill", 10, 12)]
[TestCase("Brew Masters S01E06 3 Beers For Batali DVDRip XviD SPRiNTER", "Brew Masters", 1, 6)]
[TestCase("24 7 Flyers Rangers Road to the NHL Winter Classic Part01 720p HDTV x264 ORENJI", "24 7 Flyers Rangers Road to the NHL Winter Classic", 1, 1)]
[TestCase("24 7 Flyers Rangers Road to the NHL Winter Classic Part 02 720p HDTV x264 ORENJI", "24 7 Flyers Rangers Road to the NHL Winter Classic", 1, 2)]
[TestCase("24-7 Flyers-Rangers- Road to the NHL Winter Classic - S01E01 - Part 1", "24 7 Flyers Rangers Road to the NHL Winter Classic", 1, 1)]
[TestCase("The.Kennedys.Part.2.DSR.XviD-SYS", "The Kennedys", 1, 2)]
[TestCase("the-pacific-e07-720p", "The Pacific", 1, 7)]
[TestCase("S6E02-Unwrapped-(Playing With Food) - [DarkData]", "", 6, 2)]
[TestCase("S06E03-Unwrapped-(Number Ones Unwrapped) - [DarkData]", "", 6, 3)]
[TestCase("The Mentalist S02E21 18 5 4 720p WEB DL DD5 1 h 264 EbP", "The Mentalist", 2, 21)]
[TestCase("01x04 - Halloween, Part 1 - 720p WEB-DL", "", 1, 4)]
[TestCase("extras.s03.e05.ws.dvdrip.xvid-m00tv", "Extras", 3, 5)]
[TestCase("castle.2009.416.hdtv-lol", "Castle 2009", 4, 16)]
[TestCase("hawaii.five-0.2010.217.hdtv-lol", "Hawaii Five-0 (2010)", 2, 17)]
[TestCase("Looney Tunes - S1936E18 - I Love to Singa", "Looney Tunes", 1936, 18)]
[TestCase("American_Dad!_-_7x6_-_The_Scarlett_Getter_[SDTV]", "American Dad!", 7, 6)]
[TestCase("Falling_Skies_-_1x1_-_Live_and_Learn_[HDTV-720p]", "Falling Skies", 1, 1)]
[TestCase("Top Gear - 07x03 - 2005.11.70", "Top Gear", 7, 3)]
[TestCase("Hatfields and McCoys 2012 Part 1 REPACK 720p HDTV x264 2HD", "Hatfields and McCoys 2012", 1, 1)]
[TestCase("Glee.S04E09.Swan.Song.1080p.WEB-DL.DD5.1.H.264-ECI", "Glee", 4, 9)]
[TestCase("S08E20 50-50 Carla [DVD]", "", 8, 20)]
[TestCase("Cheers S08E20 50-50 Carla [DVD]", "Cheers", 8, 20)]
[TestCase("S02E10 6-50 to SLC [SDTV]", "", 2, 10)]
[TestCase("Franklin & Bash S02E10 6-50 to SLC [SDTV]", "Franklin & Bash", 2, 10)]
[TestCase("The_Big_Bang_Theory_-_6x12_-_The_Egg_Salad_Equivalency_[HDTV-720p]", "The Big Bang Theory", 6, 12)]
[TestCase("Top_Gear.19x06.720p_HDTV_x264-FoV", "Top Gear", 19, 6)]
[TestCase("Portlandia.S03E10.Alexandra.720p.WEB-DL.AAC2.0.H.264-CROM.mkv", "Portlandia", 3, 10)]
[TestCase("(Game of Thrones s03 e - \"Game of Thrones Season 3 Episode 10\"", "Game of Thrones", 3, 10)]
[TestCase("House.Hunters.International.S05E607.720p.hdtv.x264", "House.Hunters.International", 5, 607)]
[TestCase("Adventure.Time.With.Finn.And.Jake.S01E20.720p.BluRay.x264-DEiMOS", "Adventure.Time.With.Finn.And.Jake", 1, 20)]
[TestCase("Hostages.S01E04.2-45.PM.[HDTV-720p].mkv", "Hostages", 1, 4)]
[TestCase("S01E04", "", 1, 4)]
[TestCase("1x04", "", 1, 4)]
[TestCase("10.Things.You.Dont.Know.About.S02E04.Prohibition.HDTV.XviD-AFG", "10 Things You Dont Know About", 2, 4)]
[TestCase("30 Rock - S01E01 - Pilot.avi", "30 Rock", 1, 1)]
[TestCase("666 Park Avenue - S01E01", "666 Park Avenue", 1, 1)]
[TestCase("Warehouse 13 - S01E01", "Warehouse 13", 1, 1)]
[TestCase("Don't Trust The B---- in Apartment 23.S01E01", "Don't Trust The B---- in Apartment 23", 1, 1)]
[TestCase("Warehouse.13.S01E01", "Warehouse.13", 1, 1)]
[TestCase("Dont.Trust.The.B----.in.Apartment.23.S01E01", "Dont.Trust.The.B----.in.Apartment.23", 1, 1)]
[TestCase("24 S01E01", "24", 1, 1)]
[TestCase("24.S01E01", "24", 1, 1)]
[TestCase("Homeland - 2x12 - The Choice [HDTV-1080p].mkv", "Homeland", 2, 12)]
[TestCase("Homeland - 2x4 - New Car Smell [HDTV-1080p].mkv", "Homeland", 2, 4)]
public void ParseTitle_single(string postTitle, string title, int seasonNumber, int episodeNumber)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.Should().NotBeNull();
result.EpisodeNumbers.Should().HaveCount(1);
result.SeasonNumber.Should().Be(seasonNumber);
result.EpisodeNumbers.First().Should().Be(episodeNumber);
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeFalse();
}
[TestCase(@"z:\tv shows\battlestar galactica (2003)\Season 3\S03E05 - Collaborators.mkv", 3, 5)]
[TestCase(@"z:\tv shows\modern marvels\Season 16\S16E03 - The Potato.mkv", 16, 3)]
[TestCase(@"z:\tv shows\robot chicken\Specials\S00E16 - Dear Consumer - SD TV.avi", 0, 16)]
[TestCase(@"D:\shares\TV Shows\Parks And Recreation\Season 2\S02E21 - 94 Meetings - 720p TV.mkv", 2, 21)]
[TestCase(@"D:\shares\TV Shows\Battlestar Galactica (2003)\Season 2\S02E21.avi", 2, 21)]
[TestCase("C:/Test/TV/Chuck.4x05.HDTV.XviD-LOL", 4, 5)]
[TestCase(@"P:\TV Shows\House\Season 6\S06E13 - 5 to 9 - 720p BluRay.mkv", 6, 13)]
[TestCase(@"S:\TV Drop\House - 10x11 - Title [SDTV]\1011 - Title.avi", 10, 11)]
[TestCase(@"/TV Drop/House - 10x11 - Title [SDTV]/1011 - Title.avi", 10, 11)]
[TestCase(@"S:\TV Drop\King of the Hill - 10x12 - 24 Hour Propane People [SDTV]\1012 - 24 Hour Propane People.avi", 10, 12)]
[TestCase(@"/TV Drop/King of the Hill - 10x12 - 24 Hour Propane People [SDTV]/1012 - 24 Hour Propane People.avi", 10, 12)]
[TestCase(@"S:\TV Drop\King of the Hill - 10x12 - 24 Hour Propane People [SDTV]\Hour Propane People.avi", 10, 12)]
[TestCase(@"/TV Drop/King of the Hill - 10x12 - 24 Hour Propane People [SDTV]/Hour Propane People.avi", 10, 12)]
[TestCase(@"E:\Downloads\tv\The.Big.Bang.Theory.S01E01.720p.HDTV\ajifajjjeaeaeqwer_eppj.avi", 1, 1)]
[TestCase(@"C:\Test\Unsorted\The.Big.Bang.Theory.S01E01.720p.HDTV\tbbt101.avi", 1, 1)]
public void PathParse_tests(string path, int season, int episode)
{
var result = Parser.Parser.ParsePath(path);
result.EpisodeNumbers.Should().HaveCount(1);
result.SeasonNumber.Should().Be(season);
result.EpisodeNumbers[0].Should().Be(episode);
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeFalse();
ExceptionVerification.IgnoreWarns();
}
[TestCase("THIS SHOULD NEVER PARSE")]
public void unparsable_title_should_log_warn_and_return_null(string title)
{
Parser.Parser.ParseTitle(title).Should().BeNull();
}
//[Timeout(1000)]
[TestCase("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", "WEEDS", 3, new[] { 1, 2, 3, 4, 5, 6 })]
[TestCase("Two.and.a.Half.Men.103.104.720p.HDTV.X264-DIMENSION", "Two.and.a.Half.Men", 1, new[] { 3, 4 })]
[TestCase("Weeds.S03E01.S03E02.720p.HDTV.X264-DIMENSION", "Weeds", 3, new[] { 1, 2 })]
[TestCase("The Borgias S01e01 e02 ShoHD On Demand 1080i DD5 1 ALANiS", "The Borgias", 1, new[] { 1, 2 })]
[TestCase("White.Collar.2x04.2x05.720p.BluRay-FUTV", "White.Collar", 2, new[] { 4, 5 })]
[TestCase("Desperate.Housewives.S07E22E23.720p.HDTV.X264-DIMENSION", "Desperate.Housewives", 7, new[] { 22, 23 })]
[TestCase("Desparate Housewives - S07E22 - S07E23 - And Lots of Security.. [HDTV-720p].mkv", "Desparate Housewives", 7, new[] { 22, 23 })]
[TestCase("S03E01.S03E02.720p.HDTV.X264-DIMENSION", "", 3, new[] { 1, 2 })]
[TestCase("Desparate Housewives - S07E22 - 7x23 - And Lots of Security.. [HDTV-720p].mkv", "Desparate Housewives", 7, new[] { 22, 23 })]
[TestCase("S07E22 - 7x23 - And Lots of Security.. [HDTV-720p].mkv", "", 7, new[] { 22, 23 })]
[TestCase("2x04x05.720p.BluRay-FUTV", "", 2, new[] { 4, 5 })]
[TestCase("S02E04E05.720p.BluRay-FUTV", "", 2, new[] { 4, 5 })]
[TestCase("S02E03-04-05.720p.BluRay-FUTV", "", 2, new[] { 3, 4, 5 })]
[TestCase("Breakout.Kings.S02E09-E10.HDTV.x264-ASAP", "Breakout Kings", 2, new[] { 9, 10 })]
[TestCase("Breakout Kings - 2x9-2x10 - Served Cold [SDTV] ", "Breakout Kings", 2, new[] { 9, 10 })]
[TestCase("Breakout Kings - 2x09-2x10 - Served Cold [SDTV] ", "Breakout Kings", 2, new[] { 9, 10 })]
[TestCase("Hell on Wheels S02E09 E10 HDTV x264 EVOLVE", "Hell on Wheels", 2, new[] { 9, 10 })]
[TestCase("Hell.on.Wheels.S02E09-E10.720p.HDTV.x264-EVOLVE", "Hell on Wheels", 2, new[] { 9, 10 })]
[TestCase("Grey's Anatomy - 8x01_02 - Free Falling", "Grey's Anatomy", 8, new [] { 1,2 })]
[TestCase("8x01_02 - Free Falling", "", 8, new[] { 1, 2 })]
[TestCase("Kaamelott.S01E91-E100", "Kaamelott", 1, new[] { 91, 92, 93, 94, 95, 96, 97, 98, 99, 100 })]
[TestCase("Neighbours.S29E161-E165.PDTV.x264-FQM", "Neighbours", 29, new[] { 161, 162, 163, 164, 165 })]
[TestCase("Shortland.Street.S22E5363-E5366.HDTV.x264-FiHTV", "Shortland Street", 22, new[] { 5363, 5364, 5365, 5366 })]
public void TitleParse_multi(string postTitle, string title, int season, int[] episodes)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.SeasonNumber.Should().Be(season);
result.EpisodeNumbers.Should().BeEquivalentTo(episodes);
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeFalse();
}
[TestCase("Conan 2011 04 18 Emma Roberts HDTV XviD BFF", "Conan", 2011, 04, 18)]
[TestCase("The Tonight Show With Jay Leno 2011 04 15 1080i HDTV DD5 1 MPEG2 TrollHD", "The Tonight Show With Jay Leno", 2011, 04, 15)]
[TestCase("The.Daily.Show.2010.10.11.Johnny.Knoxville.iTouch-MW", "The.Daily.Show", 2010, 10, 11)]
[TestCase("The Daily Show - 2011-04-12 - Gov. Deval Patrick", "The.Daily.Show", 2011, 04, 12)]
[TestCase("2011.01.10 - Denis Leary - HD TV.mkv", "", 2011, 1, 10)]
[TestCase("2011.03.13 - Denis Leary - HD TV.mkv", "", 2011, 3, 13)]
[TestCase("The Tonight Show with Jay Leno - 2011-06-16 - Larry David, \"Bachelorette\" Ashley Hebert, Pitbull with Ne-Yo", "The Tonight Show with Jay Leno", 2011, 6, 16)]
[TestCase("2020.NZ.2012.16.02.PDTV.XviD-C4TV", "2020nz", 2012, 2, 16)]
[TestCase("2020.NZ.2012.13.02.PDTV.XviD-C4TV", "2020nz", 2012, 2, 13)]
[TestCase("2020.NZ.2011.12.02.PDTV.XviD-C4TV", "2020nz", 2011, 12, 2)]
public void parse_daily_episodes(string postTitle, string title, int year, int month, int day)
{
var result = Parser.Parser.ParseTitle(postTitle);
var airDate = new DateTime(year, month, day);
result.Should().NotBeNull();
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
result.AirDate.Should().Be(airDate.ToString(Episode.AIR_DATE_FORMAT));
result.EpisodeNumbers.Should().BeEmpty();
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeFalse();
}
[TestCase("[SubDESU]_High_School_DxD_07_(1280x720_x264-AAC)_[6B7FD717]", "High School DxD", 7, 0, 0)] [TestCase("[SubDESU]_High_School_DxD_07_(1280x720_x264-AAC)_[6B7FD717]", "High School DxD", 7, 0, 0)]
[TestCase("[Chihiro]_Working!!_-_06_[848x480_H.264_AAC][859EEAFA]", "Working!!", 6, 0, 0)] [TestCase("[Chihiro]_Working!!_-_06_[848x480_H.264_AAC][859EEAFA]", "Working!!", 6, 0, 0)]
[TestCase("[Commie]_Senki_Zesshou_Symphogear_-_11_[65F220B4]", "Senki_Zesshou_Symphogear", 11, 0, 0)] [TestCase("[Commie]_Senki_Zesshou_Symphogear_-_11_[65F220B4]", "Senki_Zesshou_Symphogear", 11, 0, 0)]
@ -232,138 +56,6 @@ namespace NzbDrone.Core.Test.ParserTests
result.FullSeason.Should().BeFalse(); result.FullSeason.Should().BeFalse();
} }
[TestCase("Conan {year} {month} {day} Emma Roberts HDTV XviD BFF")]
[TestCase("The Tonight Show With Jay Leno {year} {month} {day} 1080i HDTV DD5 1 MPEG2 TrollHD")]
[TestCase("The.Daily.Show.{year}.{month}.{day}.Johnny.Knoxville.iTouch-MW")]
[TestCase("The Daily Show - {year}-{month}-{day} - Gov. Deval Patrick")]
[TestCase("{year}.{month}.{day} - Denis Leary - HD TV.mkv")]
[TestCase("The Tonight Show with Jay Leno - {year}-{month}-{day} - Larry David, \"Bachelorette\" Ashley Hebert, Pitbull with Ne-Yo")]
[TestCase("2020.NZ.{year}.{month}.{day}.PDTV.XviD-C4TV")]
public void should_not_accept_ancient_daily_series(string title)
{
var yearTooLow = title.Expand(new { year = 1950, month = 10, day = 14 });
Parser.Parser.ParseTitle(yearTooLow).Should().BeNull();
}
[TestCase("Conan {year} {month} {day} Emma Roberts HDTV XviD BFF")]
[TestCase("The Tonight Show With Jay Leno {year} {month} {day} 1080i HDTV DD5 1 MPEG2 TrollHD")]
[TestCase("The.Daily.Show.{year}.{month}.{day}.Johnny.Knoxville.iTouch-MW")]
[TestCase("The Daily Show - {year}-{month}-{day} - Gov. Deval Patrick")]
[TestCase("{year}.{month}.{day} - Denis Leary - HD TV.mkv")]
[TestCase("The Tonight Show with Jay Leno - {year}-{month}-{day} - Larry David, \"Bachelorette\" Ashley Hebert, Pitbull with Ne-Yo")]
[TestCase("2020.NZ.{year}.{month}.{day}.PDTV.XviD-C4TV")]
public void should_not_accept_future_dates(string title)
{
var twoDaysFromNow = DateTime.Now.AddDays(2);
var validDate = title.Expand(new { year = twoDaysFromNow.Year, month = twoDaysFromNow.Month.ToString("00"), day = twoDaysFromNow.Day.ToString("00") });
Parser.Parser.ParseTitle(validDate).Should().BeNull();
}
[Test]
public void parse_daily_should_fail_if_episode_is_far_in_future()
{
var title = string.Format("{0:yyyy.MM.dd} - Denis Leary - HD TV.mkv", DateTime.Now.AddDays(2));
Parser.Parser.ParseTitle(title).Should().BeNull();
}
[TestCase("30.Rock.Season.04.HDTV.XviD-DIMENSION", "30.Rock", 4)]
[TestCase("Parks.and.Recreation.S02.720p.x264-DIMENSION", "Parks.and.Recreation", 2)]
[TestCase("The.Office.US.S03.720p.x264-DIMENSION", "The.Office.US", 3)]
[TestCase(@"Sons.of.Anarchy.S03.720p.BluRay-CLUE\REWARD", "Sons.of.Anarchy", 3)]
[TestCase("Adventure Time S02 720p HDTV x264 CRON", "Adventure Time", 2)]
[TestCase("Sealab.2021.S04.iNTERNAL.DVDRip.XviD-VCDVaULT", "Sealab 2021", 4)]
public void full_season_release_parse(string postTitle, string title, int season)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.SeasonNumber.Should().Be(season);
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
result.EpisodeNumbers.Should().BeEmpty();
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeTrue();
}
[TestCase("Conan", "conan")]
[TestCase("The Tonight Show With Jay Leno", "tonightshowwithjayleno")]
[TestCase("The.Daily.Show", "dailyshow")]
[TestCase("Castle (2009)", "castle2009")]
[TestCase("Parenthood.2010", "parenthood2010")]
[TestCase("Law_and_Order_SVU", "lawordersvu")]
public void series_name_normalize(string parsedSeriesName, string seriesName)
{
var result = parsedSeriesName.CleanSeriesTitle();
result.Should().Be(seriesName);
}
[TestCase("CaPitAl", "capital")]
[TestCase("peri.od", "period")]
[TestCase("this.^&%^**$%@#$!That", "thisthat")]
[TestCase("test/test", "testtest")]
[TestCase("90210", "90210")]
[TestCase("24", "24")]
public void Normalize_Title(string dirty, string clean)
{
var result = dirty.CleanSeriesTitle();
result.Should().Be(clean);
}
[TestCase("the")]
[TestCase("and")]
[TestCase("or")]
[TestCase("a")]
[TestCase("an")]
[TestCase("of")]
public void Normalize_removed_common_words(string word)
{
var dirtyFormat = new[]
{
"word.{0}.word",
"word {0} word",
"word-{0}-word",
"{0}.word.word",
"{0}-word-word",
"{0} word word",
"word.word.{0}",
"word-word-{0}",
"word-word {0}",
};
foreach (var s in dirtyFormat)
{
var dirty = String.Format(s, word);
dirty.CleanSeriesTitle().Should().Be("wordword");
}
}
[TestCase("the")]
[TestCase("and")]
[TestCase("or")]
[TestCase("a")]
[TestCase("an")]
[TestCase("of")]
public void Normalize_not_removed_common_words_in_the_middle(string word)
{
var dirtyFormat = new[]
{
"word.{0}word",
"word {0}word",
"word-{0}word",
"word{0}.word",
"word{0}-word",
"word{0}-word",
};
foreach (var s in dirtyFormat)
{
var dirty = String.Format(s, word);
dirty.CleanSeriesTitle().Should().Be(("word" + word.ToLower() + "word"));
}
}
[TestCase("Chuck - 4x05 - Title", "Chuck")] [TestCase("Chuck - 4x05 - Title", "Chuck")]
[TestCase("Law & Order - 4x05 - Title", "laworder")] [TestCase("Law & Order - 4x05 - Title", "laworder")]
[TestCase("Bad Format", "badformat")] [TestCase("Bad Format", "badformat")]
@ -376,115 +68,10 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Hawaii Five 0", "hawaiifive0")] [TestCase("Hawaii Five 0", "hawaiifive0")]
[TestCase("Match of the Day", "matchday")] [TestCase("Match of the Day", "matchday")]
[TestCase("Match of the Day 2", "matchday2")] [TestCase("Match of the Day 2", "matchday2")]
public void parse_series_name(string postTitle, string title) public void should_parse_series_name(string postTitle, string title)
{ {
var result = Parser.Parser.ParseSeriesName(postTitle); var result = Parser.Parser.ParseSeriesName(postTitle);
result.Should().Be(title.CleanSeriesTitle()); result.Should().Be(title.CleanSeriesTitle());
} }
[TestCase("Castle.2009.S01E14.English.HDTV.XviD-LOL", Language.English)]
[TestCase("Castle.2009.S01E14.French.HDTV.XviD-LOL", Language.French)]
[TestCase("Castle.2009.S01E14.Spanish.HDTV.XviD-LOL", Language.Spanish)]
[TestCase("Castle.2009.S01E14.German.HDTV.XviD-LOL", Language.German)]
[TestCase("Castle.2009.S01E14.Germany.HDTV.XviD-LOL", Language.English)]
[TestCase("Castle.2009.S01E14.Italian.HDTV.XviD-LOL", Language.Italian)]
[TestCase("Castle.2009.S01E14.Danish.HDTV.XviD-LOL", Language.Danish)]
[TestCase("Castle.2009.S01E14.Dutch.HDTV.XviD-LOL", Language.Dutch)]
[TestCase("Castle.2009.S01E14.Japanese.HDTV.XviD-LOL", Language.Japanese)]
[TestCase("Castle.2009.S01E14.Cantonese.HDTV.XviD-LOL", Language.Cantonese)]
[TestCase("Castle.2009.S01E14.Mandarin.HDTV.XviD-LOL", Language.Mandarin)]
[TestCase("Castle.2009.S01E14.Korean.HDTV.XviD-LOL", Language.Korean)]
[TestCase("Castle.2009.S01E14.Russian.HDTV.XviD-LOL", Language.Russian)]
[TestCase("Castle.2009.S01E14.Polish.HDTV.XviD-LOL", Language.Polish)]
[TestCase("Castle.2009.S01E14.Vietnamese.HDTV.XviD-LOL", Language.Vietnamese)]
[TestCase("Castle.2009.S01E14.Swedish.HDTV.XviD-LOL", Language.Swedish)]
[TestCase("Castle.2009.S01E14.Norwegian.HDTV.XviD-LOL", Language.Norwegian)]
[TestCase("Castle.2009.S01E14.Finnish.HDTV.XviD-LOL", Language.Finnish)]
[TestCase("Castle.2009.S01E14.Turkish.HDTV.XviD-LOL", Language.Turkish)]
[TestCase("Castle.2009.S01E14.Portuguese.HDTV.XviD-LOL", Language.Portuguese)]
[TestCase("Castle.2009.S01E14.HDTV.XviD-LOL", Language.English)]
[TestCase("person.of.interest.1x19.ita.720p.bdmux.x264-novarip", Language.Italian)]
[TestCase("Salamander.S01E01.FLEMISH.HDTV.x264-BRiGAND", Language.Flemish)]
[TestCase("H.Polukatoikia.S03E13.Greek.PDTV.XviD-Ouzo", Language.Greek)]
[TestCase("Burn.Notice.S04E15.Brotherly.Love.GERMAN.DUBBED.WS.WEBRiP.XviD.REPACK-TVP", Language.German)]
[TestCase("Ray Donovan - S01E01.720p.HDtv.x264-Evolve (NLsub)", Language.Norwegian)]
[TestCase("Shield,.The.1x13.Tueurs.De.Flics.FR.DVDRip.XviD", Language.French)]
[TestCase("True.Detective.S01E01.1080p.WEB-DL.Rus.Eng.TVKlondike", Language.Russian)]
public void parse_language(string postTitle, Language language)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.Language.Should().Be(language);
}
[TestCase("Hawaii Five 0 S01 720p WEB DL DD5 1 H 264 NT", "Hawaii Five 0", 1)]
[TestCase("30 Rock S03 WS PDTV XviD FUtV", "30 Rock", 3)]
[TestCase("The Office Season 4 WS PDTV XviD FUtV", "The Office", 4)]
[TestCase("Eureka Season 1 720p WEB DL DD 5 1 h264 TjHD", "Eureka", 1)]
[TestCase("The Office Season4 WS PDTV XviD FUtV", "The Office", 4)]
[TestCase("Eureka S 01 720p WEB DL DD 5 1 h264 TjHD", "Eureka", 1)]
[TestCase("Doctor Who Confidential Season 3", "Doctor Who Confidential", 3)]
public void parse_season_info(string postTitle, string seriesName, int seasonNumber)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.SeriesTitle.Should().Be(seriesName.CleanSeriesTitle());
result.SeasonNumber.Should().Be(seasonNumber);
result.FullSeason.Should().BeTrue();
}
[TestCase("Acropolis Now S05 EXTRAS DVDRip XviD RUNNER")]
[TestCase("Punky Brewster S01 EXTRAS DVDRip XviD RUNNER")]
[TestCase("Instant Star S03 EXTRAS DVDRip XviD OSiTV")]
public void parse_season_extras(string postTitle)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.Should().BeNull();
}
[TestCase("Lie.to.Me.S03.SUBPACK.DVDRip.XviD-REWARD")]
[TestCase("The.Middle.S02.SUBPACK.DVDRip.XviD-REWARD")]
[TestCase("CSI.S11.SUBPACK.DVDRip.XviD-REWARD")]
public void parse_season_subpack(string postTitle)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.Should().BeNull();
}
[TestCase("76El6LcgLzqb426WoVFg1vVVVGx4uCYopQkfjmLe")]
[TestCase("Vrq6e1Aba3U amCjuEgV5R2QvdsLEGYF3YQAQkw8")]
[TestCase("TDAsqTea7k4o6iofVx3MQGuDK116FSjPobMuh8oB")]
[TestCase("yp4nFodAAzoeoRc467HRh1mzuT17qeekmuJ3zFnL")]
[TestCase("oxXo8S2272KE1 lfppvxo3iwEJBrBmhlQVK1gqGc")]
[TestCase("dPBAtu681Ycy3A4NpJDH6kNVQooLxqtnsW1Umfiv")]
[TestCase("password - \"bdc435cb-93c4-4902-97ea-ca00568c3887.337\" yEnc")]
public void should_not_parse_crap(string title)
{
Parser.Parser.ParseTitle(title).Should().BeNull();
ExceptionVerification.IgnoreWarns();
}
[TestCase("Castle.2009.S01E14.English.HDTV.XviD-LOL", "LOL")]
[TestCase("Castle 2009 S01E14 English HDTV XviD LOL", "LOL")]
[TestCase("Acropolis Now S05 EXTRAS DVDRip XviD RUNNER", "RUNNER")]
[TestCase("Punky.Brewster.S01.EXTRAS.DVDRip.XviD-RUNNER", "RUNNER")]
[TestCase("2020.NZ.2011.12.02.PDTV.XviD-C4TV", "C4TV")]
[TestCase("The.Office.S03E115.DVDRip.XviD-OSiTV", "OSiTV")]
[TestCase("The Office - S01E01 - Pilot [HTDV-480p]", "DRONE")]
[TestCase("The Office - S01E01 - Pilot [HTDV-720p]", "DRONE")]
[TestCase("The Office - S01E01 - Pilot [HTDV-1080p]", "DRONE")]
public void parse_releaseGroup(string title, string expected)
{
Parser.Parser.ParseReleaseGroup(title).Should().Be(expected);
}
[Test]
public void should_not_include_extension_in_releaseGroup()
{
const string path = @"C:\Test\Doctor.Who.2005.s01e01.internal.bdrip.x264-archivist.mkv";
Parser.Parser.ParsePath(path).ReleaseGroup.Should().Be("archivist");
}
} }
} }

View File

@ -0,0 +1,46 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Expansive;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class PathParserFixture : CoreTest
{
[TestCase(@"z:\tv shows\battlestar galactica (2003)\Season 3\S03E05 - Collaborators.mkv", 3, 5)]
[TestCase(@"z:\tv shows\modern marvels\Season 16\S16E03 - The Potato.mkv", 16, 3)]
[TestCase(@"z:\tv shows\robot chicken\Specials\S00E16 - Dear Consumer - SD TV.avi", 0, 16)]
[TestCase(@"D:\shares\TV Shows\Parks And Recreation\Season 2\S02E21 - 94 Meetings - 720p TV.mkv", 2, 21)]
[TestCase(@"D:\shares\TV Shows\Battlestar Galactica (2003)\Season 2\S02E21.avi", 2, 21)]
[TestCase("C:/Test/TV/Chuck.4x05.HDTV.XviD-LOL", 4, 5)]
[TestCase(@"P:\TV Shows\House\Season 6\S06E13 - 5 to 9 - 720p BluRay.mkv", 6, 13)]
[TestCase(@"S:\TV Drop\House - 10x11 - Title [SDTV]\1011 - Title.avi", 10, 11)]
[TestCase(@"/TV Drop/House - 10x11 - Title [SDTV]/1011 - Title.avi", 10, 11)]
[TestCase(@"S:\TV Drop\King of the Hill - 10x12 - 24 Hour Propane People [SDTV]\1012 - 24 Hour Propane People.avi", 10, 12)]
[TestCase(@"/TV Drop/King of the Hill - 10x12 - 24 Hour Propane People [SDTV]/1012 - 24 Hour Propane People.avi", 10, 12)]
[TestCase(@"S:\TV Drop\King of the Hill - 10x12 - 24 Hour Propane People [SDTV]\Hour Propane People.avi", 10, 12)]
[TestCase(@"/TV Drop/King of the Hill - 10x12 - 24 Hour Propane People [SDTV]/Hour Propane People.avi", 10, 12)]
[TestCase(@"E:\Downloads\tv\The.Big.Bang.Theory.S01E01.720p.HDTV\ajifajjjeaeaeqwer_eppj.avi", 1, 1)]
[TestCase(@"C:\Test\Unsorted\The.Big.Bang.Theory.S01E01.720p.HDTV\tbbt101.avi", 1, 1)]
[TestCase(@"C:\Test\Unsorted\Terminator.The.Sarah.Connor.Chronicles.S02E19.720p.BluRay.x264-SiNNERS-RP\ba27283b17c00d01193eacc02a8ba98eeb523a76.mkv", 2, 19)]
[TestCase(@"C:\Test\Unsorted\Terminator.The.Sarah.Connor.Chronicles.S02E18.720p.BluRay.x264-SiNNERS-RP\45a55debe3856da318cc35882ad07e43cd32fd15.mkv", 2, 18)]
public void should_parse_from_path(string path, int season, int episode)
{
var result = Parser.Parser.ParsePath(path);
result.EpisodeNumbers.Should().HaveCount(1);
result.SeasonNumber.Should().Be(season);
result.EpisodeNumbers[0].Should().Be(episode);
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeFalse();
ExceptionVerification.IgnoreWarns();
}
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class ReleaseGroupParserFixture : CoreTest
{
[TestCase("Castle.2009.S01E14.English.HDTV.XviD-LOL", "LOL")]
[TestCase("Castle 2009 S01E14 English HDTV XviD LOL", "LOL")]
[TestCase("Acropolis Now S05 EXTRAS DVDRip XviD RUNNER", "RUNNER")]
[TestCase("Punky.Brewster.S01.EXTRAS.DVDRip.XviD-RUNNER", "RUNNER")]
[TestCase("2020.NZ.2011.12.02.PDTV.XviD-C4TV", "C4TV")]
[TestCase("The.Office.S03E115.DVDRip.XviD-OSiTV", "OSiTV")]
[TestCase("The Office - S01E01 - Pilot [HTDV-480p]", "DRONE")]
[TestCase("The Office - S01E01 - Pilot [HTDV-720p]", "DRONE")]
[TestCase("The Office - S01E01 - Pilot [HTDV-1080p]", "DRONE")]
public void should_parse_release_group(string title, string expected)
{
Parser.Parser.ParseReleaseGroup(title).Should().Be(expected);
}
[Test]
public void should_not_include_extension_in_release_roup()
{
const string path = @"C:\Test\Doctor.Who.2005.s01e01.internal.bdrip.x264-archivist.mkv";
Parser.Parser.ParsePath(path).ReleaseGroup.Should().Be("archivist");
}
}
}

View File

@ -0,0 +1,57 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class SeasonParserFixture : CoreTest
{
[TestCase("30.Rock.Season.04.HDTV.XviD-DIMENSION", "30.Rock", 4)]
[TestCase("Parks.and.Recreation.S02.720p.x264-DIMENSION", "Parks.and.Recreation", 2)]
[TestCase("The.Office.US.S03.720p.x264-DIMENSION", "The.Office.US", 3)]
[TestCase(@"Sons.of.Anarchy.S03.720p.BluRay-CLUE\REWARD", "Sons.of.Anarchy", 3)]
[TestCase("Adventure Time S02 720p HDTV x264 CRON", "Adventure Time", 2)]
[TestCase("Sealab.2021.S04.iNTERNAL.DVDRip.XviD-VCDVaULT", "Sealab 2021", 4)]
[TestCase("Hawaii Five 0 S01 720p WEB DL DD5 1 H 264 NT", "Hawaii Five 0", 1)]
[TestCase("30 Rock S03 WS PDTV XviD FUtV", "30 Rock", 3)]
[TestCase("The Office Season 4 WS PDTV XviD FUtV", "The Office", 4)]
[TestCase("Eureka Season 1 720p WEB DL DD 5 1 h264 TjHD", "Eureka", 1)]
[TestCase("The Office Season4 WS PDTV XviD FUtV", "The Office", 4)]
[TestCase("Eureka S 01 720p WEB DL DD 5 1 h264 TjHD", "Eureka", 1)]
[TestCase("Doctor Who Confidential Season 3", "Doctor Who Confidential", 3)]
public void should_parsefull_season_release(string postTitle, string title, int season)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.SeasonNumber.Should().Be(season);
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
result.EpisodeNumbers.Should().BeEmpty();
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeTrue();
}
[TestCase("Acropolis Now S05 EXTRAS DVDRip XviD RUNNER")]
[TestCase("Punky Brewster S01 EXTRAS DVDRip XviD RUNNER")]
[TestCase("Instant Star S03 EXTRAS DVDRip XviD OSiTV")]
public void should_parse_season_extras(string postTitle)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.Should().BeNull();
}
[TestCase("Lie.to.Me.S03.SUBPACK.DVDRip.XviD-REWARD")]
[TestCase("The.Middle.S02.SUBPACK.DVDRip.XviD-REWARD")]
[TestCase("CSI.S11.SUBPACK.DVDRip.XviD-REWARD")]
public void should_parse_season_subpack(string postTitle)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.Should().BeNull();
}
}
}

View File

@ -0,0 +1,97 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ParserTests
{
[TestFixture]
public class SingleEpisodeParserFixture : CoreTest
{
[TestCase("Sonny.With.a.Chance.S02E15", "Sonny.With.a.Chance", 2, 15)]
[TestCase("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", "Two.and.a.Half.Me", 1, 3)]
[TestCase("Two.and.a.Half.Me.113.720p.HDTV.X264-DIMENSION", "Two.and.a.Half.Me", 1, 13)]
[TestCase("Two.and.a.Half.Me.1013.720p.HDTV.X264-DIMENSION", "Two.and.a.Half.Me", 10, 13)]
[TestCase("Chuck.4x05.HDTV.XviD-LOL", "Chuck", 4, 5)]
[TestCase("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", "The.Girls.Next.Door", 3, 6)]
[TestCase("Degrassi.S10E27.WS.DSR.XviD-2HD", "Degrassi", 10, 27)]
[TestCase("Parenthood.2010.S02E14.HDTV.XviD-LOL", "Parenthood 2010", 2, 14)]
[TestCase("Hawaii Five 0 S01E19 720p WEB DL DD5 1 H 264 NT", "Hawaii Five 0", 1, 19)]
[TestCase("The Event S01E14 A Message Back 720p WEB DL DD5 1 H264 SURFER", "The Event", 1, 14)]
[TestCase("Adam Hills In Gordon St Tonight S01E07 WS PDTV XviD FUtV", "Adam Hills In Gordon St Tonight", 1, 7)]
[TestCase("Adam Hills In Gordon St Tonight S01E07 WS PDTV XviD FUtV", "Adam Hills In Gordon St Tonight", 1, 7)]
[TestCase("Adventure.Inc.S03E19.DVDRip.XviD-OSiTV", "Adventure.Inc", 3, 19)]
[TestCase("S03E09 WS PDTV XviD FUtV", "", 3, 9)]
[TestCase("5x10 WS PDTV XviD FUtV", "", 5, 10)]
[TestCase("Castle.2009.S01E14.HDTV.XviD-LOL", "Castle 2009", 1, 14)]
[TestCase("Pride.and.Prejudice.1995.S03E20.HDTV.XviD-LOL", "Pride and Prejudice 1995", 3, 20)]
[TestCase("The.Office.S03E115.DVDRip.XviD-OSiTV", "The.Office", 3, 115)]
[TestCase(@"Parks and Recreation - S02E21 - 94 Meetings - 720p TV.mkv", "Parks and Recreation", 2, 21)]
[TestCase(@"24-7 Penguins-Capitals- Road to the NHL Winter Classic - S01E03 - Episode 3.mkv", "24-7 Penguins-Capitals- Road to the NHL Winter Classic", 1, 3)]
[TestCase("Adventure.Inc.S03E19.DVDRip.\"XviD\"-OSiTV", "Adventure.Inc", 3, 19)]
[TestCase("Hawaii Five-0 (2010) - 1x05 - Nalowale (Forgotten/Missing)", "Hawaii Five-0 (2010)", 1, 5)]
[TestCase("Hawaii Five-0 (2010) - 1x05 - Title", "Hawaii Five-0 (2010)", 1, 5)]
[TestCase("House - S06E13 - 5 to 9 [DVD]", "House", 6, 13)]
[TestCase("The Mentalist - S02E21 - 18-5-4", "The Mentalist", 2, 21)]
[TestCase("Breaking.In.S01E07.21.0.Jump.Street.720p.WEB-DL.DD5.1.h.264-KiNGS", "Breaking In", 1, 7)]
[TestCase("CSI.525", "CSI", 5, 25)]
[TestCase("King of the Hill - 10x12 - 24 Hour Propane People [SDTV]", "King of the Hill", 10, 12)]
[TestCase("Brew Masters S01E06 3 Beers For Batali DVDRip XviD SPRiNTER", "Brew Masters", 1, 6)]
[TestCase("24 7 Flyers Rangers Road to the NHL Winter Classic Part01 720p HDTV x264 ORENJI", "24 7 Flyers Rangers Road to the NHL Winter Classic", 1, 1)]
[TestCase("24 7 Flyers Rangers Road to the NHL Winter Classic Part 02 720p HDTV x264 ORENJI", "24 7 Flyers Rangers Road to the NHL Winter Classic", 1, 2)]
[TestCase("24-7 Flyers-Rangers- Road to the NHL Winter Classic - S01E01 - Part 1", "24 7 Flyers Rangers Road to the NHL Winter Classic", 1, 1)]
[TestCase("The.Kennedys.Part.2.DSR.XviD-SYS", "The Kennedys", 1, 2)]
[TestCase("the-pacific-e07-720p", "The Pacific", 1, 7)]
[TestCase("S6E02-Unwrapped-(Playing With Food) - [DarkData]", "", 6, 2)]
[TestCase("S06E03-Unwrapped-(Number Ones Unwrapped) - [DarkData]", "", 6, 3)]
[TestCase("The Mentalist S02E21 18 5 4 720p WEB DL DD5 1 h 264 EbP", "The Mentalist", 2, 21)]
[TestCase("01x04 - Halloween, Part 1 - 720p WEB-DL", "", 1, 4)]
[TestCase("extras.s03.e05.ws.dvdrip.xvid-m00tv", "Extras", 3, 5)]
[TestCase("castle.2009.416.hdtv-lol", "Castle 2009", 4, 16)]
[TestCase("hawaii.five-0.2010.217.hdtv-lol", "Hawaii Five-0 (2010)", 2, 17)]
[TestCase("Looney Tunes - S1936E18 - I Love to Singa", "Looney Tunes", 1936, 18)]
[TestCase("American_Dad!_-_7x6_-_The_Scarlett_Getter_[SDTV]", "American Dad!", 7, 6)]
[TestCase("Falling_Skies_-_1x1_-_Live_and_Learn_[HDTV-720p]", "Falling Skies", 1, 1)]
[TestCase("Top Gear - 07x03 - 2005.11.70", "Top Gear", 7, 3)]
[TestCase("Hatfields and McCoys 2012 Part 1 REPACK 720p HDTV x264 2HD", "Hatfields and McCoys 2012", 1, 1)]
[TestCase("Glee.S04E09.Swan.Song.1080p.WEB-DL.DD5.1.H.264-ECI", "Glee", 4, 9)]
[TestCase("S08E20 50-50 Carla [DVD]", "", 8, 20)]
[TestCase("Cheers S08E20 50-50 Carla [DVD]", "Cheers", 8, 20)]
[TestCase("S02E10 6-50 to SLC [SDTV]", "", 2, 10)]
[TestCase("Franklin & Bash S02E10 6-50 to SLC [SDTV]", "Franklin & Bash", 2, 10)]
[TestCase("The_Big_Bang_Theory_-_6x12_-_The_Egg_Salad_Equivalency_[HDTV-720p]", "The Big Bang Theory", 6, 12)]
[TestCase("Top_Gear.19x06.720p_HDTV_x264-FoV", "Top Gear", 19, 6)]
[TestCase("Portlandia.S03E10.Alexandra.720p.WEB-DL.AAC2.0.H.264-CROM.mkv", "Portlandia", 3, 10)]
[TestCase("(Game of Thrones s03 e - \"Game of Thrones Season 3 Episode 10\"", "Game of Thrones", 3, 10)]
[TestCase("House.Hunters.International.S05E607.720p.hdtv.x264", "House.Hunters.International", 5, 607)]
[TestCase("Adventure.Time.With.Finn.And.Jake.S01E20.720p.BluRay.x264-DEiMOS", "Adventure.Time.With.Finn.And.Jake", 1, 20)]
[TestCase("Hostages.S01E04.2-45.PM.[HDTV-720p].mkv", "Hostages", 1, 4)]
[TestCase("S01E04", "", 1, 4)]
[TestCase("1x04", "", 1, 4)]
[TestCase("10.Things.You.Dont.Know.About.S02E04.Prohibition.HDTV.XviD-AFG", "10 Things You Dont Know About", 2, 4)]
[TestCase("30 Rock - S01E01 - Pilot.avi", "30 Rock", 1, 1)]
[TestCase("666 Park Avenue - S01E01", "666 Park Avenue", 1, 1)]
[TestCase("Warehouse 13 - S01E01", "Warehouse 13", 1, 1)]
[TestCase("Don't Trust The B---- in Apartment 23.S01E01", "Don't Trust The B---- in Apartment 23", 1, 1)]
[TestCase("Warehouse.13.S01E01", "Warehouse.13", 1, 1)]
[TestCase("Dont.Trust.The.B----.in.Apartment.23.S01E01", "Dont.Trust.The.B----.in.Apartment.23", 1, 1)]
[TestCase("24 S01E01", "24", 1, 1)]
[TestCase("24.S01E01", "24", 1, 1)]
[TestCase("Homeland - 2x12 - The Choice [HDTV-1080p].mkv", "Homeland", 2, 12)]
[TestCase("Homeland - 2x4 - New Car Smell [HDTV-1080p].mkv", "Homeland", 2, 4)]
public void should_parse_single_episode(string postTitle, string title, int seasonNumber, int episodeNumber)
{
var result = Parser.Parser.ParseTitle(postTitle);
result.Should().NotBeNull();
result.EpisodeNumbers.Should().HaveCount(1);
result.SeasonNumber.Should().Be(seasonNumber);
result.EpisodeNumbers.First().Should().Be(episodeNumber);
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
result.FullSeason.Should().BeFalse();
}
}
}

View File

@ -23,6 +23,7 @@ namespace NzbDrone.Core.Annotations
Textbox, Textbox,
Password, Password,
Checkbox, Checkbox,
Select Select,
Path
} }
} }

View File

@ -1,4 +1,7 @@
using NzbDrone.Core.Datastore; using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Blacklisting namespace NzbDrone.Core.Blacklisting
@ -6,6 +9,7 @@ namespace NzbDrone.Core.Blacklisting
public interface IBlacklistRepository : IBasicRepository<Blacklist> public interface IBlacklistRepository : IBasicRepository<Blacklist>
{ {
bool Blacklisted(string sourceTitle); bool Blacklisted(string sourceTitle);
List<Blacklist> BlacklistedBySeries(int seriesId);
} }
public class BlacklistRepository : BasicRepository<Blacklist>, IBlacklistRepository public class BlacklistRepository : BasicRepository<Blacklist>, IBlacklistRepository
@ -17,7 +21,12 @@ namespace NzbDrone.Core.Blacklisting
public bool Blacklisted(string sourceTitle) public bool Blacklisted(string sourceTitle)
{ {
return Query.Any(e => e.SourceTitle.Contains(sourceTitle)); return Query.Where(e => e.SourceTitle.Contains(sourceTitle)).Any();
}
public List<Blacklist> BlacklistedBySeries(int seriesId)
{
return Query.Where(b => b.SeriesId == seriesId);
} }
} }
} }

View File

@ -3,6 +3,7 @@ using NzbDrone.Core.Datastore;
using NzbDrone.Core.Download; using NzbDrone.Core.Download;
using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Tv.Events;
namespace NzbDrone.Core.Blacklisting namespace NzbDrone.Core.Blacklisting
{ {
@ -13,7 +14,7 @@ namespace NzbDrone.Core.Blacklisting
void Delete(int id); void Delete(int id);
} }
public class BlacklistService : IBlacklistService, IHandle<DownloadFailedEvent>, IExecute<ClearBlacklistCommand> public class BlacklistService : IBlacklistService, IExecute<ClearBlacklistCommand>, IHandle<DownloadFailedEvent>, IHandle<SeriesDeletedEvent>
{ {
private readonly IBlacklistRepository _blacklistRepository; private readonly IBlacklistRepository _blacklistRepository;
private readonly IRedownloadFailedDownloads _redownloadFailedDownloadService; private readonly IRedownloadFailedDownloads _redownloadFailedDownloadService;
@ -39,6 +40,11 @@ namespace NzbDrone.Core.Blacklisting
_blacklistRepository.Delete(id); _blacklistRepository.Delete(id);
} }
public void Execute(ClearBlacklistCommand message)
{
_blacklistRepository.Purge();
}
public void Handle(DownloadFailedEvent message) public void Handle(DownloadFailedEvent message)
{ {
var blacklist = new Blacklist var blacklist = new Blacklist
@ -55,9 +61,11 @@ namespace NzbDrone.Core.Blacklisting
_redownloadFailedDownloadService.Redownload(message.SeriesId, message.EpisodeIds); _redownloadFailedDownloadService.Redownload(message.SeriesId, message.EpisodeIds);
} }
public void Execute(ClearBlacklistCommand message) public void Handle(SeriesDeletedEvent message)
{ {
_blacklistRepository.Purge(); var blacklisted = _blacklistRepository.BlacklistedBySeries(message.Series.Id);
_blacklistRepository.DeleteMany(blacklisted);
} }
} }
} }

View File

@ -21,9 +21,7 @@ namespace NzbDrone.Core.Configuration
public Config Get(string key) public Config Get(string key)
{ {
return Query.SingleOrDefault(c => c.Key == key); return Query.Where(c => c.Key == key).SingleOrDefault();
} }
} }
} }

View File

@ -54,7 +54,7 @@ namespace NzbDrone.Core.Configuration
return dict; return dict;
} }
public void SaveValues(Dictionary<string, object> configValues) public void SaveConfigDictionary(Dictionary<string, object> configValues)
{ {
var allWithDefaults = AllWithDefaults(); var allWithDefaults = AllWithDefaults();
@ -73,69 +73,6 @@ namespace NzbDrone.Core.Configuration
_eventAggregator.PublishEvent(new ConfigSavedEvent()); _eventAggregator.PublishEvent(new ConfigSavedEvent());
} }
public String SabHost
{
get { return GetValue("SabHost", "localhost"); }
set { SetValue("SabHost", value); }
}
public int SabPort
{
get { return GetValueInt("SabPort", 8080); }
set { SetValue("SabPort", value); }
}
public String SabApiKey
{
get { return GetValue("SabApiKey"); }
set { SetValue("SabApiKey", value); }
}
public String SabUsername
{
get { return GetValue("SabUsername"); }
set { SetValue("SabUsername", value); }
}
public String SabPassword
{
get { return GetValue("SabPassword"); }
set { SetValue("SabPassword", value); }
}
public String SabTvCategory
{
get { return GetValue("SabTvCategory", "tv"); }
set { SetValue("SabTvCategory", value); }
}
public SabPriorityType SabRecentTvPriority
{
get { return GetValueEnum("SabRecentTvPriority", SabPriorityType.Default); }
set { SetValue("SabRecentTvPriority", value); }
}
public SabPriorityType SabOlderTvPriority
{
get { return GetValueEnum("SabOlderTvPriority", SabPriorityType.Default); }
set { SetValue("SabOlderTvPriority", value); }
}
public bool SabUseSsl
{
get { return GetValueBoolean("SabUseSsl", false); }
set { SetValue("SabUseSsl", value); }
}
public String DownloadedEpisodesFolder public String DownloadedEpisodesFolder
{ {
get { return GetValue(ConfigKey.DownloadedEpisodesFolder.ToString()); } get { return GetValue(ConfigKey.DownloadedEpisodesFolder.ToString()); }
@ -155,80 +92,12 @@ namespace NzbDrone.Core.Configuration
set { SetValue("Retention", value); } set { SetValue("Retention", value); }
} }
public DownloadClientType DownloadClient
{
get { return GetValueEnum("DownloadClient", DownloadClientType.Blackhole); }
set { SetValue("DownloadClient", value); }
}
public string BlackholeFolder
{
get { return GetValue("BlackholeFolder", String.Empty); }
set { SetValue("BlackholeFolder", value); }
}
public string PneumaticFolder
{
get { return GetValue("PneumaticFolder", String.Empty); }
set { SetValue("PneumaticFolder", value); }
}
public string RecycleBin public string RecycleBin
{ {
get { return GetValue("RecycleBin", String.Empty); } get { return GetValue("RecycleBin", String.Empty); }
set { SetValue("RecycleBin", value); } set { SetValue("RecycleBin", value); }
} }
public String NzbgetUsername
{
get { return GetValue("NzbgetUsername", "nzbget"); }
set { SetValue("NzbgetUsername", value); }
}
public String NzbgetPassword
{
get { return GetValue("NzbgetPassword", ""); }
set { SetValue("NzbgetPassword", value); }
}
public String NzbgetHost
{
get { return GetValue("NzbgetHost", "localhost"); }
set { SetValue("NzbgetHost", value); }
}
public Int32 NzbgetPort
{
get { return GetValueInt("NzbgetPort", 6789); }
set { SetValue("NzbgetPort", value); }
}
public String NzbgetTvCategory
{
get { return GetValue("NzbgetTvCategory", ""); }
set { SetValue("NzbgetTvCategory", value); }
}
public PriorityType NzbgetRecentTvPriority
{
get { return GetValueEnum("NzbgetRecentTvPriority", PriorityType.Normal); }
set { SetValue("NzbgetRecentTvPriority", value); }
}
public PriorityType NzbgetOlderTvPriority
{
get { return GetValueEnum("NzbgetOlderTvPriority", PriorityType.Normal); }
set { SetValue("NzbgetOlderTvPriority", value); }
}
public string ReleaseRestrictions public string ReleaseRestrictions
{ {
get { return GetValue("ReleaseRestrictions", String.Empty).Trim('\r', '\n'); } get { return GetValue("ReleaseRestrictions", String.Empty).Trim('\r', '\n'); }

View File

@ -1,8 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Nzbget;
using NzbDrone.Core.Download.Clients.Sabnzbd;
namespace NzbDrone.Core.Configuration namespace NzbDrone.Core.Configuration
{ {
@ -10,42 +7,33 @@ namespace NzbDrone.Core.Configuration
{ {
IEnumerable<Config> All(); IEnumerable<Config> All();
Dictionary<String, Object> AllWithDefaults(); Dictionary<String, Object> AllWithDefaults();
String SabHost { get; set; } void SaveConfigDictionary(Dictionary<string, object> configValues);
int SabPort { get; set; }
String SabApiKey { get; set; } //Download Client
String SabUsername { get; set; }
String SabPassword { get; set; }
String SabTvCategory { get; set; }
SabPriorityType SabRecentTvPriority { get; set; }
SabPriorityType SabOlderTvPriority { get; set; }
Boolean SabUseSsl { get; set; }
String DownloadedEpisodesFolder { get; set; } String DownloadedEpisodesFolder { get; set; }
bool AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; }
int Retention { get; set; }
DownloadClientType DownloadClient { get; set; }
string BlackholeFolder { get; set; }
string PneumaticFolder { get; set; }
string RecycleBin { get; set; }
String NzbgetUsername { get; set; }
String NzbgetPassword { get; set; }
String NzbgetHost { get; set; }
Int32 NzbgetPort { get; set; }
String NzbgetTvCategory { get; set; }
PriorityType NzbgetRecentTvPriority { get; set; }
PriorityType NzbgetOlderTvPriority { get; set; }
string ReleaseRestrictions { get; set; }
Int32 RssSyncInterval { get; set; }
Boolean AutoDownloadPropers { get; set; }
String DownloadClientWorkingFolders { get; set; } String DownloadClientWorkingFolders { get; set; }
//Failed Download Handling (Download client)
Boolean AutoRedownloadFailed { get; set; } Boolean AutoRedownloadFailed { get; set; }
Boolean RemoveFailedDownloads { get; set; } Boolean RemoveFailedDownloads { get; set; }
Boolean EnableFailedDownloadHandling { get; set; } Boolean EnableFailedDownloadHandling { get; set; }
//Media Management
Boolean AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; }
String RecycleBin { get; set; }
Boolean AutoDownloadPropers { get; set; }
Boolean CreateEmptySeriesFolders { get; set; } Boolean CreateEmptySeriesFolders { get; set; }
void SaveValues(Dictionary<string, object> configValues);
//Permissions (Media Management)
Boolean SetPermissionsLinux { get; set; } Boolean SetPermissionsLinux { get; set; }
String FileChmod { get; set; } String FileChmod { get; set; }
String FolderChmod { get; set; } String FolderChmod { get; set; }
String ChownUser { get; set; } String ChownUser { get; set; }
String ChownGroup { get; set; } String ChownGroup { get; set; }
//Indexers
Int32 Retention { get; set; }
Int32 RssSyncInterval { get; set; }
String ReleaseRestrictions { get; set; }
} }
} }

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Web.UI.WebControls;
using NLog; using NLog;
using NzbDrone.Common.Cache; using NzbDrone.Common.Cache;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;

View File

@ -73,7 +73,7 @@ namespace NzbDrone.Core.Datastore
public TModel Get(int id) public TModel Get(int id)
{ {
var model = DataMapper.Query<TModel>().SingleOrDefault(c => c.Id == id); var model = Query.Where(c => c.Id == id).SingleOrDefault();
if (model == null) if (model == null)
{ {
@ -142,23 +142,44 @@ namespace NzbDrone.Core.Datastore
public void InsertMany(IList<TModel> models) public void InsertMany(IList<TModel> models)
{ {
foreach (var model in models) using (var unitOfWork = new UnitOfWork(() => DataMapper))
{ {
Insert(model); unitOfWork.BeginTransaction();
foreach (var model in models)
{
unitOfWork.DB.Insert(model);
}
unitOfWork.Commit();
} }
} }
public void UpdateMany(IList<TModel> models) public void UpdateMany(IList<TModel> models)
{ {
foreach (var model in models) using (var unitOfWork = new UnitOfWork(() => DataMapper))
{ {
Update(model); unitOfWork.BeginTransaction();
foreach (var model in models)
{
var localModel = model;
if (model.Id == 0)
{
throw new InvalidOperationException("Can't update model with ID 0");
}
unitOfWork.DB.Update(model, c => c.Id == localModel.Id);
}
unitOfWork.Commit();
} }
} }
public void DeleteMany(List<TModel> models) public void DeleteMany(List<TModel> models)
{ {
models.ForEach(Delete); DeleteMany(models.Select(m => m.Id));
} }
public TModel Upsert(TModel model) public TModel Upsert(TModel model)
@ -179,7 +200,19 @@ namespace NzbDrone.Core.Datastore
public void DeleteMany(IEnumerable<int> ids) public void DeleteMany(IEnumerable<int> ids)
{ {
ids.ToList().ForEach(Delete); using (var unitOfWork = new UnitOfWork(() => DataMapper))
{
unitOfWork.BeginTransaction();
foreach (var id in ids)
{
var localId = id;
unitOfWork.DB.Delete<TModel>(c => c.Id == localId);
}
unitOfWork.Commit();
}
} }
public void Purge() public void Purge()

View File

@ -0,0 +1,20 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(42)]
public class add_download_clients_table : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Create.TableForModel("DownloadClients")
.WithColumn("Enable").AsBoolean().NotNullable()
.WithColumn("Name").AsString().NotNullable()
.WithColumn("Implementation").AsString().NotNullable()
.WithColumn("Settings").AsString().NotNullable()
.WithColumn("ConfigContract").AsString().NotNullable()
.WithColumn("Protocol").AsInt32().NotNullable();
}
}
}

View File

@ -0,0 +1,197 @@
using System;
using System.Collections.Generic;
using System.Data;
using FluentMigrator;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(43)]
public class convert_config_to_download_clients : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Execute.WithConnection(ConvertToThingyProvder);
}
private void ConvertToThingyProvder(IDbConnection conn, IDbTransaction tran)
{
var config = new Dictionary<string, string>();
using (IDbCommand configCmd = conn.CreateCommand())
{
configCmd.Transaction = tran;
configCmd.CommandText = @"SELECT * FROM Config";
using (IDataReader configReader = configCmd.ExecuteReader())
{
var keyIndex = configReader.GetOrdinal("Key");
var valueIndex = configReader.GetOrdinal("Value");
while (configReader.Read())
{
var key = configReader.GetString(keyIndex);
var value = configReader.GetString(valueIndex);
config.Add(key.ToLowerInvariant(), value);
}
}
}
var client = GetConfigValue(config, "DownloadClient", "");
if (String.IsNullOrWhiteSpace(client))
{
return;
}
if (client.Equals("sabnzbd", StringComparison.InvariantCultureIgnoreCase))
{
var settings = new ClientSettingsForMigration
{
Host = GetConfigValue(config, "SabHost", "localhost"),
Port = GetConfigValue(config, "SabPort", 8080),
ApiKey = GetConfigValue(config, "SabApiKey", ""),
Username = GetConfigValue(config, "SabUsername", ""),
Password = GetConfigValue(config, "SabPassword", ""),
TvCategory = GetConfigValue(config, "SabTvCategory", "tv"),
RecentTvPriority = GetSabnzbdPriority(GetConfigValue(config, "NzbgetRecentTvPriority", "Default")),
OlderTvPriority = GetSabnzbdPriority(GetConfigValue(config, "NzbgetOlderTvPriority", "Default")),
UseSsl = GetConfigValue(config, "SabUseSsl", false)
};
AddDownloadClient(conn, tran, "Sabnzbd", "Sabnzbd", settings.ToJson(), "SabnzbdSettings", 1);
}
else if (client.Equals("nzbget", StringComparison.InvariantCultureIgnoreCase))
{
var settings = new ClientSettingsForMigration
{
Host = GetConfigValue(config, "NzbGetHost", "localhost"),
Port = GetConfigValue(config, "NzbgetPort", 6789),
Username = GetConfigValue(config, "NzbgetUsername", "nzbget"),
Password = GetConfigValue(config, "NzbgetPassword", ""),
TvCategory = GetConfigValue(config, "NzbgetTvCategory", "tv"),
RecentTvPriority = GetNzbgetPriority(GetConfigValue(config, "NzbgetRecentTvPriority", "Normal")),
OlderTvPriority = GetNzbgetPriority(GetConfigValue(config, "NzbgetOlderTvPriority", "Normal")),
};
AddDownloadClient(conn, tran, "Nzbget", "Nzbget", settings.ToJson(), "NzbgetSettings", 1);
}
else if (client.Equals("pneumatic", StringComparison.InvariantCultureIgnoreCase))
{
var settings = new FolderSettingsForMigration
{
Folder = GetConfigValue(config, "PneumaticFolder", "")
};
AddDownloadClient(conn, tran, "Pneumatic", "Pneumatic", settings.ToJson(), "FolderSettings", 1);
}
else if (client.Equals("blackhole", StringComparison.InvariantCultureIgnoreCase))
{
var settings = new FolderSettingsForMigration
{
Folder = GetConfigValue(config, "BlackholeFolder", "")
};
AddDownloadClient(conn, tran, "Blackhole", "Blackhole", settings.ToJson(), "FolderSettings", 1);
}
DeleteOldConfigValues(conn, tran);
}
private T GetConfigValue<T>(Dictionary<string, string> config, string key, T defaultValue)
{
key = key.ToLowerInvariant();
if (config.ContainsKey(key))
{
return (T) Convert.ChangeType(config[key], typeof (T));
}
return defaultValue;
}
private void AddDownloadClient(IDbConnection conn, IDbTransaction tran, string name, string implementation, string settings,
string configContract, int protocol)
{
using (IDbCommand updateCmd = conn.CreateCommand())
{
var text = String.Format("INSERT INTO DownloadClients (Enable, Name, Implementation, Settings, ConfigContract, Protocol) VALUES (1, ?, ?, ?, ?, ?)");
updateCmd.AddParameter(name);
updateCmd.AddParameter(implementation);
updateCmd.AddParameter(settings);
updateCmd.AddParameter(configContract);
updateCmd.AddParameter(protocol);
updateCmd.Transaction = tran;
updateCmd.CommandText = text;
updateCmd.ExecuteNonQuery();
}
}
private void DeleteOldConfigValues(IDbConnection conn, IDbTransaction tran)
{
using (IDbCommand updateCmd = conn.CreateCommand())
{
var text = "DELETE FROM Config WHERE [KEY] IN ('nzbgetusername', 'nzbgetpassword', 'nzbgethost', 'nzbgetport', " +
"'nzbgettvcategory', 'nzbgetrecenttvpriority', 'nzbgetoldertvpriority', 'sabhost', 'sabport', " +
"'sabapikey', 'sabusername', 'sabpassword', 'sabtvcategory', 'sabrecenttvpriority', " +
"'saboldertvpriority', 'sabusessl', 'downloadclient', 'blackholefolder', 'pneumaticfolder')";
updateCmd.Transaction = tran;
updateCmd.CommandText = text;
updateCmd.ExecuteNonQuery();
}
}
private int GetSabnzbdPriority(string priority)
{
return (int)Enum.Parse(typeof(SabnzbdPriorityForMigration), priority, true);
}
private int GetNzbgetPriority(string priority)
{
return (int)Enum.Parse(typeof(NzbGetPriorityForMigration), priority, true);
}
private class ClientSettingsForMigration
{
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; }
}
private class FolderSettingsForMigration
{
public String Folder { get; set; }
}
private enum SabnzbdPriorityForMigration
{
Default = -100,
Paused = -2,
Low = -1,
Normal = 0,
High = 1,
Force = 2
}
private enum NzbGetPriorityForMigration
{
VeryLow = -100,
Low = -50,
Normal = 0,
High = 50,
VeryHigh = 100
}
}
}

View File

@ -0,0 +1,27 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(44)]
public class fix_xbmc_episode_metadata : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
//Convert Episode Metadata to proper type
Execute.Sql("UPDATE MetadataFiles " +
"SET Type = 2 " +
"WHERE Consumer = 'XbmcMetadata' " +
"AND EpisodeFileId IS NOT NULL " +
"AND Type = 4 " +
"AND RelativePath LIKE '%.nfo'");
//Convert Episode Images to proper type
Execute.Sql("UPDATE MetadataFiles " +
"SET Type = 5 " +
"WHERE Consumer = 'XbmcMetadata' " +
"AND EpisodeFileId IS NOT NULL " +
"AND Type = 4");
}
}
}

View File

@ -7,6 +7,7 @@ using NzbDrone.Core.Blacklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.DataAugmentation.Scene; using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.Datastore.Converters; using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Download;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.Instrumentation; using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Jobs; using NzbDrone.Core.Jobs;
@ -39,6 +40,7 @@ namespace NzbDrone.Core.Datastore
Mapper.Entity<ScheduledTask>().RegisterModel("ScheduledTasks"); Mapper.Entity<ScheduledTask>().RegisterModel("ScheduledTasks");
Mapper.Entity<NotificationDefinition>().RegisterModel("Notifications"); Mapper.Entity<NotificationDefinition>().RegisterModel("Notifications");
Mapper.Entity<MetadataDefinition>().RegisterModel("Metadata"); Mapper.Entity<MetadataDefinition>().RegisterModel("Metadata");
Mapper.Entity<DownloadClientDefinition>().RegisterModel("DownloadClients");
Mapper.Entity<SceneMapping>().RegisterModel("SceneMappings"); Mapper.Entity<SceneMapping>().RegisterModel("SceneMappings");

View File

@ -23,7 +23,7 @@ namespace NzbDrone.Core.DecisionEngine
private readonly IParsingService _parsingService; private readonly IParsingService _parsingService;
private readonly Logger _logger; private readonly Logger _logger;
public DownloadDecisionMaker(IEnumerable<IRejectWithReason> specifications, IParsingService parsingService, Logger logger) public DownloadDecisionMaker(IEnumerable<IDecisionEngineSpecification> specifications, IParsingService parsingService, Logger logger)
{ {
_specifications = specifications; _specifications = specifications;
_parsingService = parsingService; _parsingService = parsingService;
@ -63,6 +63,15 @@ namespace NzbDrone.Core.DecisionEngine
{ {
var parsedEpisodeInfo = Parser.Parser.ParseTitle(report.Title); var parsedEpisodeInfo = Parser.Parser.ParseTitle(report.Title);
if (parsedEpisodeInfo == null || parsedEpisodeInfo.IsPossibleSpecialEpisode())
{
var specialEpisodeInfo = _parsingService.ParseSpecialEpisodeTitle(report.Title, report.TvRageId, searchCriteria);
if (specialEpisodeInfo != null)
{
parsedEpisodeInfo = specialEpisodeInfo;
}
}
if (parsedEpisodeInfo != null && !string.IsNullOrWhiteSpace(parsedEpisodeInfo.SeriesTitle)) if (parsedEpisodeInfo != null && !string.IsNullOrWhiteSpace(parsedEpisodeInfo.SeriesTitle))
{ {
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, report.TvRageId, searchCriteria); var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, report.TvRageId, searchCriteria);
@ -91,13 +100,12 @@ namespace NzbDrone.Core.DecisionEngine
yield return decision; yield return decision;
} }
} }
} }
private DownloadDecision GetDecisionForReport(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria = null) private DownloadDecision GetDecisionForReport(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria = null)
{ {
var reasons = _specifications.Select(c => EvaluateSpec(c, remoteEpisode, searchCriteria)) var reasons = _specifications.Select(c => EvaluateSpec(c, remoteEpisode, searchCriteria))
.Where(c => !string.IsNullOrWhiteSpace(c)); .Where(c => !string.IsNullOrWhiteSpace(c));
return new DownloadDecision(remoteEpisode, reasons.ToArray()); return new DownloadDecision(remoteEpisode, reasons.ToArray());
} }

View File

@ -1,6 +1,5 @@
using NLog; using NLog;
using NzbDrone.Core.Qualities; using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.DecisionEngine namespace NzbDrone.Core.DecisionEngine
{ {

View File

@ -27,7 +27,6 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria) public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
{ {
_logger.Trace("Beginning size check for: {0}", subject); _logger.Trace("Beginning size check for: {0}", subject);
var quality = subject.ParsedEpisodeInfo.Quality.Quality; var quality = subject.ParsedEpisodeInfo.Quality.Quality;
@ -45,34 +44,43 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
} }
var qualityDefinition = _qualityDefinitionService.Get(quality); var qualityDefinition = _qualityDefinitionService.Get(quality);
var minSize = qualityDefinition.MinSize.Megabytes();
//Multiply maxSize by Series.Runtime
minSize = minSize * subject.Series.Runtime * subject.Episodes.Count;
//If the parsed size is smaller than minSize we don't want it
if (subject.Release.Size < minSize)
{
_logger.Trace("Item: {0}, Size: {1} is smaller than minimum allowed size ({2}), rejecting.", subject, subject.Release.Size, minSize);
return false;
}
if (qualityDefinition.MaxSize == 0) if (qualityDefinition.MaxSize == 0)
{ {
_logger.Trace("Max size is 0 (unlimited) - skipping check."); _logger.Trace("Max size is 0 (unlimited) - skipping check.");
return true;
} }
else
var maxSize = qualityDefinition.MaxSize.Megabytes();
//Multiply maxSize by Series.Runtime
maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count;
//Check if there was only one episode parsed and it is the first
if (subject.Episodes.Count == 1 && subject.Episodes.First().EpisodeNumber == 1)
{ {
maxSize = maxSize * 2; var maxSize = qualityDefinition.MaxSize.Megabytes();
}
//If the parsed size is greater than maxSize we don't want it //Multiply maxSize by Series.Runtime
if (subject.Release.Size > maxSize) maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count;
{
_logger.Trace("Item: {0}, Size: {1} is greater than maximum allowed size ({2}), rejecting.", subject, subject.Release.Size, maxSize);
return false;
}
//Check if there was only one episode parsed and it is the first
if (subject.Episodes.Count == 1 && _episodeService.IsFirstOrLastEpisodeOfSeason(subject.Episodes.First().Id))
{
maxSize = maxSize * 2;
}
//If the parsed size is greater than maxSize we don't want it
if (subject.Release.Size > maxSize)
{
_logger.Trace("Item: {0}, Size: {1} is greater than maximum allowed size ({2}), rejecting.", subject, subject.Release.Size, maxSize);
return false;
}
}
_logger.Trace("Item: {0}, meets size constraints.", subject); _logger.Trace("Item: {0}, meets size constraints.", subject);
return true; return true;
} }
} }
} }

View File

@ -5,7 +5,6 @@ using NzbDrone.Core.Download;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities; using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.DecisionEngine.Specifications namespace NzbDrone.Core.DecisionEngine.Specifications
{ {
@ -32,9 +31,9 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
{ {
var downloadClient = _downloadClientProvider.GetDownloadClient(); var downloadClient = _downloadClientProvider.GetDownloadClient();
if (!downloadClient.IsConfigured) if (downloadClient == null)
{ {
_logger.Warn("Download client {0} isn't configured yet.", downloadClient.GetType().Name); _logger.Warn("Download client isn't configured yet.");
return true; return true;
} }

View File

@ -28,9 +28,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria) public virtual bool IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
{ {
var age = subject.Release.Age; var age = subject.Release.Age;
var retention = _configService.Retention;
_logger.Trace("Checking if report meets retention requirements. {0}", age); _logger.Trace("Checking if report meets retention requirements. {0}", age);
if (_configService.Retention > 0 && age > _configService.Retention) if (retention > 0 && age > retention)
{ {
_logger.Trace("Report age: {0} rejected by user's retention limit", age); _logger.Trace("Report age: {0} rejected by user's retention limit", age);
return false; return false;

View File

@ -41,7 +41,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
return true; return true;
} }
if (_downloadClientProvider.GetDownloadClient().GetType() == typeof (SabnzbdClient)) if (_downloadClientProvider.GetDownloadClient().GetType() == typeof (Sabnzbd))
{ {
_logger.Trace("Performing history status check on report"); _logger.Trace("Performing history status check on report");
foreach (var episode in subject.Episodes) foreach (var episode in subject.Episodes)

View File

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.IO;
using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Disk;
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.Trace("Downloading NZB from: {0} to: {1}", url, filename);
_httpProvider.DownloadFile(url, filename);
_logger.Trace("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 void Execute(TestBlackholeCommand message)
{
var testPath = Path.Combine(message.Folder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath);
}
}
}

View File

@ -0,0 +1,18 @@
using System;
using NzbDrone.Core.Messaging.Commands;
namespace NzbDrone.Core.Download.Clients.Blackhole
{
public class TestBlackholeCommand : Command
{
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
public String Folder { get; set; }
}
}

View File

@ -1,68 +0,0 @@
using System.Collections.Generic;
using System.IO;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Organizer;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Download.Clients
{
public class BlackholeProvider : IDownloadClient
{
private readonly IConfigService _configService;
private readonly IHttpProvider _httpProvider;
private readonly Logger _logger;
public BlackholeProvider(IConfigService configService, IHttpProvider httpProvider, Logger logger)
{
_configService = configService;
_httpProvider = httpProvider;
_logger = logger;
}
public string DownloadNzb(RemoteEpisode remoteEpisode)
{
var url = remoteEpisode.Release.DownloadUrl;
var title = remoteEpisode.Release.Title;
title = FileNameBuilder.CleanFilename(title);
var filename = Path.Combine(_configService.BlackholeFolder, title + ".nzb");
_logger.Trace("Downloading NZB from: {0} to: {1}", url, filename);
_httpProvider.DownloadFile(url, filename);
_logger.Trace("NZB Download succeeded, saved to: {0}", filename);
return null;
}
public bool IsConfigured
{
get
{
return !string.IsNullOrWhiteSpace(_configService.BlackholeFolder);
}
}
public IEnumerable<QueueItem> GetQueue()
{
return new QueueItem[0];
}
public IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0)
{
return new HistoryItem[0];
}
public void RemoveFromQueue(string id)
{
}
public void RemoveFromHistory(string id)
{
}
}
}

View File

@ -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
{
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);
}
}
}

View File

@ -4,11 +4,11 @@ using Newtonsoft.Json;
namespace NzbDrone.Core.Download.Clients.Nzbget namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
public class NzbGetQueue public class NzbgetQueue
{ {
public String Version { get; set; } public String Version { get; set; }
[JsonProperty(PropertyName = "result")] [JsonProperty(PropertyName = "result")]
public List<NzbGetQueueItem> QueueItems { get; set; } public List<NzbgetQueueItem> QueueItems { get; set; }
} }
} }

View File

@ -2,14 +2,11 @@
namespace NzbDrone.Core.Download.Clients.Nzbget namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
public class NzbGetQueueItem public class NzbgetQueueItem
{ {
private string _nzbName; private string _nzbName;
public Int32 NzbId { get; set; } public Int32 NzbId { get; set; }
public string NzbName { get; set; } public string NzbName { get; set; }
public String Category { get; set; } public String Category { get; set; }
public Int32 FileSizeMb { get; set; } public Int32 FileSizeMb { get; set; }
public Int32 RemainingSizeMb { get; set; } public Int32 RemainingSizeMb { get; set; }

View File

@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using NLog;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using Omu.ValueInjecter;
namespace NzbDrone.Core.Download.Clients.Nzbget
{
public class Nzbget : DownloadClientBase<NzbgetSettings>, IExecute<TestNzbgetCommand>
{
private readonly INzbgetProxy _proxy;
private readonly IParsingService _parsingService;
private readonly Logger _logger;
public Nzbget(INzbgetProxy proxy,
IParsingService parsingService,
Logger logger)
{
_proxy = proxy;
_parsingService = parsingService;
_logger = logger;
}
public override string DownloadNzb(RemoteEpisode remoteEpisode)
{
var url = remoteEpisode.Release.DownloadUrl;
var title = remoteEpisode.Release.Title + ".nzb";
string cat = Settings.TvCategory;
int priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority;
_logger.Info("Adding report [{0}] to the queue.", title);
var success = _proxy.AddNzb(Settings, title, cat, priority, false, url);
_logger.Debug("Queue Response: [{0}]", success);
return null;
}
public override IEnumerable<QueueItem> GetQueue()
{
var items = _proxy.GetQueue(Settings);
foreach (var nzbGetQueueItem in items)
{
var queueItem = new QueueItem();
queueItem.Id = nzbGetQueueItem.NzbId.ToString();
queueItem.Title = nzbGetQueueItem.NzbName;
queueItem.Size = nzbGetQueueItem.FileSizeMb;
queueItem.Sizeleft = nzbGetQueueItem.RemainingSizeMb;
queueItem.Status = nzbGetQueueItem.FileSizeMb == nzbGetQueueItem.PausedSizeMb ? "paused" : "queued";
var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title);
if (parsedEpisodeInfo == null) continue;
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0);
if (remoteEpisode.Series == null) continue;
queueItem.RemoteEpisode = remoteEpisode;
yield return queueItem;
}
}
public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10)
{
return new HistoryItem[0];
}
public override void RemoveFromQueue(string id)
{
throw new NotImplementedException();
}
public override void RemoveFromHistory(string id)
{
throw new NotImplementedException();
}
public VersionResponse GetVersion(string host = null, int port = 0, string username = null, string password = null)
{
return _proxy.GetVersion(Settings);
}
public void Execute(TestNzbgetCommand message)
{
var settings = new NzbgetSettings();
settings.InjectFrom(message);
_proxy.GetVersion(settings);
}
}
}

View File

@ -1,136 +0,0 @@
using System;
using System.Collections.Generic;
using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Download.Clients.Nzbget
{
public class NzbgetClient : IDownloadClient
{
private readonly IConfigService _configService;
private readonly IHttpProvider _httpProvider;
private readonly INzbGetCommunicationProxy _proxy;
private readonly IParsingService _parsingService;
private readonly Logger _logger;
public NzbgetClient(IConfigService configService,
IHttpProvider httpProvider,
INzbGetCommunicationProxy proxy,
IParsingService parsingService,
Logger logger)
{
_configService = configService;
_httpProvider = httpProvider;
_proxy = proxy;
_parsingService = parsingService;
_logger = logger;
}
public string DownloadNzb(RemoteEpisode remoteEpisode)
{
var url = remoteEpisode.Release.DownloadUrl;
var title = remoteEpisode.Release.Title + ".nzb";
string cat = _configService.NzbgetTvCategory;
int priority = remoteEpisode.IsRecentEpisode() ? (int)_configService.NzbgetRecentTvPriority : (int)_configService.NzbgetOlderTvPriority;
_logger.Info("Adding report [{0}] to the queue.", title);
var success = _proxy.AddNzb(title, cat, priority, false, url);
_logger.Debug("Queue Response: [{0}]", success);
return null;
}
public bool IsConfigured
{
get
{
return !string.IsNullOrWhiteSpace(_configService.NzbgetHost) && _configService.NzbgetPort != 0;
}
}
public virtual IEnumerable<QueueItem> GetQueue()
{
var items = _proxy.GetQueue();
foreach (var nzbGetQueueItem in items)
{
var queueItem = new QueueItem();
queueItem.Id = nzbGetQueueItem.NzbId.ToString();
queueItem.Title = nzbGetQueueItem.NzbName;
queueItem.Size = nzbGetQueueItem.FileSizeMb;
queueItem.Sizeleft = nzbGetQueueItem.RemainingSizeMb;
queueItem.Status = nzbGetQueueItem.FileSizeMb == nzbGetQueueItem.PausedSizeMb ? "paused" : "queued";
var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title);
if (parsedEpisodeInfo == null) continue;
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0);
if (remoteEpisode.Series == null) continue;
queueItem.RemoteEpisode = remoteEpisode;
yield return queueItem;
}
}
public IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0)
{
return new HistoryItem[0];
}
public void RemoveFromQueue(string id)
{
throw new NotImplementedException();
}
public void RemoveFromHistory(string id)
{
throw new NotImplementedException();
}
public virtual VersionModel GetVersion(string host = null, int port = 0, string username = null, string password = null)
{
throw new NotImplementedException();
//Get saved values if any of these are defaults
if (host == null)
host = _configService.NzbgetHost;
if (port == 0)
port = _configService.NzbgetPort;
if (username == null)
username = _configService.NzbgetUsername;
if (password == null)
password = _configService.NzbgetPassword;
var response = _proxy.GetVersion();
return Json.Deserialize<VersionModel>(response);
}
public virtual string Test(string host, int port, string username, string password)
{
try
{
var version = GetVersion(host, port, username, password);
return version.Result;
}
catch (Exception ex)
{
_logger.DebugException("Failed to Test Nzbget", ex);
}
return String.Empty;
}
}
}

View File

@ -1,6 +1,6 @@
namespace NzbDrone.Core.Download.Clients.Nzbget namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
public enum PriorityType public enum NzbgetPriority
{ {
VeryLow = -100, VeryLow = -100,
Low = -50, Low = -50,

View File

@ -1,57 +1,52 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using NLog; using NLog;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Rest; using NzbDrone.Core.Rest;
using RestSharp; using RestSharp;
namespace NzbDrone.Core.Download.Clients.Nzbget namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
public interface INzbGetCommunicationProxy public interface INzbgetProxy
{ {
bool AddNzb(params object[] parameters); bool AddNzb(NzbgetSettings settings, params object[] parameters);
List<NzbGetQueueItem> GetQueue(); List<NzbgetQueueItem> GetQueue(NzbgetSettings settings);
string GetVersion(); VersionResponse GetVersion(NzbgetSettings settings);
} }
public class NzbGetCommunicationProxy : INzbGetCommunicationProxy public class NzbgetProxy : INzbgetProxy
{ {
private readonly IConfigService _configService;
private readonly Logger _logger; private readonly Logger _logger;
public NzbGetCommunicationProxy(IConfigService configService, Logger logger) public NzbgetProxy(Logger logger)
{ {
_configService = configService;
_logger = logger; _logger = logger;
} }
public bool AddNzb(params object[] parameters) public bool AddNzb(NzbgetSettings settings, params object[] parameters)
{ {
var request = BuildRequest(new JsonRequest("appendurl", parameters)); var request = BuildRequest(new JsonRequest("appendurl", parameters));
return Json.Deserialize<EnqueueResponse>(ProcessRequest(request)).Result; return Json.Deserialize<EnqueueResponse>(ProcessRequest(request, settings)).Result;
} }
public List<NzbGetQueueItem> GetQueue() public List<NzbgetQueueItem> GetQueue(NzbgetSettings settings)
{ {
var request = BuildRequest(new JsonRequest("listgroups")); var request = BuildRequest(new JsonRequest("listgroups"));
return Json.Deserialize<NzbGetQueue>(ProcessRequest(request)).QueueItems; return Json.Deserialize<NzbgetQueue>(ProcessRequest(request, settings)).QueueItems;
} }
public string GetVersion() public VersionResponse GetVersion(NzbgetSettings settings)
{ {
var request = BuildRequest(new JsonRequest("version")); var request = BuildRequest(new JsonRequest("version"));
return ProcessRequest(request); return Json.Deserialize<VersionResponse>(ProcessRequest(request, settings));
} }
private string ProcessRequest(IRestRequest restRequest) private string ProcessRequest(IRestRequest restRequest, NzbgetSettings settings)
{ {
var client = BuildClient(); var client = BuildClient(settings);
var response = client.Execute(restRequest); var response = client.Execute(restRequest);
_logger.Trace("Response: {0}", response.Content); _logger.Trace("Response: {0}", response.Content);
@ -60,14 +55,14 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
return response.Content; return response.Content;
} }
private IRestClient BuildClient() private IRestClient BuildClient(NzbgetSettings settings)
{ {
var url = String.Format("http://{0}:{1}/jsonrpc", var url = String.Format("http://{0}:{1}/jsonrpc",
_configService.NzbgetHost, settings.Host,
_configService.NzbgetPort); settings.Port);
var client = new RestClient(url); var client = new RestClient(url);
client.Authenticator = new HttpBasicAuthenticator(_configService.NzbgetUsername, _configService.NzbgetPassword); client.Authenticator = new HttpBasicAuthenticator(settings.Username, settings.Password);
return client; return client;
} }

View File

@ -0,0 +1,59 @@
using System;
using FluentValidation;
using FluentValidation.Results;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Download.Clients.Nzbget
{
public class NzbgetSettingsValidator : AbstractValidator<NzbgetSettings>
{
public NzbgetSettingsValidator()
{
RuleFor(c => c.Host).NotEmpty();
RuleFor(c => c.Port).GreaterThan(0);
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.Password).NotEmpty();
}
}
public class NzbgetSettings : IProviderConfig
{
private static readonly NzbgetSettingsValidator Validator = new NzbgetSettingsValidator();
public NzbgetSettings()
{
Host = "localhost";
Port = 6789;
TvCategory = "tv";
RecentTvPriority = (int)NzbgetPriority.Normal;
OlderTvPriority = (int)NzbgetPriority.Normal;
}
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
public String Host { get; set; }
[FieldDefinition(1, Label = "Port", Type = FieldType.Textbox)]
public Int32 Port { get; set; }
[FieldDefinition(2, Label = "Username", Type = FieldType.Textbox)]
public String Username { get; set; }
[FieldDefinition(3, Label = "Password", Type = FieldType.Password)]
public String Password { get; set; }
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox)]
public String TvCategory { get; set; }
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority))]
public Int32 RecentTvPriority { get; set; }
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority))]
public Int32 OlderTvPriority { get; set; }
public ValidationResult Validate()
{
return Validator.Validate(this);
}
}
}

View File

@ -0,0 +1,21 @@
using System;
using NzbDrone.Core.Messaging.Commands;
namespace NzbDrone.Core.Download.Clients.Nzbget
{
public class TestNzbgetCommand : Command
{
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
public String Host { get; set; }
public Int32 Port { get; set; }
public String Username { get; set; }
public String Password { get; set; }
}
}

View File

@ -2,7 +2,7 @@
namespace NzbDrone.Core.Download.Clients.Nzbget namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
public class VersionModel public class VersionResponse
{ {
public String Version { get; set; } public String Version { get; set; }
public String Result { get; set; } public String Result { get; set; }

View File

@ -6,12 +6,13 @@ using NzbDrone.Common;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Instrumentation;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Organizer; using NzbDrone.Core.Organizer;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Download.Clients namespace NzbDrone.Core.Download.Clients.Pneumatic
{ {
public class PneumaticClient : IDownloadClient public class Pneumatic : DownloadClientBase<FolderSettings>, IExecute<TestPneumaticCommand>
{ {
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly IHttpProvider _httpProvider; private readonly IHttpProvider _httpProvider;
@ -19,7 +20,7 @@ namespace NzbDrone.Core.Download.Clients
private static readonly Logger logger = NzbDroneLogger.GetLogger(); private static readonly Logger logger = NzbDroneLogger.GetLogger();
public PneumaticClient(IConfigService configService, IHttpProvider httpProvider, public Pneumatic(IConfigService configService, IHttpProvider httpProvider,
IDiskProvider diskProvider) IDiskProvider diskProvider)
{ {
_configService = configService; _configService = configService;
@ -27,20 +28,20 @@ namespace NzbDrone.Core.Download.Clients
_diskProvider = diskProvider; _diskProvider = diskProvider;
} }
public string DownloadNzb(RemoteEpisode remoteEpisode) public override string DownloadNzb(RemoteEpisode remoteEpisode)
{ {
var url = remoteEpisode.Release.DownloadUrl; var url = remoteEpisode.Release.DownloadUrl;
var title = remoteEpisode.Release.Title; var title = remoteEpisode.Release.Title;
if (remoteEpisode.ParsedEpisodeInfo.FullSeason) if (remoteEpisode.ParsedEpisodeInfo.FullSeason)
{ {
throw new NotImplementedException("Full season Pneumatic releases are not supported."); throw new NotImplementedException("Full season releases are not supported with Pneumatic.");
} }
title = FileNameBuilder.CleanFilename(title); title = FileNameBuilder.CleanFilename(title);
//Save to the Pneumatic directory (The user will need to ensure its accessible by XBMC) //Save to the Pneumatic directory (The user will need to ensure its accessible by XBMC)
var filename = Path.Combine(_configService.PneumaticFolder, title + ".nzb"); var filename = Path.Combine(Settings.Folder, title + ".nzb");
logger.Trace("Downloading NZB from: {0} to: {1}", url, filename); logger.Trace("Downloading NZB from: {0} to: {1}", url, filename);
_httpProvider.DownloadFile(url, filename); _httpProvider.DownloadFile(url, filename);
@ -57,31 +58,33 @@ namespace NzbDrone.Core.Download.Clients
{ {
get get
{ {
return !string.IsNullOrWhiteSpace(_configService.PneumaticFolder); return !string.IsNullOrWhiteSpace(Settings.Folder);
} }
} }
public IEnumerable<QueueItem> GetQueue() public override IEnumerable<QueueItem> GetQueue()
{ {
return new QueueItem[0]; return new QueueItem[0];
} }
public IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0) public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10)
{ {
return new HistoryItem[0]; return new HistoryItem[0];
} }
public void RemoveFromQueue(string id) public override void RemoveFromQueue(string id)
{ {
} }
public void RemoveFromHistory(string id) public override void RemoveFromHistory(string id)
{ {
} }
public virtual bool IsInQueue(RemoteEpisode newEpisode) public void Execute(TestPneumaticCommand message)
{ {
return false; var testPath = Path.Combine(message.Folder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath);
} }
} }
} }

View File

@ -0,0 +1,18 @@
using System;
using NzbDrone.Core.Messaging.Commands;
namespace NzbDrone.Core.Download.Clients.Pneumatic
{
public class TestPneumaticCommand : Command
{
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
public String Folder { get; set; }
}
}

View File

@ -1,8 +0,0 @@
namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
public class ConnectionInfoModel
{
public string Address { get; set; }
public int Port { get; set; }
}
}

View File

@ -7,7 +7,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd.JsonConverters
{ {
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
var priorityType = (SabPriorityType)value; var priorityType = (SabnzbdPriority)value;
writer.WriteValue(priorityType.ToString()); writer.WriteValue(priorityType.ToString());
} }
@ -15,7 +15,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd.JsonConverters
{ {
var queuePriority = reader.Value.ToString(); var queuePriority = reader.Value.ToString();
SabPriorityType output; SabnzbdPriority output;
Enum.TryParse(queuePriority, out output); Enum.TryParse(queuePriority, out output);
return output; return output;
@ -23,7 +23,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd.JsonConverters
public override bool CanConvert(Type objectType) public override bool CanConvert(Type objectType)
{ {
return objectType == typeof(SabPriorityType); return objectType == typeof(SabnzbdPriority);
} }
} }
} }

View File

@ -0,0 +1,18 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace NzbDrone.Core.Download.Clients.Sabnzbd.Responses
{
public class SabnzbdAddResponse
{
public SabnzbdAddResponse()
{
Ids = new List<string>();
}
public bool Status { get; set; }
[JsonProperty(PropertyName = "nzo_ids")]
public List<string> Ids { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
namespace NzbDrone.Core.Download.Clients.Sabnzbd.Responses
{
public class SabnzbdCategoryResponse
{
public SabnzbdCategoryResponse()
{
Categories = new List<String>();
}
public List<String> Categories { get; set; }
}
}

View File

@ -0,0 +1,7 @@
namespace NzbDrone.Core.Download.Clients.Sabnzbd.Responses
{
public class SabnzbdVersionResponse
{
public string Version { get; set; }
}
}

View File

@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
public class SabAddResponse
{
public SabAddResponse()
{
Ids = new List<String>();
}
public bool Status { get; set; }
[JsonProperty(PropertyName = "nzo_ids")]
public List<String> Ids { get; set; }
}
}

View File

@ -1,100 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Common.Instrumentation;
namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
public class SabAutoConfigureService
{
private static readonly Logger Logger = NzbDroneLogger.GetLogger();
public SabModel AutoConfigureSab()
{
var info = GetConnectionList();
return FindApiKey(info);
}
private List<ConnectionInfoModel> GetConnectionList()
{
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
var info =
ipProperties.GetActiveTcpListeners().Select(
p =>
new ConnectionInfoModel { Address = p.Address.ToString().Replace("0.0.0.0", "127.0.0.1"), Port = p.Port }).Distinct().
ToList();
info.RemoveAll(i => i.Port == 135);
info.RemoveAll(i => i.Port == 139);
info.RemoveAll(i => i.Port == 445);
info.RemoveAll(i => i.Port == 3389);
info.RemoveAll(i => i.Port == 5900);
info.RemoveAll(i => i.Address.Contains("::"));
info.Reverse();
return info;
}
private SabModel FindApiKey(List<ConnectionInfoModel> info)
{
foreach (var connection in info)
{
var apiKey = GetApiKey(connection.Address, connection.Port);
if (!String.IsNullOrEmpty(apiKey))
return new SabModel
{
Host = connection.Address,
Port = connection.Port,
ApiKey = apiKey
};
}
return null;
}
private string GetApiKey(string ipAddress, int port)
{
var request = String.Format("http://{0}:{1}/config/general/", ipAddress, port);
var result = DownloadString(request);
Regex regex =
new Regex("\\<input\\Wtype\\=\\\"text\\\"\\Wid\\=\\\"apikey\\\"\\Wvalue\\=\\\"(?<apikey>\\w+)\\W",
RegexOptions.IgnoreCase
| RegexOptions.Compiled);
var match = regex.Match(result);
if (match.Success)
{
return match.Groups["apikey"].Value;
}
return String.Empty;
}
private string DownloadString(string url)
{
try
{
var request = WebRequest.Create(url);
request.Timeout = 2000;
var response = request.GetResponse();
var reader = new StreamReader(response.GetResponseStream());
return reader.ReadToEnd();
}
catch (Exception ex)
{
Logger.Trace("Failed to get response from: {0}", url);
Logger.Trace(ex.Message, ex);
}
return String.Empty;
}
}
}

View File

@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
public class SabCategoryModel
{
public List<string> categories { get; set; }
}
}

View File

@ -1,130 +0,0 @@
using System;
using System.IO;
using NLog;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Configuration;
using RestSharp;
namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
public interface ISabCommunicationProxy
{
SabAddResponse DownloadNzb(Stream nzb, string name, string category, int priority);
void RemoveFrom(string source, string id);
string ProcessRequest(IRestRequest restRequest, string action);
}
public class SabCommunicationProxy : ISabCommunicationProxy
{
private readonly IConfigService _configService;
private readonly Logger _logger;
public SabCommunicationProxy(IConfigService configService, Logger logger)
{
_configService = configService;
_logger = logger;
}
public SabAddResponse DownloadNzb(Stream nzb, string title, string category, int priority)
{
var request = new RestRequest(Method.POST);
var action = String.Format("mode=addfile&cat={0}&priority={1}", category, priority);
request.AddFile("name", ReadFully(nzb), title, "application/x-nzb");
SabAddResponse response;
if (!Json.TryDeserialize<SabAddResponse>(ProcessRequest(request, action), out response))
{
response = new SabAddResponse();
response.Status = true;
}
return response;
}
public void RemoveFrom(string source, string id)
{
var request = new RestRequest();
var action = String.Format("mode={0}&name=delete&del_files=1&value={1}", source, id);
ProcessRequest(request, action);
}
public string ProcessRequest(IRestRequest restRequest, string action)
{
var client = BuildClient(action);
var response = client.Execute(restRequest);
_logger.Trace("Response: {0}", response.Content);
CheckForError(response);
return response.Content;
}
private IRestClient BuildClient(string action)
{
var protocol = _configService.SabUseSsl ? "https" : "http";
var url = string.Format(@"{0}://{1}:{2}/api?{3}&apikey={4}&ma_username={5}&ma_password={6}&output=json",
protocol,
_configService.SabHost,
_configService.SabPort,
action,
_configService.SabApiKey,
_configService.SabUsername,
_configService.SabPassword);
_logger.Trace(url);
return new RestClient(url);
}
private void CheckForError(IRestResponse response)
{
if (response.ResponseStatus != ResponseStatus.Completed)
{
throw new ApplicationException("Unable to connect to SABnzbd, please check your settings");
}
SabJsonError result;
if (!Json.TryDeserialize<SabJsonError>(response.Content, out result))
{
//Handle plain text responses from SAB
result = new SabJsonError();
if (response.Content.StartsWith("error", StringComparison.InvariantCultureIgnoreCase))
{
result.Status = "false";
result.Error = response.Content.Replace("error: ", "");
}
else
{
result.Status = "true";
}
result.Error = response.Content.Replace("error: ", "");
}
if (result.Failed)
throw new ApplicationException(result.Error);
}
//TODO: Find a better home for this
private byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
}
}

View File

@ -1,9 +0,0 @@
namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
public class SabModel
{
public string Host { get; set; }
public int Port { get; set; }
public string ApiKey { get; set; }
}
}

View File

@ -1,7 +0,0 @@
namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
public class SabVersionModel
{
public string Version { get; set; }
}
}

Some files were not shown because too many files have changed in this diff Show More