mirror of
https://github.com/Radarr/Radarr.git
synced 2024-11-04 10:02:40 +01:00
Merge branch 'develop'
This commit is contained in:
commit
db690adadf
126
Gruntfile.js
126
Gruntfile.js
@ -105,69 +105,65 @@ module.exports = function (grunt) {
|
||||
},
|
||||
|
||||
copy: {
|
||||
index : {
|
||||
content: {
|
||||
cwd : srcRoot,
|
||||
expand: true,
|
||||
src : '*ndex.html',
|
||||
src : [
|
||||
'index.html',
|
||||
'**/*.css',
|
||||
'**/*.png',
|
||||
'**/*.jpg',
|
||||
'**/*.ico',
|
||||
'**/FontAwesome/*.*',
|
||||
'**/fonts/*.*'
|
||||
],
|
||||
dest : outputDir
|
||||
},
|
||||
scripts: {
|
||||
cwd : srcRoot,
|
||||
expand: true,
|
||||
src : '**/*.js',
|
||||
dest : outputDir
|
||||
},
|
||||
styles : {
|
||||
cwd : srcRoot,
|
||||
expand: true,
|
||||
src : '**/*.css',
|
||||
dest : outputDir
|
||||
},
|
||||
images : {
|
||||
cwd : srcRoot,
|
||||
expand: true,
|
||||
src : '**/*.png',
|
||||
dest : outputDir
|
||||
},
|
||||
jpg : {
|
||||
cwd : srcRoot,
|
||||
expand: true,
|
||||
src : '**/*.jpg',
|
||||
dest : outputDir
|
||||
},
|
||||
icon : {
|
||||
cwd : srcRoot,
|
||||
expand: true,
|
||||
src : '**/*.ico',
|
||||
dest : outputDir
|
||||
},
|
||||
fontAwesome : {
|
||||
cwd : srcRoot,
|
||||
expand: true,
|
||||
src : '**/FontAwesome/*.*',
|
||||
dest : outputDir
|
||||
},
|
||||
fonts : {
|
||||
cwd : srcRoot,
|
||||
expand: true,
|
||||
src : '**/fonts/*.*',
|
||||
src : [
|
||||
'**/*.js',
|
||||
],
|
||||
dest : outputDir
|
||||
}
|
||||
},
|
||||
|
||||
jshint: {
|
||||
options: {
|
||||
'-W030': false,
|
||||
'-W064': false,
|
||||
'-W097': false,
|
||||
'-W100': false,
|
||||
'undef': true,
|
||||
'globals': {
|
||||
'require': true,
|
||||
'define': true,
|
||||
'window': true,
|
||||
'document': true,
|
||||
'console': true
|
||||
}
|
||||
},
|
||||
all: [
|
||||
srcRoot + '**/*.js',
|
||||
'!**/JsLibraries/*.js'
|
||||
]
|
||||
},
|
||||
|
||||
requirejs: {
|
||||
compile:{
|
||||
options: {
|
||||
mainConfigFile: "_output/UI/app.js",
|
||||
mainConfigFile: "src/UI/app.js",
|
||||
fileExclusionRegExp: /^.*\.(?!js$)[^.]+$/,
|
||||
preserveLicenseComments: true,
|
||||
dir: "rjs/",
|
||||
preserveLicenseComments: false,
|
||||
dir: outputDir,
|
||||
optimize: 'none',
|
||||
removeCombined: true,
|
||||
inlineText: false,
|
||||
keepBuildDir : true,
|
||||
modules: [{
|
||||
name: 'app',
|
||||
exclude: ['JsLibraries/jquery']
|
||||
exclude: ['JsLibraries/jquery', 'templates.js']
|
||||
}],
|
||||
|
||||
}
|
||||
@ -190,37 +186,21 @@ module.exports = function (grunt) {
|
||||
files: '<%= handlebars.files.src %>',
|
||||
tasks: ['handlebars']
|
||||
},
|
||||
copyIndex : {
|
||||
files: '<%= copy.index.cwd %><%= copy.index.src %>',
|
||||
tasks: ['copy:index']
|
||||
content : {
|
||||
files: [
|
||||
'**/index.html',
|
||||
'**/*.css',
|
||||
'**/*.png',
|
||||
'**/*.jpg',
|
||||
'**/*.ico',
|
||||
'**/FontAwesome/*.*',
|
||||
'**/fonts/*.*'
|
||||
],
|
||||
tasks: ['copy:content']
|
||||
},
|
||||
copyScripts: {
|
||||
scripts: {
|
||||
files: '<%= copy.scripts.cwd %><%= copy.scripts.src %>',
|
||||
tasks: ['copy:scripts']
|
||||
},
|
||||
copyStyles : {
|
||||
files: '<%= copy.styles.cwd %><%= copy.styles.src %>',
|
||||
tasks: ['copy:styles']
|
||||
},
|
||||
copyImages : {
|
||||
files: '<%= copy.images.cwd %><%= copy.images.src %>',
|
||||
tasks: ['copy:images']
|
||||
},
|
||||
copyJpg : {
|
||||
files: '<%= copy.jpg.cwd %><%= copy.jpg.src %>',
|
||||
tasks: ['copy:jpg']
|
||||
},
|
||||
copyIcon : {
|
||||
files: '<%= copy.icon.cwd %><%= copy.icon.src %>',
|
||||
tasks: ['copy:icon']
|
||||
},
|
||||
copyFontAwesome : {
|
||||
files: '<%= copy.fontAwesome.cwd %><%= copy.fontAwesome.src %>',
|
||||
tasks: ['copy:fontAwesome']
|
||||
},
|
||||
copyFonts : {
|
||||
files: '<%= copy.fonts.cwd %><%= copy.fonts.src %>',
|
||||
tasks: ['copy:fonts']
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -233,8 +213,10 @@ module.exports = function (grunt) {
|
||||
grunt.loadNpmTasks('grunt-notify');
|
||||
grunt.loadNpmTasks('grunt-curl');
|
||||
grunt.loadNpmTasks('grunt-contrib-requirejs');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
|
||||
grunt.registerTask('package', ['clean:output', 'copy', 'less', 'handlebars']);
|
||||
grunt.registerTask('package', ['clean:output', 'jshint', 'handlebars', 'copy', 'less']);
|
||||
grunt.registerTask('packagerjs', ['clean:output','jshint', 'handlebars', 'requirejs', 'copy:content', 'less']);
|
||||
grunt.registerTask('default', ['package', 'watch']);
|
||||
grunt.registerTask('update', ['curl']);
|
||||
|
||||
|
1
NzbDrone.sln.DotSettings
Normal file
1
NzbDrone.sln.DotSettings
Normal file
@ -0,0 +1 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
|
15
build.ps1
15
build.ps1
@ -6,6 +6,8 @@ $testSearchPattern = '*.Test\bin\x86\Release'
|
||||
|
||||
Function Build()
|
||||
{
|
||||
Write-Host "##teamcity[progressStart 'Build']"
|
||||
|
||||
$clean = $msbuild + " src\nzbdrone.sln /t:Clean /m"
|
||||
$build = $msbuild + " src\nzbdrone.sln /p:Configuration=Release /p:Platform=x86 /t:Build /m"
|
||||
|
||||
@ -23,6 +25,8 @@ Function Build()
|
||||
CleanFolder $outputFolder
|
||||
|
||||
AddJsonNet
|
||||
|
||||
Write-Host "##teamcity[progressFinish 'Build']"
|
||||
}
|
||||
|
||||
Function CleanFolder($path)
|
||||
@ -53,6 +57,8 @@ Function CleanFolder($path)
|
||||
|
||||
Function PackageMono()
|
||||
{
|
||||
Write-Host "##teamcity[progressStart 'Creating Mono Package']"
|
||||
|
||||
if(Test-Path $outputFolderMono)
|
||||
{
|
||||
Remove-Item -Recurse -Force $outputFolderMono -ErrorAction Continue
|
||||
@ -77,6 +83,8 @@ Function PackageMono()
|
||||
Write-Host Renaming NzbDrone.Console.exe to NzbDrone.exe
|
||||
get-childitem $outputFolderMono -File -Filter NzbDrone.exe -Recurse | foreach ($_) {remove-item $_.fullname}
|
||||
Rename-Item "$outputFolderMono\NzbDrone.Console.exe" "NzbDrone.exe"
|
||||
|
||||
Write-Host "##teamcity[progressFinish 'Creating Mono Package']"
|
||||
}
|
||||
|
||||
|
||||
@ -89,7 +97,9 @@ Function AddJsonNet()
|
||||
|
||||
Function PackageTests()
|
||||
{
|
||||
|
||||
Write-Host Packaging Tests
|
||||
Write-Host "##teamcity[progressStart 'Creating Mono Package']"
|
||||
|
||||
if(Test-Path $testPackageFolder)
|
||||
{
|
||||
@ -111,17 +121,22 @@ Function PackageTests()
|
||||
get-childitem $testPackageFolder -File -Filter *log.config | foreach ($_) {remove-item $_.fullname}
|
||||
|
||||
CleanFolder $testPackageFolder
|
||||
|
||||
Write-Host "##teamcity[progressFinish 'Creating Mono Package']"
|
||||
}
|
||||
|
||||
|
||||
Function RunGrunt()
|
||||
{
|
||||
Write-Host "##teamcity[progressStart 'Running Grunt']"
|
||||
$gruntPath = [environment]::getfolderpath("applicationdata") + '\npm\node_modules\grunt-cli\bin\grunt'
|
||||
Invoke-Expression 'npm install'
|
||||
CheckExitCode
|
||||
|
||||
Invoke-Expression ('node ' + $gruntPath + ' package')
|
||||
CheckExitCode
|
||||
|
||||
Write-Host "##teamcity[progressFinish 'Running Grunt']"
|
||||
}
|
||||
|
||||
Function CheckExitCode()
|
||||
|
@ -23,6 +23,7 @@
|
||||
"grunt-curl": "*",
|
||||
"grunt-notify": "*",
|
||||
"grunt-contrib-clean": "*",
|
||||
"grunt-contrib-requirejs": "*"
|
||||
"grunt-contrib-requirejs": "*",
|
||||
"grunt-contrib-jshint": "*"
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -2,38 +2,62 @@
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
|
||||
|
||||
<!-- Windows specific commands -->
|
||||
<NuGetToolsPath Condition=" '$(OS)' == 'Windows_NT'">$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
|
||||
<PackagesConfig Condition=" '$(OS)' == 'Windows_NT'">$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
|
||||
<PackagesDir Condition=" '$(OS)' == 'Windows_NT'">$([System.IO.Path]::Combine($(SolutionDir), "packages"))</PackagesDir>
|
||||
|
||||
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
|
||||
<NuGetToolsPath Condition=" '$(OS)' != 'Windows_NT'">$(SolutionDir).nuget</NuGetToolsPath>
|
||||
<PackagesConfig Condition=" '$(OS)' != 'Windows_NT' ">packages.config</PackagesConfig>
|
||||
<PackagesDir Condition=" '$(OS)' != 'Windows_NT'">$(SolutionDir)packages</PackagesDir>
|
||||
|
||||
<!-- Enable the restore command to run before builds -->
|
||||
<RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
|
||||
|
||||
<!-- Property that enables building a package from a project -->
|
||||
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
|
||||
|
||||
<!-- Determines if package restore consent is required to restore packages -->
|
||||
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
|
||||
|
||||
<!-- Download NuGet.exe if it does not already exist -->
|
||||
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(PackageSources)' == '' ">
|
||||
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
|
||||
<!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
|
||||
<!--
|
||||
<PackageSource Include="https://www.nuget.org/api/v2/" />
|
||||
<PackageSource Include="https://my-nuget-source/nuget/" />
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
|
||||
<!-- Windows specific commands -->
|
||||
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
|
||||
<PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
|
||||
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
|
||||
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
|
||||
<PackagesConfig>packages.config</PackagesConfig>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- NuGet command -->
|
||||
<NuGetExePath>$(NuGetToolsPath)\nuget.exe</NuGetExePath>
|
||||
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
|
||||
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
|
||||
|
||||
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
|
||||
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
|
||||
|
||||
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
|
||||
|
||||
<!-- Package sources used to restore packages. By default will used the registered sources under %APPDATA%\NuGet\NuGet.Config -->
|
||||
<PackageSources>"http://build.nzbdrone.com/guestAuth/app/nuget/v1/FeedService.svc";"https://nuget.org/api/v2/"</PackageSources>
|
||||
|
||||
<!-- Enable the restore command to run before builds -->
|
||||
<RestorePackages Condition="$(RestorePackages) == ''">false</RestorePackages>
|
||||
|
||||
<!-- Property that enables building a package from a project -->
|
||||
<BuildPackage Condition="$(BuildPackage) == ''">false</BuildPackage>
|
||||
|
||||
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
|
||||
<NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
|
||||
|
||||
<PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
|
||||
<PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>
|
||||
|
||||
<!-- Commands -->
|
||||
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source $(PackageSources) -o "$(PackagesDir)"</RestoreCommand>
|
||||
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols</BuildCommand>
|
||||
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
|
||||
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
|
||||
|
||||
<!-- Make the build depend on restore packages -->
|
||||
<!-- We need to ensure packages are restored prior to assembly resolve -->
|
||||
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
|
||||
RestorePackages;
|
||||
$(BuildDependsOn);
|
||||
@ -48,7 +72,17 @@
|
||||
|
||||
<Target Name="CheckPrerequisites">
|
||||
<!-- Raise an error if we're unable to locate nuget.exe -->
|
||||
<Error Condition="!Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
|
||||
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
|
||||
<!--
|
||||
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
|
||||
This effectively acts as a lock that makes sure that the download operation will only happen once and all
|
||||
parallel builds will have to wait for it to complete.
|
||||
-->
|
||||
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_DownloadNuGet">
|
||||
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
|
||||
@ -68,4 +102,35 @@
|
||||
LogStandardErrorAsError="true"
|
||||
Condition=" '$(OS)' == 'Windows_NT' " />
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
||||
<ParameterGroup>
|
||||
<OutputFilename ParameterType="System.String" Required="true" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Reference Include="System.Core" />
|
||||
<Using Namespace="System" />
|
||||
<Using Namespace="System.IO" />
|
||||
<Using Namespace="System.Net" />
|
||||
<Using Namespace="Microsoft.Build.Framework" />
|
||||
<Using Namespace="Microsoft.Build.Utilities" />
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
try {
|
||||
OutputFilename = Path.GetFullPath(OutputFilename);
|
||||
|
||||
Log.LogMessage("Downloading latest version of NuGet.exe...");
|
||||
WebClient webClient = new WebClient();
|
||||
webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Log.LogErrorFromException(ex);
|
||||
return false;
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
</Project>
|
@ -17,11 +17,10 @@ public NzbDroneErrorPipeline(Logger logger)
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Response HandleException(NancyContext context, Exception aggregateException)
|
||||
public Response HandleException(NancyContext context, Exception exception)
|
||||
{
|
||||
var innerException = (aggregateException.InnerException).InnerException;
|
||||
|
||||
var apiException = innerException as ApiException;
|
||||
var apiException = exception as ApiException;
|
||||
|
||||
if (apiException != null)
|
||||
{
|
||||
@ -29,7 +28,7 @@ public Response HandleException(NancyContext context, Exception aggregateExcepti
|
||||
return apiException.ToErrorResponse();
|
||||
}
|
||||
|
||||
var validationException = innerException as ValidationException;
|
||||
var validationException = exception as ValidationException;
|
||||
|
||||
if (validationException != null)
|
||||
{
|
||||
@ -38,23 +37,23 @@ public Response HandleException(NancyContext context, Exception aggregateExcepti
|
||||
return validationException.Errors.AsResponse(HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
var clientException = innerException as NzbDroneClientException;
|
||||
var clientException = exception as NzbDroneClientException;
|
||||
|
||||
if (clientException != null)
|
||||
{
|
||||
return new ErrorModel
|
||||
{
|
||||
Message = innerException.Message,
|
||||
Description = innerException.ToString()
|
||||
Message = exception.Message,
|
||||
Description = exception.ToString()
|
||||
}.AsResponse((HttpStatusCode)clientException.StatusCode);
|
||||
}
|
||||
|
||||
_logger.FatalException("Request Failed", innerException);
|
||||
_logger.FatalException("Request Failed", exception);
|
||||
|
||||
return new ErrorModel
|
||||
{
|
||||
Message = innerException.Message,
|
||||
Description = innerException.ToString()
|
||||
Message = exception.Message,
|
||||
Description = exception.ToString()
|
||||
}.AsResponse(HttpStatusCode.InternalServerError);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Nancy;
|
||||
|
||||
namespace NzbDrone.Api.Extensions
|
||||
|
@ -19,7 +19,6 @@ public static class ValueInjectorExtensions
|
||||
source.GetType().GetGenericTypeDefinition() != null &&
|
||||
source.GetType().GetGenericTypeDefinition().GetInterfaces().Contains(typeof(IEnumerable)))
|
||||
{
|
||||
|
||||
var result = new TTarget();
|
||||
|
||||
var listSubType = targetType.GetGenericArguments()[0];
|
||||
|
@ -38,29 +38,29 @@
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="FluentValidation, Version=4.0.0.1, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="FluentValidation, Version=5.0.0.1, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentValidation.4.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
|
||||
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.SignalR.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Nancy, Version=0.20.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Nancy, Version=0.21.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Nancy.0.20.0\lib\net40\Nancy.dll</HintPath>
|
||||
<HintPath>..\packages\Nancy.0.21.1\lib\net40\Nancy.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Nancy.Authentication.Basic, Version=0.20.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Nancy.Authentication.Basic, Version=0.21.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Nancy.Authentication.Basic.0.20.0\lib\net40\Nancy.Authentication.Basic.dll</HintPath>
|
||||
<HintPath>..\packages\Nancy.Authentication.Basic.0.21.1\lib\net40\Nancy.Authentication.Basic.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=2.0.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.2.0.1.2\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Omu.ValueInjecter">
|
||||
<HintPath>..\packages\ValueInjecter.2.3.3\lib\net35\Omu.ValueInjecter.dll</HintPath>
|
||||
|
@ -1,15 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Api.Validation;
|
||||
|
||||
namespace NzbDrone.Api.RootFolders
|
||||
{
|
||||
public class RootFolderModule : NzbDroneRestModule<RootFolderResource>
|
||||
public class RootFolderModule : NzbDroneRestModuleWithSignalR<RootFolderResource, RootFolder>
|
||||
{
|
||||
private readonly IRootFolderService _rootFolderService;
|
||||
|
||||
public RootFolderModule(IRootFolderService rootFolderService)
|
||||
public RootFolderModule(IRootFolderService rootFolderService, ICommandExecutor commandExecutor)
|
||||
: base(commandExecutor)
|
||||
{
|
||||
_rootFolderService = rootFolderService;
|
||||
|
||||
@ -18,7 +20,7 @@ public RootFolderModule(IRootFolderService rootFolderService)
|
||||
CreateResource = CreateRootFolder;
|
||||
DeleteResource = DeleteFolder;
|
||||
|
||||
SharedValidator.RuleFor(c=>c.Path).IsValidPath();
|
||||
SharedValidator.RuleFor(c => c.Path).IsValidPath();
|
||||
}
|
||||
|
||||
private RootFolderResource GetRootFolder(int id)
|
||||
|
@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentValidation" version="4.0.0.1" targetFramework="net40" />
|
||||
<package id="FluentValidation" version="5.0.0.1" targetFramework="net40" />
|
||||
<package id="Microsoft.AspNet.SignalR.Core" version="1.1.3" targetFramework="net40" />
|
||||
<package id="Nancy" version="0.20.0" targetFramework="net40" />
|
||||
<package id="Nancy.Authentication.Basic" version="0.20.0" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" />
|
||||
<package id="NLog" version="2.0.1.2" targetFramework="net40" />
|
||||
<package id="Nancy" version="0.21.1" targetFramework="net40" />
|
||||
<package id="Nancy.Authentication.Basic" version="0.21.1" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net40" />
|
||||
<package id="NLog" version="2.1.0" targetFramework="net40" />
|
||||
<package id="ValueInjecter" version="2.3.3" targetFramework="net40" />
|
||||
</packages>
|
@ -44,9 +44,9 @@
|
||||
<Reference Include="Moq">
|
||||
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=2.0.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.2.0.1.2\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
@ -3,6 +3,6 @@
|
||||
<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" />
|
||||
<package id="NLog" version="2.1.0" targetFramework="net40" />
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net40" />
|
||||
</packages>
|
76
src/NzbDrone.Automation.Test/AutomationTest.cs
Normal file
76
src/NzbDrone.Automation.Test/AutomationTest.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using FluentAssertions;
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
using NLog.Targets;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Automation.Test.PageModel;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Test.Common;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Firefox;
|
||||
using OpenQA.Selenium.IE;
|
||||
using OpenQA.Selenium.Remote;
|
||||
using OpenQA.Selenium.Support.UI;
|
||||
|
||||
namespace NzbDrone.Automation.Test
|
||||
{
|
||||
[TestFixture]
|
||||
[AutomationTest]
|
||||
public abstract class AutomationTest
|
||||
{
|
||||
private NzbDroneRunner _runner;
|
||||
protected RemoteWebDriver driver;
|
||||
|
||||
public AutomationTest()
|
||||
{
|
||||
new StartupArguments();
|
||||
|
||||
LogManager.Configuration = new LoggingConfiguration();
|
||||
var consoleTarget = new ConsoleTarget { Layout = "${level}: ${message} ${exception}" };
|
||||
LogManager.Configuration.AddTarget(consoleTarget.GetType().Name, consoleTarget);
|
||||
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, consoleTarget));
|
||||
}
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void SmokeTestSetup()
|
||||
{
|
||||
driver = new FirefoxDriver();
|
||||
|
||||
_runner = new NzbDroneRunner();
|
||||
_runner.KillAll();
|
||||
_runner.Start();
|
||||
|
||||
|
||||
driver.Url = "http://localhost:8989";
|
||||
|
||||
var page = new PageBase(driver);
|
||||
page.WaitForNoSpinner();
|
||||
|
||||
GetPageErrors().Should().BeEmpty();
|
||||
|
||||
}
|
||||
|
||||
protected IEnumerable<string> GetPageErrors()
|
||||
{
|
||||
return driver.FindElements(By.CssSelector("#errors div"))
|
||||
.Select(e => e.Text);
|
||||
}
|
||||
|
||||
[TestFixtureTearDown]
|
||||
public void SmokeTestTearDown()
|
||||
{
|
||||
_runner.KillAll();
|
||||
driver.Quit();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void AutomationTearDown()
|
||||
{
|
||||
GetPageErrors().Should().BeEmpty();
|
||||
}
|
||||
}
|
||||
}
|
13
src/NzbDrone.Automation.Test/AutomationTestAttribute.cs
Normal file
13
src/NzbDrone.Automation.Test/AutomationTestAttribute.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace NzbDrone.Automation.Test
|
||||
{
|
||||
public class AutomationTestAttribute : CategoryAttribute
|
||||
{
|
||||
public AutomationTestAttribute()
|
||||
: base("AutomationTest")
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
81
src/NzbDrone.Automation.Test/MainPagesTest.cs
Normal file
81
src/NzbDrone.Automation.Test/MainPagesTest.cs
Normal file
@ -0,0 +1,81 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Automation.Test.PageModel;
|
||||
using OpenQA.Selenium;
|
||||
|
||||
namespace NzbDrone.Automation.Test
|
||||
{
|
||||
[TestFixture]
|
||||
public class MainPagesTest : AutomationTest
|
||||
{
|
||||
private PageBase page;
|
||||
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
page = new PageBase(driver);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void series_page()
|
||||
{
|
||||
page.SeriesNavIcon.Click();
|
||||
page.WaitForNoSpinner();
|
||||
page.FindByClass("iv-series-index-seriesindexlayout").Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void calendar_page()
|
||||
{
|
||||
page.CalendarNavIcon.Click();
|
||||
page.WaitForNoSpinner();
|
||||
|
||||
page.FindByClass("iv-calendar-calendarlayout").Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void history_page()
|
||||
{
|
||||
page.HistoryNavIcon.Click();
|
||||
page.WaitForNoSpinner();
|
||||
|
||||
page.FindByClass("iv-history-historylayout").Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void missing_page()
|
||||
{
|
||||
page.MissingNavIcon.Click();
|
||||
page.WaitForNoSpinner();
|
||||
|
||||
page.FindByClass("iv-missing-missinglayout").Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void system_page()
|
||||
{
|
||||
page.SystemNavIcon.Click();
|
||||
page.WaitForNoSpinner();
|
||||
|
||||
page.FindByClass("iv-system-systemlayout").Should().NotBeNull();
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void add_series_page()
|
||||
{
|
||||
page.SeriesNavIcon.Click();
|
||||
page.WaitForNoSpinner();
|
||||
|
||||
page.Find(By.LinkText("Add Series")).Click();
|
||||
|
||||
page.WaitForNoSpinner();
|
||||
|
||||
page.FindByClass("iv-addseries-addserieslayout").Should().NotBeNull();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
90
src/NzbDrone.Automation.Test/NzbDrone.Automation.Test.csproj
Normal file
90
src/NzbDrone.Automation.Test/NzbDrone.Automation.Test.csproj
Normal file
@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{CC26800D-F67E-464B-88DE-8EB1A0C227A3}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>NzbDrone.Automation.Test</RootNamespace>
|
||||
<AssemblyName>NzbDrone.Automation.Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<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="NLog">
|
||||
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework">
|
||||
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WebDriver">
|
||||
<HintPath>..\packages\Selenium.WebDriver.2.37.0\lib\net40\WebDriver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WebDriver.Support">
|
||||
<HintPath>..\packages\Selenium.Support.2.37.0\lib\net40\WebDriver.Support.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AutomationTestAttribute.cs" />
|
||||
<Compile Include="AutomationTest.cs" />
|
||||
<Compile Include="MainPagesTest.cs" />
|
||||
<Compile Include="PageModel\PageBase.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
|
||||
<Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
|
||||
<Name>NzbDrone.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\NzbDrone.Test.Common\NzbDrone.Test.Common.csproj">
|
||||
<Project>{CADDFCE0-7509-4430-8364-2074E1EEFCA2}</Project>
|
||||
<Name>NzbDrone.Test.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
100
src/NzbDrone.Automation.Test/PageModel/PageBase.cs
Normal file
100
src/NzbDrone.Automation.Test/PageModel/PageBase.cs
Normal file
@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Remote;
|
||||
using OpenQA.Selenium.Support.UI;
|
||||
|
||||
namespace NzbDrone.Automation.Test.PageModel
|
||||
{
|
||||
public class PageBase
|
||||
{
|
||||
private readonly RemoteWebDriver _driver;
|
||||
|
||||
public PageBase(RemoteWebDriver driver)
|
||||
{
|
||||
_driver = driver;
|
||||
}
|
||||
|
||||
public IWebElement FindByClass(string className, int timeout = 5)
|
||||
{
|
||||
return Find(By.ClassName(className), timeout);
|
||||
}
|
||||
|
||||
public IWebElement Find(By by, int timeout = 5)
|
||||
{
|
||||
var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(timeout));
|
||||
return wait.Until(d => d.FindElement(by));
|
||||
}
|
||||
|
||||
|
||||
public void WaitForNoSpinner(int timeout = 20)
|
||||
{
|
||||
//give the spinner some time to show up.
|
||||
Thread.Sleep(100);
|
||||
|
||||
var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(timeout));
|
||||
wait.Until(d =>
|
||||
{
|
||||
try
|
||||
{
|
||||
IWebElement element = d.FindElement(By.Id("followingBalls"));
|
||||
return !element.Displayed;
|
||||
}
|
||||
catch (NoSuchElementException)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public IWebElement SeriesNavIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
return Find(By.LinkText("Series"));
|
||||
}
|
||||
}
|
||||
|
||||
public IWebElement CalendarNavIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
return Find(By.LinkText("Calendar"));
|
||||
}
|
||||
}
|
||||
|
||||
public IWebElement HistoryNavIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
return Find(By.LinkText("History"));
|
||||
}
|
||||
}
|
||||
|
||||
public IWebElement MissingNavIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
return Find(By.LinkText("Missing"));
|
||||
}
|
||||
}
|
||||
|
||||
public IWebElement SettingNavIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
return Find(By.LinkText("Settings"));
|
||||
}
|
||||
}
|
||||
|
||||
public IWebElement SystemNavIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
return Find(By.LinkText("System"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
36
src/NzbDrone.Automation.Test/Properties/AssemblyInfo.cs
Normal file
36
src/NzbDrone.Automation.Test/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("NzbDrone.Automation.Test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("NzbDrone.Automation.Test")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("6b8945f5-f5b5-4729-865d-f958fbd673d9")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
8
src/NzbDrone.Automation.Test/packages.config
Normal file
8
src/NzbDrone.Automation.Test/packages.config
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="2.1.0.0" targetFramework="net40" />
|
||||
<package id="NLog" version="2.1.0" targetFramework="net40" />
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net40" />
|
||||
<package id="Selenium.Support" version="2.37.0" targetFramework="net40" />
|
||||
<package id="Selenium.WebDriver" version="2.37.0" targetFramework="net40" />
|
||||
</packages>
|
@ -155,10 +155,14 @@ public void empty_folder_should_return_folder_modified_date()
|
||||
[Test]
|
||||
public void folder_should_return_correct_value_for_last_write()
|
||||
{
|
||||
var testFile = GetTestFilePath();
|
||||
var testDir = Path.Combine(SandboxFolder, "LastWrite");
|
||||
var testFile = Path.Combine(testDir, Path.GetRandomFileName());
|
||||
|
||||
Directory.CreateDirectory(testDir);
|
||||
|
||||
TestLogger.Info("Path is: {0}", testFile);
|
||||
|
||||
|
||||
Subject.WriteAllText(testFile, "Test");
|
||||
|
||||
Subject.GetLastFolderWrite(SandboxFolder).Should().BeOnOrAfter(DateTime.UtcNow.AddMinutes(-1));
|
||||
|
@ -41,9 +41,9 @@
|
||||
<Reference Include="Moq">
|
||||
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=2.0.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.2.0.1.2\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
@ -2,6 +2,6 @@
|
||||
<packages>
|
||||
<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="NLog" version="2.1.0" targetFramework="net40" />
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net40" />
|
||||
</packages>
|
@ -301,27 +301,18 @@ public void InheritFolderPermissions(string filename)
|
||||
|
||||
if (OsInfo.IsLinux)
|
||||
{
|
||||
var drives = DriveInfo.GetDrives();
|
||||
|
||||
foreach (var drive in drives)
|
||||
try
|
||||
{
|
||||
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 GetDriveInfoLinux(path).AvailableFreeSpace;
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
Logger.ErrorException("Couldn't get free space for " + path, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return DriveFreeSpaceEx(root);
|
||||
}
|
||||
|
||||
@ -471,27 +462,18 @@ public string[] GetFixedDrives()
|
||||
|
||||
if (OsInfo.IsLinux)
|
||||
{
|
||||
var drives = DriveInfo.GetDrives();
|
||||
|
||||
foreach (var drive in drives)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (drive.IsReady && path.StartsWith(drive.Name, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return drive.TotalSize;
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
Logger.ErrorException("Couldn't get total space for " + path, e);
|
||||
}
|
||||
return GetDriveInfoLinux(path).TotalSize;
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
Logger.ErrorException("Couldn't get total space for " + path, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return DriveTotalSizeEx(root);
|
||||
}
|
||||
|
||||
@ -554,5 +536,16 @@ private static long DriveTotalSizeEx(string folderName)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private DriveInfo GetDriveInfoLinux(string path)
|
||||
{
|
||||
var drives = DriveInfo.GetDrives();
|
||||
|
||||
return
|
||||
drives.Where(drive =>
|
||||
drive.IsReady && path.StartsWith(drive.Name, StringComparison.CurrentCultureIgnoreCase))
|
||||
.OrderByDescending(drive => drive.Name.Length)
|
||||
.First();
|
||||
}
|
||||
}
|
||||
}
|
@ -92,7 +92,6 @@ public static Param<string> IsRelativePath(this Param<string> param)
|
||||
throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid relative path. relative paths can not start with \\", param.Value));
|
||||
}
|
||||
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
|
@ -46,11 +46,11 @@
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=2.0.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.2.0.1.2\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="loggly-csharp" version="2.3" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" />
|
||||
<package id="NLog" version="2.0.1.2" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net40" />
|
||||
<package id="NLog" version="2.1.0" targetFramework="net40" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
|
||||
</packages>
|
@ -81,11 +81,11 @@
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=2.0.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.2.0.1.2\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<package id="Microsoft.AspNet.SignalR.Owin" version="1.1.3" targetFramework="net40" />
|
||||
<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="Newtonsoft.Json" version="5.0.8" targetFramework="net40" />
|
||||
<package id="NLog" version="2.1.0" targetFramework="net40" />
|
||||
<package id="Owin" version="1.0" targetFramework="net40" />
|
||||
</packages>
|
||||
</packages>
|
||||
|
@ -0,0 +1,37 @@
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Housekeeping.Housekeepers;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||
{
|
||||
[TestFixture]
|
||||
public class CleanupAdditionalNamingSpecsFixture : DbTest<CleanupAdditionalNamingSpecs, NamingConfig>
|
||||
{
|
||||
[Test]
|
||||
public void should_delete_additional_naming_configs()
|
||||
{
|
||||
var specs = Builder<NamingConfig>.CreateListOfSize(5)
|
||||
.BuildListOfNew();
|
||||
|
||||
Db.InsertMany(specs);
|
||||
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_delete_if_only_one_spec()
|
||||
{
|
||||
var spec = Builder<NamingConfig>.CreateNew()
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(spec);
|
||||
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(1);
|
||||
}
|
||||
}
|
||||
}
|
@ -124,7 +124,7 @@ public void should_delete_folder_if_files_were_imported()
|
||||
imported.Add(new ImportDecision(localEpisode));
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Setup(s => s.GetImportDecisions(It.IsAny<IEnumerable<String>>(), It.IsAny<Series>(), true))
|
||||
.Setup(s => s.GetImportDecisions(It.IsAny<IEnumerable<String>>(), It.IsAny<Series>(), true, null))
|
||||
.Returns(imported);
|
||||
|
||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||
|
@ -9,6 +9,7 @@
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Test.Common;
|
||||
@ -21,6 +22,7 @@ public class ImportDecisionMakerFixture : CoreTest<ImportDecisionMaker>
|
||||
private List<string> _videoFiles;
|
||||
private LocalEpisode _localEpisode;
|
||||
private Series _series;
|
||||
private QualityModel _quality;
|
||||
|
||||
private Mock<IImportDecisionEngineSpecification> _pass1;
|
||||
private Mock<IImportDecisionEngineSpecification> _pass2;
|
||||
@ -62,7 +64,13 @@ public void Setup()
|
||||
|
||||
_videoFiles = new List<string> { @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.XviD-OSiTV.avi" };
|
||||
_series = new Series();
|
||||
_localEpisode = new LocalEpisode { Series = _series, Path = @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.XviD-OSiTV.avi" };
|
||||
_quality = new QualityModel(Quality.DVD);
|
||||
_localEpisode = new LocalEpisode
|
||||
{
|
||||
Series = _series,
|
||||
Quality = _quality,
|
||||
Path = @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.XviD-OSiTV.avi"
|
||||
};
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(c => c.GetEpisodes(It.IsAny<String>(), It.IsAny<Series>(), It.IsAny<Boolean>()))
|
||||
@ -161,5 +169,38 @@ public void failed_parse_shouldnt_blowup_the_process()
|
||||
|
||||
ExceptionVerification.ExpectedErrors(3);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_file_quality_if_folder_quality_is_null()
|
||||
{
|
||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||
var expectedQuality = QualityParser.ParseQuality(_videoFiles.Single());
|
||||
|
||||
var result = Subject.GetImportDecisions(_videoFiles, new Series(), false, null);
|
||||
|
||||
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_file_quality_if_folder_quality_is_lower_than_file_quality()
|
||||
{
|
||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||
var expectedQuality = QualityParser.ParseQuality(_videoFiles.Single());
|
||||
|
||||
var result = Subject.GetImportDecisions(_videoFiles, new Series(), false, new QualityModel(Quality.SDTV));
|
||||
|
||||
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_folder_quality_when_it_is_greater_than_file_quality()
|
||||
{
|
||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||
var expectedQuality = new QualityModel(Quality.Bluray1080p);
|
||||
|
||||
var result = Subject.GetImportDecisions(_videoFiles, new Series(), false, expectedQuality);
|
||||
|
||||
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
||||
}
|
||||
}
|
||||
}
|
@ -46,13 +46,14 @@ public void Setup()
|
||||
{
|
||||
Series = series,
|
||||
Episodes = new List<Episode> {episode},
|
||||
Path = @"C:\Test\TV\30 Rock\30 Rock - S01E01 - Pilit.avi".AsOsAgnostic(),
|
||||
Path = @"C:\Test\TV\30 Rock\30 Rock - S01E01 - Pilot.avi".AsOsAgnostic(),
|
||||
Quality = new QualityModel(Quality.Bluray720p)
|
||||
}));
|
||||
}
|
||||
|
||||
Mocker.GetMock<IUpgradeMediaFiles>()
|
||||
.Setup(s => s.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), It.IsAny<LocalEpisode>()));
|
||||
.Setup(s => s.UpgradeEpisodeFile(It.IsAny<EpisodeFile>(), It.IsAny<LocalEpisode>()))
|
||||
.Returns(new EpisodeFileMoveResult());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Marr.Data;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
@ -149,5 +150,21 @@ public void should_not_try_to_recyclebin_existing_file_if_file_doesnt_exist()
|
||||
|
||||
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_old_episode_file_in_oldFiles()
|
||||
{
|
||||
GivenSingleEpisodeWithSingleEpisodeFile();
|
||||
|
||||
Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode).OldFiles.Count.Should().Be(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_old_episode_files_in_oldFiles()
|
||||
{
|
||||
GivenMultipleEpisodesWithMultipleEpisodeFiles();
|
||||
|
||||
Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode).OldFiles.Count.Should().Be(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FizzWare.NBuilder;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Notifications;
|
||||
using NzbDrone.Core.Notifications.Xbmc;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.NotificationTests.Xbmc
|
||||
{
|
||||
[TestFixture]
|
||||
public class OnDownloadFixture : CoreTest<Notifications.Xbmc.Xbmc>
|
||||
{
|
||||
private DownloadMessage _downloadMessage;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.Build();
|
||||
|
||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.Build();
|
||||
|
||||
_downloadMessage = Builder<DownloadMessage>.CreateNew()
|
||||
.With(d => d.Series = series)
|
||||
.With(d => d.EpisodeFile = episodeFile)
|
||||
.With(d => d.OldFiles = new List<EpisodeFile>())
|
||||
.Build();
|
||||
|
||||
Subject.Definition = new NotificationDefinition();
|
||||
Subject.Definition.Settings = new XbmcSettings
|
||||
{
|
||||
UpdateLibrary = true
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenOldFiles()
|
||||
{
|
||||
_downloadMessage.OldFiles = Builder<EpisodeFile>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Subject.Definition.Settings = new XbmcSettings
|
||||
{
|
||||
UpdateLibrary = true,
|
||||
CleanLibrary = true
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_clean_if_no_episode_was_replaced()
|
||||
{
|
||||
Subject.OnDownload(_downloadMessage);
|
||||
|
||||
Mocker.GetMock<IXbmcService>().Verify(v => v.Clean(It.IsAny<XbmcSettings>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_clean_if_episode_was_replaced()
|
||||
{
|
||||
GivenOldFiles();
|
||||
Subject.OnDownload(_downloadMessage);
|
||||
|
||||
Mocker.GetMock<IXbmcService>().Verify(v => v.Clean(It.IsAny<XbmcSettings>()), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
@ -55,8 +55,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentMigrator.1.1.1.0\tools\FluentMigrator.Runner.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentValidation">
|
||||
<HintPath>..\packages\FluentValidation.4.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
|
||||
<Reference Include="FluentValidation, Version=5.0.0.1, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Microsoft.Practices.ServiceLocation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
@ -79,11 +80,11 @@
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=2.0.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.2.0.1.2\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@ -131,6 +132,7 @@
|
||||
<Compile Include="Framework\NBuilderExtensions.cs" />
|
||||
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedHistoryItemsFixture.cs" />
|
||||
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedEpisodeFilesFixture.cs" />
|
||||
<Compile Include="Housekeeping\Housekeepers\CleanupAdditionalNamingSpecsFixture.cs" />
|
||||
<Compile Include="IndexerSearchTests\SearchDefinitionFixture.cs" />
|
||||
<Compile Include="IndexerTests\BasicRssParserFixture.cs" />
|
||||
<Compile Include="IndexerTests\IndexerServiceFixture.cs" />
|
||||
@ -167,6 +169,7 @@
|
||||
<Compile Include="NotificationTests\Xbmc\Json\CheckForErrorFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Json\GetSeriesPathFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Json\UpdateFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\OnDownloadFixture.cs" />
|
||||
<Compile Include="OrganizerTests\BuildFilePathFixture.cs" />
|
||||
<Compile Include="ParserTests\ParsingServiceTests\GetEpisodesFixture.cs" />
|
||||
<Compile Include="ParserTests\ParsingServiceTests\GetSeriesFixture.cs" />
|
||||
|
@ -120,7 +120,7 @@ public void PathParse_tests(string path, int season, int episode)
|
||||
ExceptionVerification.IgnoreWarns();
|
||||
}
|
||||
|
||||
[TestCase("[DmonHiro] The Severing Crime Edge - Cut 02 - Portrait Of Heresy [BD, 720p] [BE36E9E0]")]
|
||||
[TestCase("THIS SHOULD NEVER PARSE")]
|
||||
public void unparsable_title_should_log_warn_and_return_null(string title)
|
||||
{
|
||||
Parser.Parser.ParseTitle(title).Should().BeNull();
|
||||
@ -147,7 +147,9 @@ public void unparsable_title_should_log_warn_and_return_null(string title)
|
||||
[TestCase("Hell.on.Wheels.S02E09-E10.720p.HDTV.x264-EVOLVE", "Hell on Wheels", 2, new[] { 9, 10 })]
|
||||
[TestCase("Grey's Anatomy - 8x01_02 - Free Falling", "Grey's Anatomy", 8, new [] { 1,2 })]
|
||||
[TestCase("8x01_02 - Free Falling", "", 8, new[] { 1, 2 })]
|
||||
[TestCase("Kaamelott.S01E91-E100", "Kaamelott", 1,new[] { 91, 92, 93, 94, 95, 96, 97, 98, 99, 100 })]
|
||||
[TestCase("Kaamelott.S01E91-E100", "Kaamelott", 1, new[] { 91, 92, 93, 94, 95, 96, 97, 98, 99, 100 })]
|
||||
[TestCase("Neighbours.S29E161-E165.PDTV.x264-FQM", "Neighbours", 29, new[] { 161, 162, 163, 164, 165 })]
|
||||
[TestCase("Shortland.Street.S22E5363-E5366.HDTV.x264-FiHTV", "Shortland Street", 22, new[] { 5363, 5364, 5365, 5366 })]
|
||||
public void TitleParse_multi(string postTitle, string title, int season, int[] episodes)
|
||||
{
|
||||
var result = Parser.Parser.ParseTitle(postTitle);
|
||||
@ -174,7 +176,39 @@ public void parse_daily_episodes(string postTitle, string title, int year, int m
|
||||
result.Should().NotBeNull();
|
||||
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
|
||||
result.AirDate.Should().Be(airDate.ToString(Episode.AIR_DATE_FORMAT));
|
||||
result.EpisodeNumbers.Should().BeNull();
|
||||
result.EpisodeNumbers.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[TestCase("[SubDESU]_High_School_DxD_07_(1280x720_x264-AAC)_[6B7FD717]", "High School DxD", 7, 0, 0)]
|
||||
[TestCase("[Chihiro]_Working!!_-_06_[848x480_H.264_AAC][859EEAFA]", "Working!!", 6, 0, 0)]
|
||||
[TestCase("[Commie]_Senki_Zesshou_Symphogear_-_11_[65F220B4]", "Senki_Zesshou_Symphogear", 11, 0, 0)]
|
||||
[TestCase("[Underwater]_Rinne_no_Lagrange_-_12_(720p)_[5C7BC4F9]", "Rinne_no_Lagrange", 12, 0, 0)]
|
||||
[TestCase("[Commie]_Rinne_no_Lagrange_-_15_[E76552EA]", "Rinne_no_Lagrange", 15, 0, 0)]
|
||||
[TestCase("[HorribleSubs]_Hunter_X_Hunter_-_33_[720p]", "Hunter_X_Hunter", 33, 0, 0)]
|
||||
[TestCase("[HorribleSubs]_Fairy_Tail_-_145_[720p]", "Fairy_Tail", 145, 0, 0)]
|
||||
[TestCase("[HorribleSubs] Tonari no Kaibutsu-kun - 13 [1080p].mkv", "Tonari no Kaibutsu-kun", 13, 0, 0)]
|
||||
[TestCase("[Doremi].Yes.Pretty.Cure.5.Go.Go!.31.[1280x720].[C65D4B1F].mkv", "Yes.Pretty.Cure.5.Go.Go!", 31, 0, 0)]
|
||||
[TestCase("[K-F] One Piece 214", "One Piece", 214, 0, 0)]
|
||||
[TestCase("[K-F] One Piece S10E14 214", "One Piece", 214, 10, 14)]
|
||||
[TestCase("[K-F] One Piece 10x14 214", "One Piece", 214, 10, 14)]
|
||||
[TestCase("[K-F] One Piece 214 10x14", "One Piece", 214, 10, 14)]
|
||||
[TestCase("One Piece S10E14 214", "One Piece", 214, 10, 14)]
|
||||
[TestCase("One Piece 10x14 214", "One Piece", 214, 10, 14)]
|
||||
[TestCase("One Piece 214 10x14", "One Piece", 214, 10, 14)]
|
||||
[TestCase("214 One Piece 10x14", "One Piece", 214, 10, 14)]
|
||||
[TestCase("Bleach - 031 - The Resolution to Kill [Lunar].avi", "Bleach", 31, 0, 0)]
|
||||
[TestCase("Bleach - 031 - The Resolution to Kill [Lunar]", "Bleach", 31, 0, 0)]
|
||||
[TestCase("[ACX]Hack Sign 01 Role Play [Kosaka] [9C57891E].mkv", "Hack Sign", 1, 0, 0)]
|
||||
[TestCase("[SFW-sage] Bakuman S3 - 12 [720p][D07C91FC]", "Bakuman S3", 12, 0, 0)]
|
||||
[TestCase("ducktales_e66_time_is_money_part_one_marking_time", "DuckTales", 66, 0, 0)]
|
||||
public void parse_absolute_numbers(string postTitle, string title, int absoluteEpisodeNumber, int seasonNumber, int episodeNumber)
|
||||
{
|
||||
var result = Parser.Parser.ParseTitle(postTitle);
|
||||
result.Should().NotBeNull();
|
||||
result.AbsoluteEpisodeNumbers.First().Should().Be(absoluteEpisodeNumber);
|
||||
result.SeasonNumber.Should().Be(seasonNumber);
|
||||
result.EpisodeNumbers.FirstOrDefault().Should().Be(episodeNumber);
|
||||
result.SeriesTitle.Should().Be(title.CleanSeriesTitle());
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,7 +38,8 @@ public void Setup()
|
||||
{
|
||||
SeriesTitle = _series.Title,
|
||||
SeasonNumber = 1,
|
||||
EpisodeNumbers = new[] { 1 }
|
||||
EpisodeNumbers = new[] { 1 },
|
||||
AbsoluteEpisodeNumbers = new int[0]
|
||||
};
|
||||
|
||||
_singleEpisodeSearchCriteria = new SingleEpisodeSearchCriteria
|
||||
@ -69,6 +70,11 @@ private void GivenSceneNumberingSeries()
|
||||
_series.UseSceneNumbering = true;
|
||||
}
|
||||
|
||||
private void GivenAbsoluteNumberingSeries()
|
||||
{
|
||||
_parsedEpisodeInfo.AbsoluteEpisodeNumbers = new[] { 1 };
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_get_daily_episode_episode_when_search_criteria_is_null()
|
||||
{
|
||||
@ -105,6 +111,17 @@ public void should_fallback_to_daily_episode_lookup_when_search_criteria_episode
|
||||
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<String>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_search_criteria_episode_when_it_matches_absolute()
|
||||
{
|
||||
GivenAbsoluteNumberingSeries();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<IEpisodeService>()
|
||||
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<String>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_scene_numbering_when_series_uses_scene_numbering()
|
||||
{
|
||||
|
@ -21,7 +21,7 @@ public class FreeSpaceOnDrivesFixture : CoreTest<RootFolderService>
|
||||
[Test]
|
||||
public void should_return_one_drive_when_only_one_root_dir_exists()
|
||||
{
|
||||
Mocker.GetMock<IBasicRepository<RootFolder>>()
|
||||
Mocker.GetMock<IRootFolderRepository>()
|
||||
.Setup(s => s.All())
|
||||
.Returns(new List<RootFolder> { new RootFolder { Id = 1, Path = @"C:\Test\TV" } });
|
||||
|
||||
@ -41,7 +41,7 @@ public void should_return_one_drive_when_only_one_root_dir_exists()
|
||||
[Test]
|
||||
public void should_return_one_drive_when_two_rootDirs_on_the_same_drive_exist()
|
||||
{
|
||||
Mocker.GetMock<IBasicRepository<RootFolder>>()
|
||||
Mocker.GetMock<IRootFolderRepository>()
|
||||
.Setup(s => s.All())
|
||||
.Returns(new List<RootFolder> { new RootFolder { Id = 1, Path = @"C:\Test\TV" },
|
||||
new RootFolder { Id = 2, Path = @"C:\Test\TV2" }});
|
||||
@ -62,7 +62,7 @@ public void should_return_one_drive_when_two_rootDirs_on_the_same_drive_exist()
|
||||
[Test]
|
||||
public void should_return_two_drives_when_two_rootDirs_on_the_different_drive_exist()
|
||||
{
|
||||
Mocker.GetMock<IBasicRepository<RootFolder>>()
|
||||
Mocker.GetMock<IRootFolderRepository>()
|
||||
.Setup(s => s.All())
|
||||
.Returns(new List<RootFolder> { new RootFolder { Id = 1, Path = @"C:\Test\TV" },
|
||||
new RootFolder { Id = 2, Path = @"D:\Test\TV" }});
|
||||
@ -87,7 +87,7 @@ public void should_return_two_drives_when_two_rootDirs_on_the_different_drive_ex
|
||||
[Test]
|
||||
public void should_skip_rootDir_if_not_found_on_disk()
|
||||
{
|
||||
Mocker.GetMock<IBasicRepository<RootFolder>>()
|
||||
Mocker.GetMock<IRootFolderRepository>()
|
||||
.Setup(s => s.All())
|
||||
.Returns(new List<RootFolder> { new RootFolder { Id = 1, Path = @"C:\Test\TV" } });
|
||||
|
||||
|
@ -1,13 +1,10 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
@ -25,7 +22,7 @@ public void Setup()
|
||||
.Setup(m => m.FolderExists(It.IsAny<string>()))
|
||||
.Returns(true);
|
||||
|
||||
Mocker.GetMock<IBasicRepository<RootFolder>>()
|
||||
Mocker.GetMock<IRootFolderRepository>()
|
||||
.Setup(s => s.All())
|
||||
.Returns(new List<RootFolder>());
|
||||
}
|
||||
@ -45,7 +42,7 @@ public void should_be_able_to_add_root_dir(string path)
|
||||
|
||||
Subject.Add(root);
|
||||
|
||||
Mocker.GetMock<IBasicRepository<RootFolder>>().Verify(c => c.Insert(root), Times.Once());
|
||||
Mocker.GetMock<IRootFolderRepository>().Verify(c => c.Insert(root), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -60,14 +57,15 @@ public void should_throw_if_folder_being_added_doesnt_exist()
|
||||
public void should_be_able_to_remove_root_dir()
|
||||
{
|
||||
Subject.Remove(1);
|
||||
Mocker.GetMock<IBasicRepository<RootFolder>>().Verify(c => c.Delete(1), Times.Once());
|
||||
Mocker.GetMock<IRootFolderRepository>().Verify(c => c.Delete(1), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void None_existing_folder_returns_empty_list()
|
||||
{
|
||||
WithNoneExistingFolder();
|
||||
|
||||
Mocker.GetMock<IBasicRepository<RootFolder>>().Setup(c => c.All()).Returns(new List<RootFolder>());
|
||||
Mocker.GetMock<IRootFolderRepository>().Setup(c => c.All()).Returns(new List<RootFolder>());
|
||||
|
||||
const string path = "d:\\bad folder";
|
||||
|
||||
@ -97,7 +95,7 @@ public void invalid_folder_path_throws_on_add(string path)
|
||||
[Test]
|
||||
public void adding_duplicated_root_folder_should_throw()
|
||||
{
|
||||
Mocker.GetMock<IBasicRepository<RootFolder>>().Setup(c => c.All()).Returns(new List<RootFolder> { new RootFolder { Path = "C:\\TV".AsOsAgnostic() } });
|
||||
Mocker.GetMock<IRootFolderRepository>().Setup(c => c.All()).Returns(new List<RootFolder> { new RootFolder { Path = "C:\\TV".AsOsAgnostic() } });
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => Subject.Add(new RootFolder { Path = @"C:\TV".AsOsAgnostic() }));
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ public void Setup()
|
||||
.With(e => e.SeasonNumber = 1)
|
||||
.With(e => e.SceneSeasonNumber = 2)
|
||||
.With(e => e.EpisodeNumber = 3)
|
||||
.With(e => e.AbsoluteEpisodeNumber = 3)
|
||||
.With(e => e.SceneEpisodeNumber = 4)
|
||||
.Build();
|
||||
|
||||
@ -51,5 +52,14 @@ public void should_not_find_episode_that_does_not_exist()
|
||||
.Should()
|
||||
.BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_find_episode_by_absolute_numbering()
|
||||
{
|
||||
Subject.Find(_episode.SeriesId, _episode.AbsoluteEpisodeNumber.Value)
|
||||
.Id
|
||||
.Should()
|
||||
.Be(_episode.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,12 @@
|
||||
<package id="CommonServiceLocator" version="1.0" 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="FluentValidation" version="5.0.0.1" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="NBuilder" version="3.0.1.1" />
|
||||
<package id="NCrunch.Framework" version="1.46.0.9" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" />
|
||||
<package id="NLog" version="2.0.1.2" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net40" />
|
||||
<package id="NLog" version="2.1.0" targetFramework="net40" />
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net40" />
|
||||
<package id="Prowlin" version="0.9.4456.26422" targetFramework="net40" />
|
||||
<package id="Unity" version="2.1.505.2" targetFramework="net40" />
|
||||
|
@ -116,6 +116,8 @@ public TModel Insert(TModel model)
|
||||
|
||||
DataMapper.Insert(model);
|
||||
|
||||
ModelCreated(model);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
@ -127,12 +129,15 @@ public TModel Update(TModel model)
|
||||
}
|
||||
|
||||
DataMapper.Update(model, c => c.Id == model.Id);
|
||||
|
||||
ModelUpdated(model);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
public void Delete(TModel model)
|
||||
{
|
||||
DataMapper.Delete<TModel>(c => c.Id == model.Id);
|
||||
Delete(model.Id);
|
||||
}
|
||||
|
||||
public void InsertMany(IList<TModel> models)
|
||||
@ -199,6 +204,8 @@ public void SetFields(TModel model, params Expression<Func<TModel, object>>[] pr
|
||||
.ColumnsIncluding(properties)
|
||||
.Entity(model)
|
||||
.Execute();
|
||||
|
||||
ModelUpdated(model);
|
||||
}
|
||||
|
||||
public virtual PagingSpec<TModel> GetPaged(PagingSpec<TModel> pagingSpec)
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using RestSharp;
|
||||
@ -16,10 +17,12 @@ public interface ISabCommunicationProxy
|
||||
public class SabCommunicationProxy : ISabCommunicationProxy
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public SabCommunicationProxy(IConfigService configService)
|
||||
public SabCommunicationProxy(IConfigService configService, Logger logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string DownloadNzb(Stream nzb, string title, string category, int priority)
|
||||
@ -44,7 +47,8 @@ public string ProcessRequest(IRestRequest restRequest, string action)
|
||||
{
|
||||
var client = BuildClient(action);
|
||||
var response = client.Execute(restRequest);
|
||||
|
||||
_logger.Trace("Response: {0}", response);
|
||||
|
||||
CheckForError(response);
|
||||
|
||||
return response.Content;
|
||||
|
@ -0,0 +1,29 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
{
|
||||
public class CleanupAdditionalNamingSpecs : IHousekeepingTask
|
||||
{
|
||||
private readonly IDatabase _database;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public CleanupAdditionalNamingSpecs(IDatabase database, Logger logger)
|
||||
{
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
_logger.Trace("Running naming spec cleanup");
|
||||
|
||||
var mapper = _database.GetDataMapper();
|
||||
|
||||
mapper.ExecuteNonQuery(@"DELETE FROM NamingConfig
|
||||
WHERE ID NOT IN (
|
||||
SELECT ID FROM NamingConfig
|
||||
LIMIT 1)");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
{
|
||||
|
@ -1,6 +1,5 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.History;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
{
|
||||
|
@ -101,10 +101,10 @@ public override IEnumerable<string> GetDailyEpisodeSearchUrls(string seriesTitle
|
||||
{
|
||||
if (tvRageId > 0)
|
||||
{
|
||||
return RecentFeed.Select(url => String.Format("{0}&limit=100&rid={1}&season={2:yyyy}&ep={2:MM/dd}", url, tvRageId, date)).ToList();
|
||||
return RecentFeed.Select(url => String.Format("{0}&limit=100&rid={1}&season={2:yyyy}&ep={2:MM}/{2:dd}", url, tvRageId, date)).ToList();
|
||||
}
|
||||
|
||||
return RecentFeed.Select(url => String.Format("{0}&limit=100&q={1}&season={2:yyyy}&ep={2:MM/dd}", url, NewsnabifyTitle(seriesTitle), date)).ToList();
|
||||
return RecentFeed.Select(url => String.Format("{0}&limit=100&q={1}&season={2:yyyy}&ep={2:MM}/{2:dd}", url, NewsnabifyTitle(seriesTitle), date)).ToList();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetSeasonSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int offset)
|
||||
|
@ -54,6 +54,7 @@ private void Scan(Series series)
|
||||
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, series, false);
|
||||
_importApprovedEpisodes.Import(decisions);
|
||||
_logger.Info("Completed scanning disk for {0}", series.Title);
|
||||
}
|
||||
|
||||
public string[] GetVideoFiles(string path, bool allDirectories = true)
|
||||
@ -65,7 +66,7 @@ public string[] GetVideoFiles(string path, bool allDirectories = true)
|
||||
|
||||
var mediaFileList = filesOnDisk.Where(c => MediaFileExtensions.Extensions.Contains(Path.GetExtension(c).ToLower())).ToList();
|
||||
|
||||
_logger.Trace("{0} video files were found in {1}", mediaFileList.Count, path);
|
||||
_logger.Debug("{0} video files were found in {1}", mediaFileList.Count, path);
|
||||
return mediaFileList.ToArray();
|
||||
}
|
||||
|
||||
|
@ -99,6 +99,7 @@ private List<ImportDecision> ProcessSubFolder(DirectoryInfo subfolderInfo)
|
||||
{
|
||||
var cleanedUpName = GetCleanedUpFolderName(subfolderInfo.Name);
|
||||
var series = _parsingService.GetSeries(cleanedUpName);
|
||||
var quality = QualityParser.ParseQuality(cleanedUpName);
|
||||
|
||||
if (series == null)
|
||||
{
|
||||
@ -108,7 +109,7 @@ private List<ImportDecision> ProcessSubFolder(DirectoryInfo subfolderInfo)
|
||||
|
||||
var videoFiles = _diskScanService.GetVideoFiles(subfolderInfo.FullName);
|
||||
|
||||
return ProcessFiles(series, videoFiles);
|
||||
return ProcessFiles(series, quality, videoFiles);
|
||||
}
|
||||
|
||||
private void ProcessVideoFile(string videoFile)
|
||||
@ -127,12 +128,12 @@ private void ProcessVideoFile(string videoFile)
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessFiles(series, videoFile);
|
||||
ProcessFiles(series, null, videoFile);
|
||||
}
|
||||
|
||||
private List<ImportDecision> ProcessFiles(Series series, params string[] videoFiles)
|
||||
private List<ImportDecision> ProcessFiles(Series series, QualityModel quality, params string[] videoFiles)
|
||||
{
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles, series, true);
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles, series, true, quality);
|
||||
return _importApprovedEpisodes.Import(decisions, true);
|
||||
}
|
||||
|
||||
|
16
src/NzbDrone.Core/MediaFiles/EpisodeFileMoveResult.cs
Normal file
16
src/NzbDrone.Core/MediaFiles/EpisodeFileMoveResult.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
public class EpisodeFileMoveResult
|
||||
{
|
||||
public EpisodeFileMoveResult()
|
||||
{
|
||||
OldFiles = new List<EpisodeFile>();
|
||||
}
|
||||
|
||||
public String Path { get; set; }
|
||||
public List<EpisodeFile> OldFiles { get; set; }
|
||||
}
|
||||
}
|
@ -44,6 +44,7 @@ public List<ImportDecision> Import(List<ImportDecision> decisions, bool newDownl
|
||||
foreach (var importDecision in qualifiedImports.OrderByDescending(e => e.LocalEpisode.Size))
|
||||
{
|
||||
var localEpisode = importDecision.LocalEpisode;
|
||||
var oldFiles = new List<EpisodeFile>();
|
||||
|
||||
try
|
||||
{
|
||||
@ -65,11 +66,12 @@ public List<ImportDecision> Import(List<ImportDecision> decisions, bool newDownl
|
||||
episodeFile.SeasonNumber = localEpisode.SeasonNumber;
|
||||
episodeFile.Episodes = localEpisode.Episodes;
|
||||
|
||||
|
||||
if (newDownload)
|
||||
{
|
||||
episodeFile.SceneName = Path.GetFileNameWithoutExtension(localEpisode.Path.CleanFilePath());
|
||||
episodeFile.Path = _episodeFileUpgrader.UpgradeEpisodeFile(episodeFile, localEpisode);
|
||||
var moveResult = _episodeFileUpgrader.UpgradeEpisodeFile(episodeFile, localEpisode);
|
||||
episodeFile.Path = moveResult.Path;
|
||||
oldFiles = moveResult.OldFiles;
|
||||
}
|
||||
|
||||
_mediaFileService.Add(episodeFile);
|
||||
@ -78,7 +80,7 @@ public List<ImportDecision> Import(List<ImportDecision> decisions, bool newDownl
|
||||
if (newDownload)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new EpisodeImportedEvent(localEpisode, episodeFile));
|
||||
_eventAggregator.PublishEvent(new EpisodeDownloadedEvent(localEpisode));
|
||||
_eventAggregator.PublishEvent(new EpisodeDownloadedEvent(localEpisode, episodeFile, oldFiles));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -6,6 +6,7 @@
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
|
||||
@ -13,7 +14,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
{
|
||||
public interface IMakeImportDecision
|
||||
{
|
||||
List<ImportDecision> GetImportDecisions(IEnumerable<String> videoFiles, Series series, bool sceneSource);
|
||||
List<ImportDecision> GetImportDecisions(IEnumerable<String> videoFiles, Series series, bool sceneSource, QualityModel quality = null);
|
||||
}
|
||||
|
||||
public class ImportDecisionMaker : IMakeImportDecision
|
||||
@ -38,16 +39,16 @@ public ImportDecisionMaker(IEnumerable<IRejectWithReason> specifications,
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(IEnumerable<string> videoFiles, Series series, bool sceneSource)
|
||||
public List<ImportDecision> GetImportDecisions(IEnumerable<string> videoFiles, Series series, bool sceneSource, QualityModel quality = null)
|
||||
{
|
||||
var newFiles = _mediaFileService.FilterExistingFiles(videoFiles.ToList(), series.Id);
|
||||
|
||||
_logger.Debug("Analysing {0}/{1} files.", newFiles.Count, videoFiles.Count());
|
||||
|
||||
return GetDecisions(newFiles, series, sceneSource).ToList();
|
||||
return GetDecisions(newFiles, series, sceneSource, quality).ToList();
|
||||
}
|
||||
|
||||
private IEnumerable<ImportDecision> GetDecisions(IEnumerable<String> videoFiles, Series series, bool sceneSource)
|
||||
private IEnumerable<ImportDecision> GetDecisions(IEnumerable<String> videoFiles, Series series, bool sceneSource, QualityModel quality = null)
|
||||
{
|
||||
foreach (var file in videoFiles)
|
||||
{
|
||||
@ -59,6 +60,11 @@ private IEnumerable<ImportDecision> GetDecisions(IEnumerable<String> videoFiles,
|
||||
|
||||
if (parsedEpisode != null)
|
||||
{
|
||||
if (quality != null && quality > parsedEpisode.Quality)
|
||||
{
|
||||
parsedEpisode.Quality = quality;
|
||||
}
|
||||
|
||||
parsedEpisode.Size = _diskProvider.GetFileSize(file);
|
||||
decision = GetDecision(parsedEpisode);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using NzbDrone.Common.Messaging;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.Events
|
||||
@ -6,10 +7,14 @@ namespace NzbDrone.Core.MediaFiles.Events
|
||||
public class EpisodeDownloadedEvent : IEvent
|
||||
{
|
||||
public LocalEpisode Episode { get; private set; }
|
||||
public EpisodeFile EpisodeFile { get; private set; }
|
||||
public List<EpisodeFile> OldFiles { get; private set; }
|
||||
|
||||
public EpisodeDownloadedEvent(LocalEpisode episode)
|
||||
public EpisodeDownloadedEvent(LocalEpisode episode, EpisodeFile episodeFile, List<EpisodeFile> oldFiles)
|
||||
{
|
||||
Episode = episode;
|
||||
EpisodeFile = episodeFile;
|
||||
OldFiles = oldFiles;
|
||||
}
|
||||
}
|
||||
}
|
@ -61,7 +61,7 @@ public MediaInfoModel GetMediaInfo(string filename)
|
||||
aBitRate = aBitRate.Remove(ABindex);
|
||||
|
||||
Int32.TryParse(aBitRate, out audioBitRate);
|
||||
Int32.TryParse(mediaInfo.Get(StreamKind.General, 0, "PlayTime"), out runTime);
|
||||
Int32.TryParse(mediaInfo.Get(StreamKind.Video, 0, "PlayTime"), out runTime);
|
||||
Int32.TryParse(mediaInfo.Get(StreamKind.Audio, 0, "StreamCount"), out streamCount);
|
||||
|
||||
string audioChannelsStr = mediaInfo.Get(StreamKind.Audio, 0, "Channel(s)");
|
||||
|
@ -7,7 +7,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
public interface IUpgradeMediaFiles
|
||||
{
|
||||
string UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode);
|
||||
EpisodeFileMoveResult UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode);
|
||||
}
|
||||
|
||||
public class UpgradeMediaFileService : IUpgradeMediaFiles
|
||||
@ -31,8 +31,9 @@ public UpgradeMediaFileService(IRecycleBinProvider recycleBinProvider,
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode)
|
||||
public EpisodeFileMoveResult UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode)
|
||||
{
|
||||
var moveFileResult = new EpisodeFileMoveResult();
|
||||
var existingFiles = localEpisode.Episodes
|
||||
.Where(e => e.EpisodeFileId > 0)
|
||||
.Select(e => e.EpisodeFile.Value)
|
||||
@ -48,11 +49,14 @@ public string UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpis
|
||||
_recycleBinProvider.DeleteFile(file.Path);
|
||||
}
|
||||
|
||||
moveFileResult.OldFiles.Add(file);
|
||||
_mediaFileService.Delete(file, true);
|
||||
}
|
||||
|
||||
_logger.Trace("Moving episode file: {0}", episodeFile);
|
||||
return _episodeFileMover.MoveEpisodeFile(episodeFile, localEpisode);
|
||||
moveFileResult.Path = _episodeFileMover.MoveEpisodeFile(episodeFile, localEpisode);
|
||||
|
||||
return moveFileResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ public class Show
|
||||
public int tvrage_id { get; set; }
|
||||
public int last_updated { get; set; }
|
||||
public string poster { get; set; }
|
||||
public bool? ended { get; set; }
|
||||
public Images images { get; set; }
|
||||
public List<string> genres { get; set; }
|
||||
public List<Season> seasons { get; set; }
|
||||
|
@ -78,7 +78,7 @@ private static Series MapSeries(Show show)
|
||||
series.Network = show.network;
|
||||
series.AirTime = show.air_time_utc;
|
||||
series.TitleSlug = show.url.ToLower().Replace("http://trakt.tv/show/", "");
|
||||
series.Status = GetSeriesStatus(show.status);
|
||||
series.Status = GetSeriesStatus(show.status, show.ended);
|
||||
|
||||
series.Seasons = show.seasons.Select(s => new Tv.Season
|
||||
{
|
||||
@ -135,9 +135,17 @@ private static string GetPosterThumbnailUrl(string posterUrl)
|
||||
return withoutExtension + "-300" + extension;
|
||||
}
|
||||
|
||||
private static SeriesStatusType GetSeriesStatus(string status)
|
||||
private static SeriesStatusType GetSeriesStatus(string status, bool? ended)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(status)) return SeriesStatusType.Continuing;
|
||||
if (string.IsNullOrWhiteSpace(status))
|
||||
{
|
||||
if (ended.HasValue && ended.Value)
|
||||
{
|
||||
return SeriesStatusType.Ended;
|
||||
}
|
||||
|
||||
return SeriesStatusType.Continuing;
|
||||
}
|
||||
if (status.Equals("Ended", StringComparison.InvariantCultureIgnoreCase)) return SeriesStatusType.Ended;
|
||||
return SeriesStatusType.Continuing;
|
||||
}
|
||||
|
20
src/NzbDrone.Core/Notifications/DownloadMessage.cs
Normal file
20
src/NzbDrone.Core/Notifications/DownloadMessage.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public class DownloadMessage
|
||||
{
|
||||
public String Message { get; set; }
|
||||
public Series Series { get; set; }
|
||||
public EpisodeFile EpisodeFile { get; set; }
|
||||
public List<EpisodeFile> OldFiles { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Message;
|
||||
}
|
||||
}
|
||||
}
|
@ -25,10 +25,10 @@ public override void OnGrab(string message)
|
||||
_smtpProvider.SendEmail(Settings, subject, body);
|
||||
}
|
||||
|
||||
public override void OnDownload(string message, Series series)
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string subject = "NzbDrone [TV] - Downloaded";
|
||||
var body = String.Format("{0} Downloaded and sorted.", message);
|
||||
var body = String.Format("{0} Downloaded and sorted.", message.Message);
|
||||
|
||||
_smtpProvider.SendEmail(Settings, subject, body);
|
||||
}
|
||||
|
@ -23,11 +23,11 @@ public override void OnGrab(string message)
|
||||
_growlProvider.SendNotification(title, message, "GRAB", Settings.Host, Settings.Port, Settings.Password);
|
||||
}
|
||||
|
||||
public override void OnDownload(string message, Series series)
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
|
||||
_growlProvider.SendNotification(title, message, "DOWNLOAD", Settings.Host, Settings.Port, Settings.Password);
|
||||
_growlProvider.SendNotification(title, message.Message, "DOWNLOAD", Settings.Host, Settings.Port, Settings.Password);
|
||||
}
|
||||
|
||||
public override void AfterRename(Series series)
|
||||
|
@ -8,7 +8,7 @@ public interface INotification : IProvider
|
||||
string Link { get; }
|
||||
|
||||
void OnGrab(string message);
|
||||
void OnDownload(string message, Series series);
|
||||
void OnDownload(DownloadMessage message);
|
||||
void AfterRename(Series series);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public IEnumerable<ProviderDefinition> DefaultDefinitions
|
||||
public abstract string Link { get; }
|
||||
|
||||
public abstract void OnGrab(string message);
|
||||
public abstract void OnDownload(string message, Series series);
|
||||
public abstract void OnDownload(DownloadMessage message);
|
||||
public abstract void AfterRename(Series series);
|
||||
|
||||
protected TSettings Settings
|
||||
|
@ -73,13 +73,17 @@ public void Handle(EpisodeGrabbedEvent message)
|
||||
|
||||
public void Handle(EpisodeDownloadedEvent message)
|
||||
{
|
||||
var messageBody = GetMessage(message.Episode.Series, message.Episode.Episodes, message.Episode.ParsedEpisodeInfo.Quality);
|
||||
var downloadMessage = new DownloadMessage();
|
||||
downloadMessage.Message = GetMessage(message.Episode.Series, message.Episode.Episodes, message.Episode.ParsedEpisodeInfo.Quality);
|
||||
downloadMessage.Series = message.Episode.Series;
|
||||
downloadMessage.EpisodeFile = message.EpisodeFile;
|
||||
downloadMessage.OldFiles = message.OldFiles;
|
||||
|
||||
foreach (var notification in _notificationFactory.OnDownloadEnabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
notification.OnDownload(messageBody, message.Episode.Series);
|
||||
notification.OnDownload(downloadMessage);
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
|
@ -23,11 +23,11 @@ public override void OnGrab(string message)
|
||||
_notifyMyAndroidProxy.SendNotification(title, message, Settings.ApiKey, (NotifyMyAndroidPriority)Settings.Priority);
|
||||
}
|
||||
|
||||
public override void OnDownload(string message, Series series)
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
|
||||
_notifyMyAndroidProxy.SendNotification(title, message, Settings.ApiKey, (NotifyMyAndroidPriority)Settings.Priority);
|
||||
_notifyMyAndroidProxy.SendNotification(title, message.Message, Settings.ApiKey, (NotifyMyAndroidPriority)Settings.Priority);
|
||||
}
|
||||
|
||||
public override void AfterRename(Series series)
|
||||
|
@ -22,10 +22,10 @@ public override void OnGrab(string message)
|
||||
_plexProvider.Notify(Settings, header, message);
|
||||
}
|
||||
|
||||
public override void OnDownload(string message, Series series)
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string header = "NzbDrone [TV] - Downloaded";
|
||||
_plexProvider.Notify(Settings, header, message);
|
||||
_plexProvider.Notify(Settings, header, message.Message);
|
||||
}
|
||||
|
||||
public override void AfterRename(Series series)
|
||||
|
@ -20,7 +20,7 @@ public override void OnGrab(string message)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnDownload(string message, Series series)
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
UpdateIfEnabled();
|
||||
}
|
||||
|
@ -24,11 +24,11 @@ public override void OnGrab(string message)
|
||||
_prowlProvider.SendNotification(title, message, Settings.ApiKey, (NotificationPriority)Settings.Priority);
|
||||
}
|
||||
|
||||
public override void OnDownload(string message, Series series)
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
|
||||
_prowlProvider.SendNotification(title, message, Settings.ApiKey, (NotificationPriority)Settings.Priority);
|
||||
_prowlProvider.SendNotification(title, message.Message, Settings.ApiKey, (NotificationPriority)Settings.Priority);
|
||||
}
|
||||
|
||||
public override void AfterRename(Series series)
|
||||
|
@ -23,11 +23,11 @@ public override void OnGrab(string message)
|
||||
_pushBulletProxy.SendNotification(title, message, Settings.ApiKey, Settings.DeviceId);
|
||||
}
|
||||
|
||||
public override void OnDownload(string message, Series series)
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
|
||||
_pushBulletProxy.SendNotification(title, message, Settings.ApiKey, Settings.DeviceId);
|
||||
_pushBulletProxy.SendNotification(title, message.Message, Settings.ApiKey, Settings.DeviceId);
|
||||
}
|
||||
|
||||
public override void AfterRename(Series series)
|
||||
|
@ -23,11 +23,11 @@ public override void OnGrab(string message)
|
||||
_pushoverProxy.SendNotification(title, message, Settings.UserKey, (PushoverPriority)Settings.Priority);
|
||||
}
|
||||
|
||||
public override void OnDownload(string message, Series series)
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
|
||||
_pushoverProxy.SendNotification(title, message, Settings.UserKey, (PushoverPriority)Settings.Priority);
|
||||
_pushoverProxy.SendNotification(title, message.Message, Settings.UserKey, (PushoverPriority)Settings.Priority);
|
||||
}
|
||||
|
||||
public override void AfterRename(Series series)
|
||||
|
@ -119,7 +119,7 @@ public string GetSeriesPath(XbmcSettings settings, Series series)
|
||||
return String.Empty;
|
||||
|
||||
var xDoc = XDocument.Load(new StringReader(response.Replace("&", "&")));
|
||||
var xml = (from x in xDoc.Descendants("xml") select x).FirstOrDefault();
|
||||
var xml = xDoc.Descendants("xml").Select(x => x).FirstOrDefault();
|
||||
|
||||
if (xml == null)
|
||||
return null;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using NzbDrone.Core.Tv;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Xbmc
|
||||
{
|
||||
@ -26,16 +27,16 @@ public override void OnGrab(string message)
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDownload(string message, Series series)
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string header = "NzbDrone [TV] - Downloaded";
|
||||
|
||||
if (Settings.Notify)
|
||||
{
|
||||
_xbmcProvider.Notify(Settings, header, message);
|
||||
_xbmcProvider.Notify(Settings, header, message.Message);
|
||||
}
|
||||
|
||||
UpdateAndClean(series);
|
||||
UpdateAndClean(message.Series, message.OldFiles.Any());
|
||||
}
|
||||
|
||||
public override void AfterRename(Series series)
|
||||
@ -43,14 +44,14 @@ public override void AfterRename(Series series)
|
||||
UpdateAndClean(series);
|
||||
}
|
||||
|
||||
private void UpdateAndClean(Series series)
|
||||
private void UpdateAndClean(Series series, bool clean = true)
|
||||
{
|
||||
if (Settings.UpdateLibrary)
|
||||
{
|
||||
_xbmcProvider.Update(Settings, series);
|
||||
}
|
||||
|
||||
if (Settings.CleanLibrary)
|
||||
if (clean && Settings.CleanLibrary)
|
||||
{
|
||||
_xbmcProvider.Clean(Settings);
|
||||
}
|
||||
|
@ -67,9 +67,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentMigrator.1.1.1.0\tools\FluentMigrator.Runner.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentValidation, Version=4.0.0.1, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="FluentValidation, Version=5.0.0.1, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentValidation.4.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
|
||||
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Growl.Connector">
|
||||
<HintPath>..\packages\Growl.0.6\lib\Growl.Connector.dll</HintPath>
|
||||
@ -83,11 +83,11 @@
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=2.0.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.2.0.1.2\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Omu.ValueInjecter">
|
||||
<HintPath>..\packages\valueinjecter.2.3.3\lib\net35\Omu.ValueInjecter.dll</HintPath>
|
||||
@ -96,9 +96,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Prowlin.0.9.4456.26422\lib\net40\Prowlin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RestSharp, Version=104.2.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="RestSharp, Version=104.3.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\RestSharp.104.2.0\lib\net4\RestSharp.dll</HintPath>
|
||||
<HintPath>..\packages\RestSharp.104.3.3\lib\net4\RestSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
@ -247,6 +247,7 @@
|
||||
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedEpisodes.cs" />
|
||||
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedHistoryItems.cs" />
|
||||
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedEpisodeFiles.cs" />
|
||||
<Compile Include="Housekeeping\Housekeepers\CleanupAdditionalNamingSpecs.cs" />
|
||||
<Compile Include="Housekeeping\HousekeepingCommand.cs" />
|
||||
<Compile Include="Housekeeping\HousekeepingService.cs" />
|
||||
<Compile Include="Housekeeping\IHousekeepingTask.cs" />
|
||||
@ -274,6 +275,7 @@
|
||||
<Compile Include="Instrumentation\Commands\DeleteLogFilesCommand.cs" />
|
||||
<Compile Include="Instrumentation\Commands\TrimLogCommand.cs" />
|
||||
<Compile Include="Instrumentation\DeleteLogFilesService.cs" />
|
||||
<Compile Include="MediaFiles\EpisodeFileMoveResult.cs" />
|
||||
<Compile Include="MediaFiles\MediaFileExtensions.cs" />
|
||||
<Compile Include="MediaFiles\MediaInfo\VideoFileInfoReader.cs" />
|
||||
<Compile Include="Messaging\Commands\CommandExecutor.cs" />
|
||||
@ -289,6 +291,7 @@
|
||||
<Compile Include="MetadataSource\Trakt\TraktException.cs" />
|
||||
<Compile Include="Notifications\NotificationFactory.cs" />
|
||||
<Compile Include="Notifications\NotificationService.cs" />
|
||||
<Compile Include="Notifications\DownloadMessage.cs" />
|
||||
<Compile Include="Notifications\PushBullet\PushBullet.cs" />
|
||||
<Compile Include="Notifications\PushBullet\PushBulletProxy.cs" />
|
||||
<Compile Include="Notifications\PushBullet\PushBulletSettings.cs" />
|
||||
@ -436,6 +439,7 @@
|
||||
<Compile Include="Parser\Parser.cs" />
|
||||
<Compile Include="Parser\ParsingService.cs" />
|
||||
<Compile Include="Parser\QualityParser.cs" />
|
||||
<Compile Include="RootFolders\RootFolderRepository.cs" />
|
||||
<Compile Include="ThingiProvider\ConfigContractNotFoundException.cs" />
|
||||
<Compile Include="ThingiProvider\IProvider.cs" />
|
||||
<Compile Include="Qualities\QualityProfileInUseException.cs" />
|
||||
|
@ -11,11 +11,27 @@ public class ParsedEpisodeInfo
|
||||
public QualityModel Quality { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
public int[] EpisodeNumbers { get; set; }
|
||||
public int[] AbsoluteEpisodeNumbers { get; set; }
|
||||
public String AirDate { get; set; }
|
||||
public Language Language { get; set; }
|
||||
|
||||
public bool FullSeason { get; set; }
|
||||
|
||||
public ParsedEpisodeInfo()
|
||||
{
|
||||
EpisodeNumbers = new int[0];
|
||||
AbsoluteEpisodeNumbers = new int[0];
|
||||
}
|
||||
|
||||
public bool IsDaily()
|
||||
{
|
||||
return !String.IsNullOrWhiteSpace(AirDate);
|
||||
}
|
||||
|
||||
public bool IsAbsoluteNumbering()
|
||||
{
|
||||
return AbsoluteEpisodeNumbers.Any();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string episodeString = "[Unknown Episode]";
|
||||
@ -35,10 +51,5 @@ public override string ToString()
|
||||
|
||||
return string.Format("{0} - {1} {2}", SeriesTitle, episodeString, Quality);
|
||||
}
|
||||
|
||||
public bool IsDaily()
|
||||
{
|
||||
return !String.IsNullOrWhiteSpace(AirDate);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,13 @@ public int Age
|
||||
{
|
||||
return DateTime.UtcNow.Subtract(PublishDate).Days;
|
||||
}
|
||||
|
||||
//This prevents manually downloading a release from blowing up in mono
|
||||
//TODO: Is there a better way?
|
||||
private set
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public string ReleaseGroup { get; set; }
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
@ -20,6 +21,22 @@ public static class Parser
|
||||
new Regex(@"^(?<title>.+?)?\W*(?<airyear>\d{4})\W+(?<airmonth>[0-1][0-9])\W+(?<airday>[0-3][0-9])(\W+|_|$)(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - Absolute Episode Number + Title + Season+Episode
|
||||
new Regex(@"^(?:(?<absoluteepisode>\d{2,3})(?:_|-|\s|\.)+)+(?<title>.+?)(?:\W|_)+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - [SubGroup] Title Absolute Episode Number + Season+Episode
|
||||
new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.))?(?<title>.+?)(?:(?:\W|_)+(?<absoluteepisode>\d{2,3}))+(?:_|-|\s|\.)+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - [SubGroup] Title Season+Episode + Absolute Episode Number
|
||||
new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.))?(?<title>.+?)(?:\W|_)+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)(?:\s|\.)(?:(?<absoluteepisode>\d{2,3})(?:_|-|\s|\.|$)+)+",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - [SubGroup] Title Absolute Episode Number
|
||||
new Regex(@"^\[(?<subgroup>.+?)\](?:_|-|\s|\.)?(?<title>.+?)(?:(?:\W|_)+(?<absoluteepisode>\d{2,}))+",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Multi-Part episodes without a title (S01E05.S01E06)
|
||||
new Regex(@"^(?:\W*S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:[ex]){1,2}(?<episode>\d{1,3}(?!\d+)))+){2,}(\W+|_|$)(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
@ -44,6 +61,10 @@ public static class Parser
|
||||
new Regex(@"^(?<title>.*?)(?:\W?S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]){1,2}(?<episode>\d{1}))+)+(\W+|_|$)(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - Title Absolute Episode Number [SubGroup]
|
||||
new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+(?<absoluteepisode>\d{2,3}))+(?:.+?)\[(?<subgroup>.+?)\](?:\.|$)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Supports 103/113 naming
|
||||
new Regex(@"^(?<title>.+?)?(?:\W?(?<season>(?<!\d+)\d{1})(?<episode>\d{2}(?!p|i|\d+)))+(\W+|_|$)(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
@ -53,7 +74,7 @@ public static class Parser
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Supports 1103/1113 naming
|
||||
new Regex(@"^(?<title>.+?)?(?:\W?(?<season>(?<!\d+|\(|\[)\d{2})(?<episode>\d{2}(?!p|i|\d+|\)|\]|\W\d+)))+(\W+|_|$)(?!\\)",
|
||||
new Regex(@"^(?<title>.+?)?(?:\W?(?<season>(?<!\d+|\(|\[|e|x)\d{2})(?<episode>(?<!e|x)\d{2}(?!p|i|\d+|\)|\]|\W\d+)))+(\W+|_|$)(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Supports Season 01 Episode 03
|
||||
@ -62,7 +83,20 @@ public static class Parser
|
||||
|
||||
//Supports Season only releases
|
||||
new Regex(@"^(?<title>.+?)\W(?:S|Season)\W?(?<season>\d{1,2}(?!\d+))(\W+|_|$)(?<extras>EXTRAS|SUBPACK)?(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled)
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//4-digit episode number
|
||||
//Episodes without a title, Single (S01E05, 1x05) AND Multi (S01E04E05, 1x04x05, etc)
|
||||
new Regex(@"^(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{4}(?!\d+|i|p)))+)(\W+|_|$)(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Episodes with a title, Single episodes (S01E05, 1x05, etc) & Multi-episode (S01E05E06, S01E05-06, S01E05 E06, etc)
|
||||
new Regex(@"^(?<title>.+?)(?:(\W|_)+S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{4}(?!\d+|i|p)))+)\W?(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - Title Absolute Episode Number
|
||||
new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+e(?<absoluteepisode>\d{2,3}))+",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
};
|
||||
|
||||
private static readonly Regex NormalizeRegex = new Regex(@"((^|\W|_)(a|an|the|and|or|of)($|\W|_))|\W|_|(?:(?<=[^0-9]+)|\b)(?!(?:19\d{2}|20\d{2}))\d+(?=[^0-9ip]+|\b)",
|
||||
@ -114,6 +148,7 @@ public static ParsedEpisodeInfo ParseTitle(string title)
|
||||
|
||||
if (match.Count != 0)
|
||||
{
|
||||
Debug.WriteLine(regex);
|
||||
try
|
||||
{
|
||||
var result = ParseMatchCollection(match);
|
||||
@ -226,11 +261,13 @@ private static ParsedEpisodeInfo ParseMatchCollection(MatchCollection matchColle
|
||||
{
|
||||
SeasonNumber = seasons.First(),
|
||||
EpisodeNumbers = new int[0],
|
||||
AbsoluteEpisodeNumbers = new int[0]
|
||||
};
|
||||
|
||||
foreach (Match matchGroup in matchCollection)
|
||||
{
|
||||
var episodeCaptures = matchGroup.Groups["episode"].Captures.Cast<Capture>().ToList();
|
||||
var absoluteEpisodeCaptures = matchGroup.Groups["absoluteepisode"].Captures.Cast<Capture>().ToList();
|
||||
|
||||
//Allows use to return a list of 0 episodes (We can handle that as a full season release)
|
||||
if (episodeCaptures.Any())
|
||||
@ -246,6 +283,20 @@ private static ParsedEpisodeInfo ParseMatchCollection(MatchCollection matchColle
|
||||
var count = last - first + 1;
|
||||
result.EpisodeNumbers = Enumerable.Range(first, count).ToArray();
|
||||
}
|
||||
|
||||
if (absoluteEpisodeCaptures.Any())
|
||||
{
|
||||
var first = Convert.ToInt32(absoluteEpisodeCaptures.First().Value);
|
||||
var last = Convert.ToInt32(absoluteEpisodeCaptures.Last().Value);
|
||||
|
||||
if (first > last)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var count = last - first + 1;
|
||||
result.AbsoluteEpisodeNumbers = Enumerable.Range(first, count).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Check to see if this is an "Extras" or "SUBPACK" release, if it is, return NULL
|
||||
@ -256,6 +307,10 @@ private static ParsedEpisodeInfo ParseMatchCollection(MatchCollection matchColle
|
||||
result.FullSeason = true;
|
||||
}
|
||||
}
|
||||
if (result.AbsoluteEpisodeNumbers.Any() && !result.EpisodeNumbers.Any())
|
||||
{
|
||||
result.SeasonNumber = 0;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -129,6 +129,26 @@ public List<Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series ser
|
||||
return result;
|
||||
}
|
||||
|
||||
if (parsedEpisodeInfo.IsAbsoluteNumbering())
|
||||
{
|
||||
foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers)
|
||||
{
|
||||
var episodeInfo = _episodeService.FindEpisode(series.Id, absoluteEpisodeNumber);
|
||||
|
||||
if (episodeInfo != null)
|
||||
{
|
||||
_logger.Info("Using absolute episode number {0} for: {1} - TVDB: {2}x{3:00}",
|
||||
absoluteEpisodeNumber,
|
||||
series.Title,
|
||||
episodeInfo.SeasonNumber,
|
||||
episodeInfo.EpisodeNumber);
|
||||
result.Add(episodeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (parsedEpisodeInfo.EpisodeNumbers == null)
|
||||
return result;
|
||||
|
||||
|
27
src/NzbDrone.Core/RootFolders/RootFolderRepository.cs
Normal file
27
src/NzbDrone.Core/RootFolders/RootFolderRepository.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.RootFolders
|
||||
{
|
||||
public interface IRootFolderRepository : IBasicRepository<RootFolder>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class RootFolderRepository : BasicRepository<RootFolder>, IRootFolderRepository
|
||||
{
|
||||
|
||||
public RootFolderRepository(IDatabase database, IEventAggregator eventAggregator)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool PublishModelEvents
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -25,15 +25,15 @@ public interface IRootFolderService
|
||||
public class RootFolderService : IRootFolderService
|
||||
{
|
||||
private static readonly Logger Logger = NzbDroneLogger.GetLogger();
|
||||
private readonly IBasicRepository<RootFolder> _rootFolderRepository;
|
||||
private readonly IRootFolderRepository _rootFolderRepository;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly ISeriesRepository _seriesRepository;
|
||||
private readonly IConfigService _configService;
|
||||
|
||||
private static readonly HashSet<string> SpecialFolders = new HashSet<string> { "$recycle.bin", "system volume information", "recycler" };
|
||||
private static readonly HashSet<string> SpecialFolders = new HashSet<string> { "$recycle.bin", "system volume information", "recycler", "lost+found" };
|
||||
|
||||
|
||||
public RootFolderService(IBasicRepository<RootFolder> rootFolderRepository,
|
||||
public RootFolderService(IRootFolderRepository rootFolderRepository,
|
||||
IDiskProvider diskProvider,
|
||||
ISeriesRepository seriesRepository,
|
||||
IConfigService configService)
|
||||
|
@ -11,6 +11,7 @@ namespace NzbDrone.Core.Tv
|
||||
public interface IEpisodeRepository : IBasicRepository<Episode>
|
||||
{
|
||||
Episode Find(int seriesId, int season, int episodeNumber);
|
||||
Episode Find(int seriesId, int absoluteEpisodeNumber);
|
||||
Episode Get(int seriesId, String date);
|
||||
Episode Find(int seriesId, String date);
|
||||
List<Episode> GetEpisodes(int seriesId);
|
||||
@ -39,6 +40,11 @@ public Episode Find(int seriesId, int season, int episodeNumber)
|
||||
return Query.SingleOrDefault(s => s.SeriesId == seriesId && s.SeasonNumber == season && s.EpisodeNumber == episodeNumber);
|
||||
}
|
||||
|
||||
public Episode Find(int seriesId, int absoluteEpisodeNumber)
|
||||
{
|
||||
return Query.SingleOrDefault(s => s.SeriesId == seriesId && s.AbsoluteEpisodeNumber == absoluteEpisodeNumber);
|
||||
}
|
||||
|
||||
public Episode Get(int seriesId, String date)
|
||||
{
|
||||
return Query.Single(s => s.SeriesId == seriesId && s.AirDate == date);
|
||||
|
@ -14,6 +14,7 @@ public interface IEpisodeService
|
||||
{
|
||||
Episode GetEpisode(int id);
|
||||
Episode FindEpisode(int seriesId, int seasonNumber, int episodeNumber, bool useScene = false);
|
||||
Episode FindEpisode(int seriesId, int absoluteEpisodeNumber);
|
||||
Episode GetEpisode(int seriesId, String date);
|
||||
Episode FindEpisode(int seriesId, String date);
|
||||
List<Episode> GetEpisodeBySeries(int seriesId);
|
||||
@ -62,6 +63,11 @@ public Episode FindEpisode(int seriesId, int seasonNumber, int episodeNumber, bo
|
||||
return _episodeRepository.Find(seriesId, seasonNumber, episodeNumber);
|
||||
}
|
||||
|
||||
public Episode FindEpisode(int seriesId, int absoluteEpisodeNumber)
|
||||
{
|
||||
return _episodeRepository.Find(seriesId, absoluteEpisodeNumber);
|
||||
}
|
||||
|
||||
public Episode GetEpisode(int seriesId, String date)
|
||||
{
|
||||
return _episodeRepository.Get(seriesId, date);
|
||||
|
@ -106,7 +106,7 @@ public void Execute(RefreshSeriesCommand message)
|
||||
}
|
||||
else
|
||||
{
|
||||
var allSeries = _seriesService.GetAllSeries().OrderBy(c => c.LastInfoSync).ToList();
|
||||
var allSeries = _seriesService.GetAllSeries().OrderBy(c => c.Title).ToList();
|
||||
|
||||
foreach (var series in allSeries)
|
||||
{
|
||||
|
@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentMigrator" version="1.1.1.0" targetFramework="net40" />
|
||||
<package id="FluentValidation" version="4.0.0.1" targetFramework="net40" />
|
||||
<package id="FluentValidation" version="5.0.0.1" targetFramework="net40" />
|
||||
<package id="Growl" version="0.6" />
|
||||
<package id="MediaInfoNet" version="0.3" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" />
|
||||
<package id="NLog" version="2.0.1.2" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net40" />
|
||||
<package id="NLog" version="2.1.0" targetFramework="net40" />
|
||||
<package id="Prowlin" version="0.9.4456.26422" targetFramework="net40" />
|
||||
<package id="RestSharp" version="104.2.0" targetFramework="net40" />
|
||||
<package id="RestSharp" version="104.3.3" targetFramework="net40" />
|
||||
<package id="valueinjecter" version="2.3.3" targetFramework="net40" />
|
||||
</packages>
|
@ -22,7 +22,6 @@ private MainAppContainerBuilder(StartupArguments args)
|
||||
|
||||
AutoRegisterImplementations<NzbDronePersistentConnection>();
|
||||
|
||||
Container.Register(typeof(IBasicRepository<RootFolder>), typeof(BasicRepository<RootFolder>));
|
||||
Container.Register(typeof(IBasicRepository<NamingConfig>), typeof(BasicRepository<NamingConfig>));
|
||||
|
||||
Container.Register<INancyBootstrapper, NancyBootstrapper>();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -89,21 +89,21 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Nancy, Version=0.20.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Nancy, Version=0.21.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Nancy.0.20.0\lib\net40\Nancy.dll</HintPath>
|
||||
<HintPath>..\packages\Nancy.0.21.1\lib\net40\Nancy.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Nancy.Owin, Version=0.20.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Nancy.Owin, Version=0.21.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Nancy.Owin.0.20.0\lib\net40\Nancy.Owin.dll</HintPath>
|
||||
<HintPath>..\packages\Nancy.Owin.0.21.1\lib\net40\Nancy.Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=2.0.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.2.0.1.2\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
@ -14,7 +14,7 @@ public SignalRMiddleWare(IContainer container)
|
||||
{
|
||||
SignalrDependencyResolver.Register(container);
|
||||
|
||||
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(300000);
|
||||
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromMinutes(3);
|
||||
}
|
||||
|
||||
public void Attach(IAppBuilder appBuilder)
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
@ -72,6 +72,10 @@ public void StartServer()
|
||||
|
||||
try
|
||||
{
|
||||
// options.ServerFactory = new
|
||||
//_host = WebApp.Start(OwinServiceProviderFactory.Create(), options, BuildApp);
|
||||
//_host = WebApp.Start(options, BuildApp);
|
||||
|
||||
_host = WebApp.Start(OwinServiceProviderFactory.Create(), options, BuildApp);
|
||||
}
|
||||
catch (TargetInvocationException ex)
|
||||
|
@ -5,11 +5,10 @@
|
||||
<package id="Microsoft.Owin" version="1.1.0-beta2" targetFramework="net40" />
|
||||
<package id="Microsoft.Owin.Host.HttpListener" version="1.1.0-beta2" targetFramework="net40" />
|
||||
<package id="Microsoft.Owin.Hosting" version="1.1.0-beta2" targetFramework="net40" />
|
||||
<package id="Nancy" version="0.20.0" targetFramework="net40" />
|
||||
<package id="Nancy.Owin" version="0.20.0" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" />
|
||||
<package id="NLog" version="2.0.1.2" targetFramework="net40" />
|
||||
<package id="NLog.Config" version="2.0.1.2" targetFramework="net40" />
|
||||
<package id="NLog.Schema" version="2.0.1.2" targetFramework="net40" />
|
||||
<package id="Nancy" version="0.21.1" targetFramework="net40" />
|
||||
<package id="Nancy.Owin" version="0.21.1" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net40" />
|
||||
<package id="NLog" version="2.1.0" targetFramework="net40" />
|
||||
<package id="NLog.Schema" version="2.1.0" targetFramework="net40" />
|
||||
<package id="Owin" version="1.0" targetFramework="net40" />
|
||||
</packages>
|
||||
</packages>
|
||||
|
@ -10,20 +10,28 @@ namespace NzbDrone.Integration.Test
|
||||
[TestFixture]
|
||||
public class EpisodeIntegrationTests : IntegrationTest
|
||||
{
|
||||
private SeriesResource series;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
series = GivenSeriesWithEpisodes();
|
||||
}
|
||||
|
||||
private SeriesResource GivenSeriesWithEpisodes()
|
||||
{
|
||||
var series = Series.Lookup("archer").First();
|
||||
var newSeries = Series.Lookup("archer").First();
|
||||
|
||||
series.QualityProfileId = 1;
|
||||
series.Path = @"C:\Test\Archer".AsOsAgnostic();
|
||||
newSeries.QualityProfileId = 1;
|
||||
newSeries.Path = @"C:\Test\Archer".AsOsAgnostic();
|
||||
|
||||
series = Series.Post(series);
|
||||
newSeries = Series.Post(newSeries);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (Episodes.GetEpisodesInSeries(series.Id).Count > 0)
|
||||
if (Episodes.GetEpisodesInSeries(newSeries.Id).Count > 0)
|
||||
{
|
||||
return series;
|
||||
return newSeries;
|
||||
}
|
||||
|
||||
Thread.Sleep(1000);
|
||||
@ -33,28 +41,33 @@ private SeriesResource GivenSeriesWithEpisodes()
|
||||
[Test]
|
||||
public void should_be_able_to_get_all_episodes_in_series()
|
||||
{
|
||||
var series = GivenSeriesWithEpisodes();
|
||||
Episodes.GetEpisodesInSeries(series.Id).Count.Should().BeGreaterThan(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_get_a_single_episode()
|
||||
{
|
||||
var series = GivenSeriesWithEpisodes();
|
||||
var episodes = Episodes.GetEpisodesInSeries(series.Id);
|
||||
|
||||
Episodes.Get(episodes.First().Id).Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_set_monitor_status_via_api()
|
||||
public void should_be_able_to_set_monitor_status()
|
||||
{
|
||||
var series = GivenSeriesWithEpisodes();
|
||||
var episodes = Episodes.GetEpisodesInSeries(series.Id);
|
||||
var updatedEpisode = episodes.First();
|
||||
updatedEpisode.Monitored = false;
|
||||
|
||||
Episodes.Put(updatedEpisode).Monitored.Should().BeFalse();
|
||||
}
|
||||
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
Series.Delete(series.Id);
|
||||
Thread.Sleep(2000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,9 @@
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNet.SignalR.Client;
|
||||
using Microsoft.AspNet.SignalR.Client.Transports;
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
using NLog.Targets;
|
||||
using NUnit.Framework;
|
||||
@ -7,7 +12,10 @@
|
||||
using NzbDrone.Api.History;
|
||||
using NzbDrone.Api.RootFolders;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Integration.Test.Client;
|
||||
using NzbDrone.SignalR;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Test.Common.Categories;
|
||||
using RestSharp;
|
||||
|
||||
@ -29,6 +37,16 @@ public abstract class IntegrationTest
|
||||
protected ClientBase<NamingConfigResource> NamingConfig;
|
||||
|
||||
private NzbDroneRunner _runner;
|
||||
private List<SignalRMessage> _signalRReceived;
|
||||
private Connection _signalrConnection;
|
||||
|
||||
protected IEnumerable<SignalRMessage> SignalRMessages
|
||||
{
|
||||
get
|
||||
{
|
||||
return _signalRReceived;
|
||||
}
|
||||
}
|
||||
|
||||
public IntegrationTest()
|
||||
{
|
||||
@ -40,8 +58,8 @@ public IntegrationTest()
|
||||
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, consoleTarget));
|
||||
}
|
||||
|
||||
//[TestFixtureSetUp]
|
||||
[SetUp]
|
||||
[TestFixtureSetUp]
|
||||
//[SetUp]
|
||||
public void SmokeTestSetup()
|
||||
{
|
||||
_runner = new NzbDroneRunner();
|
||||
@ -64,11 +82,61 @@ private void InitRestClients()
|
||||
NamingConfig = new ClientBase<NamingConfigResource>(RestClient, _runner.ApiKey, "config/naming");
|
||||
}
|
||||
|
||||
//[TestFixtureTearDown]
|
||||
[TearDown]
|
||||
[TestFixtureTearDown]
|
||||
//[TearDown]
|
||||
public void SmokeTestTearDown()
|
||||
{
|
||||
_runner.KillAll();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void IntegrationSetup()
|
||||
{
|
||||
if (_signalrConnection != null)
|
||||
{
|
||||
switch (_signalrConnection.State)
|
||||
{
|
||||
case ConnectionState.Connected:
|
||||
case ConnectionState.Connecting:
|
||||
{
|
||||
_signalrConnection.Stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_signalrConnection = null;
|
||||
_signalRReceived = new List<SignalRMessage>();
|
||||
}
|
||||
}
|
||||
|
||||
protected void ConnectSignalR()
|
||||
{
|
||||
_signalRReceived = new List<SignalRMessage>();
|
||||
_signalrConnection = new Connection("http://localhost:8989/signalr");
|
||||
_signalrConnection.Start(new LongPollingTransport()).ContinueWith(task =>
|
||||
{
|
||||
if (task.IsFaulted)
|
||||
{
|
||||
Assert.Fail("SignalrConnection failed. {0}", task.Exception.GetBaseException());
|
||||
}
|
||||
});
|
||||
|
||||
var retryCount = 0;
|
||||
|
||||
while (_signalrConnection.State != ConnectionState.Connected)
|
||||
{
|
||||
if (retryCount > 25)
|
||||
{
|
||||
Assert.Fail("Couldn't establish signalr connection. State: {0}", _signalrConnection.State);
|
||||
}
|
||||
|
||||
retryCount++;
|
||||
Console.WriteLine("Connecting to signalR" + _signalrConnection.State);
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
|
||||
_signalrConnection.Received += json => _signalRReceived.Add(Json.Deserialize<SignalRMessage>(json)); ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -37,11 +37,12 @@
|
||||
<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">
|
||||
<Reference Include="FluentValidation, Version=5.0.0.1, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\FluentValidation.4.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
|
||||
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.SignalR.Client">
|
||||
<Reference Include="Microsoft.AspNet.SignalR.Client, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.AspNet.SignalR.Client.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Client.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin">
|
||||
@ -59,20 +60,21 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Nancy, Version=0.20.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Nancy, Version=0.21.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Nancy.0.20.0\lib\net40\Nancy.dll</HintPath>
|
||||
<HintPath>..\packages\Nancy.0.21.1\lib\net40\Nancy.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Nancy.Owin, Version=0.20.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Nancy.Owin, Version=0.21.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Nancy.Owin.0.20.0\lib\net40\Nancy.Owin.dll</HintPath>
|
||||
<HintPath>..\packages\Nancy.Owin.0.21.1\lib\net40\Nancy.Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog">
|
||||
<HintPath>..\packages\NLog.2.0.1.2\lib\net40\NLog.dll</HintPath>
|
||||
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework">
|
||||
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
|
||||
@ -81,9 +83,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RestSharp, Version=104.2.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="RestSharp, Version=104.3.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\RestSharp.104.2.0\lib\net4\RestSharp.dll</HintPath>
|
||||
<HintPath>..\packages\RestSharp.104.3.3\lib\net4\RestSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
@ -105,7 +107,6 @@
|
||||
<Compile Include="EpisodeIntegrationTests.cs" />
|
||||
<Compile Include="IndexerIntegrationFixture.cs" />
|
||||
<Compile Include="IntegrationTestDirectoryInfo.cs" />
|
||||
<Compile Include="NzbDroneRunner.cs" />
|
||||
<Compile Include="QualityProfileIntegrationTest.cs" />
|
||||
<Compile Include="ReleaseIntegrationTest.cs" />
|
||||
<Compile Include="IntegrationTest.cs" />
|
||||
@ -136,6 +137,10 @@
|
||||
<Project>{95C11A9E-56ED-456A-8447-2C89C1139266}</Project>
|
||||
<Name>NzbDrone.Host</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\NzbDrone.SignalR\NzbDrone.SignalR.csproj">
|
||||
<Project>{7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}</Project>
|
||||
<Name>NzbDrone.SignalR</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\NzbDrone.Test.Common\NzbDrone.Test.Common.csproj">
|
||||
<Project>{CADDFCE0-7509-4430-8364-2074E1EEFCA2}</Project>
|
||||
<Name>NzbDrone.Test.Common</Name>
|
||||
|
@ -1,8 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FluentAssertions;
|
||||
using Microsoft.AspNet.SignalR.Client;
|
||||
using Microsoft.AspNet.SignalR.Client.Transports;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Api.RootFolders;
|
||||
|
||||
@ -11,39 +8,25 @@ namespace NzbDrone.Integration.Test
|
||||
[TestFixture]
|
||||
public class RootFolderIntegrationTest : IntegrationTest
|
||||
{
|
||||
private Connection _connection;
|
||||
private List<object> _signalRReceived;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_signalRReceived = new List<object>();
|
||||
_connection = new Connection("http://localhost:8989/signalr/rootfolder");
|
||||
_connection.Start(new LongPollingTransport()).ContinueWith(task =>
|
||||
{
|
||||
if (task.IsFaulted)
|
||||
{
|
||||
Assert.Fail("SignalrConnection failed. {0}", task.Exception.GetBaseException());
|
||||
}
|
||||
});
|
||||
|
||||
_connection.Received += _connection_Received;
|
||||
}
|
||||
|
||||
private void _connection_Received(string obj)
|
||||
{
|
||||
_signalRReceived.Add(obj);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_have_no_root_folder_initially()
|
||||
{
|
||||
RootFolders.All().Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_add_and_delete_root_folders()
|
||||
{
|
||||
|
||||
ConnectSignalR();
|
||||
|
||||
var rootFolder = new RootFolderResource
|
||||
{
|
||||
Path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
|
||||
};
|
||||
{
|
||||
Path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
|
||||
};
|
||||
|
||||
var postResponse = RootFolders.Post(rootFolder);
|
||||
|
||||
@ -56,6 +39,11 @@ public void should_have_no_root_folder_initially()
|
||||
RootFolders.Delete(postResponse.Id);
|
||||
|
||||
RootFolders.All().Should().BeEmpty();
|
||||
|
||||
|
||||
SignalRMessages.Should().Contain(c => c.Name == "rootfolder");
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -1,17 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="2.1.0.0" targetFramework="net40" />
|
||||
<package id="FluentValidation" version="4.0.0.1" targetFramework="net40" />
|
||||
<package id="FluentValidation" version="5.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" />
|
||||
<package id="Microsoft.Owin.Host.HttpListener" version="1.1.0-beta2" targetFramework="net40" />
|
||||
<package id="Microsoft.Owin.Hosting" version="1.1.0-beta2" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" targetFramework="net40" />
|
||||
<package id="Nancy" version="0.20.0" targetFramework="net40" />
|
||||
<package id="Nancy.Owin" version="0.20.0" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" />
|
||||
<package id="NLog" version="2.0.1.2" targetFramework="net40" />
|
||||
<package id="Nancy" version="0.21.1" targetFramework="net40" />
|
||||
<package id="Nancy.Owin" version="0.21.1" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net40" />
|
||||
<package id="NLog" version="2.1.0" targetFramework="net40" />
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net40" />
|
||||
<package id="Owin" version="1.0" targetFramework="net40" />
|
||||
<package id="RestSharp" version="104.2.0" targetFramework="net40" />
|
||||
<package id="RestSharp" version="104.3.3" targetFramework="net40" />
|
||||
</packages>
|
@ -39,7 +39,7 @@
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework">
|
||||
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FluentAssertions" version="2.1.0.0" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net40" />
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net40" />
|
||||
</packages>
|
@ -36,8 +36,9 @@
|
||||
<Reference Include="Microsoft.AspNet.SignalR.Core">
|
||||
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.AspNet.SignalR.Core" version="1.1.3" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" />
|
||||
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net40" />
|
||||
</packages>
|
@ -54,16 +54,20 @@
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=2.0.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NLog.2.0.1.2\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RestSharp, Version=104.3.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\RestSharp.104.3.3\lib\net4\RestSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
@ -82,6 +86,7 @@
|
||||
<Compile Include="Categories\IntegrationTestAttribute.cs" />
|
||||
<Compile Include="LoggingTest.cs" />
|
||||
<Compile Include="MockerExtensions.cs" />
|
||||
<Compile Include="NzbDroneRunner.cs" />
|
||||
<Compile Include="ObjectExtentions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ReflectionExtensions.cs" />
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user