Merge branch 'develop'
Conflicts: NzbDrone.Core/Tv/SeasonService.cs NzbDrone.Integration.Test/EpisodeIntegrationTests.cs NzbDrone.Integration.Test/SeasonIntegrationTests.cs
This commit is contained in:
commit
08203b1f6f
|
@ -149,7 +149,11 @@ namespace Exceptron.Client
|
|||
SetHttpInfo(exceptionData, report);
|
||||
SetEnviromentInfo(report);
|
||||
|
||||
return RestClient.Put<ExceptionResponse>(Configuration.Host, report);
|
||||
var exceptionResponse = RestClient.Put<ExceptionResponse>(Configuration.Host, report);
|
||||
|
||||
exceptionData.Exception.Data["et"] = exceptionResponse.RefId;
|
||||
|
||||
return exceptionResponse;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
<Reference Include="FizzWare.NBuilder">
|
||||
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions, Version=2.0.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentAssertions.2.0.1\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Moq">
|
||||
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="2.0.1" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="2.1.0.0" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="NBuilder" version="3.0.1.1" targetFramework="net40" />
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net40" />
|
||||
<package id="valueinjecter" version="2.3.3" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
</packages>
|
|
@ -25,7 +25,7 @@ namespace NzbDrone.Api.Frontend.Mappers
|
|||
|
||||
public override bool CanHandle(string resourceUrl)
|
||||
{
|
||||
return resourceUrl.StartsWith("/Content") || resourceUrl.EndsWith(".js") || resourceUrl.EndsWith(".css");
|
||||
return resourceUrl.StartsWith("/Content") || resourceUrl.EndsWith(".js") || resourceUrl.EndsWith(".css") || resourceUrl.EndsWith(".ico");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -164,6 +164,7 @@
|
|||
<Compile Include="System\SystemModule.cs" />
|
||||
<Compile Include="TinyIoCNancyBootstrapper.cs" />
|
||||
<Compile Include="Update\UpdateModule.cs" />
|
||||
<Compile Include="Validation\PathValidator.cs" />
|
||||
<Compile Include="Validation\RuleBuilderExtensions.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Api.Validation;
|
||||
|
||||
namespace NzbDrone.Api.RootFolders
|
||||
{
|
||||
|
@ -17,6 +18,8 @@ namespace NzbDrone.Api.RootFolders
|
|||
GetResourceById = GetRootFolder;
|
||||
CreateResource = CreateRootFolder;
|
||||
DeleteResource = DeleteFolder;
|
||||
|
||||
SharedValidator.RuleFor(c=>c.Path).IsValidPath();
|
||||
}
|
||||
|
||||
private RootFolderResource GetRootFolder(int id)
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace NzbDrone.Api.RootFolders
|
|||
public class RootFolderResource : RestResource
|
||||
{
|
||||
public String Path { get; set; }
|
||||
public Int64 FreeSpace { get; set; }
|
||||
public Int64? FreeSpace { get; set; }
|
||||
|
||||
public List<UnmappedFolder> UnmappedFolders { get; set; }
|
||||
}
|
||||
|
|
|
@ -31,10 +31,10 @@ namespace NzbDrone.Api.Series
|
|||
|
||||
SharedValidator.RuleFor(s => s.QualityProfileId).ValidId();
|
||||
|
||||
PutValidator.RuleFor(s => s.Path).NotEmpty();
|
||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||
|
||||
PostValidator.RuleFor(s => s.Path).NotEmpty().When(s => String.IsNullOrEmpty(s.RootFolderPath));
|
||||
PostValidator.RuleFor(s => s.RootFolderPath).NotEmpty().When(s => String.IsNullOrEmpty(s.Path));
|
||||
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => String.IsNullOrEmpty(s.RootFolderPath));
|
||||
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => String.IsNullOrEmpty(s.Path));
|
||||
PostValidator.RuleFor(s => s.Title).NotEmpty();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Update;
|
||||
using NzbDrone.Api.Mapping;
|
||||
|
@ -32,7 +33,13 @@ namespace NzbDrone.Api.Update
|
|||
|
||||
public class UpdateResource : RestResource
|
||||
{
|
||||
public String Id { get; set; }
|
||||
|
||||
[JsonConverter(typeof(Newtonsoft.Json.Converters.VersionConverter))]
|
||||
public Version Version { get; set; }
|
||||
|
||||
public String Branch { get; set; }
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
public String FileName { get; set; }
|
||||
public String Url { get; set; }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
using FluentValidation.Validators;
|
||||
using NzbDrone.Common;
|
||||
|
||||
namespace NzbDrone.Api.Validation
|
||||
{
|
||||
public class PathValidator : PropertyValidator
|
||||
{
|
||||
public PathValidator()
|
||||
: base("Invalid Path")
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool IsValid(PropertyValidatorContext context)
|
||||
{
|
||||
if (context.PropertyValue == null) return false;
|
||||
return context.PropertyValue.ToString().IsPathValid();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
using System.Text.RegularExpressions;
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Validators;
|
||||
|
||||
|
@ -20,5 +22,10 @@ namespace NzbDrone.Api.Validation
|
|||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,9 +37,9 @@
|
|||
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions, Version=2.0.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentAssertions.2.0.1\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Moq">
|
||||
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="2.0.1" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="2.1.0.0" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="NBuilder" version="3.0.1.1" />
|
||||
<package id="NLog" version="2.0.1.2" targetFramework="net40" />
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Common.Test.DiskProviderTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class IsParentFixture : TestBase<DiskProvider>
|
||||
{
|
||||
private string _parent = @"C:\Test".AsOsAgnostic();
|
||||
|
||||
[Test]
|
||||
public void should_return_false_when_not_a_child()
|
||||
{
|
||||
var path = @"C:\Another Folder".AsOsAgnostic();
|
||||
|
||||
Subject.IsParent(_parent, path).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_folder_is_parent_of_another_folder()
|
||||
{
|
||||
var path = @"C:\Test\TV".AsOsAgnostic();
|
||||
|
||||
Subject.IsParent(_parent, path).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_folder_is_parent_of_a_file()
|
||||
{
|
||||
var path = @"C:\Test\30.Rock.S01E01.Pilot.avi".AsOsAgnostic();
|
||||
|
||||
Subject.IsParent(_parent, path).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
@ -9,32 +6,38 @@ using NzbDrone.Test.Common;
|
|||
namespace NzbDrone.Common.Test.DiskProviderTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class IsParentFixture : TestBase<DiskProvider>
|
||||
public class FreeSpaceFixture : TestBase<DiskProvider>
|
||||
{
|
||||
private string _parent = @"C:\Test".AsOsAgnostic();
|
||||
|
||||
[Test]
|
||||
public void should_return_false_when_not_a_child()
|
||||
public void should_get_free_space_for_folder()
|
||||
{
|
||||
var path = @"C:\Another Folder".AsOsAgnostic();
|
||||
var path = @"C:\".AsOsAgnostic();
|
||||
|
||||
Subject.IsParent(_parent, path).Should().BeFalse();
|
||||
Subject.GetAvailableSpace(path).Should().NotBe(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_folder_is_parent_of_another_folder()
|
||||
public void should_get_free_space_for_folder_that_doesnt_exist()
|
||||
{
|
||||
var path = @"C:\Test\TV".AsOsAgnostic();
|
||||
var path = @"C:\".AsOsAgnostic();
|
||||
|
||||
Subject.IsParent(_parent, path).Should().BeTrue();
|
||||
Subject.GetAvailableSpace(Path.Combine(path, "invalidFolder")).Should().NotBe(0);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_get_free_space_for_drive_that_doesnt_exist()
|
||||
{
|
||||
WindowsOnly();
|
||||
|
||||
Assert.Throws<DirectoryNotFoundException>(() => Subject.GetAvailableSpace("J:\\").Should().NotBe(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_when_folder_is_parent_of_a_file()
|
||||
public void should_be_able_to_check_space_on_ramdrive()
|
||||
{
|
||||
var path = @"C:\Test\30.Rock.S01E01.Pilot.avi".AsOsAgnostic();
|
||||
|
||||
Subject.IsParent(_parent, path).Should().BeTrue();
|
||||
LinuxOnly();
|
||||
Subject.GetAvailableSpace("/run/").Should().NotBe(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,9 +34,9 @@
|
|||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="FluentAssertions, Version=2.0.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentAssertions.2.0.1\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Moq">
|
||||
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||
|
@ -62,6 +62,7 @@
|
|||
<Compile Include="CacheTests\CachedManagerFixture.cs" />
|
||||
<Compile Include="CacheTests\CachedFixture.cs" />
|
||||
<Compile Include="ConfigFileProviderTest.cs" />
|
||||
<Compile Include="DiskProviderTests\FreeSpaceFixture.cs" />
|
||||
<Compile Include="DiskProviderTests\IsParentFixture.cs" />
|
||||
<Compile Include="EnsureTest\PathExtensionFixture.cs" />
|
||||
<Compile Include="EnvironmentTests\StartupArgumentsFixture.cs" />
|
||||
|
|
|
@ -102,10 +102,18 @@ namespace NzbDrone.Common.Test
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void get_actual_casing_for_none_existing_file_should_throw()
|
||||
public void get_actual_casing_for_none_existing_file_return_partially_fixed_result()
|
||||
{
|
||||
WindowsOnly();
|
||||
Assert.Throws<DirectoryNotFoundException>(() => "C:\\InValidFolder\\invalidfile.exe".GetActualCasing());
|
||||
"C:\\WINDOWS\\invalidfile.exe".GetActualCasing().Should().Be("C:\\Windows\\invalidfile.exe");
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void get_actual_casing_for_none_existing_folder_return_partially_fixed_result()
|
||||
{
|
||||
WindowsOnly();
|
||||
"C:\\WINDOWS\\SYSTEM32\\FAKEFOLDER\\invalidfile.exe".GetActualCasing().Should().Be("C:\\Windows\\System32\\FAKEFOLDER\\invalidfile.exe");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -117,14 +125,7 @@ namespace NzbDrone.Common.Test
|
|||
path.ToLower().GetActualCasing().Should().Be(path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void get_actual_casing_should_return_origibal_value_in_linux()
|
||||
{
|
||||
LinuxOnly();
|
||||
var path = Process.GetCurrentProcess().MainModule.FileName;
|
||||
path.GetActualCasing().Should().Be(path);
|
||||
path.GetActualCasing().Should().Be(path);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void get_actual_casing_should_return_actual_casing_for_local_dir_in_windows()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="2.0.1" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="2.1.0.0" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="NLog" version="2.0.1.2" targetFramework="net40" />
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net40" />
|
||||
|
|
|
@ -17,7 +17,6 @@ namespace NzbDrone.Common
|
|||
DateTime GetLastFolderWrite(string path);
|
||||
DateTime GetLastFileWrite(string path);
|
||||
void EnsureFolder(string path);
|
||||
bool FolderExists(string path, bool caseSensitive);
|
||||
bool FolderExists(string path);
|
||||
bool FileExists(string path);
|
||||
bool FileExists(string path, bool caseSensitive);
|
||||
|
@ -32,7 +31,7 @@ namespace NzbDrone.Common
|
|||
void MoveFile(string source, string destination);
|
||||
void DeleteFolder(string path, bool recursive);
|
||||
void InheritFolderPermissions(string filename);
|
||||
long GetAvilableSpace(string path);
|
||||
long? GetAvailableSpace(string path);
|
||||
string ReadAllText(string filePath);
|
||||
void WriteAllText(string filename, string contents);
|
||||
void FileSetLastWriteTimeUtc(string path, DateTime dateTime);
|
||||
|
@ -113,16 +112,6 @@ namespace NzbDrone.Common
|
|||
return Directory.Exists(path);
|
||||
}
|
||||
|
||||
public bool FolderExists(string path, bool caseSensitive)
|
||||
{
|
||||
if (caseSensitive)
|
||||
{
|
||||
return FolderExists(path) && path == path.GetActualCasing();
|
||||
}
|
||||
|
||||
return FolderExists(path);
|
||||
}
|
||||
|
||||
public bool FileExists(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
@ -289,27 +278,38 @@ namespace NzbDrone.Common
|
|||
File.SetAccessControl(filename, fs);
|
||||
}
|
||||
|
||||
public long GetAvilableSpace(string path)
|
||||
public long? GetAvailableSpace(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
if (OsInfo.IsLinux)
|
||||
{
|
||||
var driveInfo = DriveInfo.GetDrives().SingleOrDefault(c => c.IsReady && path.StartsWith(c.Name, StringComparison.CurrentCultureIgnoreCase));
|
||||
|
||||
if (driveInfo == null)
|
||||
{
|
||||
throw new DirectoryNotFoundException(path);
|
||||
}
|
||||
|
||||
return driveInfo.AvailableFreeSpace;
|
||||
}
|
||||
|
||||
var root = GetPathRoot(path);
|
||||
|
||||
if (!FolderExists(root))
|
||||
throw new DirectoryNotFoundException(root);
|
||||
|
||||
if (OsInfo.IsLinux)
|
||||
{
|
||||
var drives = DriveInfo.GetDrives();
|
||||
|
||||
foreach (var drive in drives)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (drive.IsReady && path.StartsWith(drive.Name, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return drive.AvailableFreeSpace;
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
Logger.ErrorException("Couldn't get free space for " + path, e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return DriveFreeSpaceEx(root);
|
||||
}
|
||||
|
||||
|
|
|
@ -95,8 +95,7 @@ namespace NzbDrone.Common.EnsureThat
|
|||
return param;
|
||||
}
|
||||
|
||||
private static readonly Regex windowsInvalidPathRegex = new Regex(@"[/*<>""|]", RegexOptions.Compiled);
|
||||
private static readonly Regex windowsPathRegex = new Regex(@"^[a-zA-Z]:\\", RegexOptions.Compiled);
|
||||
|
||||
|
||||
[DebuggerStepThrough]
|
||||
public static Param<string> IsValidPath(this Param<string> param)
|
||||
|
@ -104,31 +103,14 @@ namespace NzbDrone.Common.EnsureThat
|
|||
if (string.IsNullOrWhiteSpace(param.Value))
|
||||
throw ExceptionFactory.CreateForParamValidation(param.Name, ExceptionMessages.EnsureExtensions_IsNotNullOrWhiteSpace);
|
||||
|
||||
if (param.Value.IsPathValid()) return param;
|
||||
|
||||
if (OsInfo.IsLinux)
|
||||
{
|
||||
if (!param.Value.StartsWith(Path.DirectorySeparatorChar.ToString()))
|
||||
{
|
||||
throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid *nix path. paths must start with /", param.Value));
|
||||
}
|
||||
throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid *nix path. paths must start with /", param.Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (windowsInvalidPathRegex.IsMatch(param.Value))
|
||||
{
|
||||
throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid Windows path. It contains invalid characters", param.Value));
|
||||
}
|
||||
|
||||
//Network path
|
||||
if (param.Value.StartsWith(Path.DirectorySeparatorChar.ToString())) return param;
|
||||
|
||||
if (!windowsPathRegex.IsMatch(param.Value))
|
||||
{
|
||||
throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid Windows path. paths must be a full path eg. C:\\Windows", param.Value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return param;
|
||||
|
||||
throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid Windows path. paths must be a full path eg. C:\\Windows", param.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
<Compile Include="Instrumentation\GlobalExceptionHandlers.cs" />
|
||||
<Compile Include="Instrumentation\ExceptronTarget.cs" />
|
||||
<Compile Include="PathEqualityComparer.cs" />
|
||||
<Compile Include="Services.cs" />
|
||||
<Compile Include="TPL\LimitedConcurrencyLevelTaskScheduler.cs" />
|
||||
<Compile Include="Security\IgnoreCertErrorPolicy.cs" />
|
||||
<Compile Include="StringExtensions.cs" />
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using NzbDrone.Common.EnsureThat;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
|
||||
|
@ -45,6 +46,29 @@ namespace NzbDrone.Common
|
|||
return String.Equals(firstPath.CleanFilePath(), secondPath.CleanFilePath(), StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
private static readonly Regex WindowsPathWithDriveRegex = new Regex(@"^[a-zA-Z]:\\", RegexOptions.Compiled);
|
||||
|
||||
public static bool IsPathValid(this string path)
|
||||
{
|
||||
if (path.ContainsInvalidPathChars() || string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OsInfo.IsLinux)
|
||||
{
|
||||
return path.StartsWith(Path.DirectorySeparatorChar.ToString());
|
||||
}
|
||||
|
||||
if (path.StartsWith("\\") || WindowsPathWithDriveRegex.IsMatch(path))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static bool ContainsInvalidPathChars(this string text)
|
||||
{
|
||||
return text.IndexOfAny(Path.GetInvalidPathChars()) >= 0;
|
||||
|
@ -58,28 +82,40 @@ namespace NzbDrone.Common
|
|||
//Drive letter
|
||||
return dirInfo.Name.ToUpper();
|
||||
}
|
||||
return Path.Combine(GetProperCapitalization(parentDirInfo), parentDirInfo.GetDirectories(dirInfo.Name)[0].Name);
|
||||
|
||||
var folderName = dirInfo.Name;
|
||||
|
||||
if (dirInfo.Exists)
|
||||
{
|
||||
folderName = parentDirInfo.GetDirectories(dirInfo.Name)[0].Name;
|
||||
}
|
||||
|
||||
return Path.Combine(GetProperCapitalization(parentDirInfo), folderName);
|
||||
}
|
||||
|
||||
public static string GetActualCasing(this string path)
|
||||
{
|
||||
var attributes = File.GetAttributes(path);
|
||||
|
||||
if (OsInfo.IsLinux || path.StartsWith("\\"))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
|
||||
if (Directory.Exists(path) && (File.GetAttributes(path) & FileAttributes.Directory) == FileAttributes.Directory)
|
||||
{
|
||||
return GetProperCapitalization(new DirectoryInfo(path));
|
||||
}
|
||||
|
||||
var fileInfo = new FileInfo(path);
|
||||
var dirInfo = fileInfo.Directory;
|
||||
|
||||
var fileName = fileInfo.Name;
|
||||
|
||||
DirectoryInfo dirInfo = fileInfo.Directory;
|
||||
return Path.Combine(GetProperCapitalization(dirInfo), dirInfo.GetFiles(fileInfo.Name)[0].Name);
|
||||
if (dirInfo != null && fileInfo.Exists)
|
||||
{
|
||||
fileName = dirInfo.GetFiles(fileInfo.Name)[0].Name;
|
||||
}
|
||||
|
||||
return Path.Combine(GetProperCapitalization(dirInfo), fileName);
|
||||
}
|
||||
|
||||
public static string GetAppDataPath(this IAppFolderInfo appFolderInfo)
|
||||
|
|
|
@ -40,7 +40,6 @@ namespace NzbDrone.Common.Serializer
|
|||
return JsonConvert.SerializeObject(obj);
|
||||
}
|
||||
|
||||
|
||||
public static void Serialize<TModel>(TModel model, TextWriter outputStream)
|
||||
{
|
||||
var jsonTextWriter = new JsonTextWriter(outputStream);
|
||||
|
@ -52,7 +51,5 @@ namespace NzbDrone.Common.Serializer
|
|||
{
|
||||
Serialize(model, new StreamWriter(outputStream));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
|
||||
namespace NzbDrone.Common
|
||||
{
|
||||
public class Services
|
||||
{
|
||||
public static String RootUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
return "http://services.nzbdrone.com";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Host;
|
||||
|
||||
|
@ -18,7 +19,6 @@ namespace NzbDrone.Console
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.Console.WriteLine(e.ToString());
|
||||
System.Console.ReadLine();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,14 +15,6 @@ namespace NzbDrone.Core.Test.DataAugmentationFixture.Scene
|
|||
{
|
||||
private const string SCENE_MAPPING_URL = "http://services.nzbdrone.com/SceneMapping/Active";
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Mocker.GetMock<IConfigService>().SetupGet(s => s.ServiceRootUrl)
|
||||
.Returns("http://services.nzbdrone.com");
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void fetch_should_return_list_of_mappings()
|
||||
{
|
||||
|
|
|
@ -44,17 +44,17 @@ namespace NzbDrone.Core.Test.IndexerTests.IntegrationTests
|
|||
|
||||
|
||||
[Test]
|
||||
[Explicit("needs newznab api key")]
|
||||
public void nzbsorg_rss()
|
||||
{
|
||||
var indexer = new Newznab();
|
||||
indexer.Settings = new NewznabSettings
|
||||
{
|
||||
ApiKey = "",
|
||||
ApiKey = "64d61d3cfd4b75e51d01cbc7c6a78275",
|
||||
Url = "http://nzbs.org"
|
||||
};
|
||||
|
||||
indexer.InstanceDefinition = new IndexerDefinition();
|
||||
indexer.InstanceDefinition.Name = "nzbs.org";
|
||||
|
||||
var result = Subject.FetchRss(indexer);
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace NzbDrone.Core.Test.MediaFileTests.EpisodeImportTests
|
|||
private void GivenFreeSpace(long size)
|
||||
{
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetAvilableSpace(It.IsAny<String>()))
|
||||
.Setup(s => s.GetAvailableSpace(It.IsAny<String>()))
|
||||
.Returns(size);
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.MediaFileTests.EpisodeImportTests
|
|||
Subject.IsSatisfiedBy(_localEpisode).Should().BeTrue();
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(v => v.GetAvilableSpace(_rootFolder), Times.Once());
|
||||
.Verify(v => v.GetAvailableSpace(_rootFolder), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,8 +53,7 @@ namespace NzbDrone.Core.Test.MediaFileTests
|
|||
}
|
||||
|
||||
Mocker.GetMock<IUpgradeMediaFiles>()
|
||||
.Setup(s => s.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), It.IsAny<LocalEpisode>()))
|
||||
.Returns(new EpisodeFile());
|
||||
.Setup(s => s.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), It.IsAny<LocalEpisode>()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -60,8 +60,7 @@ namespace NzbDrone.Core.Test.MediaFileTests
|
|||
private void GivenMovedFiles()
|
||||
{
|
||||
Mocker.GetMock<IMoveEpisodeFiles>()
|
||||
.Setup(s => s.MoveEpisodeFile(It.IsAny<EpisodeFile>(), _series))
|
||||
.Returns(_episodeFiles.First());
|
||||
.Setup(s => s.MoveEpisodeFile(It.IsAny<EpisodeFile>(), _series));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -43,9 +43,9 @@
|
|||
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions, Version=2.0.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentAssertions.2.0.1\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentMigrator, Version=1.1.1.0, Culture=neutral, PublicKeyToken=aacfc7de5acabf05, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
@ -186,6 +186,7 @@
|
|||
<Compile Include="ProviderTests\DiskProviderTests\ArchiveProviderFixture.cs" />
|
||||
<Compile Include="MediaFileTests\DropFolderImportServiceFixture.cs" />
|
||||
<Compile Include="SeriesStatsTests\SeriesStatisticsFixture.cs" />
|
||||
<Compile Include="TvTests\SeasonServiceTests\HandleEpisodeInfoDeletedEventFixture.cs" />
|
||||
<Compile Include="TvTests\SeasonServiceTests\SetSeasonPassFixture.cs" />
|
||||
<Compile Include="TvTests\SeasonServiceTests\SetMonitoredFixture.cs" />
|
||||
<Compile Include="TvTests\SeriesRepositoryTests\QualityProfileRepositoryFixture.cs" />
|
||||
|
|
|
@ -353,6 +353,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
[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)]
|
||||
public void parse_language(string postTitle, Language language)
|
||||
{
|
||||
var result = Parser.Parser.ParseTitle(postTitle);
|
||||
|
|
|
@ -12,74 +12,118 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
|
||||
public class QualityParserFixture : CoreTest
|
||||
{
|
||||
public static object[] QualityParserCases =
|
||||
public static object[] SdtvCases =
|
||||
{
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", Quality.DVD, false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.BDRip.X-viD.AC3.-HELLYWOOD", Quality.DVD, false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", Quality.DVD, false },
|
||||
new object[] { "Two.and.a.Half.Men.S08E05.720p.HDTV.X264-DIMENSION", Quality.HDTV720p, false },
|
||||
new object[] { "Chuck S11E03 has no periods or extension HDTV", Quality.SDTV, false },
|
||||
new object[] { "Chuck.S04E05.HDTV.XviD-LOL", Quality.SDTV, false },
|
||||
new object[] { "The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", Quality.DVD, false },
|
||||
new object[] { "The.Girls.Next.Door.S03E06.DVD.Rip.XviD-WiDE", Quality.DVD, false },
|
||||
new object[] { "The.Girls.Next.Door.S03E06.HDTV-WiDE", Quality.SDTV, false },
|
||||
new object[] { "Degrassi.S10E27.WS.DSR.XviD-2HD", Quality.SDTV, false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.720p.WEB-DL.DD5.1.H.264-SURFER", Quality.WEBDL720p, false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.720p", Quality.HDTV720p, false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.mkv", Quality.HDTV720p, false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.avi", Quality.SDTV, false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.xvid", Quality.SDTV, false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.divx", Quality.SDTV, false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15", Quality.Unknown, false },
|
||||
new object[] { "Chuck - S01E04 - So Old - Playdate - 720p TV.mkv", Quality.HDTV720p, false },
|
||||
new object[] { "Chuck - S22E03 - MoneyBART - HD TV.mkv", Quality.HDTV720p, false },
|
||||
new object[] { "Chuck - S01E03 - Come Fly With Me - 720p BluRay.mkv", Quality.Bluray720p, false },
|
||||
new object[] { "Chuck - S01E03 - Come Fly With Me - 1080p BluRay.mkv", Quality.Bluray1080p, false },
|
||||
new object[] { "Chuck - S11E06 - D-Yikes! - 720p WEB-DL.mkv", Quality.WEBDL720p, false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi", Quality.DVD, false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi", Quality.DVD, false },
|
||||
new object[] { "Law & Order: Special Victims Unit - 11x11 - Quickie", Quality.Unknown, false },
|
||||
new object[] { "S07E23 - [HDTV-720p].mkv ", Quality.HDTV720p, false },
|
||||
new object[] { "S07E23 - [WEBDL].mkv ", Quality.WEBDL720p, false },
|
||||
new object[] { "S07E23.mkv ", Quality.HDTV720p, false },
|
||||
new object[] { "S07E23 .avi ", Quality.SDTV, false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.XviD.Bluray.AC3.-HELLYWOOD.avi", Quality.DVD, false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.Bluray.AC3.-HELLYWOOD.avi", Quality.Bluray720p, false },
|
||||
new object[] { "The Voice S01E11 The Finals 1080i HDTV DD5.1 MPEG2-TrollHD", Quality.RAWHD, false },
|
||||
new object[] { "Nikita S02E01 HDTV XviD 2HD", Quality.SDTV, false },
|
||||
new object[] { "Gossip Girl S05E11 PROPER HDTV XviD 2HD", Quality.SDTV, true },
|
||||
new object[] { "The Jonathan Ross Show S02E08 HDTV x264 FTP", Quality.SDTV, false },
|
||||
new object[] { "White.Van.Man.2011.S02E01.WS.PDTV.x264-TLA", Quality.SDTV, false },
|
||||
new object[] { "White.Van.Man.2011.S02E01.WS.PDTV.x264-REPACK-TLA", Quality.SDTV, true },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.XviD.Bluray.AC3-REPACK.-HELLYWOOD.avi", Quality.DVD, true },
|
||||
new object[] { "Pawn Stars S04E87 REPACK 720p HDTV x264 aAF", Quality.HDTV720p, true },
|
||||
new object[] { "The Real Housewives of Vancouver S01E04 DSR x264 2HD", Quality.SDTV, false },
|
||||
new object[] { "Vanguard S01E04 Mexicos Death Train DSR x264 MiNDTHEGAP", Quality.SDTV, false },
|
||||
new object[] { "Vanguard S01E04 Mexicos Death Train 720p WEB DL", Quality.WEBDL720p, false },
|
||||
new object[] { "Hawaii Five 0 S02E21 720p WEB DL DD5 1 H 264", Quality.WEBDL720p, false },
|
||||
new object[] { "Castle S04E22 720p WEB DL DD5 1 H 264 NFHD", Quality.WEBDL720p, false },
|
||||
new object[] { "Fringe S04E22 720p WEB-DL DD5.1 H264-EbP.mkv", Quality.WEBDL720p, false },
|
||||
new object[] { "CSI NY S09E03 1080p WEB DL DD5 1 H264 NFHD", Quality.WEBDL1080p, false },
|
||||
new object[] { "Two and a Half Men S10E03 1080p WEB DL DD5 1 H 264 NFHD", Quality.WEBDL1080p, false },
|
||||
new object[] { "Criminal.Minds.S08E01.1080p.WEB-DL.DD5.1.H264-NFHD", Quality.WEBDL1080p, false },
|
||||
new object[] { "Its.Always.Sunny.in.Philadelphia.S08E01.1080p.WEB-DL.proper.AAC2.0.H.264", Quality.WEBDL1080p, true },
|
||||
new object[] { "Two and a Half Men S10E03 1080p WEB DL DD5 1 H 264 REPACK NFHD", Quality.WEBDL1080p, true },
|
||||
new object[] { "Glee.S04E09.Swan.Song.1080p.WEB-DL.DD5.1.H.264-ECI", Quality.WEBDL1080p, false },
|
||||
new object[] { "Elementary.S01E10.The.Leviathan.480p.WEB-DL.x264-mSD", Quality.WEBDL480p, false },
|
||||
new object[] { "Glee.S04E10.Glee.Actually.480p.WEB-DL.x264-mSD", Quality.WEBDL480p, false },
|
||||
new object[] { "The.Big.Bang.Theory.S06E11.The.Santa.Simulation.480p.WEB-DL.x264-mSD", Quality.WEBDL480p, false },
|
||||
new object[] { "The.Big.Bang.Theory.S06E11.The.Santa.Simulation.1080p.WEB-DL.DD5.1.H.264", Quality.WEBDL1080p, false },
|
||||
new object[] { "DEXTER.S07E01.ARE.YOU.1080P.HDTV.X264-QCF", Quality.HDTV1080p, false },
|
||||
new object[] { "DEXTER.S07E01.ARE.YOU.1080P.HDTV.x264-QCF", Quality.HDTV1080p, false },
|
||||
new object[] { "DEXTER.S07E01.ARE.YOU.1080P.HDTV.proper.X264-QCF", Quality.HDTV1080p, true },
|
||||
new object[] { "Dexter - S01E01 - Title [HDTV]", Quality.HDTV720p, false },
|
||||
new object[] { "Dexter - S01E01 - Title [HDTV-720p]", Quality.HDTV720p, false },
|
||||
new object[] { "Dexter - S01E01 - Title [HDTV-1080p]", Quality.HDTV1080p, false },
|
||||
new object[] { "POI S02E11 1080i HDTV DD5.1 MPEG2-TrollHD", Quality.RAWHD, false },
|
||||
new object[] { "How I Met Your Mother S01E18 Nothing Good Happens After 2 A.M. 720p HDTV DD5.1 MPEG2-TrollHD", Quality.RAWHD, false },
|
||||
new object[] { "Arrested.Development.S04E01.iNTERNAL.1080p.WEBRip.x264-QRUS", Quality.WEBDL1080p, false },
|
||||
new object[] { "Arrested.Development.S04E01.720p.WEBRip.AAC2.0.x264-NFRiP", Quality.WEBDL720p, false },
|
||||
new object[] { "Sons.Of.Anarchy.S02E13.1080p.BluRay.x264-AVCDVD", Quality.Bluray1080p, false }
|
||||
new object[] { "S07E23 .avi ", false },
|
||||
new object[] {"The.Shield.S01E13.x264-CtrlSD", false},
|
||||
new object[] { "Nikita S02E01 HDTV XviD 2HD", false },
|
||||
new object[] { "Gossip Girl S05E11 PROPER HDTV XviD 2HD", true },
|
||||
new object[] { "The Jonathan Ross Show S02E08 HDTV x264 FTP", false },
|
||||
new object[] { "White.Van.Man.2011.S02E01.WS.PDTV.x264-TLA", false },
|
||||
new object[] { "White.Van.Man.2011.S02E01.WS.PDTV.x264-REPACK-TLA", true },
|
||||
new object[] { "The Real Housewives of Vancouver S01E04 DSR x264 2HD", false },
|
||||
new object[] { "Vanguard S01E04 Mexicos Death Train DSR x264 MiNDTHEGAP", false },
|
||||
new object[] { "Chuck S11E03 has no periods or extension HDTV", false },
|
||||
new object[] { "Chuck.S04E05.HDTV.XviD-LOL", false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.avi", false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.xvid", false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.divx", false },
|
||||
new object[] { "The.Girls.Next.Door.S03E06.HDTV-WiDE", false },
|
||||
new object[] { "Degrassi.S10E27.WS.DSR.XviD-2HD", false },
|
||||
};
|
||||
|
||||
public static object[] DvdCases =
|
||||
{
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.XviD.Bluray.AC3-REPACK.-HELLYWOOD.avi", true },
|
||||
new object[] { "The.Shield.S01E13.NTSC.x264-CtrlSD", false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.BDRip.X-viD.AC3.-HELLYWOOD", false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi", false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi", false },
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.XviD.Bluray.AC3.-HELLYWOOD.avi", false },
|
||||
new object[] { "The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", false },
|
||||
new object[] { "The.Girls.Next.Door.S03E06.DVD.Rip.XviD-WiDE", false },
|
||||
new object[] { "the.shield.1x13.circles.ws.xvidvd-tns", false}
|
||||
};
|
||||
|
||||
public static object[] Webdl480pCases =
|
||||
{
|
||||
new object[] { "Elementary.S01E10.The.Leviathan.480p.WEB-DL.x264-mSD", false },
|
||||
new object[] { "Glee.S04E10.Glee.Actually.480p.WEB-DL.x264-mSD", false },
|
||||
new object[] { "The.Big.Bang.Theory.S06E11.The.Santa.Simulation.480p.WEB-DL.x264-mSD", false },
|
||||
};
|
||||
|
||||
public static object[] Hdtv720pCases =
|
||||
{
|
||||
new object[] { "Dexter - S01E01 - Title [HDTV]", false },
|
||||
new object[] { "Dexter - S01E01 - Title [HDTV-720p]", false },
|
||||
new object[] { "Pawn Stars S04E87 REPACK 720p HDTV x264 aAF", true },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.720p", false },
|
||||
new object[] { "S07E23 - [HDTV-720p].mkv ", false },
|
||||
new object[] { "Chuck - S22E03 - MoneyBART - HD TV.mkv", false },
|
||||
new object[] { "S07E23.mkv ", false },
|
||||
new object[] { "Two.and.a.Half.Men.S08E05.720p.HDTV.X264-DIMENSION", false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.mkv", false },
|
||||
};
|
||||
|
||||
public static object[] Hdtv1080pCases =
|
||||
{
|
||||
new object[] { "Under the Dome S01E10 Let the Games Begin 1080p", false },
|
||||
new object[] { "DEXTER.S07E01.ARE.YOU.1080P.HDTV.X264-QCF", false },
|
||||
new object[] { "DEXTER.S07E01.ARE.YOU.1080P.HDTV.x264-QCF", false },
|
||||
new object[] { "DEXTER.S07E01.ARE.YOU.1080P.HDTV.proper.X264-QCF", true },
|
||||
new object[] { "Dexter - S01E01 - Title [HDTV-1080p]", false },
|
||||
};
|
||||
|
||||
public static object[] Webdl720pCases =
|
||||
{
|
||||
new object[] { "Arrested.Development.S04E01.720p.WEBRip.AAC2.0.x264-NFRiP", false },
|
||||
new object[] { "Vanguard S01E04 Mexicos Death Train 720p WEB DL", false },
|
||||
new object[] { "Hawaii Five 0 S02E21 720p WEB DL DD5 1 H 264", false },
|
||||
new object[] { "Castle S04E22 720p WEB DL DD5 1 H 264 NFHD", false },
|
||||
new object[] { "Chuck - S11E06 - D-Yikes! - 720p WEB-DL.mkv", false },
|
||||
new object[] { "Sonny.With.a.Chance.S02E15.720p.WEB-DL.DD5.1.H.264-SURFER", false },
|
||||
new object[] { "S07E23 - [WEBDL].mkv ", false },
|
||||
new object[] { "Fringe S04E22 720p WEB-DL DD5.1 H264-EbP.mkv", false },
|
||||
};
|
||||
|
||||
public static object[] Webdl1080pCases =
|
||||
{
|
||||
new object[] { "Arrested.Development.S04E01.iNTERNAL.1080p.WEBRip.x264-QRUS", false },
|
||||
new object[] { "CSI NY S09E03 1080p WEB DL DD5 1 H264 NFHD", false },
|
||||
new object[] { "Two and a Half Men S10E03 1080p WEB DL DD5 1 H 264 NFHD", false },
|
||||
new object[] { "Criminal.Minds.S08E01.1080p.WEB-DL.DD5.1.H264-NFHD", false },
|
||||
new object[] { "Its.Always.Sunny.in.Philadelphia.S08E01.1080p.WEB-DL.proper.AAC2.0.H.264", true },
|
||||
new object[] { "Two and a Half Men S10E03 1080p WEB DL DD5 1 H 264 REPACK NFHD", true },
|
||||
new object[] { "Glee.S04E09.Swan.Song.1080p.WEB-DL.DD5.1.H.264-ECI", false },
|
||||
new object[] { "The.Big.Bang.Theory.S06E11.The.Santa.Simulation.1080p.WEB-DL.DD5.1.H.264", false },
|
||||
};
|
||||
|
||||
public static object[] Bluray720pCases =
|
||||
{
|
||||
new object[] { "WEEDS.S03E01-06.DUAL.Bluray.AC3.-HELLYWOOD.avi", false },
|
||||
new object[] { "Chuck - S01E03 - Come Fly With Me - 720p BluRay.mkv", false },
|
||||
};
|
||||
|
||||
public static object[] Bluray1080pCases =
|
||||
{
|
||||
new object[] { "Chuck - S01E03 - Come Fly With Me - 1080p BluRay.mkv", false },
|
||||
new object[] { "Sons.Of.Anarchy.S02E13.1080p.BluRay.x264-AVCDVD", false },
|
||||
};
|
||||
|
||||
public static object[] RawCases =
|
||||
{
|
||||
new object[] { "POI S02E11 1080i HDTV DD5.1 MPEG2-TrollHD", false },
|
||||
new object[] { "How I Met Your Mother S01E18 Nothing Good Happens After 2 A.M. 720p HDTV DD5.1 MPEG2-TrollHD", false },
|
||||
new object[] { "The Voice S01E11 The Finals 1080i HDTV DD5.1 MPEG2-TrollHD", false },
|
||||
};
|
||||
|
||||
public static object[] UnknownCases =
|
||||
{
|
||||
new object[] { "Sonny.With.a.Chance.S02E15", false },
|
||||
new object[] { "Law & Order: Special Victims Unit - 11x11 - Quickie", false },
|
||||
|
||||
};
|
||||
|
||||
public static object[] SelfQualityParserCases =
|
||||
|
@ -94,20 +138,100 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||
new object[] { Quality.Bluray1080p }
|
||||
};
|
||||
|
||||
[Test, TestCaseSource("QualityParserCases")]
|
||||
public void quality_parse(string postTitle, Quality quality, bool proper)
|
||||
[Test, TestCaseSource("SdtvCases")]
|
||||
public void should_parse_sdtv_quality(string postTitle, bool proper)
|
||||
{
|
||||
var result = Parser.Parser.ParseTitle(postTitle);
|
||||
result.Quality.Quality.Should().Be(quality);
|
||||
result.Quality.Proper.Should().Be(proper);
|
||||
var result = Parser.QualityParser.ParseQuality(postTitle);
|
||||
result.Quality.Should().Be(Quality.SDTV);
|
||||
result.Proper.Should().Be(proper);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("DvdCases")]
|
||||
public void should_parse_dvd_quality(string postTitle, bool proper)
|
||||
{
|
||||
var result = Parser.QualityParser.ParseQuality(postTitle);
|
||||
result.Quality.Should().Be(Quality.DVD);
|
||||
result.Proper.Should().Be(proper);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("Webdl480pCases")]
|
||||
public void should_parse_webdl480p_quality(string postTitle, bool proper)
|
||||
{
|
||||
var result = Parser.QualityParser.ParseQuality(postTitle);
|
||||
result.Quality.Should().Be(Quality.WEBDL480p);
|
||||
result.Proper.Should().Be(proper);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("Hdtv720pCases")]
|
||||
public void should_parse_hdtv720p_quality(string postTitle, bool proper)
|
||||
{
|
||||
var result = Parser.QualityParser.ParseQuality(postTitle);
|
||||
result.Quality.Should().Be(Quality.HDTV720p);
|
||||
result.Proper.Should().Be(proper);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("Hdtv1080pCases")]
|
||||
public void should_parse_hdtv1080p_quality(string postTitle, bool proper)
|
||||
{
|
||||
var result = Parser.QualityParser.ParseQuality(postTitle);
|
||||
result.Quality.Should().Be(Quality.HDTV1080p);
|
||||
result.Proper.Should().Be(proper);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("Webdl720pCases")]
|
||||
public void should_parse_webdl720p_quality(string postTitle, bool proper)
|
||||
{
|
||||
var result = Parser.QualityParser.ParseQuality(postTitle);
|
||||
result.Quality.Should().Be(Quality.WEBDL720p);
|
||||
result.Proper.Should().Be(proper);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("Webdl1080pCases")]
|
||||
public void should_parse_webdl1080p_quality(string postTitle, bool proper)
|
||||
{
|
||||
var result = Parser.QualityParser.ParseQuality(postTitle);
|
||||
result.Quality.Should().Be(Quality.WEBDL1080p);
|
||||
result.Proper.Should().Be(proper);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("Bluray720pCases")]
|
||||
public void should_parse_bluray720p_quality(string postTitle, bool proper)
|
||||
{
|
||||
var result = Parser.QualityParser.ParseQuality(postTitle);
|
||||
result.Quality.Should().Be(Quality.Bluray720p);
|
||||
result.Proper.Should().Be(proper);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("Bluray1080pCases")]
|
||||
public void should_parse_bluray1080p_quality(string postTitle, bool proper)
|
||||
{
|
||||
var result = Parser.QualityParser.ParseQuality(postTitle);
|
||||
result.Quality.Should().Be(Quality.Bluray1080p);
|
||||
result.Proper.Should().Be(proper);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("RawCases")]
|
||||
public void should_parse_raw_quality(string postTitle, bool proper)
|
||||
{
|
||||
var result = Parser.QualityParser.ParseQuality(postTitle);
|
||||
result.Quality.Should().Be(Quality.RAWHD);
|
||||
result.Proper.Should().Be(proper);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("UnknownCases")]
|
||||
public void quality_parse(string postTitle, bool proper)
|
||||
{
|
||||
var result = Parser.QualityParser.ParseQuality(postTitle);
|
||||
result.Quality.Should().Be(Quality.Unknown);
|
||||
result.Proper.Should().Be(proper);
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("SelfQualityParserCases")]
|
||||
public void parsing_our_own_quality_enum(Quality quality)
|
||||
{
|
||||
var fileName = String.Format("My series S01E01 [{0}]", quality);
|
||||
var result = Parser.Parser.ParseTitle(fileName);
|
||||
result.Quality.Quality.Should().Be(quality);
|
||||
var result = Parser.QualityParser.ParseQuality(fileName);
|
||||
result.Quality.Should().Be(quality);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskProviderTests
|
|||
[Test]
|
||||
public void should_return_free_disk_space()
|
||||
{
|
||||
var result = Subject.GetAvilableSpace(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
|
||||
var result = Subject.GetAvailableSpace(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
|
||||
result.Should().BeGreaterThan(0);
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskProviderTests
|
|||
{
|
||||
WindowsOnly();
|
||||
|
||||
var result = Subject.GetAvilableSpace(@"\\localhost\c$\Windows");
|
||||
var result = Subject.GetAvailableSpace(@"\\localhost\c$\Windows");
|
||||
result.Should().BeGreaterThan(0);
|
||||
}
|
||||
|
||||
|
@ -32,13 +32,13 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskProviderTests
|
|||
{
|
||||
WindowsOnly();
|
||||
|
||||
Assert.Throws<DirectoryNotFoundException>(() => Subject.GetAvilableSpace(@"Z:\NOT_A_REAL_PATH\DOES_NOT_EXIST".AsOsAgnostic()));
|
||||
Assert.Throws<DirectoryNotFoundException>(() => Subject.GetAvailableSpace(@"Z:\NOT_A_REAL_PATH\DOES_NOT_EXIST".AsOsAgnostic()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_get_space_on_folder_that_doesnt_exist()
|
||||
{
|
||||
var result = Subject.GetAvilableSpace(@"C:\I_DO_NOT_EXIST".AsOsAgnostic());
|
||||
var result = Subject.GetAvailableSpace(@"C:\I_DO_NOT_EXIST".AsOsAgnostic());
|
||||
result.Should().BeGreaterThan(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace NzbDrone.Core.Test.RootFolderTests
|
|||
.Returns(@"C:\");
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetAvilableSpace(@"C:\"))
|
||||
.Setup(s => s.GetAvailableSpace(@"C:\"))
|
||||
.Returns(123456);
|
||||
|
||||
var result = Subject.FreeSpaceOnDrives();
|
||||
|
@ -51,7 +51,7 @@ namespace NzbDrone.Core.Test.RootFolderTests
|
|||
.Returns(@"C:\");
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetAvilableSpace(@"C:\"))
|
||||
.Setup(s => s.GetAvailableSpace(@"C:\"))
|
||||
.Returns(123456);
|
||||
|
||||
var result = Subject.FreeSpaceOnDrives();
|
||||
|
@ -76,7 +76,7 @@ namespace NzbDrone.Core.Test.RootFolderTests
|
|||
.Returns(@"D:\");
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetAvilableSpace(It.IsAny<string>()))
|
||||
.Setup(s => s.GetAvailableSpace(It.IsAny<string>()))
|
||||
.Returns(123456);
|
||||
|
||||
var result = Subject.FreeSpaceOnDrives();
|
||||
|
@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.RootFolderTests
|
|||
.Returns(@"C:\");
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetAvilableSpace(It.IsAny<string>()))
|
||||
.Setup(s => s.GetAvailableSpace(It.IsAny<string>()))
|
||||
.Throws(new DirectoryNotFoundException());
|
||||
|
||||
var result = Subject.FreeSpaceOnDrives();
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FizzWare.NBuilder;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
|
||||
namespace NzbDrone.Core.Test.TvTests.SeasonServiceTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class HandleEpisodeInfoDeletedEventFixture : CoreTest<SeasonService>
|
||||
{
|
||||
private List<Season> _seasons;
|
||||
private List<Episode> _episodes;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_seasons = Builder<Season>
|
||||
.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(s => s.SeriesId = 1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
_episodes = Builder<Episode>
|
||||
.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(e => e.SeasonNumber = _seasons.First().SeasonNumber)
|
||||
.With(s => s.SeriesId = _seasons.First().SeasonNumber)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Mocker.GetMock<ISeasonRepository>()
|
||||
.Setup(s => s.GetSeasonBySeries(It.IsAny<int>()))
|
||||
.Returns(_seasons);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Setup(s => s.GetEpisodesBySeason(It.IsAny<int>(), _seasons.First().SeasonNumber))
|
||||
.Returns(_episodes);
|
||||
}
|
||||
|
||||
private void GivenAbandonedSeason()
|
||||
{
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Setup(s => s.GetEpisodesBySeason(It.IsAny<int>(), _seasons.First().SeasonNumber))
|
||||
.Returns(new List<Episode>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_delete_when_season_is_still_valid()
|
||||
{
|
||||
Subject.Handle(new EpisodeInfoDeletedEvent(_episodes));
|
||||
|
||||
Mocker.GetMock<ISeasonRepository>()
|
||||
.Verify(v => v.Delete(It.IsAny<Season>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_delete_season_if_no_episodes_exist_in_that_season()
|
||||
{
|
||||
GivenAbandonedSeason();
|
||||
|
||||
Subject.Handle(new EpisodeInfoDeletedEvent(_episodes));
|
||||
|
||||
Mocker.GetMock<ISeasonRepository>()
|
||||
.Verify(v => v.Delete(It.IsAny<Season>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_only_delete_a_season_once()
|
||||
{
|
||||
_episodes = Builder<Episode>
|
||||
.CreateListOfSize(5)
|
||||
.All()
|
||||
.With(e => e.SeasonNumber = _seasons.First().SeasonNumber)
|
||||
.With(s => s.SeriesId = _seasons.First().SeasonNumber)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
GivenAbandonedSeason();
|
||||
|
||||
Subject.Handle(new EpisodeInfoDeletedEvent(_episodes));
|
||||
|
||||
Mocker.GetMock<ISeasonRepository>()
|
||||
.Verify(v => v.Delete(It.IsAny<Season>()), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,13 +16,7 @@ namespace NzbDrone.Core.Test.UpdateTests
|
|||
|
||||
Mocker.GetMock<IConfigFileProvider>().SetupGet(c => c.Branch).Returns("master");
|
||||
|
||||
var updates = Subject.GetAvailablePackages().ToList();
|
||||
|
||||
updates.Should().NotBeEmpty();
|
||||
updates.Should().OnlyContain(c => !string.IsNullOrWhiteSpace(c.FileName));
|
||||
updates.Should().OnlyContain(c => !string.IsNullOrWhiteSpace(c.Url));
|
||||
updates.Should().OnlyContain(c => c.Version != null);
|
||||
updates.Should().OnlyContain(c => c.Version.Major == 2);
|
||||
Subject.GetLatestUpdate().Should().BeNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<packages>
|
||||
<package id="AutoMoq" version="1.6.1" targetFramework="net40" />
|
||||
<package id="CommonServiceLocator" version="1.0" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="2.0.1" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="2.1.0.0" targetFramework="net40" />
|
||||
<package id="FluentMigrator" version="1.1.1.0" targetFramework="net40" />
|
||||
<package id="FluentValidation" version="4.0.0.1" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
|
|
|
@ -172,11 +172,6 @@ namespace NzbDrone.Core.Configuration
|
|||
set { SetValue("BlackholeFolder", value); }
|
||||
}
|
||||
|
||||
public string ServiceRootUrl
|
||||
{
|
||||
get { return "http://services.nzbdrone.com"; }
|
||||
}
|
||||
|
||||
public string PneumaticFolder
|
||||
{
|
||||
get { return GetValue("PneumaticFolder", String.Empty); }
|
||||
|
|
|
@ -25,7 +25,6 @@ namespace NzbDrone.Core.Configuration
|
|||
int Retention { get; set; }
|
||||
DownloadClientType DownloadClient { get; set; }
|
||||
string BlackholeFolder { get; set; }
|
||||
string ServiceRootUrl { get; }
|
||||
string PneumaticFolder { get; set; }
|
||||
string RecycleBin { get; set; }
|
||||
String NzbgetUsername { get; set; }
|
||||
|
|
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Core.DataAugmentation.DailySeries
|
||||
{
|
||||
|
@ -17,13 +16,11 @@ namespace NzbDrone.Core.DataAugmentation.DailySeries
|
|||
public class DailySeriesDataProxy : IDailySeriesDataProxy
|
||||
{
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public DailySeriesDataProxy(IHttpProvider httpProvider, IConfigService configService, Logger logger)
|
||||
public DailySeriesDataProxy(IHttpProvider httpProvider, Logger logger)
|
||||
{
|
||||
_httpProvider = httpProvider;
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -31,7 +28,7 @@ namespace NzbDrone.Core.DataAugmentation.DailySeries
|
|||
{
|
||||
try
|
||||
{
|
||||
var dailySeriesIds = _httpProvider.DownloadString(_configService.ServiceRootUrl + "/DailySeries/AllIds");
|
||||
var dailySeriesIds = _httpProvider.DownloadString(Services.RootUrl + "/DailySeries/AllIds");
|
||||
|
||||
var seriesIds = Json.Deserialize<List<int>>(dailySeriesIds);
|
||||
|
||||
|
@ -49,7 +46,7 @@ namespace NzbDrone.Core.DataAugmentation.DailySeries
|
|||
{
|
||||
try
|
||||
{
|
||||
var result = _httpProvider.DownloadString(_configService.ServiceRootUrl + "/DailySeries/Check?seriesId=" + tvdbid);
|
||||
var result = _httpProvider.DownloadString(Services.RootUrl + "/DailySeries/Check?seriesId=" + tvdbid);
|
||||
return Convert.ToBoolean(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -13,19 +13,15 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
|||
public class SceneMappingProxy : ISceneMappingProxy
|
||||
{
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
private readonly IConfigService _configService;
|
||||
|
||||
|
||||
public SceneMappingProxy(IHttpProvider httpProvider, IConfigService configService)
|
||||
public SceneMappingProxy(IHttpProvider httpProvider)
|
||||
{
|
||||
_httpProvider = httpProvider;
|
||||
_configService = configService;
|
||||
|
||||
}
|
||||
|
||||
public List<SceneMapping> Fetch()
|
||||
{
|
||||
var mappingsJson = _httpProvider.DownloadString(_configService.ServiceRootUrl + "/SceneMapping/Active");
|
||||
var mappingsJson = _httpProvider.DownloadString(Services.RootUrl + "/SceneMapping/Active");
|
||||
return Json.Deserialize<List<SceneMapping>>(mappingsJson);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(16)]
|
||||
public class updated_imported_history_item : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.Sql(@"UPDATE HISTORY SET Data = replace( Data, '""Path""', '""ImportedPath""' ) WHERE EventType=3");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(17)]
|
||||
public class reset_scene_names : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
//we were storing new file name as scene name.
|
||||
Execute.Sql(@"UPDATE EpisodeFiles SET SceneName = NULL where SceneName != NULL");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -62,7 +62,7 @@ namespace NzbDrone.Core.History
|
|||
{
|
||||
var history = new History
|
||||
{
|
||||
EventType = HistoryEventType.Grabbed,
|
||||
EventType = HistoryEventType.Grabbed,
|
||||
Date = DateTime.UtcNow,
|
||||
Quality = message.Episode.ParsedEpisodeInfo.Quality,
|
||||
SourceTitle = message.Episode.Report.Title,
|
||||
|
@ -81,20 +81,22 @@ namespace NzbDrone.Core.History
|
|||
|
||||
public void Handle(EpisodeImportedEvent message)
|
||||
{
|
||||
foreach (var episode in message.EpisodeFile.Episodes.Value)
|
||||
foreach (var episode in message.DroppedEpisode.Episodes)
|
||||
{
|
||||
var history = new History
|
||||
{
|
||||
EventType = HistoryEventType.DownloadFolderImported,
|
||||
Date = DateTime.UtcNow,
|
||||
Quality = message.EpisodeFile.Quality,
|
||||
SourceTitle = message.EpisodeFile.Path,
|
||||
SeriesId = message.EpisodeFile.SeriesId,
|
||||
Quality = message.DroppedEpisode.Quality,
|
||||
SourceTitle = message.ImportedEpisode.SceneName,
|
||||
SeriesId = message.ImportedEpisode.SeriesId,
|
||||
EpisodeId = episode.Id
|
||||
};
|
||||
|
||||
history.Data.Add("Path", message.EpisodeFile.Path);
|
||||
history.Data.Add("Filename", Path.GetFileNameWithoutExtension(message.EpisodeFile.Path));
|
||||
//Won't have a value since we publish this event before saving to DB.
|
||||
//history.Data.Add("FileId", message.ImportedEpisode.Id.ToString());
|
||||
history.Data.Add("DroppedPath", message.DroppedEpisode.Path);
|
||||
history.Data.Add("ImportedPath", message.ImportedEpisode.Path);
|
||||
|
||||
_historyRepository.Insert(history);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Globalization;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
@ -12,7 +13,7 @@ namespace NzbDrone.Core.Indexers
|
|||
{
|
||||
public interface IParseFeed
|
||||
{
|
||||
IEnumerable<ReportInfo> Process(Stream source, string url);
|
||||
IEnumerable<ReportInfo> Process(string xml, string url);
|
||||
}
|
||||
|
||||
public class BasicRssParser : IParseFeed
|
||||
|
@ -24,34 +25,37 @@ namespace NzbDrone.Core.Indexers
|
|||
_logger = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
|
||||
public IEnumerable<ReportInfo> Process(Stream source, string url)
|
||||
public IEnumerable<ReportInfo> Process(string xml, string url)
|
||||
{
|
||||
var document = XDocument.Load(source);
|
||||
var items = document.Descendants("item");
|
||||
|
||||
var result = new List<ReportInfo>();
|
||||
|
||||
foreach (var item in items)
|
||||
using (var xmlTextReader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { ProhibitDtd = false, IgnoreComments = true }))
|
||||
{
|
||||
try
|
||||
{
|
||||
var reportInfo = ParseFeedItem(item);
|
||||
if (reportInfo != null)
|
||||
{
|
||||
reportInfo.NzbUrl = GetNzbUrl(item);
|
||||
reportInfo.NzbInfoUrl = GetNzbInfoUrl(item);
|
||||
var document = XDocument.Load(xmlTextReader);
|
||||
var items = document.Descendants("item");
|
||||
|
||||
result.Add(reportInfo);
|
||||
var result = new List<ReportInfo>();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
try
|
||||
{
|
||||
var reportInfo = ParseFeedItem(item);
|
||||
if (reportInfo != null)
|
||||
{
|
||||
reportInfo.NzbUrl = GetNzbUrl(item);
|
||||
reportInfo.NzbInfoUrl = GetNzbInfoUrl(item);
|
||||
|
||||
result.Add(reportInfo);
|
||||
}
|
||||
}
|
||||
catch (Exception itemEx)
|
||||
{
|
||||
itemEx.Data.Add("Item", item.Title());
|
||||
_logger.ErrorException("An error occurred while processing feed item from " + url, itemEx);
|
||||
}
|
||||
}
|
||||
catch (Exception itemEx)
|
||||
{
|
||||
itemEx.Data.Add("Item", item.Title());
|
||||
_logger.ErrorException("An error occurred while processing feed item from " + url, itemEx);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -106,19 +106,26 @@ namespace NzbDrone.Core.Indexers
|
|||
try
|
||||
{
|
||||
_logger.Trace("Downloading Feed " + url);
|
||||
var stream = _httpProvider.DownloadStream(url);
|
||||
result.AddRange(indexer.Parser.Process(stream, url));
|
||||
var xml = _httpProvider.DownloadString(url);
|
||||
if (!string.IsNullOrWhiteSpace(xml))
|
||||
{
|
||||
result.AddRange(indexer.Parser.Process(xml, url));
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("{0} returned empty response.", url);
|
||||
}
|
||||
|
||||
}
|
||||
catch (WebException webException)
|
||||
{
|
||||
if (webException.Message.Contains("503") || webException.Message.Contains("timed out"))
|
||||
if (webException.Message.Contains("502") || webException.Message.Contains("503") || webException.Message.Contains("timed out"))
|
||||
{
|
||||
_logger.Warn("{0} server is currently unavailable. {1} {2}", indexer.Name, url, webException.Message);
|
||||
}
|
||||
else
|
||||
{
|
||||
webException.Data.Add("FeedUrl", url);
|
||||
_logger.WarnException("An error occurred while processing feed. " + url, webException);
|
||||
_logger.Warn("{0} {1} {2}", indexer.Name, url, webException.Message);
|
||||
}
|
||||
}
|
||||
catch (Exception feedEx)
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace NzbDrone.Core.Instrumentation
|
|||
|
||||
public void Trim()
|
||||
{
|
||||
var trimDate = DateTime.UtcNow.AddDays(-15).Date;
|
||||
var trimDate = DateTime.UtcNow.AddDays(-7).Date;
|
||||
Delete(c => c.Time <= trimDate);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,30 +44,31 @@ namespace NzbDrone.Core.MediaCover
|
|||
foreach (var cover in series.Images)
|
||||
{
|
||||
var fileName = GetCoverPath(series.Id, cover.CoverType);
|
||||
if (!_coverExistsSpecification.AlreadyExists(cover.Url, fileName))
|
||||
try
|
||||
{
|
||||
DownloadCover(series, cover);
|
||||
if (!_coverExistsSpecification.AlreadyExists(cover.Url, fileName))
|
||||
{
|
||||
DownloadCover(series, cover);
|
||||
}
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
_logger.Warn(string.Format("Couldn't download media cover for {0}. {1}", series, e.Message));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorException("Couldn't download media cover for " + series, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DownloadCover(Series series, MediaCover cover)
|
||||
{
|
||||
try
|
||||
{
|
||||
var fileName = GetCoverPath(series.Id, cover.CoverType);
|
||||
var fileName = GetCoverPath(series.Id, cover.CoverType);
|
||||
|
||||
_logger.Info("Downloading {0} for {1} {2}", cover.CoverType, series, cover.Url);
|
||||
_httpProvider.DownloadFile(cover.Url, fileName);
|
||||
|
||||
_logger.Info("Downloading {0} for {1} {2}", cover.CoverType, series, cover.Url);
|
||||
_httpProvider.DownloadFile(cover.Url, fileName);
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
_logger.Warn("Couldn't download media cover for " + series);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorException("Couldn't download media cover for " + series, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleAsync(SeriesDeletedEvent message)
|
||||
|
|
|
@ -24,9 +24,9 @@ namespace NzbDrone.Core.MediaFiles
|
|||
|
||||
private const string EXTENSIONS =
|
||||
//XBMC
|
||||
".m4v .3gp .nsv .ts .ty .strm .rm .rmvb .m3u .ifo .mov .qt .divx .xvid .bivx .vob .nrg .img" +
|
||||
".m4v .3gp .nsv .ts .ty .strm .rm .rmvb .m3u .ifo .mov .qt .divx .xvid .bivx .vob .nrg .img " +
|
||||
".iso .pva .wmv .asf .asx .ogm .m2v .avi .bin .dat .dvr-ms .mpg .mpeg .mp4 .mkv .avc .vp3 " +
|
||||
".svq3 .nuv .viv .dv .fli .flv .wpl" +
|
||||
".svq3 .nuv .viv .dv .fli .flv .wpl " +
|
||||
//Other
|
||||
".m2ts";
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ namespace NzbDrone.Core.MediaFiles
|
|||
{
|
||||
public interface IMoveEpisodeFiles
|
||||
{
|
||||
EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, Series series);
|
||||
EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode);
|
||||
string MoveEpisodeFile(EpisodeFile episodeFile, Series series);
|
||||
string MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode);
|
||||
}
|
||||
|
||||
public class MoveEpisodeFiles : IMoveEpisodeFiles
|
||||
|
@ -38,27 +38,26 @@ namespace NzbDrone.Core.MediaFiles
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, Series series)
|
||||
public string MoveEpisodeFile(EpisodeFile episodeFile, Series series)
|
||||
{
|
||||
var episodes = _episodeService.GetEpisodesByFileId(episodeFile.Id);
|
||||
var newFileName = _buildFileNames.BuildFilename(episodes, series, episodeFile);
|
||||
var destinationFilename = _buildFileNames.BuildFilePath(series, episodes.First().SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path));
|
||||
var filePath = _buildFileNames.BuildFilePath(series, episodes.First().SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path));
|
||||
MoveFile(episodeFile, filePath);
|
||||
|
||||
return MoveFile(episodeFile, destinationFilename);
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode)
|
||||
public string MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode)
|
||||
{
|
||||
var newFileName = _buildFileNames.BuildFilename(localEpisode.Episodes, localEpisode.Series, episodeFile);
|
||||
var destinationFilename = _buildFileNames.BuildFilePath(localEpisode.Series, localEpisode.SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path));
|
||||
episodeFile = MoveFile(episodeFile, destinationFilename);
|
||||
var filePath = _buildFileNames.BuildFilePath(localEpisode.Series, localEpisode.SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path));
|
||||
MoveFile(episodeFile, filePath);
|
||||
|
||||
_messageAggregator.PublishEvent(new EpisodeDownloadedEvent(localEpisode));
|
||||
|
||||
return episodeFile;
|
||||
return filePath;
|
||||
}
|
||||
|
||||
private EpisodeFile MoveFile(EpisodeFile episodeFile, string destinationFilename)
|
||||
private void MoveFile(EpisodeFile episodeFile, string destinationFilename)
|
||||
{
|
||||
if (!_diskProvider.FileExists(episodeFile.Path))
|
||||
{
|
||||
|
@ -85,10 +84,6 @@ namespace NzbDrone.Core.MediaFiles
|
|||
_logger.Debug("Unable to apply folder permissions to: ", destinationFilename);
|
||||
_logger.TraceException(ex.Message, ex);
|
||||
}
|
||||
|
||||
episodeFile.Path = destinationFilename;
|
||||
|
||||
return episodeFile;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
|||
{
|
||||
List<ImportDecision> Import(List<ImportDecision> decisions, bool newDownloads = false);
|
||||
}
|
||||
|
||||
|
||||
public class ImportApprovedEpisodes : IImportApprovedEpisodes
|
||||
{
|
||||
private readonly IUpgradeMediaFiles _episodeFileUpgrader;
|
||||
|
@ -62,15 +62,17 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
|||
episodeFile.Size = _diskProvider.GetFileSize(localEpisode.Path);
|
||||
episodeFile.Quality = localEpisode.Quality;
|
||||
episodeFile.SeasonNumber = localEpisode.SeasonNumber;
|
||||
episodeFile.SceneName = Path.GetFileNameWithoutExtension(localEpisode.Path.CleanFilePath());
|
||||
episodeFile.Episodes = localEpisode.Episodes;
|
||||
|
||||
|
||||
if (newDownload)
|
||||
{
|
||||
episodeFile = _episodeFileUpgrader.UpgradeEpisodeFile(episodeFile, localEpisode);
|
||||
_messageAggregator.PublishEvent(new EpisodeImportedEvent(episodeFile));
|
||||
episodeFile.SceneName = Path.GetFileNameWithoutExtension(localEpisode.Path.CleanFilePath());
|
||||
episodeFile.Path = _episodeFileUpgrader.UpgradeEpisodeFile(episodeFile, localEpisode);
|
||||
_messageAggregator.PublishEvent(new EpisodeImportedEvent(localEpisode, episodeFile));
|
||||
_messageAggregator.PublishEvent(new EpisodeDownloadedEvent(localEpisode));
|
||||
}
|
||||
|
||||
|
||||
_mediaFileService.Add(episodeFile);
|
||||
imported.Add(importDecision);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
|||
try
|
||||
{
|
||||
var path = Directory.GetParent(localEpisode.Series.Path);
|
||||
var freeSpace = _diskProvider.GetAvilableSpace(path.FullName);
|
||||
var freeSpace = _diskProvider.GetAvailableSpace(path.FullName);
|
||||
|
||||
if (freeSpace < localEpisode.Size + 100.Megabytes())
|
||||
{
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.Events
|
||||
{
|
||||
public class EpisodeImportedEvent : IEvent
|
||||
{
|
||||
public EpisodeFile EpisodeFile { get; private set; }
|
||||
public LocalEpisode DroppedEpisode { get; private set; }
|
||||
public EpisodeFile ImportedEpisode { get; private set; }
|
||||
|
||||
public EpisodeImportedEvent(EpisodeFile episodeFile)
|
||||
public EpisodeImportedEvent(LocalEpisode droppedEpisode, EpisodeFile importedEpisode)
|
||||
{
|
||||
EpisodeFile = episodeFile;
|
||||
DroppedEpisode = droppedEpisode;
|
||||
ImportedEpisode = importedEpisode;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,14 +34,12 @@ namespace NzbDrone.Core.MediaFiles
|
|||
{
|
||||
var renamed = new List<EpisodeFile>();
|
||||
|
||||
foreach (var file in episodeFiles)
|
||||
foreach (var episodeFile in episodeFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
var episodeFile = file;
|
||||
|
||||
_logger.Trace("Renaming episode file: {0}", episodeFile);
|
||||
episodeFile = _episodeFileMover.MoveEpisodeFile(episodeFile, series);
|
||||
episodeFile.Path = _episodeFileMover.MoveEpisodeFile(episodeFile, series);
|
||||
|
||||
_mediaFileService.Update(episodeFile);
|
||||
renamed.Add(episodeFile);
|
||||
|
@ -54,7 +52,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Failed to rename file: " + file.Path, ex);
|
||||
_logger.ErrorException("Failed to rename file: " + episodeFile.Path, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
{
|
||||
public interface IUpgradeMediaFiles
|
||||
{
|
||||
EpisodeFile UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode);
|
||||
string UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode);
|
||||
}
|
||||
|
||||
public class UpgradeMediaFileService : IUpgradeMediaFiles
|
||||
|
@ -31,7 +31,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public EpisodeFile UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode)
|
||||
public string UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode)
|
||||
{
|
||||
var existingFiles = localEpisode.Episodes
|
||||
.Where(e => e.EpisodeFileId > 0)
|
||||
|
|
|
@ -158,6 +158,8 @@
|
|||
<Compile Include="Datastore\Migration\013_add_air_date_utc.cs" />
|
||||
<Compile Include="Datastore\Migration\014_drop_air_date.cs" />
|
||||
<Compile Include="Datastore\Migration\015_add_air_date_as_string.cs" />
|
||||
<Compile Include="Datastore\Migration\016_updated_imported_history_item.cs" />
|
||||
<Compile Include="Datastore\Migration\017_reset_scene_names.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />
|
||||
|
@ -342,6 +344,7 @@
|
|||
<Compile Include="Parser\Model\ReportInfo.cs" />
|
||||
<Compile Include="Parser\Parser.cs" />
|
||||
<Compile Include="Parser\ParsingService.cs" />
|
||||
<Compile Include="Parser\QualityParser.cs" />
|
||||
<Compile Include="Providers\UpdateXemMappingsCommand.cs" />
|
||||
<Compile Include="Qualities\QualityProfileInUseException.cs" />
|
||||
<Compile Include="Qualities\QualitySizeRepository.cs" />
|
||||
|
@ -350,6 +353,7 @@
|
|||
<Compile Include="Rest\RestException.cs" />
|
||||
<Compile Include="SeriesStats\SeriesStatisticsService.cs" />
|
||||
<Compile Include="Tv\EpisodeService.cs" />
|
||||
<Compile Include="Tv\Events\EpisodeInfoDeletedEvent.cs" />
|
||||
<Compile Include="Tv\Events\EpisodeInfoUpdatedEvent.cs" />
|
||||
<Compile Include="Tv\Events\EpisodeInfoAddedEvent.cs" />
|
||||
<Compile Include="Tv\Events\SeriesAddedEvent.cs" />
|
||||
|
@ -493,6 +497,7 @@
|
|||
<Compile Include="Tv\RefreshSeriesService.cs" />
|
||||
<Compile Include="Update\Commands\ApplicationUpdateCommand.cs" />
|
||||
<Compile Include="Update\InstallUpdateService.cs" />
|
||||
<Compile Include="Update\UpdatePackageAvailable.cs" />
|
||||
<Compile Include="Update\UpdatePackageProvider.cs" />
|
||||
<Compile Include="Update\UpdatePackage.cs" />
|
||||
<Compile Include="Update\UpdateCheckService.cs" />
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace NzbDrone.Core.Parser.Model
|
|||
|
||||
public bool IsRecentEpisode()
|
||||
{
|
||||
return Episodes.Any(e => e.AirDateUtc >= DateTime.Today.AddDays(-14));
|
||||
return Episodes.Any(e => e.AirDateUtc >= DateTime.UtcNow.Date.AddDays(-14));
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
|
|
@ -74,7 +74,8 @@ namespace NzbDrone.Core.Parser
|
|||
|
||||
private static readonly Regex MultiPartCleanupRegex = new Regex(@"\(\d+\)$", RegexOptions.Compiled);
|
||||
|
||||
private static readonly Regex LanguageRegex = new Regex(@"(?:\W|_)(?<italian>ita|italian)|(?<german>german\b)|(?<flemish>flemish)|(?<greek>greek)(?:\W|_)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
private static readonly Regex LanguageRegex = new Regex(@"(?:\W|_)(?<italian>ita|italian)|(?<german>german\b)|(?<flemish>flemish)|(?<greek>greek)|(?<french>(?:\W|_)FR)(?:\W|_)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
public static ParsedEpisodeInfo ParsePath(string path)
|
||||
{
|
||||
|
@ -119,7 +120,7 @@ namespace NzbDrone.Core.Parser
|
|||
break;
|
||||
|
||||
result.Language = ParseLanguage(title);
|
||||
result.Quality = ParseQuality(title);
|
||||
result.Quality = QualityParser.ParseQuality(title);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -240,155 +241,6 @@ namespace NzbDrone.Core.Parser
|
|||
return parseResult.SeriesTitle;
|
||||
}
|
||||
|
||||
private static QualityModel ParseQuality(string name)
|
||||
{
|
||||
Logger.Trace("Trying to parse quality for {0}", name);
|
||||
|
||||
name = name.Trim();
|
||||
var normalizedName = CleanSeriesTitle(name);
|
||||
var result = new QualityModel { Quality = Quality.Unknown };
|
||||
result.Proper = (normalizedName.Contains("proper") || normalizedName.Contains("repack"));
|
||||
|
||||
if ((normalizedName.Contains("dvd") && !normalizedName.Contains("avcdvd")) || normalizedName.Contains("bdrip") || normalizedName.Contains("brrip"))
|
||||
{
|
||||
result.Quality = Quality.DVD;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (normalizedName.Contains("xvid") || normalizedName.Contains("divx") || normalizedName.Contains("dsr"))
|
||||
{
|
||||
if (normalizedName.Contains("bluray"))
|
||||
{
|
||||
result.Quality = Quality.DVD;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.Quality = Quality.SDTV;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (normalizedName.Contains("bluray"))
|
||||
{
|
||||
if (normalizedName.Contains("720p"))
|
||||
{
|
||||
result.Quality = Quality.Bluray720p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (normalizedName.Contains("1080p"))
|
||||
{
|
||||
result.Quality = Quality.Bluray1080p;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.Quality = Quality.Bluray720p;
|
||||
return result;
|
||||
}
|
||||
if (normalizedName.Contains("webdl") || normalizedName.Contains("webrip"))
|
||||
{
|
||||
if (normalizedName.Contains("1080p"))
|
||||
{
|
||||
result.Quality = Quality.WEBDL1080p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (normalizedName.Contains("720p"))
|
||||
{
|
||||
result.Quality = Quality.WEBDL720p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (name.Contains("[WEBDL]"))
|
||||
{
|
||||
result.Quality = Quality.WEBDL720p;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.Quality = Quality.WEBDL480p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (normalizedName.Contains("trollhd") || normalizedName.Contains("rawhd"))
|
||||
{
|
||||
result.Quality = Quality.RAWHD;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (normalizedName.Contains("x264") || normalizedName.Contains("h264") || normalizedName.Contains("720p"))
|
||||
{
|
||||
if (normalizedName.Contains("1080p"))
|
||||
{
|
||||
result.Quality = Quality.HDTV1080p;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.Quality = Quality.HDTV720p;
|
||||
return result;
|
||||
}
|
||||
|
||||
//Based on extension
|
||||
if (result.Quality == Quality.Unknown && !name.ContainsInvalidPathChars())
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (Path.GetExtension(name).ToLower())
|
||||
{
|
||||
case ".avi":
|
||||
case ".xvid":
|
||||
case ".divx":
|
||||
case ".wmv":
|
||||
case ".mp4":
|
||||
case ".mpg":
|
||||
case ".mpeg":
|
||||
case ".mov":
|
||||
case ".rm":
|
||||
case ".rmvb":
|
||||
case ".flv":
|
||||
case ".dvr-ms":
|
||||
case ".ogm":
|
||||
case ".strm":
|
||||
{
|
||||
result.Quality = Quality.SDTV;
|
||||
break;
|
||||
}
|
||||
case ".mkv":
|
||||
case ".ts":
|
||||
{
|
||||
result.Quality = Quality.HDTV720p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
//Swallow exception for cases where string contains illegal
|
||||
//path characters.
|
||||
}
|
||||
}
|
||||
|
||||
if (name.Contains("[HDTV]"))
|
||||
{
|
||||
result.Quality = Quality.HDTV720p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (normalizedName.Contains("hdtv") && normalizedName.Contains("1080p"))
|
||||
{
|
||||
result.Quality = Quality.HDTV1080p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((normalizedName.Contains("sdtv") || normalizedName.Contains("pdtv") ||
|
||||
(result.Quality == Quality.Unknown && normalizedName.Contains("hdtv"))) &&
|
||||
!normalizedName.Contains("mpeg"))
|
||||
{
|
||||
result.Quality = Quality.SDTV;
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Language ParseLanguage(string title)
|
||||
{
|
||||
var lowerTitle = title.ToLower();
|
||||
|
@ -461,6 +313,9 @@ namespace NzbDrone.Core.Parser
|
|||
if (match.Groups["greek"].Captures.Cast<Capture>().Any())
|
||||
return Language.Greek;
|
||||
|
||||
if (match.Groups["french"].Success)
|
||||
return Language.French;
|
||||
|
||||
return Language.English;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,213 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Parser
|
||||
{
|
||||
public class QualityParser
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private static readonly Regex SourceRegex = new Regex(@"(?<bluray>BluRay)|
|
||||
(?<webdl>WEB-DL|WEBDL|WEB\sDL|WEB\-DL|WebRip)|
|
||||
(?<hdtv>HDTV)|
|
||||
(?<bdrip>BDRiP)|(?<brrip>BRRip)|(?<dvd>\bDVD\b|DVDRip|NTSC|PAL|xvidvd)|
|
||||
(?<dsr>WS\sDSR|WS_DSR|WS\.DSR|DSR)|(?<pdtv>PDTV)|(?<sdtv>SDTV)",
|
||||
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
|
||||
private static readonly Regex ResolutionRegex = new Regex(@"(?<_480p>480p)|(?<_720p>720p)|(?<_1080p>1080p)",
|
||||
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
private static readonly Regex CodecRegex = new Regex(@"(?<x264>x264)|(?<h264>h264)|(?<xvidhd>XvidHD)|(?<xvid>Xvid)|(?<divx>divx)",
|
||||
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public static QualityModel ParseQuality(string name)
|
||||
{
|
||||
Logger.Trace("Trying to parse quality for {0}", name);
|
||||
|
||||
name = name.Trim();
|
||||
var normalizedName = name.CleanSeriesTitle();
|
||||
var result = new QualityModel { Quality = Quality.Unknown };
|
||||
result.Proper = (normalizedName.Contains("proper") || normalizedName.Contains("repack"));
|
||||
|
||||
if (normalizedName.Contains("trollhd") || normalizedName.Contains("rawhd"))
|
||||
{
|
||||
result.Quality = Quality.RAWHD;
|
||||
return result;
|
||||
}
|
||||
|
||||
var sourceMatch = SourceRegex.Match(name);
|
||||
var resolution = ParseResolution(name);
|
||||
var codecRegex = CodecRegex.Match(name);
|
||||
|
||||
if (sourceMatch.Groups["bluray"].Success)
|
||||
{
|
||||
if (codecRegex.Groups["xvid"].Success || codecRegex.Groups["divx"].Success)
|
||||
{
|
||||
result.Quality = Quality.DVD;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (resolution == Resolution._1080p)
|
||||
{
|
||||
result.Quality = Quality.Bluray1080p;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.Quality = Quality.Bluray720p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (sourceMatch.Groups["webdl"].Success)
|
||||
{
|
||||
if (resolution == Resolution._1080p)
|
||||
{
|
||||
result.Quality = Quality.WEBDL1080p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (resolution == Resolution._720p)
|
||||
{
|
||||
result.Quality = Quality.WEBDL720p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (name.Contains("[WEBDL]"))
|
||||
{
|
||||
result.Quality = Quality.WEBDL720p;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.Quality = Quality.WEBDL480p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (sourceMatch.Groups["hdtv"].Success)
|
||||
{
|
||||
if (resolution == Resolution._1080p)
|
||||
{
|
||||
result.Quality = Quality.HDTV1080p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (resolution == Resolution._720p)
|
||||
{
|
||||
result.Quality = Quality.HDTV720p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (name.Contains("[HDTV]"))
|
||||
{
|
||||
result.Quality = Quality.HDTV720p;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.Quality = Quality.SDTV;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (sourceMatch.Groups["dvd"].Success ||
|
||||
sourceMatch.Groups["bdrip"].Success ||
|
||||
sourceMatch.Groups["brrip"].Success)
|
||||
{
|
||||
result.Quality = Quality.DVD;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (sourceMatch.Groups["pdtv"].Success ||
|
||||
sourceMatch.Groups["sdtv"].Success ||
|
||||
sourceMatch.Groups["dsr"].Success)
|
||||
{
|
||||
result.Quality = Quality.SDTV;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (resolution == Resolution._1080p)
|
||||
{
|
||||
result.Quality = Quality.HDTV1080p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (resolution == Resolution._720p)
|
||||
{
|
||||
result.Quality = Quality.HDTV720p;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (codecRegex.Groups["x264"].Success)
|
||||
{
|
||||
result.Quality = Quality.SDTV;
|
||||
return result;
|
||||
}
|
||||
|
||||
//Based on extension
|
||||
if (result.Quality == Quality.Unknown && !name.ContainsInvalidPathChars())
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (Path.GetExtension(name).ToLower())
|
||||
{
|
||||
case ".avi":
|
||||
case ".xvid":
|
||||
case ".divx":
|
||||
case ".wmv":
|
||||
case ".mp4":
|
||||
case ".mpg":
|
||||
case ".mpeg":
|
||||
case ".mov":
|
||||
case ".rm":
|
||||
case ".rmvb":
|
||||
case ".flv":
|
||||
case ".dvr-ms":
|
||||
case ".ogm":
|
||||
case ".strm":
|
||||
{
|
||||
result.Quality = Quality.SDTV;
|
||||
break;
|
||||
}
|
||||
case ".mkv":
|
||||
case ".ts":
|
||||
{
|
||||
result.Quality = Quality.HDTV720p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
//Swallow exception for cases where string contains illegal
|
||||
//path characters.
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Resolution ParseResolution(string name)
|
||||
{
|
||||
var match = ResolutionRegex.Match(name);
|
||||
|
||||
if (!match.Success) return Resolution.Unknown;
|
||||
if (match.Groups["_480p"].Success) return Resolution._480p;
|
||||
if (match.Groups["_720p"].Success) return Resolution._720p;
|
||||
if (match.Groups["_1080p"].Success) return Resolution._1080p;
|
||||
|
||||
return Resolution.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Resolution
|
||||
{
|
||||
_480p,
|
||||
_720p,
|
||||
_1080p,
|
||||
Unknown
|
||||
}
|
||||
}
|
|
@ -2,7 +2,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.Lifecycle;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
|
||||
|
@ -12,31 +14,37 @@ namespace NzbDrone.Core.Providers
|
|||
{
|
||||
void UpdateMappings();
|
||||
void UpdateMappings(int seriesId);
|
||||
void UpdateMappings(Series series);
|
||||
void PerformUpdate(Series series);
|
||||
}
|
||||
|
||||
public class XemProvider : IXemProvider, IExecute<UpdateXemMappingsCommand>, IHandle<SeriesUpdatedEvent>
|
||||
public class XemProvider : IXemProvider, IExecute<UpdateXemMappingsCommand>, IHandle<SeriesUpdatedEvent>, IHandleAsync<ApplicationStartedEvent>
|
||||
{
|
||||
private readonly IEpisodeService _episodeService;
|
||||
private readonly IXemCommunicationProvider _xemCommunicationProvider;
|
||||
private readonly ISeriesService _seriesService;
|
||||
private readonly ICached<bool> _cache;
|
||||
|
||||
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public XemProvider(IEpisodeService episodeService, IXemCommunicationProvider xemCommunicationProvider, ISeriesService seriesService)
|
||||
public XemProvider(IEpisodeService episodeService,
|
||||
IXemCommunicationProvider xemCommunicationProvider,
|
||||
ISeriesService seriesService, ICacheManger cacheManger)
|
||||
{
|
||||
if (seriesService == null) throw new ArgumentNullException("seriesService");
|
||||
_episodeService = episodeService;
|
||||
_xemCommunicationProvider = xemCommunicationProvider;
|
||||
_seriesService = seriesService;
|
||||
_cache = cacheManger.GetCache<bool>(GetType());
|
||||
}
|
||||
|
||||
public void UpdateMappings()
|
||||
{
|
||||
_logger.Trace("Starting scene numbering update");
|
||||
|
||||
try
|
||||
{
|
||||
var ids = _xemCommunicationProvider.GetXemSeriesIds();
|
||||
var ids = GetXemSeriesIds();
|
||||
var series = _seriesService.GetAllSeries();
|
||||
var wantedSeries = series.Where(s => ids.Contains(s.TvdbId)).ToList();
|
||||
|
||||
|
@ -64,12 +72,15 @@ namespace NzbDrone.Core.Providers
|
|||
_logger.Trace("Series could not be found: {0}", seriesId);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateMappings(series);
|
||||
}
|
||||
|
||||
var xemIds = _xemCommunicationProvider.GetXemSeriesIds();
|
||||
|
||||
if (!xemIds.Contains(series.TvdbId))
|
||||
public void UpdateMappings(Series series)
|
||||
{
|
||||
if (!_cache.Find(series.TvdbId.ToString()))
|
||||
{
|
||||
_logger.Trace("Xem doesn't have a mapping for this series: {0}", series.TvdbId);
|
||||
_logger.Trace("Scene numbering is not available for {0} [{1}]", series.Title, series.TvdbId);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -125,6 +136,20 @@ namespace NzbDrone.Core.Providers
|
|||
}
|
||||
}
|
||||
|
||||
private List<int> GetXemSeriesIds()
|
||||
{
|
||||
_cache.Clear();
|
||||
|
||||
var ids = _xemCommunicationProvider.GetXemSeriesIds();
|
||||
|
||||
foreach (var id in ids)
|
||||
{
|
||||
_cache.Set(id.ToString(), true);
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
public void Execute(UpdateXemMappingsCommand message)
|
||||
{
|
||||
if (message.SeriesId.HasValue)
|
||||
|
@ -139,7 +164,12 @@ namespace NzbDrone.Core.Providers
|
|||
|
||||
public void Handle(SeriesUpdatedEvent message)
|
||||
{
|
||||
PerformUpdate(message.Series);
|
||||
UpdateMappings(message.Series);
|
||||
}
|
||||
|
||||
public void HandleAsync(ApplicationStartedEvent message)
|
||||
{
|
||||
GetXemSeriesIds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace NzbDrone.Core.RootFolders
|
|||
{
|
||||
public string Path { get; set; }
|
||||
|
||||
public long FreeSpace { get; set; }
|
||||
public long? FreeSpace { get; set; }
|
||||
|
||||
public List<UnmappedFolder> UnmappedFolders { get; set; }
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace NzbDrone.Core.RootFolders
|
|||
RootFolder Add(RootFolder rootDir);
|
||||
void Remove(int id);
|
||||
List<UnmappedFolder> GetUnmappedFolders(string path);
|
||||
Dictionary<string, long> FreeSpaceOnDrives();
|
||||
Dictionary<string, long?> FreeSpaceOnDrives();
|
||||
RootFolder Get(int id);
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ namespace NzbDrone.Core.RootFolders
|
|||
{
|
||||
if (_diskProvider.FolderExists(folder.Path))
|
||||
{
|
||||
folder.FreeSpace = _diskProvider.GetAvilableSpace(folder.Path);
|
||||
folder.FreeSpace = _diskProvider.GetAvailableSpace(folder.Path);
|
||||
folder.UnmappedFolders = GetUnmappedFolders(folder.Path);
|
||||
}
|
||||
});
|
||||
|
@ -82,7 +82,7 @@ namespace NzbDrone.Core.RootFolders
|
|||
|
||||
_rootFolderRepository.Insert(rootFolder);
|
||||
|
||||
rootFolder.FreeSpace = _diskProvider.GetAvilableSpace(rootFolder.Path);
|
||||
rootFolder.FreeSpace = _diskProvider.GetAvailableSpace(rootFolder.Path);
|
||||
rootFolder.UnmappedFolders = GetUnmappedFolders(rootFolder.Path);
|
||||
return rootFolder;
|
||||
}
|
||||
|
@ -126,9 +126,9 @@ namespace NzbDrone.Core.RootFolders
|
|||
return results;
|
||||
}
|
||||
|
||||
public Dictionary<string, long> FreeSpaceOnDrives()
|
||||
public Dictionary<string, long?> FreeSpaceOnDrives()
|
||||
{
|
||||
var freeSpace = new Dictionary<string, long>();
|
||||
var freeSpace = new Dictionary<string, long?>();
|
||||
|
||||
var rootDirs = All();
|
||||
|
||||
|
@ -140,7 +140,7 @@ namespace NzbDrone.Core.RootFolders
|
|||
{
|
||||
try
|
||||
{
|
||||
freeSpace.Add(pathRoot, _diskProvider.GetAvilableSpace(rootDir.Path));
|
||||
freeSpace.Add(pathRoot, _diskProvider.GetAvailableSpace(rootDir.Path));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -155,7 +155,7 @@ namespace NzbDrone.Core.RootFolders
|
|||
public RootFolder Get(int id)
|
||||
{
|
||||
var rootFolder = _rootFolderRepository.Get(id);
|
||||
rootFolder.FreeSpace = _diskProvider.GetAvilableSpace(rootFolder.Path);
|
||||
rootFolder.FreeSpace = _diskProvider.GetAvailableSpace(rootFolder.Path);
|
||||
rootFolder.UnmappedFolders = GetUnmappedFolders(rootFolder.Path);
|
||||
return rootFolder;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.Tv.Events
|
||||
{
|
||||
public class EpisodeInfoDeletedEvent : IEvent
|
||||
{
|
||||
public ReadOnlyCollection<Episode> Episodes { get; private set; }
|
||||
|
||||
public EpisodeInfoDeletedEvent(IList<Episode> episodes)
|
||||
{
|
||||
Episodes = new ReadOnlyCollection<Episode>(episodes);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ namespace NzbDrone.Core.Tv
|
|||
var successCount = 0;
|
||||
var failCount = 0;
|
||||
|
||||
var existinEpisodes = _episodeService.GetEpisodeBySeries(series.Id);
|
||||
var existingEpisodes = _episodeService.GetEpisodeBySeries(series.Id);
|
||||
var seasons = _seasonService.GetSeasonsBySeries(series.Id);
|
||||
|
||||
var updateList = new List<Episode>();
|
||||
|
@ -44,11 +44,11 @@ namespace NzbDrone.Core.Tv
|
|||
{
|
||||
try
|
||||
{
|
||||
var episodeToUpdate = existinEpisodes.SingleOrDefault(e => e.SeasonNumber == episode.SeasonNumber && e.EpisodeNumber == episode.EpisodeNumber);
|
||||
var episodeToUpdate = existingEpisodes.SingleOrDefault(e => e.SeasonNumber == episode.SeasonNumber && e.EpisodeNumber == episode.EpisodeNumber);
|
||||
|
||||
if (episodeToUpdate != null)
|
||||
{
|
||||
existinEpisodes.Remove(episodeToUpdate);
|
||||
existingEpisodes.Remove(episodeToUpdate);
|
||||
updateList.Add(episodeToUpdate);
|
||||
}
|
||||
else
|
||||
|
@ -82,11 +82,10 @@ namespace NzbDrone.Core.Tv
|
|||
|
||||
AdjustMultiEpisodeAirTime(series, allEpisodes);
|
||||
|
||||
_episodeService.DeleteMany(existinEpisodes);
|
||||
_episodeService.DeleteMany(existingEpisodes);
|
||||
_episodeService.UpdateMany(updateList);
|
||||
_episodeService.InsertMany(newList);
|
||||
|
||||
|
||||
if (newList.Any())
|
||||
{
|
||||
_messageAggregator.PublishEvent(new EpisodeInfoAddedEvent(newList, series));
|
||||
|
@ -97,6 +96,11 @@ namespace NzbDrone.Core.Tv
|
|||
_messageAggregator.PublishEvent(new EpisodeInfoUpdatedEvent(updateList));
|
||||
}
|
||||
|
||||
if (existingEpisodes.Any())
|
||||
{
|
||||
_messageAggregator.PublishEvent(new EpisodeInfoDeletedEvent(updateList));
|
||||
}
|
||||
|
||||
if (failCount != 0)
|
||||
{
|
||||
_logger.Info("Finished episode refresh for series: {0}. Successful: {1} - Failed: {2} ",
|
||||
|
|
Binary file not shown.
|
@ -26,7 +26,7 @@ namespace NzbDrone.Core.Update
|
|||
{
|
||||
var latestAvailable = _updatePackageProvider.GetLatestUpdate();
|
||||
|
||||
if (latestAvailable == null || latestAvailable.Version <= BuildInfo.Version)
|
||||
if (latestAvailable == null)
|
||||
{
|
||||
_logger.Debug("No update available.");
|
||||
return null;
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NzbDrone.Core.Update
|
||||
{
|
||||
public class UpdatePackage
|
||||
{
|
||||
public string Url { get; set; }
|
||||
public string FileName { get; set; }
|
||||
public String Id { get; set; }
|
||||
|
||||
[JsonConverter(typeof(Newtonsoft.Json.Converters.VersionConverter))]
|
||||
public Version Version { get; set; }
|
||||
|
||||
public String Branch { get; set; }
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
public String FileName { get; set; }
|
||||
public String Url { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Update
|
||||
{
|
||||
public class UpdatePackageAvailable
|
||||
{
|
||||
public Boolean Available { get; set; }
|
||||
public UpdatePackage UpdatePackage { get; set; }
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
|
@ -11,56 +12,30 @@ namespace NzbDrone.Core.Update
|
|||
{
|
||||
public interface IUpdatePackageProvider
|
||||
{
|
||||
IEnumerable<UpdatePackage> GetAvailablePackages();
|
||||
UpdatePackage GetLatestUpdate();
|
||||
}
|
||||
|
||||
public class UpdatePackageProvider : IUpdatePackageProvider
|
||||
{
|
||||
private readonly IConfigFileProvider _configService;
|
||||
private readonly IConfigFileProvider _configFileProvider;
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
private readonly Logger _logger;
|
||||
|
||||
private static readonly Regex ParseRegex = new Regex(@"(?:\>)(?<filename>NzbDrone.+?(?<version>(?<=\.)\d+\.\d+\.\d+\.\d+).+?)(?:\<\/a\>)",
|
||||
RegexOptions.IgnoreCase);
|
||||
|
||||
public UpdatePackageProvider(IConfigFileProvider configService, IHttpProvider httpProvider, Logger logger)
|
||||
public UpdatePackageProvider(IConfigFileProvider configFileProvider, IHttpProvider httpProvider, Logger logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_configFileProvider = configFileProvider;
|
||||
_httpProvider = httpProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public IEnumerable<UpdatePackage> GetAvailablePackages()
|
||||
{
|
||||
var updateList = new List<UpdatePackage>();
|
||||
|
||||
var branch = _configService.Branch;
|
||||
var version = BuildInfo.Version;
|
||||
var updateUrl = String.Format("http://update.nzbdrone.com/v{0}/{1}/", version.Major, branch);
|
||||
|
||||
_logger.Debug("Getting a list of updates from {0}", updateUrl);
|
||||
|
||||
var rawUpdateList = _httpProvider.DownloadString(updateUrl);
|
||||
var matches = ParseRegex.Matches(rawUpdateList);
|
||||
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
var updatePackage = new UpdatePackage();
|
||||
updatePackage.FileName = match.Groups["filename"].Value;
|
||||
updatePackage.Url = updateUrl + updatePackage.FileName;
|
||||
updatePackage.Version = new Version(match.Groups["version"].Value);
|
||||
updateList.Add(updatePackage);
|
||||
}
|
||||
|
||||
_logger.Debug("Found {0} update packages", updateUrl.Length);
|
||||
|
||||
return updateList;
|
||||
}
|
||||
|
||||
public UpdatePackage GetLatestUpdate()
|
||||
{
|
||||
return GetAvailablePackages().OrderByDescending(c => c.Version).FirstOrDefault();
|
||||
var url = String.Format("{0}/v1/update/{1}?version={2}", Services.RootUrl, _configFileProvider.Branch, BuildInfo.Version);
|
||||
var update = JsonConvert.DeserializeObject<UpdatePackageAvailable>(_httpProvider.DownloadString(url));
|
||||
|
||||
if (!update.Available) return null;
|
||||
|
||||
return update.UpdatePackage;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ namespace NzbDrone.Core.Validation
|
|||
|
||||
public static IRuleBuilderOptions<T, string> ValidRootUrl<T>(this IRuleBuilder<T, string> ruleBuilder)
|
||||
{
|
||||
ruleBuilder.SetValidator(new NotEmptyValidator(null));
|
||||
return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(?:s)?://[a-z0-9-.]+", RegexOptions.IgnoreCase)).WithMessage("must be valid URL that");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using NetFwTypeLib;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Host.AccessControl
|
||||
|
@ -31,9 +32,6 @@ namespace NzbDrone.Host.AccessControl
|
|||
return;
|
||||
}
|
||||
|
||||
CloseFirewallPort();
|
||||
|
||||
//Open the new port
|
||||
OpenFirewallPort(_configFileProvider.Port);
|
||||
}
|
||||
}
|
||||
|
@ -91,38 +89,10 @@ namespace NzbDrone.Host.AccessControl
|
|||
}
|
||||
}
|
||||
|
||||
private void CloseFirewallPort()
|
||||
{
|
||||
try
|
||||
{
|
||||
var netFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false);
|
||||
var mgr = (INetFwMgr)Activator.CreateInstance(netFwMgrType);
|
||||
var ports = mgr.LocalPolicy.CurrentProfile.GloballyOpenPorts;
|
||||
|
||||
var portNumber = 8989;
|
||||
|
||||
foreach (INetFwOpenPort p in ports)
|
||||
{
|
||||
if (p.Name == "NzbDrone")
|
||||
{
|
||||
portNumber = p.Port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (portNumber != _configFileProvider.Port)
|
||||
{
|
||||
ports.Remove(portNumber, NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.WarnException("Failed to close port in firewall for NzbDrone", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsFirewallEnabled()
|
||||
{
|
||||
if (OsInfo.IsLinux) return false;
|
||||
|
||||
try
|
||||
{
|
||||
var netFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false);
|
||||
|
@ -135,7 +105,5 @@ namespace NzbDrone.Host.AccessControl
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace NzbDrone.Host.AccessControl
|
|||
public interface IUrlAclAdapter
|
||||
{
|
||||
void RefreshRegistration();
|
||||
string UrlAcl { get; }
|
||||
}
|
||||
|
||||
public class UrlAclAdapter : IUrlAclAdapter
|
||||
|
@ -24,18 +25,25 @@ namespace NzbDrone.Host.AccessControl
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public string UrlAcl
|
||||
{
|
||||
get
|
||||
{
|
||||
return "http://*:" + _configFileProvider.Port + "/";
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshRegistration()
|
||||
{
|
||||
if (OsInfo.Version.Major < 6)
|
||||
return;
|
||||
|
||||
RegisterUrl(_configFileProvider.Port);
|
||||
RegisterUrl();
|
||||
}
|
||||
|
||||
|
||||
private void RegisterUrl(int portNumber)
|
||||
private void RegisterUrl()
|
||||
{
|
||||
var arguments = String.Format("http add urlacl http://*:{0}/ sddl=D:(A;;GX;;;S-1-1-0)", portNumber);
|
||||
var arguments = String.Format("http add urlacl {0} sddl=D:(A;;GX;;;S-1-1-0)", UrlAcl);
|
||||
RunNetsh(arguments);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ using NLog;
|
|||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Host.AccessControl;
|
||||
using NzbDrone.Host.Owin;
|
||||
|
||||
namespace NzbDrone.Host
|
||||
|
@ -23,13 +22,10 @@ namespace NzbDrone.Host
|
|||
private readonly IProcessProvider _processProvider;
|
||||
private readonly PriorityMonitor _priorityMonitor;
|
||||
private readonly IStartupArguments _startupArguments;
|
||||
private readonly IFirewallAdapter _firewallAdapter;
|
||||
private readonly IUrlAclAdapter _urlAclAdapter;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public NzbDroneServiceFactory(IConfigFileProvider configFileProvider, IHostController hostController, IRuntimeInfo runtimeInfo,
|
||||
IProcessProvider processProvider, PriorityMonitor priorityMonitor, IStartupArguments startupArguments,
|
||||
IFirewallAdapter firewallAdapter, IUrlAclAdapter urlAclAdapter, Logger logger)
|
||||
IProcessProvider processProvider, PriorityMonitor priorityMonitor, IStartupArguments startupArguments, Logger logger)
|
||||
{
|
||||
_configFileProvider = configFileProvider;
|
||||
_hostController = hostController;
|
||||
|
@ -37,8 +33,6 @@ namespace NzbDrone.Host
|
|||
_processProvider = processProvider;
|
||||
_priorityMonitor = priorityMonitor;
|
||||
_startupArguments = startupArguments;
|
||||
_firewallAdapter = firewallAdapter;
|
||||
_urlAclAdapter = urlAclAdapter;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -49,11 +43,6 @@ namespace NzbDrone.Host
|
|||
|
||||
public void Start()
|
||||
{
|
||||
if (OsInfo.IsWindows && _runtimeInfo.IsAdmin)
|
||||
{
|
||||
_urlAclAdapter.RefreshRegistration();
|
||||
_firewallAdapter.MakeAccessible();
|
||||
}
|
||||
_hostController.StartServer();
|
||||
|
||||
if (!_startupArguments.Flags.Contains(StartupArguments.NO_BROWSER) &&
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Nancy.Bootstrapper;
|
||||
using System;
|
||||
using Nancy.Bootstrapper;
|
||||
using NzbDrone.Api;
|
||||
using NzbDrone.Api.SignalR;
|
||||
using NzbDrone.Common.Composition;
|
||||
|
@ -6,6 +7,7 @@ using NzbDrone.Common.EnvironmentInfo;
|
|||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Host.Owin;
|
||||
|
||||
namespace NzbDrone.Host
|
||||
{
|
||||
|
|
|
@ -122,6 +122,9 @@
|
|||
<Compile Include="AccessControl\FirewallAdapter.cs" />
|
||||
<Compile Include="AccessControl\UrlAclAdapter.cs" />
|
||||
<Compile Include="IUserAlert.cs" />
|
||||
<Compile Include="Owin\NlogTextWriter.cs" />
|
||||
<Compile Include="Owin\OwinServiceProvider.cs" />
|
||||
<Compile Include="Owin\OwinTraceOutputFactory.cs" />
|
||||
<Compile Include="PlatformValidation.cs" />
|
||||
<Compile Include="MainAppContainerBuilder.cs" />
|
||||
<Compile Include="ApplicationModes.cs" />
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
{
|
||||
string AppUrl { get; }
|
||||
void StartServer();
|
||||
void RestartServer();
|
||||
void StopServer();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using NLog;
|
||||
|
||||
namespace NzbDrone.Host.Owin
|
||||
{
|
||||
public class NlogTextWriter : TextWriter
|
||||
{
|
||||
private readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
|
||||
public override Encoding Encoding
|
||||
{
|
||||
get
|
||||
{
|
||||
return Encoding.Default;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(char value)
|
||||
{
|
||||
logger.Trace(value);
|
||||
}
|
||||
|
||||
public override void Write(char[] buffer)
|
||||
{
|
||||
logger.Trace(buffer);
|
||||
}
|
||||
|
||||
public override void Write(string value)
|
||||
{
|
||||
logger.Trace(value);
|
||||
}
|
||||
|
||||
public override void Write(char[] buffer, int index, int count)
|
||||
{
|
||||
logger.Trace(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -3,8 +3,10 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using Microsoft.Owin.Hosting;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Security;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Host.AccessControl;
|
||||
using NzbDrone.Host.Owin.MiddleWare;
|
||||
using Owin;
|
||||
|
||||
|
@ -14,13 +16,20 @@ namespace NzbDrone.Host.Owin
|
|||
{
|
||||
private readonly IConfigFileProvider _configFileProvider;
|
||||
private readonly IEnumerable<IOwinMiddleWare> _owinMiddleWares;
|
||||
private readonly IRuntimeInfo _runtimeInfo;
|
||||
private readonly IUrlAclAdapter _urlAclAdapter;
|
||||
private readonly IFirewallAdapter _firewallAdapter;
|
||||
private readonly Logger _logger;
|
||||
private IDisposable _host;
|
||||
|
||||
public OwinHostController(IConfigFileProvider configFileProvider, IEnumerable<IOwinMiddleWare> owinMiddleWares, Logger logger)
|
||||
public OwinHostController(IConfigFileProvider configFileProvider, IEnumerable<IOwinMiddleWare> owinMiddleWares,
|
||||
IRuntimeInfo runtimeInfo, IUrlAclAdapter urlAclAdapter, IFirewallAdapter firewallAdapter, Logger logger)
|
||||
{
|
||||
_configFileProvider = configFileProvider;
|
||||
_owinMiddleWares = owinMiddleWares;
|
||||
_runtimeInfo = runtimeInfo;
|
||||
_urlAclAdapter = urlAclAdapter;
|
||||
_firewallAdapter = firewallAdapter;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -28,16 +37,20 @@ namespace NzbDrone.Host.Owin
|
|||
{
|
||||
IgnoreCertErrorPolicy.Register();
|
||||
|
||||
var url = "http://*:" + _configFileProvider.Port;
|
||||
if (OsInfo.IsWindows && _runtimeInfo.IsAdmin)
|
||||
{
|
||||
_urlAclAdapter.RefreshRegistration();
|
||||
_firewallAdapter.MakeAccessible();
|
||||
}
|
||||
|
||||
var options = new StartOptions(url)
|
||||
var options = new StartOptions(_urlAclAdapter.UrlAcl)
|
||||
{
|
||||
ServerFactory = "Microsoft.Owin.Host.HttpListener"
|
||||
};
|
||||
|
||||
_logger.Info("starting server on {0}", url);
|
||||
_logger.Info("starting server on {0}", _urlAclAdapter.UrlAcl);
|
||||
|
||||
_host = WebApp.Start(options, BuildApp);
|
||||
_host = WebApp.Start(OwinServiceProviderFactory.Create(), options, BuildApp);
|
||||
}
|
||||
|
||||
private void BuildApp(IAppBuilder appBuilder)
|
||||
|
@ -56,14 +69,6 @@ namespace NzbDrone.Host.Owin
|
|||
get { return string.Format("http://localhost:{0}", _configFileProvider.Port); }
|
||||
}
|
||||
|
||||
public void RestartServer()
|
||||
{
|
||||
_logger.Warn("Attempting to restart server.");
|
||||
|
||||
StopServer();
|
||||
StartServer();
|
||||
}
|
||||
|
||||
public void StopServer()
|
||||
{
|
||||
if (_host == null) return;
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
using Microsoft.Owin.Hosting.Services;
|
||||
using Microsoft.Owin.Hosting.Tracing;
|
||||
|
||||
namespace NzbDrone.Host.Owin
|
||||
{
|
||||
public static class OwinServiceProviderFactory
|
||||
{
|
||||
public static ServiceProvider Create()
|
||||
{
|
||||
var provider = (ServiceProvider)ServicesFactory.Create();
|
||||
provider.Add(typeof(ITraceOutputFactory), typeof(OwinTraceOutputFactory));
|
||||
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
using System.IO;
|
||||
using Microsoft.Owin.Hosting.Tracing;
|
||||
|
||||
namespace NzbDrone.Host.Owin
|
||||
{
|
||||
public class OwinTraceOutputFactory : ITraceOutputFactory
|
||||
{
|
||||
|
||||
public TextWriter Create(string outputFile)
|
||||
{
|
||||
return new NlogTextWriter();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using FluentAssertions;
|
|||
using NUnit.Framework;
|
||||
using NzbDrone.Api.Series;
|
||||
using System.Linq;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Integration.Test
|
||||
{
|
||||
|
@ -15,7 +16,7 @@ namespace NzbDrone.Integration.Test
|
|||
var series = Series.Lookup("archer").First();
|
||||
|
||||
series.QualityProfileId = 1;
|
||||
series.Path = @"C:\Test\Archer";
|
||||
series.Path = @"C:\Test\Archer".AsOsAgnostic();
|
||||
|
||||
series = Series.Post(series);
|
||||
|
||||
|
@ -57,4 +58,4 @@ namespace NzbDrone.Integration.Test
|
|||
Episodes.Put(updatedEpisode).Monitored.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using NLog;
|
||||
using System.Runtime.CompilerServices;
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
using NLog.Targets;
|
||||
using NUnit.Framework;
|
||||
|
@ -39,6 +40,7 @@ namespace NzbDrone.Integration.Test
|
|||
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, consoleTarget));
|
||||
}
|
||||
|
||||
//[TestFixtureSetUp]
|
||||
[SetUp]
|
||||
public void SmokeTestSetup()
|
||||
{
|
||||
|
@ -63,6 +65,7 @@ namespace NzbDrone.Integration.Test
|
|||
NamingConfig = new ClientBase<NamingConfigResource>(RestClient, "config/naming");
|
||||
}
|
||||
|
||||
//[TestFixtureTearDown]
|
||||
[TearDown]
|
||||
public void SmokeTestTearDown()
|
||||
{
|
||||
|
|
|
@ -33,8 +33,9 @@
|
|||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="FluentAssertions">
|
||||
<HintPath>..\packages\FluentAssertions.2.0.1\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentValidation, Version=4.0.0.1, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
|
|
@ -53,11 +53,17 @@ namespace NzbDrone.Integration.Test
|
|||
Assert.Fail("Process has exited");
|
||||
}
|
||||
|
||||
if (_restClient.Get(new RestRequest("system/status")).ResponseStatus == ResponseStatus.Completed)
|
||||
|
||||
var statusCall = _restClient.Get(new RestRequest("system/status"));
|
||||
|
||||
if (statusCall.ResponseStatus == ResponseStatus.Completed)
|
||||
{
|
||||
Console.WriteLine("NzbDrone is started. Running Tests");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Waiting for NzbDrone to start. Response Status : {0} [{1}] {2}", statusCall.ResponseStatus, statusCall.StatusDescription, statusCall.ErrorException);
|
||||
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,5 +58,17 @@ namespace NzbDrone.Integration.Test
|
|||
|
||||
RootFolders.All().Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void invalid_path_should_return_bad_request()
|
||||
{
|
||||
var rootFolder = new RootFolderResource
|
||||
{
|
||||
Path = "invalid_path"
|
||||
};
|
||||
|
||||
var postResponse = RootFolders.InvalidPost(rootFolder);
|
||||
postResponse.Should().NotBeEmpty();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using FluentAssertions;
|
|||
using NUnit.Framework;
|
||||
using NzbDrone.Api.Series;
|
||||
using System.Linq;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Integration.Test
|
||||
{
|
||||
|
@ -15,7 +16,7 @@ namespace NzbDrone.Integration.Test
|
|||
var series = Series.Lookup("archer").First();
|
||||
|
||||
series.QualityProfileId = 1;
|
||||
series.Path = @"C:\Test\Archer";
|
||||
series.Path = @"C:\Test\Archer".AsOsAgnostic();
|
||||
|
||||
series = Series.Post(series);
|
||||
|
||||
|
@ -57,4 +58,4 @@ namespace NzbDrone.Integration.Test
|
|||
Seasons.Put(updatedSeason).Monitored.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,18 +3,13 @@ using FluentAssertions;
|
|||
using NUnit.Framework;
|
||||
using NzbDrone.Api.Series;
|
||||
using System.Linq;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Integration.Test
|
||||
{
|
||||
[TestFixture]
|
||||
public class SeriesIntegrationTest : IntegrationTest
|
||||
{
|
||||
[Test]
|
||||
public void should_have_no_series_on_start_application()
|
||||
{
|
||||
Series.All().Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void series_lookup_on_trakt()
|
||||
{
|
||||
|
@ -37,7 +32,7 @@ namespace NzbDrone.Integration.Test
|
|||
var series = Series.Lookup("archer").First();
|
||||
|
||||
series.QualityProfileId = 1;
|
||||
series.Path = @"C:\Test\Archer";
|
||||
series.Path = @"C:\Test\Archer".AsOsAgnostic();
|
||||
|
||||
series = Series.Post(series);
|
||||
|
||||
|
@ -57,7 +52,7 @@ namespace NzbDrone.Integration.Test
|
|||
var series = Series.Lookup("90210").First();
|
||||
|
||||
series.QualityProfileId = 1;
|
||||
series.Path = @"C:\Test\90210";
|
||||
series.Path = @"C:\Test\90210".AsOsAgnostic();
|
||||
|
||||
series = Series.Post(series);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="2.0.1" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="2.1.0.0" targetFramework="net40" />
|
||||
<package id="FluentValidation" version="4.0.0.1" targetFramework="net40" />
|
||||
<package id="Microsoft.AspNet.SignalR.Client" version="1.1.3" targetFramework="net40" />
|
||||
<package id="Microsoft.Owin" version="1.1.0-beta2" targetFramework="net40" />
|
||||
|
|
|
@ -34,8 +34,9 @@
|
|||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="FluentAssertions">
|
||||
<HintPath>..\packages\FluentAssertions.2.0.1\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.ServiceLocation">
|
||||
<HintPath>..\packages\CommonServiceLocator.1.0\lib\NET35\Microsoft.Practices.ServiceLocation.dll</HintPath>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="CommonServiceLocator" version="1.0" />
|
||||
<package id="FluentAssertions" version="2.0.1" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="2.1.0.0" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" />
|
||||
<package id="NLog" version="2.0.1.2" targetFramework="net40" />
|
||||
|
|
|
@ -43,9 +43,9 @@
|
|||
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions, Version=2.0.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentAssertions.2.0.1\lib\net40\FluentAssertions.dll</HintPath>
|
||||
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Moq">
|
||||
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="2.0.1" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="2.1.0.0" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="NBuilder" version="3.0.1.1" />
|
||||
<package id="NLog" version="2.0.1.2" targetFramework="net40" />
|
||||
|
|
|
@ -83,6 +83,10 @@
|
|||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=2.0.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.2.0.1.2\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Windows.Forms;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Host;
|
||||
using NzbDrone.SysTray;
|
||||
|
@ -8,6 +9,7 @@ namespace NzbDrone
|
|||
{
|
||||
public static class WindowsApp
|
||||
{
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
<package id="Microsoft.Owin" version="1.1.0-beta2" targetFramework="net40" />
|
||||
<package id="Microsoft.Owin.Hosting" version="1.1.0-beta2" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" />
|
||||
<package id="NLog" version="2.0.1.2" targetFramework="net40" />
|
||||
<package id="Owin" version="1.0" targetFramework="net40" />
|
||||
</packages>
|
|
@ -1,4 +1,4 @@
|
|||
'use strict';
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
|
|
|
@ -7,10 +7,11 @@ define(
|
|||
'AddSeries/RootFolders/Collection',
|
||||
'AddSeries/RootFolders/Model',
|
||||
'Shared/LoadingView',
|
||||
'Mixins/AsValidatedView',
|
||||
'Mixins/AutoComplete'
|
||||
], function (Marionette, RootFolderCollectionView, RootFolderCollection, RootFolderModel, LoadingView) {
|
||||
], function (Marionette, RootFolderCollectionView, RootFolderCollection, RootFolderModel, LoadingView, AsValidatedView) {
|
||||
|
||||
return Marionette.Layout.extend({
|
||||
var layout = Marionette.Layout.extend({
|
||||
template: 'AddSeries/RootFolders/LayoutTemplate',
|
||||
|
||||
ui: {
|
||||
|
@ -55,12 +56,16 @@ define(
|
|||
Path: this.ui.pathInput.val()
|
||||
});
|
||||
|
||||
RootFolderCollection.add(newDir);
|
||||
this.bindToModelValidation(newDir);
|
||||
|
||||
newDir.save().done(function () {
|
||||
RootFolderCollection.add(newDir);
|
||||
self.trigger('folderSelected', {model: newDir});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return AsValidatedView.apply(layout);
|
||||
|
||||
});
|
||||
|
|
|
@ -3,10 +3,13 @@
|
|||
<h3>Select Folder</h3>
|
||||
</div>
|
||||
<div class="modal-body root-folders-modal">
|
||||
<div class="input-prepend input-append x-path">
|
||||
<div class="validation-errors"></div>
|
||||
<div class="input-prepend input-append x-path control-group">
|
||||
<span class="add-on"> <i class="icon-folder-open"></i></span>
|
||||
<input class="span9" type="text" placeholder="Start Typing Folder Path...">
|
||||
<button class="btn btn-success x-add"><i class="icon-ok"/></button>
|
||||
<input class="span9" type="text" validation-name="path" placeholder="Start Typing Folder Path...">
|
||||
<button class="btn btn-success x-add">
|
||||
<i class="icon-ok"/>
|
||||
</button>
|
||||
</div>
|
||||
{{#if items}}
|
||||
<h4>Recent Folders</h4>
|
||||
|
|
|
@ -4,6 +4,7 @@ define(
|
|||
'backbone'
|
||||
], function (Backbone) {
|
||||
return Backbone.Model.extend({
|
||||
urlRoot : window.ApiRoot + '/rootfolder',
|
||||
defaults: {
|
||||
freeSpace: 0
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue