Merge branch 'master' into nzburl
This commit is contained in:
commit
0c3de6964f
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<solution>
|
||||
<add key="disableSourceControlIntegration" value="true" />
|
||||
</solution>
|
||||
</configuration>
|
Binary file not shown.
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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>
|
||||
|
||||
<!-- NuGet command -->
|
||||
<NuGetExePath>$(NuGetToolsPath)\nuget.exe</NuGetExePath>
|
||||
<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>""</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>
|
||||
|
||||
<!-- Commands -->
|
||||
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source $(PackageSources) -o "$(PackagesDir)"</RestoreCommand>
|
||||
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols</BuildCommand>
|
||||
|
||||
<!-- Make the build depend on restore packages -->
|
||||
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
|
||||
RestorePackages;
|
||||
$(BuildDependsOn);
|
||||
</BuildDependsOn>
|
||||
|
||||
<!-- Make the build depend on restore packages -->
|
||||
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
|
||||
$(BuildDependsOn);
|
||||
BuildPackage;
|
||||
</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="CheckPrerequisites">
|
||||
<!-- Raise an error if we're unable to locate nuget.exe -->
|
||||
<Error Condition="!Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(BuildCommand)"
|
||||
Condition=" '$(OS)' != 'Windows_NT' " />
|
||||
|
||||
<Exec Command="$(BuildCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition=" '$(OS)' == 'Windows_NT' " />
|
||||
</Target>
|
||||
</Project>
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>NzbDrone.App.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|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -91,6 +93,7 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>NzbDrone.Common.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|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -88,6 +90,7 @@
|
|||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NzbDrone.Common.Contract
|
||||
{
|
||||
public class ExceptionReport : ReportBase
|
||||
{
|
||||
[JsonProperty("t")]
|
||||
public string Type { get; set; }
|
||||
[JsonProperty("l")]
|
||||
public string Logger { get; set; }
|
||||
[JsonProperty("lm")]
|
||||
public string LogMessage { get; set; }
|
||||
[JsonProperty("s")]
|
||||
public string String { get; set; }
|
||||
|
||||
[JsonProperty("xmessage")]
|
||||
public string ExceptionMessage { get; set; }
|
||||
|
||||
[JsonProperty("stk")]
|
||||
public string Stack { get; set; }
|
||||
|
||||
protected override Dictionary<string, string> GetString()
|
||||
{
|
||||
var dic = new Dictionary<string, string>
|
||||
{
|
||||
{"ExType", Type.NullSafe()},
|
||||
{"Logger", Logger.NullSafe()},
|
||||
{"Message", LogMessage.NullSafe()},
|
||||
{"Str", String.NullSafe()}
|
||||
};
|
||||
|
||||
return dic;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NzbDrone.Common.Contract
|
||||
{
|
||||
public class ExceptionReportResponse
|
||||
{
|
||||
[JsonProperty("h")]
|
||||
public string ExceptionHash { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NzbDrone.Common.Contract
|
||||
{
|
||||
public class ExistingExceptionReport : ReportBase
|
||||
{
|
||||
|
||||
[JsonProperty("h")]
|
||||
public string Hash { get; set; }
|
||||
|
||||
[JsonProperty("lm")]
|
||||
public string LogMessage { get; set; }
|
||||
|
||||
protected override Dictionary<string, string> GetString()
|
||||
{
|
||||
var dic = new Dictionary<string, string>
|
||||
{
|
||||
{"Message", LogMessage.NullSafe()}
|
||||
};
|
||||
|
||||
return dic;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>NzbDrone.Common</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -36,9 +38,11 @@
|
|||
<Reference Include="Exceptioneer.WindowsFormsClient">
|
||||
<HintPath>..\Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.0.8.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Reference Include="Exceptron.Driver, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Exceptron.Driver.0.1.0.8\lib\net20\Exceptron.Driver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.4\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Ninject">
|
||||
<HintPath>..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll</HintPath>
|
||||
|
@ -54,13 +58,10 @@
|
|||
<Reference Include="System.Xml.Linq" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Contract\ExceptionReportResponse.cs" />
|
||||
<Compile Include="Contract\ExistingExceptionReport.cs" />
|
||||
<Compile Include="StringExtention.cs" />
|
||||
<Compile Include="HttpProvider.cs" />
|
||||
<Compile Include="ConfigFileProvider.cs" />
|
||||
<Compile Include="ConsoleProvider.cs" />
|
||||
<Compile Include="Contract\ExceptionReport.cs" />
|
||||
<Compile Include="Contract\ReportBase.cs" />
|
||||
<Compile Include="Contract\ParseErrorReport.cs" />
|
||||
<Compile Include="NlogTargets\RemoteTarget.cs" />
|
||||
|
@ -95,6 +96,7 @@
|
|||
</COMReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Exceptron.Driver;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Contract;
|
||||
|
||||
|
@ -12,12 +13,13 @@ namespace NzbDrone.Common
|
|||
|
||||
private const string SERVICE_URL = "http://services.nzbdrone.com/reporting";
|
||||
private const string PARSE_URL = SERVICE_URL + "/ParseError";
|
||||
private const string EXCEPTION_URL = SERVICE_URL + "/ReportException";
|
||||
|
||||
public static RestProvider RestProvider { get; set; }
|
||||
private static readonly HashSet<string> parserErrorCache = new HashSet<string>();
|
||||
public static ExceptionClient ExceptronDriver { get; set; }
|
||||
|
||||
|
||||
private static readonly HashSet<string> parserErrorCache = new HashSet<string>();
|
||||
|
||||
public static void ClearCache()
|
||||
{
|
||||
lock (parserErrorCache)
|
||||
|
@ -30,12 +32,12 @@ namespace NzbDrone.Common
|
|||
{
|
||||
try
|
||||
{
|
||||
VerifyRestProvider();
|
||||
VerifyDependencies();
|
||||
|
||||
lock (parserErrorCache)
|
||||
{
|
||||
if (parserErrorCache.Contains(title.ToLower())) return;
|
||||
|
||||
|
||||
parserErrorCache.Add(title.ToLower());
|
||||
}
|
||||
|
||||
|
@ -54,20 +56,20 @@ namespace NzbDrone.Common
|
|||
}
|
||||
}
|
||||
|
||||
public static void ReportException(LogEventInfo logEvent)
|
||||
public static string ReportException(LogEventInfo logEvent)
|
||||
{
|
||||
try
|
||||
{
|
||||
VerifyRestProvider();
|
||||
|
||||
var report = new ExceptionReport();
|
||||
report.LogMessage = logEvent.FormattedMessage;
|
||||
report.Stack = logEvent.Exception.StackTrace;
|
||||
report.ExceptionMessage = logEvent.Exception.Message;
|
||||
report.Logger = logEvent.LoggerName;
|
||||
report.Type = logEvent.Exception.GetType().FullName;
|
||||
VerifyDependencies();
|
||||
|
||||
RestProvider.PostData(EXCEPTION_URL, report);
|
||||
var exceptionData = new ExceptionData();
|
||||
|
||||
exceptionData.Exception = logEvent.Exception;
|
||||
exceptionData.Location = logEvent.LoggerName;
|
||||
exceptionData.Message = logEvent.FormattedMessage;
|
||||
exceptionData.UserId = EnvironmentProvider.UGuid.ToString().Replace("-", string.Empty);
|
||||
|
||||
return ExceptronDriver.SubmitException(exceptionData);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -75,17 +77,32 @@ namespace NzbDrone.Common
|
|||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
//this shouldn't log an exception since it will cause a recursive loop.
|
||||
logger.Info("Unable to report exception. " + e);
|
||||
if (logEvent.LoggerName != logger.Name)//prevents a recursive loop.
|
||||
{
|
||||
logger.WarnException("Unable to report exception. ", e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void VerifyRestProvider()
|
||||
|
||||
public static void SetupExceptronDriver()
|
||||
{
|
||||
if(RestProvider == null)
|
||||
ExceptronDriver = new ExceptionClient("CB230C312E5C4FF38B4FB9644B05E60E")
|
||||
{
|
||||
ApplicationVersion = new EnvironmentProvider().Version.ToString()
|
||||
};
|
||||
|
||||
ExceptronDriver.ThrowsExceptions = !EnvironmentProvider.IsProduction;
|
||||
ExceptronDriver.Enviroment = EnvironmentProvider.IsProduction ? "Prod" : "Dev";
|
||||
}
|
||||
|
||||
private static void VerifyDependencies()
|
||||
{
|
||||
if (RestProvider == null)
|
||||
{
|
||||
if(EnvironmentProvider.IsProduction)
|
||||
if (EnvironmentProvider.IsProduction)
|
||||
{
|
||||
logger.Warn("Rest provider wasn't provided. creating new one!");
|
||||
RestProvider = new RestProvider(new EnvironmentProvider());
|
||||
|
@ -95,6 +112,19 @@ namespace NzbDrone.Common
|
|||
throw new InvalidOperationException("REST Provider wasn't configured correctly.");
|
||||
}
|
||||
}
|
||||
|
||||
if (ExceptronDriver == null)
|
||||
{
|
||||
if (EnvironmentProvider.IsProduction)
|
||||
{
|
||||
logger.Warn("Exceptron Driver wasn't provided. creating new one!");
|
||||
SetupExceptronDriver();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Exceptron Driver wasn't configured correctly.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="4.0.8" />
|
||||
<package id="Exceptron.Driver" version="0.1.0.8" />
|
||||
<package id="Newtonsoft.Json" version="4.5.4" />
|
||||
<package id="NLog" version="2.0.0.2000" />
|
||||
</packages>
|
|
@ -12,7 +12,7 @@
|
|||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.7.0" newVersion="4.0.7.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="4.5.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
|
|
@ -63,6 +63,11 @@ namespace NzbDrone.Core.Test.Framework
|
|||
}
|
||||
}
|
||||
|
||||
protected static void ThrowException()
|
||||
{
|
||||
throw new ApplicationException("This is a message for test exception");
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void CoreTestTearDown()
|
||||
{
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.ServiceModel.Syndication;
|
||||
|
||||
using System.Threading;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
|
@ -530,5 +531,37 @@ namespace NzbDrone.Core.Test
|
|||
parseResults.Should().HaveCount(1);
|
||||
parseResults[0].CleanTitle.Should().Be("britainsgottalent");
|
||||
}
|
||||
|
||||
[TestCase("wombles.xml", "de-de")]
|
||||
public void dateTime_should_parse_when_using_other_cultures(string fileName, string culture)
|
||||
{
|
||||
var currentCulture = Thread.CurrentThread.CurrentCulture;
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo(culture);
|
||||
|
||||
Mocker.GetMock<HttpProvider>()
|
||||
.Setup(h => h.DownloadStream(It.IsAny<String>(), It.IsAny<NetworkCredential>()))
|
||||
.Returns(File.OpenRead(".\\Files\\Rss\\" + fileName));
|
||||
|
||||
var fakeSettings = Builder<IndexerDefinition>.CreateNew().Build();
|
||||
Mocker.GetMock<IndexerProvider>()
|
||||
.Setup(c => c.GetSettings(It.IsAny<Type>()))
|
||||
.Returns(fakeSettings);
|
||||
|
||||
var mockIndexer = Mocker.Resolve<MockIndexer>();
|
||||
var parseResults = mockIndexer.FetchRss();
|
||||
|
||||
foreach (var episodeParseResult in parseResults)
|
||||
{
|
||||
var Uri = new Uri(episodeParseResult.NzbUrl);
|
||||
Uri.PathAndQuery.Should().NotContain("//");
|
||||
}
|
||||
|
||||
parseResults.Should().NotBeEmpty();
|
||||
parseResults.Should().OnlyContain(s => s.Indexer == mockIndexer.Name);
|
||||
parseResults.Should().OnlyContain(s => !String.IsNullOrEmpty(s.OriginalString));
|
||||
parseResults.Should().OnlyContain(s => s.Age >= 0);
|
||||
|
||||
Thread.CurrentThread.CurrentCulture = currentCulture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ using PetaPoco;
|
|||
namespace NzbDrone.Core.Test.Integeration
|
||||
{
|
||||
[TestFixture(Category = "ServiceIngeneration")]
|
||||
[Explicit]
|
||||
public class ServiceIntegerationFixture : CoreTest
|
||||
{
|
||||
private KernelBase _kernel;
|
||||
|
@ -58,14 +57,27 @@ namespace NzbDrone.Core.Test.Integeration
|
|||
[Test]
|
||||
public void should_be_able_to_submit_exceptions()
|
||||
{
|
||||
ReportingService.RestProvider = new RestProvider(new EnvironmentProvider());
|
||||
ReportingService.SetupExceptronDriver();
|
||||
|
||||
try
|
||||
{
|
||||
ThrowException();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var log = new LogEventInfo
|
||||
{
|
||||
LoggerName = "LoggerName.LoggerName.LoggerName.LoggerName",
|
||||
Exception = e,
|
||||
Message = "New message string. New message string.",
|
||||
};
|
||||
|
||||
var hash = ReportingService.ReportException(log);
|
||||
|
||||
hash.Should().HaveLength(8);
|
||||
}
|
||||
|
||||
var log = new LogEventInfo();
|
||||
log.LoggerName = "LoggerName.LoggerName.LoggerName.LoggerName";
|
||||
log.Exception = new ArgumentOutOfRangeException();
|
||||
log.Message = "New message string. New message string. New message string. New message string. New message string. New message string.";
|
||||
|
||||
ReportingService.ReportException(log);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,9 +6,11 @@ using FizzWare.NBuilder;
|
|||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Jobs;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Model.Notification;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.Repository.Search;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common.AutoMoq;
|
||||
|
||||
|
@ -39,10 +41,16 @@ namespace NzbDrone.Core.Test.JobTests
|
|||
[Test]
|
||||
public void SeasonSearch_partial_season_success()
|
||||
{
|
||||
var resultItems = Builder<SearchHistoryItem>.CreateListOfSize(5)
|
||||
.All()
|
||||
.With(e => e.SearchError = ReportRejectionType.None)
|
||||
.With(e => e.Success = true)
|
||||
.Build();
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(5)
|
||||
.All()
|
||||
.With(e => e.SeriesId = 1)
|
||||
.With(e => e.SeasonNumber = 1)
|
||||
.With(e => e.SeriesId = 5)
|
||||
.Build();
|
||||
|
||||
var notification = new ProgressNotification("Season Search");
|
||||
|
@ -88,7 +96,7 @@ namespace NzbDrone.Core.Test.JobTests
|
|||
|
||||
Mocker.GetMock<SearchProvider>()
|
||||
.Setup(c => c.PartialSeasonSearch(notification, 1, 1))
|
||||
.Returns(new List<int>{1});
|
||||
.Returns(new List<int>());
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<SeasonSearchJob>().Start(notification, 1, 1);
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>NzbDrone.Core.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|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -58,9 +60,9 @@
|
|||
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.0.8.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Ninject, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll</HintPath>
|
||||
|
@ -112,6 +114,7 @@
|
|||
<Compile Include="ProviderTests\AnalyticsProviderTests\AnalyticsProviderFixture.cs" />
|
||||
<Compile Include="ProviderTests\ConfigProviderTests\ConfigCachingFixture.cs" />
|
||||
<Compile Include="ProviderTests\BannerProviderTest.cs" />
|
||||
<Compile Include="ProviderTests\SearchHistoryProviderTest.cs" />
|
||||
<Compile Include="ProviderTests\PlexProviderTest.cs" />
|
||||
<Compile Include="ProviderTests\SeasonProviderTest.cs" />
|
||||
<Compile Include="ProviderTests\DecisionEngineTests\RetentionSpecificationFixture.cs" />
|
||||
|
@ -308,6 +311,7 @@
|
|||
xcopy /s /y "$(SolutionDir)packages\SqlServerCompact.4.0.8482.1\NativeBinaries\x86\*.*" "$(TargetDir)"
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -67,6 +67,8 @@ namespace NzbDrone.Core.Test
|
|||
[TestCase("castle.2009.416.hdtv-lol", "Castle 2009", 4, 16)]
|
||||
[TestCase("hawaii.five-0.2010.217.hdtv-lol", "Hawaii Five-0 (2010)", 2, 17)]
|
||||
[TestCase("Looney Tunes - S1936E18 - I Love to Singa", "Looney Tunes", 1936, 18)]
|
||||
[TestCase("American_Dad!_-_7x6_-_The_Scarlett_Getter_[SDTV]", "American Dad!", 7, 6)]
|
||||
[TestCase("Falling_Skies_-_1x1_-_Live_and_Learn_[HDTV]", "Falling Skies", 1, 1)]
|
||||
public void ParseTitle_single(string postTitle, string title, int seasonNumber, int episodeNumber)
|
||||
{
|
||||
var result = Parser.ParseTitle(postTitle);
|
||||
|
@ -159,6 +161,14 @@ namespace NzbDrone.Core.Test
|
|||
[TestCase("Gossip Girl S05E11 PROPER HDTV XviD 2HD", QualityTypes.SDTV, true)]
|
||||
[TestCase("The Jonathan Ross Show S02E08 HDTV x264 FTP", QualityTypes.SDTV, false)]
|
||||
[TestCase("White.Van.Man.2011.S02E01.WS.PDTV.x264-TLA", QualityTypes.SDTV, false)]
|
||||
[TestCase("White.Van.Man.2011.S02E01.WS.PDTV.x264-REPACK-TLA", QualityTypes.SDTV, true)]
|
||||
[TestCase("WEEDS.S03E01-06.DUAL.XviD.Bluray.AC3-REPACK.-HELLYWOOD.avi", QualityTypes.DVD, true)]
|
||||
[TestCase("Pawn Stars S04E87 REPACK 720p HDTV x264 aAF", QualityTypes.HDTV, true)]
|
||||
[TestCase("The Real Housewives of Vancouver S01E04 DSR x264 2HD", QualityTypes.SDTV, false)]
|
||||
[TestCase("Vanguard S01E04 Mexicos Death Train DSR x264 MiNDTHEGAP", QualityTypes.SDTV, false)]
|
||||
[TestCase("Vanguard S01E04 Mexicos Death Train 720 WEB DL", QualityTypes.WEBDL, false)]
|
||||
[TestCase("Hawaii Five 0 S02E21 720p WEB DL DD5 1 H 264", QualityTypes.WEBDL, false)]
|
||||
[TestCase("Castle S04E22 720p WEB DL DD5 1 H 264 NFHD", QualityTypes.WEBDL, false)]
|
||||
public void quality_parse(string postTitle, object quality, bool proper)
|
||||
{
|
||||
var result = Parser.ParseQuality(postTitle);
|
||||
|
@ -194,6 +204,9 @@ namespace NzbDrone.Core.Test
|
|||
[TestCase("2x04x05.720p.BluRay-FUTV", "", 2, new[] { 4, 5 })]
|
||||
[TestCase("S02E04E05.720p.BluRay-FUTV", "", 2, new[] { 4, 5 })]
|
||||
[TestCase("S02E03-04-05.720p.BluRay-FUTV", "", 2, new[] { 3,4,5 })]
|
||||
[TestCase("Breakout.Kings.S02E09-E10.HDTV.x264-ASAP", "Breakout Kings", 2, new[] { 9, 10 })]
|
||||
[TestCase("Breakout Kings - 2x9-2x10 - Served Cold [SDTV] ", "Breakout Kings", 2, new[] { 9, 10 })]
|
||||
[TestCase("Breakout Kings - 2x09-2x10 - Served Cold [SDTV] ", "Breakout Kings", 2, new[] { 9, 10 })]
|
||||
public void TitleParse_multi(string postTitle, string title, int season, int[] episodes)
|
||||
{
|
||||
var result = Parser.ParseTitle(postTitle);
|
||||
|
|
|
@ -88,42 +88,42 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
|
|||
[Test]
|
||||
public void should_be_allowed_if_all_conditions_are_met()
|
||||
{
|
||||
spec.IsSatisfiedBy(parseResult).Should().BeTrue();
|
||||
spec.IsSatisfiedBy(parseResult).Should().Be(ReportRejectionType.None);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_be_allowed_if_profile_is_not_allowed()
|
||||
{
|
||||
WithProfileNotAllowed();
|
||||
spec.IsSatisfiedBy(parseResult).Should().BeFalse();
|
||||
spec.IsSatisfiedBy(parseResult).Should().Be(ReportRejectionType.QualityNotWanted);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_be_allowed_if_size_is_not_allowed()
|
||||
{
|
||||
WithNotAcceptableSize();
|
||||
spec.IsSatisfiedBy(parseResult).Should().BeFalse();
|
||||
spec.IsSatisfiedBy(parseResult).Should().Be(ReportRejectionType.Size);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_be_allowed_if_disk_is_not_upgrade()
|
||||
{
|
||||
WithNoDiskUpgrade();
|
||||
spec.IsSatisfiedBy(parseResult).Should().BeFalse();
|
||||
spec.IsSatisfiedBy(parseResult).Should().Be(ReportRejectionType.ExistingQualityIsEqualOrBetter);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_be_allowed_if_episode_is_already_in_queue()
|
||||
{
|
||||
WithEpisodeAlreadyInQueue();
|
||||
spec.IsSatisfiedBy(parseResult).Should().BeFalse();
|
||||
spec.IsSatisfiedBy(parseResult).Should().Be(ReportRejectionType.AlreadyInQueue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_be_allowed_if_report_is_over_retention()
|
||||
{
|
||||
WithOverRetention();
|
||||
spec.IsSatisfiedBy(parseResult).Should().BeFalse();
|
||||
spec.IsSatisfiedBy(parseResult).Should().Be(ReportRejectionType.Retention);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -134,7 +134,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
|
|||
WithProfileNotAllowed();
|
||||
WithOverRetention();
|
||||
|
||||
spec.IsSatisfiedBy(parseResult).Should().BeFalse();
|
||||
spec.IsSatisfiedBy(parseResult).Should().Be(ReportRejectionType.QualityNotWanted);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -212,5 +212,104 @@ namespace NzbDrone.Core.Test.ProviderTests
|
|||
//Assert
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CleanUpDropFolder_should_do_nothing_if_no_files_are_found()
|
||||
{
|
||||
//Setup
|
||||
var folder = @"C:\Test\DropDir\The Office";
|
||||
|
||||
Mocker.GetMock<DiskProvider>().Setup(s => s.GetFiles(folder, SearchOption.AllDirectories))
|
||||
.Returns(new string[0]);
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<DiskScanProvider>().CleanUpDropFolder(folder);
|
||||
|
||||
//Assert
|
||||
Mocker.GetMock<MediaFileProvider>().Verify(v => v.GetFileByPath(It.IsAny<string>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CleanUpDropFolder_should_do_nothing_if_no_conflicting_files_are_found()
|
||||
{
|
||||
//Setup
|
||||
var folder = @"C:\Test\DropDir\The Office";
|
||||
var filename = Path.Combine(folder, "NotAProblem.avi");
|
||||
|
||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.With(f => f.Path = filename.NormalizePath())
|
||||
.With(f => f.SeriesId = 12345)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<DiskProvider>().Setup(s => s.GetFiles(folder, SearchOption.AllDirectories))
|
||||
.Returns(new string[] { filename });
|
||||
|
||||
Mocker.GetMock<MediaFileProvider>().Setup(s => s.GetFileByPath(filename))
|
||||
.Returns(() => null);
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<DiskScanProvider>().CleanUpDropFolder(folder);
|
||||
|
||||
//Assert
|
||||
Mocker.GetMock<MediaFileProvider>().Verify(v => v.GetFileByPath(filename), Times.Once());
|
||||
Mocker.GetMock<SeriesProvider>().Verify(v => v.GetSeries(It.IsAny<int>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CleanUpDropFolder_should_move_file_if_a_conflict_is_found()
|
||||
{
|
||||
//Setup
|
||||
var folder = @"C:\Test\DropDir\The Office";
|
||||
var filename = Path.Combine(folder, "Problem.avi");
|
||||
var seriesId = 12345;
|
||||
var newFilename = "S01E01 - Title";
|
||||
var newFilePath = @"C:\Test\TV\The Office\Season 01\S01E01 - Title.avi";
|
||||
|
||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.With(f => f.Path = filename.NormalizePath())
|
||||
.With(f => f.SeriesId = seriesId)
|
||||
.Build();
|
||||
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.With(s => s.SeriesId = seriesId)
|
||||
.With(s => s.Title = "The Office")
|
||||
.Build();
|
||||
|
||||
var episode = Builder<Episode>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(e => e.SeriesId = seriesId)
|
||||
.With(e => e.EpisodeFileId = episodeFile.EpisodeFileId)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<MediaFileProvider>().Setup(v => v.GetFileByPath(filename))
|
||||
.Returns(() => null);
|
||||
|
||||
Mocker.GetMock<DiskProvider>().Setup(s => s.GetFiles(folder, SearchOption.AllDirectories))
|
||||
.Returns(new string[] { filename });
|
||||
|
||||
Mocker.GetMock<MediaFileProvider>().Setup(s => s.GetFileByPath(filename))
|
||||
.Returns(episodeFile);
|
||||
|
||||
Mocker.GetMock<SeriesProvider>().Setup(s => s.GetSeries(It.IsAny<int>()))
|
||||
.Returns(series);
|
||||
|
||||
Mocker.GetMock<EpisodeProvider>().Setup(s => s.GetEpisodesByFileId(episodeFile.EpisodeFileId))
|
||||
.Returns(episode);
|
||||
|
||||
Mocker.GetMock<MediaFileProvider>().Setup(s => s.GetNewFilename(It.IsAny<IList<Episode>>(), series.Title, QualityTypes.Unknown, false))
|
||||
.Returns(newFilename);
|
||||
|
||||
Mocker.GetMock<MediaFileProvider>().Setup(s => s.CalculateFilePath(It.IsAny<Series>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Returns(new FileInfo(newFilePath));
|
||||
|
||||
Mocker.GetMock<DiskProvider>().Setup(s => s.MoveFile(episodeFile.Path, newFilePath));
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<DiskScanProvider>().CleanUpDropFolder(folder);
|
||||
|
||||
//Assert
|
||||
Mocker.GetMock<MediaFileProvider>().Verify(v => v.GetFileByPath(filename), Times.Once());
|
||||
Mocker.GetMock<DiskProvider>().Verify(v => v.MoveFile(filename.NormalizePath(), newFilePath), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,12 +179,12 @@ namespace NzbDrone.Core.Test.ProviderTests
|
|||
}
|
||||
|
||||
|
||||
[TestCase(1, new[] { 2 }, "My Episode Title", QualityTypes.DVD, false, Result = "My Series Name - 1x2 - My Episode Title [DVD]")]
|
||||
[TestCase(1, new[] { 2 }, "My Episode Title", QualityTypes.DVD, true, Result = "My Series Name - 1x2 - My Episode Title [DVD] [Proper]")]
|
||||
[TestCase(1, new[] { 2 }, "", QualityTypes.DVD, true, Result = "My Series Name - 1x2 - [DVD] [Proper]")]
|
||||
[TestCase(1, new[] { 2, 4 }, "My Episode Title", QualityTypes.HDTV, false, Result = "My Series Name - 1x2-1x4 - My Episode Title [HDTV]")]
|
||||
[TestCase(1, new[] { 2, 4 }, "My Episode Title", QualityTypes.HDTV, true, Result = "My Series Name - 1x2-1x4 - My Episode Title [HDTV] [Proper]")]
|
||||
[TestCase(1, new[] { 2, 4 }, "", QualityTypes.HDTV, true, Result = "My Series Name - 1x2-1x4 - [HDTV] [Proper]")]
|
||||
[TestCase(1, new[] { 2 }, "My Episode Title", QualityTypes.DVD, false, Result = "My Series Name - 1x02 - My Episode Title [DVD]")]
|
||||
[TestCase(1, new[] { 2 }, "My Episode Title", QualityTypes.DVD, true, Result = "My Series Name - 1x02 - My Episode Title [DVD] [Proper]")]
|
||||
[TestCase(1, new[] { 2 }, "", QualityTypes.DVD, true, Result = "My Series Name - 1x02 - [DVD] [Proper]")]
|
||||
[TestCase(1, new[] { 2, 4 }, "My Episode Title", QualityTypes.HDTV, false, Result = "My Series Name - 1x02-1x04 - My Episode Title [HDTV]")]
|
||||
[TestCase(1, new[] { 2, 4 }, "My Episode Title", QualityTypes.HDTV, true, Result = "My Series Name - 1x02-1x04 - My Episode Title [HDTV] [Proper]")]
|
||||
[TestCase(1, new[] { 2, 4 }, "", QualityTypes.HDTV, true, Result = "My Series Name - 1x02-1x04 - [HDTV] [Proper]")]
|
||||
public string create_proper_sab_titles(int seasons, int[] episodes, string title, QualityTypes quality, bool proper)
|
||||
{
|
||||
var series = Builder<Series>.CreateNew()
|
||||
|
|
|
@ -158,5 +158,40 @@ namespace NzbDrone.Core.Test.ProviderTests
|
|||
result.Should().HaveCount(9);
|
||||
result.Should().NotContain(e => e.EpisodeFileId == 1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFileByPath_should_return_null_if_file_does_not_exist_in_database()
|
||||
{
|
||||
//Setup
|
||||
WithRealDb();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<MediaFileProvider>().GetFileByPath(@"C:\Test\EpisodeFile.avi");
|
||||
|
||||
//Resolve
|
||||
result.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFileByPath_should_return_EpisodeFile_if_file_exists_in_database()
|
||||
{
|
||||
var path = @"C:\Test\EpisodeFile.avi";
|
||||
|
||||
//Setup
|
||||
WithRealDb();
|
||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.With(f => f.Path = path.NormalizePath())
|
||||
.Build();
|
||||
|
||||
var episodeFileId = Convert.ToInt32(Db.Insert(episodeFile));
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<MediaFileProvider>().GetFileByPath(path);
|
||||
|
||||
//Resolve
|
||||
result.Should().NotBeNull();
|
||||
result.Path.Should().Be(path.NormalizePath());
|
||||
result.EpisodeFileId.Should().Be(episodeFileId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -279,6 +279,7 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests
|
|||
.Build().ToList();
|
||||
|
||||
Mocker.GetMock<SeriesProvider>().Setup(s => s.FindSeries("office")).Returns(fakeSeries);
|
||||
Mocker.GetMock<DiskScanProvider>().Setup(s => s.CleanUpDropFolder(droppedFolder.FullName));
|
||||
Mocker.GetMock<DiskScanProvider>().Setup(s => s.Scan(fakeSeries, droppedFolder.FullName)).Returns(fakeEpisodeFiles);
|
||||
Mocker.GetMock<DiskScanProvider>().Setup(s => s.MoveEpisodeFile(It.IsAny<EpisodeFile>(), true)).Returns(true);
|
||||
Mocker.GetMock<DiskProvider>().Setup(s => s.GetDirectorySize(droppedFolder.FullName)).Returns(Constants.IgnoreFileSize - 1.Megabytes());
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Model.Notification;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
using NzbDrone.Core.Repository.Search;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common.AutoMoq;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.ProviderTests
|
||||
{
|
||||
[TestFixture]
|
||||
// ReSharper disable InconsistentNaming
|
||||
public class SearchHistoryProviderTest : CoreTest
|
||||
{
|
||||
private SearchHistory _searchHistory;
|
||||
private Series _series;
|
||||
private Episode _episode;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_series = Builder<Series>.CreateNew()
|
||||
.Build();
|
||||
|
||||
_episode = Builder<Episode>.CreateNew()
|
||||
.Build();
|
||||
|
||||
var items = Builder<SearchHistoryItem>.CreateListOfSize(10)
|
||||
.Build().ToList();
|
||||
|
||||
_searchHistory = Builder<SearchHistory>.CreateNew()
|
||||
.With(h => h.EpisodeId = _episode.EpisodeId)
|
||||
.With(h => h.SeriesId - _series.SeriesId)
|
||||
.With(h => h.SearchHistoryItems = items)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private void WithUnsuccessfulSearch()
|
||||
{
|
||||
foreach(var item in _searchHistory.SearchHistoryItems)
|
||||
{
|
||||
item.Success = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void WithSuccessfulSearch()
|
||||
{
|
||||
foreach(var item in _searchHistory.SearchHistoryItems)
|
||||
{
|
||||
item.Success = false;
|
||||
}
|
||||
|
||||
var i = _searchHistory.SearchHistoryItems.Last();
|
||||
i.Success = true;
|
||||
i.SearchError = ReportRejectionType.None;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Add_should_add_history_and_history_items()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
Db.Fetch<SearchHistory>().Should().HaveCount(1);
|
||||
Db.Fetch<SearchHistoryItem>().Should().HaveCount(10);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Add_should_add_return_id()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var result = Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
result.Should().NotBe(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Delete_should_delete_history_and_history_items()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
var history = Db.Fetch<SearchHistory>();
|
||||
|
||||
Mocker.Resolve<SearchHistoryProvider>().Delete(history.First().Id);
|
||||
|
||||
Db.Fetch<SearchHistory>().Should().HaveCount(0);
|
||||
Db.Fetch<SearchHistoryItem>().Should().HaveCount(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllSearchHistory_should_return_all_items()
|
||||
{
|
||||
WithRealDb();
|
||||
Db.Insert(_series);
|
||||
Db.Insert(_episode);
|
||||
|
||||
Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
var result = Mocker.Resolve<SearchHistoryProvider>().AllSearchHistory();
|
||||
|
||||
result.Count.Should().Be(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllSearchHistory_should_have_series_title()
|
||||
{
|
||||
WithRealDb();
|
||||
Db.Insert(_series);
|
||||
Db.Insert(_episode);
|
||||
|
||||
Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
var result = Mocker.Resolve<SearchHistoryProvider>().AllSearchHistory();
|
||||
|
||||
result.Count.Should().Be(1);
|
||||
result.First().SeriesTitle.Should().Be(_series.Title);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllSearchHistory_should_have_episode_information()
|
||||
{
|
||||
WithRealDb();
|
||||
Db.Insert(_series);
|
||||
Db.Insert(_episode);
|
||||
|
||||
Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
var result = Mocker.Resolve<SearchHistoryProvider>().AllSearchHistory();
|
||||
|
||||
result.Count.Should().Be(1);
|
||||
result.First().EpisodeTitle.Should().Be(_episode.Title);
|
||||
result.First().EpisodeNumber.Should().Be(_episode.EpisodeNumber);
|
||||
result.First().SeasonNumber.Should().Be(_episode.SeasonNumber);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllSearchHistory_should_have_totalItems_count()
|
||||
{
|
||||
WithRealDb();
|
||||
Db.Insert(_series);
|
||||
Db.Insert(_episode);
|
||||
|
||||
Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
var result = Mocker.Resolve<SearchHistoryProvider>().AllSearchHistory();
|
||||
|
||||
result.Count.Should().Be(1);
|
||||
result.First().TotalItems.Should().Be(_searchHistory.SearchHistoryItems.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllSearchHistory_should_have_successfulCount_equal_zero_when_all_failed()
|
||||
{
|
||||
WithRealDb();
|
||||
Db.Insert(_series);
|
||||
Db.Insert(_episode);
|
||||
|
||||
WithUnsuccessfulSearch();
|
||||
|
||||
Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
var result = Mocker.Resolve<SearchHistoryProvider>().AllSearchHistory();
|
||||
|
||||
result.Count.Should().Be(1);
|
||||
result.First().SuccessfulCount.Should().Be(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllSearchHistory_should_have_successfulCount_equal_one_when_one_was_downloaded()
|
||||
{
|
||||
WithRealDb();
|
||||
Db.Insert(_series);
|
||||
Db.Insert(_episode);
|
||||
|
||||
WithSuccessfulSearch();
|
||||
|
||||
Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
var result = Mocker.Resolve<SearchHistoryProvider>().AllSearchHistory();
|
||||
|
||||
result.Count.Should().Be(1);
|
||||
result.First().SuccessfulCount.Should().Be(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSearchHistory_should_return_searchHistory_with_items()
|
||||
{
|
||||
WithRealDb();
|
||||
Db.Insert(_series);
|
||||
Db.Insert(_episode);
|
||||
|
||||
WithSuccessfulSearch();
|
||||
var id = Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
var result = Mocker.Resolve<SearchHistoryProvider>().GetSearchHistory(id);
|
||||
|
||||
result.SearchHistoryItems.Should().HaveCount(_searchHistory.SearchHistoryItems.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSearchHistory_should_have_episodeDetails()
|
||||
{
|
||||
WithRealDb();
|
||||
Db.Insert(_series);
|
||||
Db.Insert(_episode);
|
||||
|
||||
WithSuccessfulSearch();
|
||||
var id = Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
var result = Mocker.Resolve<SearchHistoryProvider>().GetSearchHistory(id);
|
||||
|
||||
result.EpisodeNumber.Should().Be(_episode.EpisodeNumber);
|
||||
result.SeasonNumber.Should().Be(_episode.SeasonNumber);
|
||||
result.EpisodeTitle.Should().Be(_episode.Title);
|
||||
result.AirDate.Should().Be(_episode.AirDate.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetSearchHistory_should_not_have_episode_info_if_it_was_a_full_season_search()
|
||||
{
|
||||
WithRealDb();
|
||||
Db.Insert(_series);
|
||||
|
||||
_searchHistory.EpisodeId = 0;
|
||||
var id = Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
|
||||
var result = Mocker.Resolve<SearchHistoryProvider>().GetSearchHistory(id);
|
||||
|
||||
result.EpisodeNumber.Should().Be(null);
|
||||
result.SeasonNumber.Should().Be(_searchHistory.SeasonNumber);
|
||||
result.EpisodeTitle.Should().Be(null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ForceDownload_should_download_report()
|
||||
{
|
||||
WithRealDb();
|
||||
Db.Insert(_series);
|
||||
Db.Insert(_episode);
|
||||
|
||||
var reportTitle = String.Format("{0} - S{1:00}E{2:00}", _series.Title, _episode.SeasonNumber, _episode.EpisodeNumber);
|
||||
_searchHistory.SearchHistoryItems.First().ReportTitle = reportTitle;
|
||||
|
||||
Mocker.Resolve<SearchHistoryProvider>().Add(_searchHistory);
|
||||
var items = Db.Fetch<SearchHistoryItem>();
|
||||
|
||||
Mocker.Resolve<SearchHistoryProvider>().ForceDownload(items.First().Id);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(v => v.DownloadReport(It.IsAny<EpisodeParseResult>()), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -77,14 +77,14 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
{
|
||||
Mocker.GetMock<AllowedDownloadSpecification>()
|
||||
.Setup(s => s.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()))
|
||||
.Returns(true);
|
||||
.Returns(ReportRejectionType.None);
|
||||
}
|
||||
|
||||
private void WithQualityNotNeeded()
|
||||
{
|
||||
Mocker.GetMock<AllowedDownloadSpecification>()
|
||||
.Setup(s => s.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()))
|
||||
.Returns(false);
|
||||
.Returns(ReportRejectionType.ExistingQualityIsEqualOrBetter);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -103,13 +103,13 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
|
||||
Mocker.GetMock<AllowedDownloadSpecification>()
|
||||
.Setup(s => s.IsSatisfiedBy(It.Is<EpisodeParseResult>(d => d.Quality.QualityType == QualityTypes.Bluray1080p)))
|
||||
.Returns(true);
|
||||
.Returns(ReportRejectionType.None);
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(MockNotification, parseResults, _matchingSeries, DateTime.Today);
|
||||
|
||||
//Assert
|
||||
result.Should().BeTrue();
|
||||
result.Should().Contain(n => n.Success);
|
||||
|
||||
Mocker.GetMock<AllowedDownloadSpecification>().Verify(c => c.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Once());
|
||||
|
@ -133,7 +133,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(MockNotification, parseResults, _matchingSeries, DateTime.Today);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
result.Should().NotContain(n => n.Success);
|
||||
|
||||
Mocker.GetMock<AllowedDownloadSpecification>().Verify(c => c.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Exactly(5));
|
||||
|
@ -147,6 +147,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
var parseResults = Builder<EpisodeParseResult>.CreateListOfSize(5)
|
||||
.All()
|
||||
.With(e => e.AirDate = DateTime.Today)
|
||||
.With(e => e.Quality = new Quality(QualityTypes.HDTV, false))
|
||||
.Build();
|
||||
|
||||
WithNullSeries();
|
||||
|
@ -155,7 +156,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(MockNotification, parseResults, _matchingSeries, DateTime.Today);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
result.Should().NotContain(n => n.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Never());
|
||||
|
@ -167,6 +168,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
var parseResults = Builder<EpisodeParseResult>.CreateListOfSize(5)
|
||||
.All()
|
||||
.With(e => e.AirDate = DateTime.Today)
|
||||
.With(e => e.Quality = new Quality(QualityTypes.HDTV, false))
|
||||
.Build();
|
||||
|
||||
WithMisMatchedSeries();
|
||||
|
@ -175,7 +177,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(MockNotification, parseResults, _matchingSeries, DateTime.Today);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
result.Should().NotContain(n => n.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Never());
|
||||
|
@ -198,7 +200,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(MockNotification, parseResults, _matchingSeries, DateTime.Today);
|
||||
|
||||
//Assert
|
||||
result.Should().BeTrue();
|
||||
result.Should().Contain(n => n.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Once());
|
||||
|
@ -230,7 +232,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(MockNotification, parseResults, _matchingSeries, DateTime.Today);
|
||||
|
||||
//Assert
|
||||
result.Should().BeTrue();
|
||||
result.Should().Contain(n => n.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Exactly(2));
|
||||
|
@ -242,6 +244,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
var parseResults = Builder<EpisodeParseResult>.CreateListOfSize(5)
|
||||
.All()
|
||||
.With(e => e.AirDate = null)
|
||||
.With(e => e.Quality = new Quality(QualityTypes.HDTV, false))
|
||||
.Build();
|
||||
|
||||
WithMatchingSeries();
|
||||
|
@ -250,7 +253,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(MockNotification, parseResults, _matchingSeries, DateTime.Today);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
result.Should().NotContain(n => n.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Never());
|
||||
|
@ -262,6 +265,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
var parseResults = Builder<EpisodeParseResult>.CreateListOfSize(5)
|
||||
.All()
|
||||
.With(e => e.AirDate = DateTime.Today.AddDays(10))
|
||||
.With(e => e.Quality = new Quality(QualityTypes.HDTV, false))
|
||||
.Build();
|
||||
|
||||
WithMatchingSeries();
|
||||
|
@ -270,7 +274,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(MockNotification, parseResults, _matchingSeries, DateTime.Today);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
result.Should().NotContain(n => n.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Never());
|
||||
|
|
|
@ -11,6 +11,7 @@ using NzbDrone.Core.Providers;
|
|||
using NzbDrone.Core.Providers.DecisionEngine;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
using NzbDrone.Core.Repository.Search;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
||||
|
@ -73,14 +74,14 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
{
|
||||
Mocker.GetMock<AllowedDownloadSpecification>()
|
||||
.Setup(s => s.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()))
|
||||
.Returns(true);
|
||||
.Returns(ReportRejectionType.None);
|
||||
}
|
||||
|
||||
private void WithQualityNotNeeded()
|
||||
{
|
||||
Mocker.GetMock<AllowedDownloadSpecification>()
|
||||
.Setup(s => s.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()))
|
||||
.Returns(false);
|
||||
.Returns(ReportRejectionType.ExistingQualityIsEqualOrBetter);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -102,14 +103,14 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
|
||||
Mocker.GetMock<AllowedDownloadSpecification>()
|
||||
.Setup(s => s.IsSatisfiedBy(It.Is<EpisodeParseResult>(d => d.Quality.QualityType == QualityTypes.Bluray1080p)))
|
||||
.Returns(true);
|
||||
.Returns(ReportRejectionType.None);
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1);
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchHistory(), _matchingSeries, 1, 1);
|
||||
|
||||
//Assert
|
||||
result.Should().HaveCount(1);
|
||||
result.First().Should().Be(1);
|
||||
result.Should().HaveCount(parseResults.Count);
|
||||
result.Should().Contain(s => s.Success);
|
||||
|
||||
Mocker.GetMock<AllowedDownloadSpecification>().Verify(c => c.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Once());
|
||||
|
@ -135,13 +136,14 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
WithSuccessfulDownload();
|
||||
|
||||
Mocker.GetMock<AllowedDownloadSpecification>()
|
||||
.Setup(s => s.IsSatisfiedBy(It.IsAny<EpisodeParseResult>())).Returns(true);
|
||||
.Setup(s => s.IsSatisfiedBy(It.IsAny<EpisodeParseResult>())).Returns(ReportRejectionType.None);
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(MockNotification, parseResults, _matchingSeries, 1, 1);
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(MockNotification, parseResults, new SearchHistory(), _matchingSeries, 1, 1);
|
||||
|
||||
//Assert
|
||||
result.Should().HaveCount(1);
|
||||
result.Should().HaveCount(parseResults.Count);
|
||||
result.Should().Contain(s => s.Success);
|
||||
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.Is<EpisodeParseResult>(d => d.Age != 100)), Times.Never());
|
||||
|
@ -162,10 +164,11 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
WithQualityNotNeeded();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1);
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchHistory(), _matchingSeries, 1, 1);
|
||||
|
||||
//Assert
|
||||
result.Should().HaveCount(0);
|
||||
result.Should().HaveCount(parseResults.Count);
|
||||
result.Should().NotContain(s => s.Success);
|
||||
|
||||
Mocker.GetMock<AllowedDownloadSpecification>().Verify(c => c.IsSatisfiedBy(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Exactly(5));
|
||||
|
@ -180,15 +183,17 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
.All()
|
||||
.With(e => e.SeasonNumber = 1)
|
||||
.With(e => e.EpisodeNumbers = new List<int> { 1 })
|
||||
.With(e => e.Quality = new Quality(QualityTypes.HDTV, false))
|
||||
.Build();
|
||||
|
||||
WithNullSeries();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1);
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchHistory(), _matchingSeries, 1, 1);
|
||||
|
||||
//Assert
|
||||
result.Should().HaveCount(0);
|
||||
result.Should().HaveCount(parseResults.Count);
|
||||
result.Should().NotContain(s => s.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Never());
|
||||
|
@ -201,15 +206,17 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
.All()
|
||||
.With(e => e.SeasonNumber = 1)
|
||||
.With(e => e.EpisodeNumbers = new List<int> { 1 })
|
||||
.With(e => e.Quality = new Quality(QualityTypes.HDTV, false))
|
||||
.Build();
|
||||
|
||||
WithMisMatchedSeries();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1);
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchHistory(), _matchingSeries, 1, 1);
|
||||
|
||||
//Assert
|
||||
result.Should().HaveCount(0);
|
||||
result.Should().HaveCount(parseResults.Count);
|
||||
result.Should().NotContain(s => s.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Never());
|
||||
|
@ -222,15 +229,17 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
.All()
|
||||
.With(e => e.SeasonNumber = 2)
|
||||
.With(e => e.EpisodeNumbers = new List<int> { 1 })
|
||||
.With(e => e.Quality = new Quality(QualityTypes.HDTV, false))
|
||||
.Build();
|
||||
|
||||
WithMatchingSeries();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1);
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchHistory(), _matchingSeries, 1, 1);
|
||||
|
||||
//Assert
|
||||
result.Should().HaveCount(0);
|
||||
result.Should().HaveCount(parseResults.Count);
|
||||
result.Should().NotContain(s => s.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Never());
|
||||
|
@ -243,15 +252,17 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
.All()
|
||||
.With(e => e.SeasonNumber = 1)
|
||||
.With(e => e.EpisodeNumbers = new List<int> { 2 })
|
||||
.With(e => e.Quality = new Quality(QualityTypes.HDTV, false))
|
||||
.Build();
|
||||
|
||||
WithMatchingSeries();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1);
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchHistory(), _matchingSeries, 1, 1);
|
||||
|
||||
//Assert
|
||||
result.Should().HaveCount(0);
|
||||
result.Should().HaveCount(parseResults.Count);
|
||||
result.Should().NotContain(s => s.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Never());
|
||||
|
@ -274,10 +285,11 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
WithSuccessfulDownload();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1);
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchHistory(), _matchingSeries, 1);
|
||||
|
||||
//Assert
|
||||
result.Should().HaveCount(1);
|
||||
result.Should().HaveCount(parseResults.Count);
|
||||
result.Should().Contain(s => s.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Once());
|
||||
|
@ -307,10 +319,11 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
|
|||
.Returns(true);
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1);
|
||||
var result = Mocker.Resolve<SearchProvider>().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchHistory(), _matchingSeries, 1);
|
||||
|
||||
//Assert
|
||||
result.Should().HaveCount(1);
|
||||
result.Should().HaveCount(parseResults.Count);
|
||||
result.Should().Contain(s => s.Success);
|
||||
|
||||
Mocker.GetMock<DownloadProvider>().Verify(c => c.DownloadReport(It.IsAny<EpisodeParseResult>()),
|
||||
Times.Exactly(2));
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
<package id="NBuilder" version="3.0.1.1" />
|
||||
<package id="Newtonsoft.Json" version="4.0.8" />
|
||||
<package id="Newtonsoft.Json" version="4.5.3" />
|
||||
<package id="Ninject" version="2.2.1.4" />
|
||||
<package id="NLog" version="2.0.0.2000" />
|
||||
<package id="NUnit" version="2.6.0.12054" />
|
||||
|
|
|
@ -68,6 +68,7 @@ namespace NzbDrone.Core
|
|||
{
|
||||
EnvironmentProvider.UGuid = Kernel.Get<ConfigProvider>().UGuid;
|
||||
ReportingService.RestProvider = Kernel.Get<RestProvider>();
|
||||
ReportingService.SetupExceptronDriver();
|
||||
|
||||
var appId = AnalyticsProvider.DESKMETRICS_TEST_ID;
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
using System.Data;
|
||||
using Migrator.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migrations
|
||||
{
|
||||
[Migration(20120420)]
|
||||
public class Migration20120420 : NzbDroneMigration
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Database.AddTable("SearchHistory", new[]
|
||||
{
|
||||
new Column("Id", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity),
|
||||
new Column("SeriesId", DbType.Int32, ColumnProperty.NotNull),
|
||||
new Column("SeasonNumber", DbType.Int32, ColumnProperty.Null),
|
||||
new Column("EpisodeId", DbType.Int32, ColumnProperty.Null),
|
||||
new Column("SearchTime", DbType.DateTime, ColumnProperty.NotNull),
|
||||
new Column("SuccessfulDownload", DbType.Boolean, ColumnProperty.NotNull)
|
||||
});
|
||||
|
||||
Database.AddTable("SearchHistoryItems", new[]
|
||||
{
|
||||
new Column("Id", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity),
|
||||
new Column("SearchHistoryId", DbType.Int32, ColumnProperty.NotNull),
|
||||
new Column("ReportTitle", DbType.String, ColumnProperty.NotNull),
|
||||
new Column("Indexer", DbType.String, ColumnProperty.NotNull),
|
||||
new Column("NzbUrl", DbType.String, ColumnProperty.NotNull),
|
||||
new Column("NzbInfoUrl", DbType.String, ColumnProperty.Null),
|
||||
new Column("Success", DbType.Boolean, ColumnProperty.NotNull),
|
||||
new Column("SearchError", DbType.Int32, ColumnProperty.NotNull),
|
||||
new Column("Quality", DbType.Int32, ColumnProperty.NotNull),
|
||||
new Column("Proper", DbType.Boolean, ColumnProperty.NotNull),
|
||||
new Column("Age", DbType.Int32, ColumnProperty.NotNull),
|
||||
new Column("Language", DbType.Int32, ColumnProperty.NotNull),
|
||||
new Column("Size", DbType.Int64, ColumnProperty.NotNull),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -87,5 +87,60 @@ namespace NzbDrone.Core
|
|||
return s.Substring(0, i);
|
||||
}
|
||||
|
||||
public static string AddSpacesToEnum(this Enum enumValue)
|
||||
{
|
||||
var text = enumValue.ToString();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
return "";
|
||||
var newText = new StringBuilder(text.Length * 2);
|
||||
newText.Append(text[0]);
|
||||
for (int i = 1; i < text.Length; i++)
|
||||
{
|
||||
if (char.IsUpper(text[i]) && text[i - 1] != ' ')
|
||||
newText.Append(' ');
|
||||
newText.Append(text[i]);
|
||||
}
|
||||
return newText.ToString();
|
||||
}
|
||||
|
||||
private const Decimal ONE_KILOBYTE = 1024M;
|
||||
private const Decimal ONE_MEGABYTE = ONE_KILOBYTE * 1024M;
|
||||
private const Decimal ONE_GIGABYTE = ONE_MEGABYTE * 1024M;
|
||||
|
||||
public static string ToBestFileSize(this long bytes, int precision = 0)
|
||||
{
|
||||
if (bytes == 0)
|
||||
return "0B";
|
||||
|
||||
decimal size = Convert.ToDecimal(bytes);
|
||||
|
||||
string suffix;
|
||||
|
||||
if (size > ONE_GIGABYTE)
|
||||
{
|
||||
size /= ONE_GIGABYTE;
|
||||
suffix = "GB";
|
||||
}
|
||||
|
||||
else if (size > ONE_MEGABYTE)
|
||||
{
|
||||
size /= ONE_MEGABYTE;
|
||||
suffix = "MB";
|
||||
}
|
||||
|
||||
else if (size > ONE_KILOBYTE)
|
||||
{
|
||||
size /= ONE_KILOBYTE;
|
||||
suffix = "KB";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
suffix = " B";
|
||||
}
|
||||
|
||||
return String.Format("{0:N" + precision + "} {1}", size, suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace NzbDrone.Core.Helpers
|
||||
{
|
||||
public static class FileSizeFormatHelper
|
||||
{
|
||||
private const Decimal OneKiloByte = 1024M;
|
||||
private const Decimal OneMegaByte = OneKiloByte * 1024M;
|
||||
private const Decimal OneGigaByte = OneMegaByte * 1024M;
|
||||
|
||||
public static string Format(long bytes, int precision = 0)
|
||||
{
|
||||
if (bytes == 0)
|
||||
return "0B";
|
||||
|
||||
decimal size = Convert.ToDecimal(bytes);
|
||||
|
||||
string suffix;
|
||||
|
||||
if (size > OneGigaByte)
|
||||
{
|
||||
size /= OneGigaByte;
|
||||
suffix = "GB";
|
||||
}
|
||||
|
||||
else if (size > OneMegaByte)
|
||||
{
|
||||
size /= OneMegaByte;
|
||||
suffix = "MB";
|
||||
}
|
||||
|
||||
else if (size > OneKiloByte)
|
||||
{
|
||||
size /= OneKiloByte;
|
||||
suffix = "KB";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
suffix = " B";
|
||||
}
|
||||
|
||||
return String.Format("{0:N" + precision + "}{1}", size, suffix);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,7 +70,7 @@ namespace NzbDrone.Core.Jobs
|
|||
try
|
||||
{
|
||||
if (_isMonitoredEpisodeSpecification.IsSatisfiedBy(episodeParseResult) &&
|
||||
_allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult) &&
|
||||
_allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult) == ReportRejectionType.None &&
|
||||
_upgradeHistorySpecification.IsSatisfiedBy(episodeParseResult))
|
||||
{
|
||||
_downloadProvider.DownloadReport(episodeParseResult);
|
||||
|
|
|
@ -60,15 +60,15 @@ namespace NzbDrone.Core.Jobs
|
|||
//Perform a Partial Season Search
|
||||
var addedSeries = _searchProvider.PartialSeasonSearch(notification, targetId, secondaryTargetId);
|
||||
|
||||
addedSeries.Distinct().ToList().Sort();
|
||||
var episodeNumbers = episodes.Where(w => w.AirDate <= DateTime.Today.AddDays(1)).Select(s => s.EpisodeNumber).ToList();
|
||||
episodeNumbers.Sort();
|
||||
//addedSeries.Distinct().ToList().Sort();
|
||||
//var episodeNumbers = episodes.Where(w => w.AirDate <= DateTime.Today.AddDays(1)).Select(s => s.EpisodeNumber).ToList();
|
||||
//episodeNumbers.Sort();
|
||||
|
||||
if (addedSeries.SequenceEqual(episodeNumbers))
|
||||
return;
|
||||
//if (addedSeries.SequenceEqual(episodeNumbers))
|
||||
// return;
|
||||
|
||||
//Get the list of episodes that weren't downloaded
|
||||
var missingEpisodes = episodeNumbers.Except(addedSeries).ToList();
|
||||
////Get the list of episodes that weren't downloaded
|
||||
//var missingEpisodes = episodeNumbers.Except(addedSeries).ToList();
|
||||
|
||||
//TODO: do one by one check only when max number of feeds have been returned by the indexer
|
||||
//Only process episodes that is in missing episodes (To ensure we double check if the episode is available)
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Core.Model
|
||||
{
|
||||
public enum ReportRejectionType
|
||||
{
|
||||
None = 0,
|
||||
WrongSeries = 1,
|
||||
QualityNotWanted = 2,
|
||||
WrongSeason = 3,
|
||||
WrongEpisode = 4,
|
||||
Size = 5,
|
||||
Retention = 6,
|
||||
ExistingQualityIsEqualOrBetter = 7,
|
||||
Cutoff = 8,
|
||||
AlreadyInQueue = 9,
|
||||
DownloadClientFailure = 10,
|
||||
Skipped = 11,
|
||||
Failure = 12,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Model
|
||||
{
|
||||
public class StatsModel
|
||||
{
|
||||
[DisplayName("Number of Series")]
|
||||
public int SeriesTotal { get; set; }
|
||||
|
||||
[DisplayName("Number of Series Countinuing")]
|
||||
public int SeriesContinuing { get; set; }
|
||||
|
||||
[DisplayName("Number of Series Ended")]
|
||||
public int SeriesEnded { get; set; }
|
||||
|
||||
[DisplayName("Number of Episodes")]
|
||||
public int EpisodesTotal { get; set; }
|
||||
|
||||
[DisplayName("Number of Episodes On Disk")]
|
||||
public int EpisodesOnDisk { get; set; }
|
||||
|
||||
[DisplayName("Number of Episodes Missing")]
|
||||
public int EpisodesMissing { get; set; }
|
||||
|
||||
[DisplayName("Downloaded in the Last Week")]
|
||||
public int DownloadLastWeek { get; set; }
|
||||
|
||||
[DisplayName("Downloaded in the Last 30 days")]
|
||||
public int DownloadedLastMonth { get; set; }
|
||||
}
|
||||
}
|
|
@ -29,6 +29,8 @@
|
|||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
|
@ -158,9 +160,9 @@
|
|||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\MiniProfiler.1.9\lib\net40\MvcMiniProfiler.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.0.8.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Ninject, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll</HintPath>
|
||||
|
@ -222,6 +224,7 @@
|
|||
<Compile Include="Datastore\MigrationLogger.cs" />
|
||||
<Compile Include="Datastore\MigrationsHelper.cs" />
|
||||
<Compile Include="Datastore\CustomeMapper.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20120420.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20120228.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20120227.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20120220.cs" />
|
||||
|
@ -239,7 +242,6 @@
|
|||
<Compile Include="Datastore\PetaPoco\EpisodeSeasonRelator.cs" />
|
||||
<Compile Include="Fluent.cs" />
|
||||
<Compile Include="Helpers\EpisodeSortingHelper.cs" />
|
||||
<Compile Include="Helpers\FileSizeFormatHelper.cs" />
|
||||
<Compile Include="Helpers\SortHelper.cs" />
|
||||
<Compile Include="Helpers\SabnzbdQueueTimeConverter.cs" />
|
||||
<Compile Include="Jobs\CheckpointJob.cs" />
|
||||
|
@ -264,6 +266,7 @@
|
|||
<Compile Include="Model\Sabnzbd\SabModel.cs" />
|
||||
<Compile Include="Model\Sabnzbd\SabQueueItem.cs" />
|
||||
<Compile Include="Model\Sabnzbd\SabVersionModel.cs" />
|
||||
<Compile Include="Model\StatsModel.cs" />
|
||||
<Compile Include="Model\Twitter\TwitterAuthorizationModel.cs" />
|
||||
<Compile Include="Model\UpdatePackage.cs" />
|
||||
<Compile Include="Model\Xbmc\ActionType.cs" />
|
||||
|
@ -277,6 +280,7 @@
|
|||
<Compile Include="Providers\Indexer\NzbIndex.cs" />
|
||||
<Compile Include="Providers\Indexer\FileSharingTalk.cs" />
|
||||
<Compile Include="Providers\Indexer\Wombles.cs" />
|
||||
<Compile Include="Providers\SearchHistoryProvider.cs" />
|
||||
<Compile Include="Providers\SeasonProvider.cs" />
|
||||
<Compile Include="Jobs\RecentBacklogSearchJob.cs" />
|
||||
<Compile Include="Jobs\TrimLogsJob.cs" />
|
||||
|
@ -304,6 +308,10 @@
|
|||
<Compile Include="Providers\AnalyticsProvider.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Providers\StatsProvider.cs" />
|
||||
<Compile Include="Repository\Search\SearchHistoryItem.cs" />
|
||||
<Compile Include="Repository\Search\SearchHistory.cs" />
|
||||
<Compile Include="Model\ReportRejectionType.cs" />
|
||||
<Compile Include="Repository\Season.cs" />
|
||||
<Compile Include="Providers\AutoConfigureProvider.cs">
|
||||
<SubType>Code</SubType>
|
||||
|
@ -574,6 +582,7 @@
|
|||
if not exist "$(TargetDir)x86" md "$(TargetDir)x86"
|
||||
xcopy /s /y "$(SolutionDir)packages\SqlServerCompact.4.0.8482.1\NativeBinaries\x86\*.*" "$(TargetDir)x86"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace NzbDrone.Core
|
|||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Multi-episode Repeated (S01E05 - S01E06, 1x05 - 1x06, etc)
|
||||
new Regex(@"^(?<title>.+?)(?:\W+S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:[ex]){1,2}(?<episode>\d{2}(?!\d+)))+){2,}\W?(?!\\)",
|
||||
new Regex(@"^(?<title>.+?)(?:\W+S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:[ex]){1,2}(?<episode>\d{1,2}(?!\d+)))+){2,}\W?(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Episodes without a title, Single (S01E05, 1x05) AND Multi (S01E04E05, 1x04x05, etc)
|
||||
|
@ -65,7 +65,7 @@ namespace NzbDrone.Core
|
|||
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)",
|
||||
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)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
private static readonly Regex SimpleTitleRegex = new Regex(@"480[i|p]|720[i|p]|1080[i|p]|[x|h|x\s|h\s]264|DD\W?5\W1|\<|\>|\?|\*|\:|\||""",
|
||||
|
@ -251,7 +251,7 @@ namespace NzbDrone.Core
|
|||
name = name.Trim();
|
||||
var normalizedName = NormalizeTitle(name);
|
||||
var result = new Quality { QualityType = QualityTypes.Unknown };
|
||||
result.Proper = normalizedName.Contains("proper");
|
||||
result.Proper = (normalizedName.Contains("proper") || normalizedName.Contains("repack"));
|
||||
|
||||
if (normalizedName.Contains("dvd") || normalizedName.Contains("bdrip") || normalizedName.Contains("brrip"))
|
||||
{
|
||||
|
@ -259,7 +259,7 @@ namespace NzbDrone.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
if (normalizedName.Contains("xvid") || normalizedName.Contains("divx"))
|
||||
if (normalizedName.Contains("xvid") || normalizedName.Contains("divx") || normalizedName.Contains("dsr"))
|
||||
{
|
||||
if (normalizedName.Contains("bluray"))
|
||||
{
|
||||
|
@ -300,8 +300,6 @@ namespace NzbDrone.Core
|
|||
}
|
||||
//Based on extension
|
||||
|
||||
|
||||
|
||||
if (result.QualityType == QualityTypes.Unknown)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace NzbDrone.Core.Providers.DecisionEngine
|
|||
|
||||
public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
|
||||
{
|
||||
logger.Trace("Beginning size check for: {0}", subject);
|
||||
var qualityType = _qualityTypeProvider.Get((int)subject.Quality.QualityType);
|
||||
|
||||
//Need to determine if this is a 30 or 60 minute episode
|
||||
|
@ -33,7 +34,10 @@ namespace NzbDrone.Core.Providers.DecisionEngine
|
|||
|
||||
//0 will be treated as unlimited
|
||||
if (qualityType.MaxSize == 0)
|
||||
{
|
||||
logger.Trace("Max size is 0 (unlimited) - skipping check.");
|
||||
return true;
|
||||
}
|
||||
|
||||
var maxSize = qualityType.MaxSize.Megabytes();
|
||||
var series = subject.Series;
|
||||
|
@ -57,8 +61,12 @@ namespace NzbDrone.Core.Providers.DecisionEngine
|
|||
|
||||
//If the parsed size is greater than maxSize we don't want it
|
||||
if (subject.Size > maxSize)
|
||||
{
|
||||
logger.Trace("Item: {0}, Size: {1} is greater than maximum allowed size ({1}), rejecting.", subject, subject.Size, maxSize);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
logger.Trace("Item: {0}, meets size contraints.", subject);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using NLog;
|
||||
using Ninject;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Repository.Search;
|
||||
|
||||
namespace NzbDrone.Core.Providers.DecisionEngine
|
||||
{
|
||||
|
@ -30,16 +31,16 @@ namespace NzbDrone.Core.Providers.DecisionEngine
|
|||
{
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
|
||||
public virtual ReportRejectionType IsSatisfiedBy(EpisodeParseResult subject)
|
||||
{
|
||||
if (!_qualityAllowedByProfileSpecification.IsSatisfiedBy(subject)) return false;
|
||||
if (!_upgradeDiskSpecification.IsSatisfiedBy(subject)) return false;
|
||||
if (!_retentionSpecification.IsSatisfiedBy(subject)) return false;
|
||||
if (!_acceptableSizeSpecification.IsSatisfiedBy(subject)) return false;
|
||||
if (_alreadyInQueueSpecification.IsSatisfiedBy(subject)) return false;
|
||||
if (!_qualityAllowedByProfileSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.QualityNotWanted;
|
||||
if (!_upgradeDiskSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.ExistingQualityIsEqualOrBetter;
|
||||
if (!_retentionSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.Retention;
|
||||
if (!_acceptableSizeSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.Size;
|
||||
if (_alreadyInQueueSpecification.IsSatisfiedBy(subject)) return ReportRejectionType.AlreadyInQueue;
|
||||
|
||||
logger.Debug("Episode {0} is needed", subject);
|
||||
return true;
|
||||
return ReportRejectionType.None;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +1,19 @@
|
|||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
|
||||
namespace NzbDrone.Core.Providers.DecisionEngine
|
||||
{
|
||||
public class QualityUpgradeSpecification
|
||||
public class QualityAllowedByProfileSpecification
|
||||
{
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public virtual bool IsSatisfiedBy(Quality currentQuality, Quality newQuality, QualityTypes cutOff)
|
||||
public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
|
||||
{
|
||||
if (currentQuality >= newQuality)
|
||||
logger.Trace("Checking if report meets quality requirements. {0}", subject.Quality);
|
||||
if (!subject.Series.QualityProfile.Allowed.Contains(subject.Quality.QualityType))
|
||||
{
|
||||
logger.Trace("existing item has better or equal quality. skipping");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currentQuality.QualityType == newQuality.QualityType && newQuality.Proper)
|
||||
{
|
||||
logger.Trace("Upgrading existing item to proper.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (currentQuality.QualityType >= cutOff)
|
||||
{
|
||||
logger.Trace("Existing item meets cut-off. skipping.");
|
||||
logger.Trace("Quality {0} rejected by Series' quality profile", subject.Quality);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,31 @@
|
|||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
|
||||
namespace NzbDrone.Core.Providers.DecisionEngine
|
||||
{
|
||||
public class QualityAllowedByProfileSpecification
|
||||
public class QualityUpgradeSpecification
|
||||
{
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
|
||||
public virtual bool IsSatisfiedBy(Quality currentQuality, Quality newQuality, QualityTypes cutOff)
|
||||
{
|
||||
logger.Trace("Checking if report meets quality requirements. {0}", subject.Quality);
|
||||
if (!subject.Series.QualityProfile.Allowed.Contains(subject.Quality.QualityType))
|
||||
if (currentQuality >= newQuality)
|
||||
{
|
||||
logger.Trace("Quality {0} rejected by Series' quality profile", subject.Quality);
|
||||
logger.Trace("existing item has better or equal quality. skipping");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currentQuality.QualityType == newQuality.QualityType && newQuality.Proper)
|
||||
{
|
||||
logger.Trace("Upgrading existing item to proper.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (currentQuality.QualityType >= cutOff)
|
||||
{
|
||||
logger.Trace("Existing item meets cut-off. skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -253,6 +253,33 @@ namespace NzbDrone.Core.Providers
|
|||
}
|
||||
}
|
||||
|
||||
public virtual void CleanUpDropFolder(string path)
|
||||
{
|
||||
//Todo: We should rename files before importing them to prevent this issue from ever happening
|
||||
|
||||
var filesOnDisk = GetVideoFiles(path);
|
||||
|
||||
foreach(var file in filesOnDisk)
|
||||
{
|
||||
try
|
||||
{
|
||||
var episodeFile = _mediaFileProvider.GetFileByPath(file);
|
||||
|
||||
if (episodeFile != null)
|
||||
{
|
||||
Logger.Trace("[{0}] was imported but not moved, moving it now", file);
|
||||
|
||||
MoveEpisodeFile(episodeFile, true);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.WarnException("Failed to move epiosde file from drop folder: " + file, ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> GetVideoFiles(string path)
|
||||
{
|
||||
|
|
|
@ -46,26 +46,35 @@ namespace NzbDrone.Core.Providers.DownloadClients
|
|||
|
||||
public virtual bool IsInQueue(EpisodeParseResult newParseResult)
|
||||
{
|
||||
var queue = GetQueue().Where(c => c.ParseResult != null);
|
||||
|
||||
var matchigTitle = queue.Where(q => String.Equals(q.ParseResult.CleanTitle, newParseResult.Series.CleanTitle, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
var matchingTitleWithQuality = matchigTitle.Where(q => q.ParseResult.Quality >= newParseResult.Quality);
|
||||
|
||||
|
||||
if (newParseResult.Series.IsDaily)
|
||||
try
|
||||
{
|
||||
return matchingTitleWithQuality.Any(q => q.ParseResult.AirDate.Value.Date == newParseResult.AirDate.Value.Date);
|
||||
var queue = GetQueue().Where(c => c.ParseResult != null);
|
||||
|
||||
var matchigTitle = queue.Where(q => String.Equals(q.ParseResult.CleanTitle, newParseResult.Series.CleanTitle, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
var matchingTitleWithQuality = matchigTitle.Where(q => q.ParseResult.Quality >= newParseResult.Quality);
|
||||
|
||||
|
||||
if (newParseResult.Series.IsDaily)
|
||||
{
|
||||
return matchingTitleWithQuality.Any(q => q.ParseResult.AirDate.Value.Date == newParseResult.AirDate.Value.Date);
|
||||
}
|
||||
|
||||
var matchingSeason = matchingTitleWithQuality.Where(q => q.ParseResult.SeasonNumber == newParseResult.SeasonNumber);
|
||||
|
||||
if (newParseResult.FullSeason)
|
||||
{
|
||||
return matchingSeason.Any();
|
||||
}
|
||||
|
||||
return matchingSeason.Any(q => q.ParseResult.EpisodeNumbers != null && q.ParseResult.EpisodeNumbers.Any(e => newParseResult.EpisodeNumbers.Contains(e)));
|
||||
}
|
||||
|
||||
var matchingSeason = matchingTitleWithQuality.Where(q => q.ParseResult.SeasonNumber == newParseResult.SeasonNumber);
|
||||
|
||||
if (newParseResult.FullSeason)
|
||||
catch (Exception ex)
|
||||
{
|
||||
return matchingSeason.Any();
|
||||
logger.WarnException("Unable to connect to SABnzbd to check queue.", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
return matchingSeason.Any(q => q.ParseResult.EpisodeNumbers != null && q.ParseResult.EpisodeNumbers.Any(e => newParseResult.EpisodeNumbers.Contains(e)));
|
||||
}
|
||||
|
||||
public virtual bool DownloadNzb(string url, string title)
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace NzbDrone.Core.Providers
|
|||
|
||||
foreach (var episode in parseResult.EpisodeNumbers)
|
||||
{
|
||||
episodeString.Add(String.Format("{0}x{1}", parseResult.SeasonNumber, episode));
|
||||
episodeString.Add(String.Format("{0}x{1:00}", parseResult.SeasonNumber, episode));
|
||||
}
|
||||
|
||||
var epNumberString = String.Join("-", episodeString);
|
||||
|
|
|
@ -328,7 +328,7 @@ namespace NzbDrone.Core.Providers
|
|||
episodeToUpdate.SeasonNumber = episode.SeasonNumber;
|
||||
episodeToUpdate.Title = episode.EpisodeName;
|
||||
|
||||
episodeToUpdate.Overview = episode.Overview.Truncate(4000);
|
||||
episodeToUpdate.Overview = episode.Overview.Truncate(3500);
|
||||
|
||||
if (episode.FirstAired.Year > 1900)
|
||||
episodeToUpdate.AirDate = episode.FirstAired.Date;
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace NzbDrone.Core.Providers.ExternalNotification
|
|||
if (_configProvider.TwitterNotifyOnDownload)
|
||||
{
|
||||
_logger.Trace("Sending Notification to Twitter (On Grab)");
|
||||
_twitterProvider.SendTweet("Downloaded Complete: " + message);
|
||||
_twitterProvider.SendTweet("Download Completed: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -192,7 +192,6 @@ namespace NzbDrone.Core.Providers.Indexer
|
|||
{
|
||||
parsedEpisode.NzbUrl = NzbDownloadUrl(item);
|
||||
parsedEpisode.Indexer = Name;
|
||||
parsedEpisode.OriginalString = item.Title.Text;
|
||||
result.Add(parsedEpisode);
|
||||
}
|
||||
}
|
||||
|
@ -237,7 +236,13 @@ namespace NzbDrone.Core.Providers.Indexer
|
|||
var title = TitlePreParser(item);
|
||||
|
||||
var episodeParseResult = Parser.ParseTitle(title);
|
||||
if (episodeParseResult != null) episodeParseResult.Age = DateTime.Now.Date.Subtract(item.PublishDate.Date).Days;
|
||||
if (episodeParseResult != null)
|
||||
{
|
||||
episodeParseResult.Age = DateTime.Now.Date.Subtract(item.PublishDate.Date).Days;
|
||||
episodeParseResult.OriginalString = title;
|
||||
}
|
||||
|
||||
_logger.Trace("Parsed: {0} from: {1}", episodeParseResult, item.Title.Text);
|
||||
|
||||
return CustomParser(item, episodeParseResult);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace NzbDrone.Core.Providers.Indexer
|
|||
|
||||
protected override string NzbDownloadUrl(SyndicationItem item)
|
||||
{
|
||||
return item.Links[1].Uri.ToString();
|
||||
return item.Links[0].Uri.ToString();
|
||||
}
|
||||
|
||||
protected override IList<string> GetEpisodeSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber)
|
||||
|
|
|
@ -8,6 +8,7 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.ServiceModel.Syndication;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using NLog;
|
||||
|
||||
|
@ -60,7 +61,11 @@ namespace NzbDrone.Core.Providers.Indexer
|
|||
logger.WarnException("Unable to parse Feed date " + dateVal, e);
|
||||
}
|
||||
|
||||
dateVal = parsedDate.ToString(CultureInfo.CurrentCulture.DateTimeFormat.RFC1123Pattern);
|
||||
var currentCulture = Thread.CurrentThread.CurrentCulture;
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
|
||||
dateVal = parsedDate.ToString("ddd, dd MMM yyyy HH:mm:ss zzz");
|
||||
dateVal = dateVal.Remove(dateVal.LastIndexOf(':'), 1);
|
||||
Thread.CurrentThread.CurrentCulture = currentCulture;
|
||||
}
|
||||
|
||||
return dateVal;
|
||||
|
|
|
@ -52,6 +52,11 @@ namespace NzbDrone.Core.Providers
|
|||
return _database.Exists<EpisodeFile>("WHERE Path =@0", path.NormalizePath());
|
||||
}
|
||||
|
||||
public virtual EpisodeFile GetFileByPath(string path)
|
||||
{
|
||||
return _database.SingleOrDefault<EpisodeFile>("WHERE Path =@0", path.NormalizePath());
|
||||
}
|
||||
|
||||
public virtual EpisodeFile GetEpisodeFile(int episodeFileId)
|
||||
{
|
||||
return _database.Single<EpisodeFile>(episodeFileId);
|
||||
|
@ -133,7 +138,7 @@ namespace NzbDrone.Core.Providers
|
|||
|
||||
if (updated > 0)
|
||||
{
|
||||
Logger.Debug("Removed {0} orphan file(s) from database.S", updated);
|
||||
Logger.Debug("Removed {0} orphan file(s) from database.", updated);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,8 @@ namespace NzbDrone.Core.Providers
|
|||
return;
|
||||
}
|
||||
|
||||
_diskScanProvider.CleanUpDropFolder(subfolderInfo.FullName);
|
||||
|
||||
var importedFiles = _diskScanProvider.Scan(series, subfolderInfo.FullName);
|
||||
importedFiles.ForEach(file => _diskScanProvider.MoveEpisodeFile(file, true));
|
||||
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NLog;
|
||||
using Ninject;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.Repository.Search;
|
||||
using PetaPoco;
|
||||
|
||||
namespace NzbDrone.Core.Providers
|
||||
{
|
||||
public class SearchHistoryProvider
|
||||
{
|
||||
private readonly IDatabase _database;
|
||||
private readonly SeriesProvider _seriesProvider;
|
||||
private readonly DownloadProvider _downloadProvider;
|
||||
private readonly EpisodeProvider _episodeProvider;
|
||||
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
[Inject]
|
||||
public SearchHistoryProvider(IDatabase database, SeriesProvider seriesProvider,
|
||||
DownloadProvider downloadProvider, EpisodeProvider episodeProvider)
|
||||
{
|
||||
_database = database;
|
||||
_seriesProvider = seriesProvider;
|
||||
_downloadProvider = downloadProvider;
|
||||
_episodeProvider = episodeProvider;
|
||||
}
|
||||
|
||||
public SearchHistoryProvider()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual int Add(SearchHistory searchHistory)
|
||||
{
|
||||
logger.Trace("Adding new search result");
|
||||
searchHistory.SuccessfulDownload = searchHistory.SearchHistoryItems.Any(s => s.Success);
|
||||
var id = Convert.ToInt32(_database.Insert(searchHistory));
|
||||
|
||||
searchHistory.SearchHistoryItems.ForEach(s => s.SearchHistoryId = id);
|
||||
logger.Trace("Adding search result items");
|
||||
_database.InsertMany(searchHistory.SearchHistoryItems);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public virtual void Delete(int id)
|
||||
{
|
||||
logger.Trace("Deleting search result items attached to: {0}", id);
|
||||
_database.Execute("DELETE FROM SearchHistoryItems WHERE SearchHistoryId = @0", id);
|
||||
|
||||
logger.Trace("Deleting search result: {0}", id);
|
||||
_database.Delete<SearchHistory>(id);
|
||||
}
|
||||
|
||||
public virtual List<SearchHistory> AllSearchHistory()
|
||||
{
|
||||
var sql = @"SELECT SearchHistory.Id, SearchHistory.SeriesId, SearchHistory.SeasonNumber,
|
||||
SearchHistory.EpisodeId, SearchHistory.SearchTime,
|
||||
Series.Title as SeriesTitle, Series.IsDaily,
|
||||
Episodes.EpisodeNumber, Episodes.SeasonNumber, Episodes.Title as EpisodeTitle,
|
||||
Episodes.AirDate,
|
||||
Count(SearchHistoryItems.Id) as TotalItems,
|
||||
SUM(CASE WHEN SearchHistoryItems.Success = 1 THEN 1 ELSE 0 END) as SuccessfulCount
|
||||
FROM SearchHistory
|
||||
INNER JOIN Series
|
||||
ON Series.SeriesId = SearchHistory.SeriesId
|
||||
LEFT JOIN Episodes
|
||||
ON Episodes.EpisodeId = SearchHistory.EpisodeId
|
||||
INNER JOIN SearchHistoryItems
|
||||
ON SearchHistoryItems.SearchHistoryId = SearchHistory.Id
|
||||
GROUP BY SearchHistory.Id, SearchHistory.SeriesId, SearchHistory.SeasonNumber,
|
||||
SearchHistory.EpisodeId, SearchHistory.SearchTime,
|
||||
Series.Title, Series.IsDaily,
|
||||
Episodes.EpisodeNumber, Episodes.SeasonNumber, Episodes.Title,
|
||||
Episodes.AirDate";
|
||||
|
||||
return _database.Fetch<SearchHistory>(sql);
|
||||
}
|
||||
|
||||
public virtual SearchHistory GetSearchHistory(int id)
|
||||
{
|
||||
var sql = @"SELECT SearchHistory.Id, SearchHistory.SeriesId, SearchHistory.SeasonNumber,
|
||||
SearchHistory.EpisodeId, SearchHistory.SearchTime,
|
||||
Series.Title as SeriesTitle, Series.IsDaily,
|
||||
Episodes.EpisodeNumber, Episodes.SeasonNumber, Episodes.Title as EpisodeTitle,
|
||||
Episodes.AirDate
|
||||
FROM SearchHistory
|
||||
INNER JOIN Series
|
||||
ON Series.SeriesId = SearchHistory.SeriesId
|
||||
LEFT JOIN Episodes
|
||||
ON Episodes.EpisodeId = SearchHistory.EpisodeId
|
||||
WHERE SearchHistory.Id = @0";
|
||||
|
||||
var result = _database.Single<SearchHistory>(sql, id);
|
||||
result.SearchHistoryItems = _database.Fetch<SearchHistoryItem>("WHERE SearchHistoryId = @0", id);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual void ForceDownload(int itemId)
|
||||
{
|
||||
var item = _database.Single<SearchHistoryItem>(itemId);
|
||||
logger.Info("Starting Force Download of: {0}", item.ReportTitle);
|
||||
var searchResult = _database.Single<SearchHistory>(item.SearchHistoryId);
|
||||
var series = _seriesProvider.GetSeries(searchResult.SeriesId);
|
||||
|
||||
var parseResult = Parser.ParseTitle(item.ReportTitle);
|
||||
parseResult.NzbUrl = item.NzbUrl;
|
||||
parseResult.Series = series;
|
||||
parseResult.Indexer = item.Indexer;
|
||||
var episodes = _episodeProvider.GetEpisodesByParseResult(parseResult);
|
||||
|
||||
logger.Info("Forcing Download of: {0}", item.ReportTitle);
|
||||
_downloadProvider.DownloadReport(parseResult);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ using NzbDrone.Core.Model;
|
|||
using NzbDrone.Core.Model.Notification;
|
||||
using NzbDrone.Core.Providers.DecisionEngine;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.Repository.Search;
|
||||
|
||||
namespace NzbDrone.Core.Providers
|
||||
{
|
||||
|
@ -21,13 +22,15 @@ namespace NzbDrone.Core.Providers
|
|||
private readonly SceneMappingProvider _sceneMappingProvider;
|
||||
private readonly UpgradePossibleSpecification _upgradePossibleSpecification;
|
||||
private readonly AllowedDownloadSpecification _allowedDownloadSpecification;
|
||||
private readonly SearchHistoryProvider _searchHistoryProvider;
|
||||
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
[Inject]
|
||||
public SearchProvider(EpisodeProvider episodeProvider, DownloadProvider downloadProvider, SeriesProvider seriesProvider,
|
||||
IndexerProvider indexerProvider, SceneMappingProvider sceneMappingProvider,
|
||||
UpgradePossibleSpecification upgradePossibleSpecification, AllowedDownloadSpecification allowedDownloadSpecification)
|
||||
UpgradePossibleSpecification upgradePossibleSpecification, AllowedDownloadSpecification allowedDownloadSpecification,
|
||||
SearchHistoryProvider searchHistoryProvider)
|
||||
{
|
||||
_episodeProvider = episodeProvider;
|
||||
_downloadProvider = downloadProvider;
|
||||
|
@ -36,6 +39,7 @@ namespace NzbDrone.Core.Providers
|
|||
_sceneMappingProvider = sceneMappingProvider;
|
||||
_upgradePossibleSpecification = upgradePossibleSpecification;
|
||||
_allowedDownloadSpecification = allowedDownloadSpecification;
|
||||
_searchHistoryProvider = searchHistoryProvider;
|
||||
}
|
||||
|
||||
public SearchProvider()
|
||||
|
@ -44,13 +48,20 @@ namespace NzbDrone.Core.Providers
|
|||
|
||||
public virtual bool SeasonSearch(ProgressNotification notification, int seriesId, int seasonNumber)
|
||||
{
|
||||
var searchResult = new SearchHistory
|
||||
{
|
||||
SearchTime = DateTime.Now,
|
||||
SeriesId = seriesId,
|
||||
SeasonNumber = seasonNumber
|
||||
};
|
||||
|
||||
var series = _seriesProvider.GetSeries(seriesId);
|
||||
|
||||
if (series == null)
|
||||
{
|
||||
Logger.Error("Unable to find an series {0} in database", seriesId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Return false if the series is a daily series (we only support individual episode searching
|
||||
if (series.IsDaily)
|
||||
|
@ -80,19 +91,20 @@ namespace NzbDrone.Core.Providers
|
|||
e => e.EpisodeNumbers = episodeNumbers.ToList()
|
||||
);
|
||||
|
||||
var downloadedEpisodes = ProcessSearchResults(notification, reports, series, seasonNumber);
|
||||
searchResult.SearchHistoryItems = ProcessSearchResults(notification, reports, searchResult, series, seasonNumber);
|
||||
_searchHistoryProvider.Add(searchResult);
|
||||
|
||||
downloadedEpisodes.Sort();
|
||||
episodeNumbers.ToList().Sort();
|
||||
|
||||
//Returns true if the list of downloaded episodes matches the list of episode numbers
|
||||
//(either a full season release was grabbed or all individual episodes)
|
||||
return (downloadedEpisodes.SequenceEqual(episodeNumbers));
|
||||
return (searchResult.Successes.Count == episodeNumbers.Count);
|
||||
}
|
||||
|
||||
public virtual List<int> PartialSeasonSearch(ProgressNotification notification, int seriesId, int seasonNumber)
|
||||
{
|
||||
//This method will search for episodes in a season in groups of 10 episodes S01E0, S01E1, S01E2, etc
|
||||
var searchResult = new SearchHistory
|
||||
{
|
||||
SearchTime = DateTime.Now,
|
||||
SeriesId = seriesId,
|
||||
SeasonNumber = seasonNumber
|
||||
};
|
||||
|
||||
var series = _seriesProvider.GetSeries(seriesId);
|
||||
|
||||
|
@ -107,19 +119,18 @@ namespace NzbDrone.Core.Providers
|
|||
return new List<int>();
|
||||
|
||||
notification.CurrentMessage = String.Format("Searching for {0} Season {1}", series.Title, seasonNumber);
|
||||
|
||||
var episodes = _episodeProvider.GetEpisodesBySeason(seriesId, seasonNumber);
|
||||
|
||||
var reports = PerformSearch(notification, series, seasonNumber, episodes);
|
||||
|
||||
Logger.Debug("Finished searching all indexers. Total {0}", reports.Count);
|
||||
|
||||
if (reports.Count == 0)
|
||||
return new List<int>();
|
||||
|
||||
notification.CurrentMessage = "Processing search results";
|
||||
searchResult.SearchHistoryItems = ProcessSearchResults(notification, reports, searchResult, series, seasonNumber);
|
||||
|
||||
return ProcessSearchResults(notification, reports, series, seasonNumber);
|
||||
_searchHistoryProvider.Add(searchResult);
|
||||
return searchResult.Successes;
|
||||
}
|
||||
|
||||
public virtual bool EpisodeSearch(ProgressNotification notification, int episodeId)
|
||||
|
@ -136,7 +147,7 @@ namespace NzbDrone.Core.Providers
|
|||
if (!_upgradePossibleSpecification.IsSatisfiedBy(episode))
|
||||
{
|
||||
Logger.Info("Search for {0} was aborted, file in disk meets or exceeds Profile's Cutoff", episode);
|
||||
notification.CurrentMessage = String.Format("Skipping search for {0}, file you have is already at cutoff", episode);
|
||||
notification.CurrentMessage = String.Format("Skipping search for {0}, the file you have is already at cutoff", episode);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -145,19 +156,39 @@ namespace NzbDrone.Core.Providers
|
|||
if (episode.Series.IsDaily && !episode.AirDate.HasValue)
|
||||
{
|
||||
Logger.Warn("AirDate is not Valid for: {0}", episode);
|
||||
notification.CurrentMessage = String.Format("Search for {0} Failed, AirDate is invalid", episode);
|
||||
return false;
|
||||
}
|
||||
|
||||
var searchResult = new SearchHistory
|
||||
{
|
||||
SearchTime = DateTime.Now,
|
||||
SeriesId = episode.Series.SeriesId
|
||||
};
|
||||
|
||||
var reports = PerformSearch(notification, episode.Series, episode.SeasonNumber, new List<Episode> { episode });
|
||||
|
||||
Logger.Debug("Finished searching all indexers. Total {0}", reports.Count);
|
||||
notification.CurrentMessage = "Processing search results";
|
||||
|
||||
if (!episode.Series.IsDaily && ProcessSearchResults(notification, reports, episode.Series, episode.SeasonNumber, episode.EpisodeNumber).Count == 1)
|
||||
return true;
|
||||
if (episode.Series.IsDaily)
|
||||
{
|
||||
searchResult.SearchHistoryItems = ProcessSearchResults(notification, reports, episode.Series, episode.AirDate.Value);
|
||||
_searchHistoryProvider.Add(searchResult);
|
||||
|
||||
if (episode.Series.IsDaily && ProcessSearchResults(notification, reports, episode.Series, episode.AirDate.Value))
|
||||
if (searchResult.SearchHistoryItems.Any(r => r.Success))
|
||||
return true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
searchResult.EpisodeId = episodeId;
|
||||
searchResult.SearchHistoryItems = ProcessSearchResults(notification, reports, searchResult, episode.Series, episode.SeasonNumber, episode.EpisodeNumber);
|
||||
_searchHistoryProvider.Add(searchResult);
|
||||
|
||||
if (searchResult.SearchHistoryItems.Any(r => r.Success))
|
||||
return true;
|
||||
}
|
||||
|
||||
Logger.Warn("Unable to find {0} in any of indexers.", episode);
|
||||
|
||||
|
@ -170,7 +201,6 @@ namespace NzbDrone.Core.Providers
|
|||
notification.CurrentMessage = String.Format("Sorry, couldn't find you {0} in any of indexers.", episode);
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -227,9 +257,10 @@ namespace NzbDrone.Core.Providers
|
|||
return reports;
|
||||
}
|
||||
|
||||
public List<int> ProcessSearchResults(ProgressNotification notification, IEnumerable<EpisodeParseResult> reports, Series series, int seasonNumber, int? episodeNumber = null)
|
||||
public List<SearchHistoryItem> ProcessSearchResults(ProgressNotification notification, IEnumerable<EpisodeParseResult> reports, SearchHistory searchResult, Series series, int seasonNumber, int? episodeNumber = null)
|
||||
{
|
||||
var successes = new List<int>();
|
||||
var items = new List<SearchHistoryItem>();
|
||||
|
||||
foreach (var episodeParseResult in reports.OrderByDescending(c => c.Quality).ThenBy(c => c.Age))
|
||||
{
|
||||
|
@ -237,6 +268,20 @@ namespace NzbDrone.Core.Providers
|
|||
{
|
||||
Logger.Trace("Analysing report " + episodeParseResult);
|
||||
|
||||
var item = new SearchHistoryItem
|
||||
{
|
||||
ReportTitle = episodeParseResult.OriginalString,
|
||||
NzbUrl = episodeParseResult.NzbUrl,
|
||||
Indexer = episodeParseResult.Indexer,
|
||||
Quality = episodeParseResult.Quality.QualityType,
|
||||
Proper = episodeParseResult.Quality.Proper,
|
||||
Size = episodeParseResult.Size,
|
||||
Age = episodeParseResult.Age,
|
||||
Language = episodeParseResult.Language
|
||||
};
|
||||
|
||||
items.Add(item);
|
||||
|
||||
//Get the matching series
|
||||
episodeParseResult.Series = _seriesProvider.FindSeries(episodeParseResult.CleanTitle);
|
||||
|
||||
|
@ -244,6 +289,7 @@ namespace NzbDrone.Core.Providers
|
|||
if (episodeParseResult.Series == null || episodeParseResult.Series.SeriesId != series.SeriesId)
|
||||
{
|
||||
Logger.Trace("Unexpected series for search: {0}. Skipping.", episodeParseResult.CleanTitle);
|
||||
item.SearchError = ReportRejectionType.WrongSeries;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -251,6 +297,7 @@ namespace NzbDrone.Core.Providers
|
|||
if (episodeParseResult.SeasonNumber != seasonNumber)
|
||||
{
|
||||
Logger.Trace("Season number does not match searched season number, skipping.");
|
||||
item.SearchError = ReportRejectionType.WrongSeason;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -258,6 +305,7 @@ namespace NzbDrone.Core.Providers
|
|||
if (episodeNumber.HasValue && !episodeParseResult.EpisodeNumbers.Contains(episodeNumber.Value))
|
||||
{
|
||||
Logger.Trace("Searched episode number is not contained in post, skipping.");
|
||||
item.SearchError = ReportRejectionType.WrongEpisode;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -265,10 +313,12 @@ namespace NzbDrone.Core.Providers
|
|||
if (successes.Intersect(episodeParseResult.EpisodeNumbers).Any())
|
||||
{
|
||||
Logger.Trace("Episode has already been downloaded in this search, skipping.");
|
||||
item.SearchError = ReportRejectionType.Skipped;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult))
|
||||
item.SearchError = _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult);
|
||||
if (item.SearchError == ReportRejectionType.None)
|
||||
{
|
||||
Logger.Debug("Found '{0}'. Adding to download queue.", episodeParseResult);
|
||||
try
|
||||
|
@ -279,12 +329,18 @@ namespace NzbDrone.Core.Providers
|
|||
|
||||
//Add the list of episode numbers from this release
|
||||
successes.AddRange(episodeParseResult.EpisodeNumbers);
|
||||
item.Success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SearchError = ReportRejectionType.DownloadClientFailure;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.ErrorException("Unable to add report to download queue." + episodeParseResult, e);
|
||||
notification.CurrentMessage = String.Format("Unable to add report to download queue. {0}", episodeParseResult);
|
||||
item.SearchError = ReportRejectionType.DownloadClientFailure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,15 +350,38 @@ namespace NzbDrone.Core.Providers
|
|||
}
|
||||
}
|
||||
|
||||
return successes;
|
||||
return items;
|
||||
}
|
||||
|
||||
public bool ProcessSearchResults(ProgressNotification notification, IEnumerable<EpisodeParseResult> reports, Series series, DateTime airDate)
|
||||
public List<SearchHistoryItem> ProcessSearchResults(ProgressNotification notification, IEnumerable<EpisodeParseResult> reports, Series series, DateTime airDate)
|
||||
{
|
||||
var items = new List<SearchHistoryItem>();
|
||||
var skip = false;
|
||||
|
||||
foreach (var episodeParseResult in reports.OrderByDescending(c => c.Quality))
|
||||
{
|
||||
try
|
||||
{
|
||||
var item = new SearchHistoryItem
|
||||
{
|
||||
ReportTitle = episodeParseResult.OriginalString,
|
||||
NzbUrl = episodeParseResult.NzbUrl,
|
||||
Indexer = episodeParseResult.Indexer,
|
||||
Quality = episodeParseResult.Quality.QualityType,
|
||||
Proper = episodeParseResult.Quality.Proper,
|
||||
Size = episodeParseResult.Size,
|
||||
Age = episodeParseResult.Age,
|
||||
Language = episodeParseResult.Language
|
||||
};
|
||||
|
||||
items.Add(item);
|
||||
|
||||
if (skip)
|
||||
{
|
||||
item.SearchError = ReportRejectionType.Skipped;
|
||||
continue;
|
||||
}
|
||||
|
||||
Logger.Trace("Analysing report " + episodeParseResult);
|
||||
|
||||
//Get the matching series
|
||||
|
@ -310,13 +389,20 @@ namespace NzbDrone.Core.Providers
|
|||
|
||||
//If series is null or doesn't match the series we're looking for return
|
||||
if (episodeParseResult.Series == null || episodeParseResult.Series.SeriesId != series.SeriesId)
|
||||
{
|
||||
item.SearchError = ReportRejectionType.WrongSeries;
|
||||
continue;
|
||||
}
|
||||
|
||||
//If parse result doesn't have an air date or it doesn't match passed in airdate, skip the report.
|
||||
if (!episodeParseResult.AirDate.HasValue || episodeParseResult.AirDate.Value.Date != airDate.Date)
|
||||
{
|
||||
item.SearchError = ReportRejectionType.WrongEpisode;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult))
|
||||
item.SearchError = _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult);
|
||||
if (item.SearchError == ReportRejectionType.None)
|
||||
{
|
||||
Logger.Debug("Found '{0}'. Adding to download queue.", episodeParseResult);
|
||||
try
|
||||
|
@ -327,13 +413,19 @@ namespace NzbDrone.Core.Providers
|
|||
String.Format("{0} - {1} {2} Added to download queue",
|
||||
episodeParseResult.Series.Title, episodeParseResult.AirDate.Value.ToShortDateString(), episodeParseResult.Quality);
|
||||
|
||||
return true;
|
||||
item.Success = true;
|
||||
skip = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SearchError = ReportRejectionType.DownloadClientFailure;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.ErrorException("Unable to add report to download queue." + episodeParseResult, e);
|
||||
notification.CurrentMessage = String.Format("Unable to add report to download queue. {0}", episodeParseResult);
|
||||
item.SearchError = ReportRejectionType.DownloadClientFailure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,7 +434,8 @@ namespace NzbDrone.Core.Providers
|
|||
Logger.ErrorException("An error has occurred while processing parse result items from " + episodeParseResult, e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private List<int> GetEpisodeNumberPrefixes(IEnumerable<int> episodeNumbers)
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace NzbDrone.Core.Providers
|
|||
_configProvider = configProvider;
|
||||
}
|
||||
|
||||
public virtual bool SendEmail(string subject, string body, bool htmlBody = false)
|
||||
public virtual void SendEmail(string subject, string body, bool htmlBody = false)
|
||||
{
|
||||
//Create the Email message
|
||||
var email = new MailMessage();
|
||||
|
@ -54,7 +54,14 @@ namespace NzbDrone.Core.Providers
|
|||
credentials = new NetworkCredential(username, password);
|
||||
|
||||
//Send the email
|
||||
return Send(email, _configProvider.SmtpServer, _configProvider.SmtpPort, _configProvider.SmtpUseSsl, credentials);
|
||||
try
|
||||
{
|
||||
Send(email, _configProvider.SmtpServer, _configProvider.SmtpPort, _configProvider.SmtpUseSsl, credentials);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Logger.Error("Error sending email. Subject: {0}", email.Subject);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool SendTestEmail(string server, int port, bool ssl, string username, string password, string fromAddress, string toAddresses)
|
||||
|
@ -90,11 +97,19 @@ namespace NzbDrone.Core.Providers
|
|||
credentials = new NetworkCredential(username, password);
|
||||
|
||||
//Send the email
|
||||
return Send(email, server, port, ssl, credentials);
|
||||
try
|
||||
{
|
||||
Send(email, server, port, ssl, credentials);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Logger.TraceException("Failed to send test email", ex);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//TODO: make this throw instead of return false.
|
||||
public virtual bool Send(MailMessage email, string server, int port, bool ssl, NetworkCredential credentials)
|
||||
public virtual void Send(MailMessage email, string server, int port, bool ssl, NetworkCredential credentials)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -109,15 +124,12 @@ namespace NzbDrone.Core.Providers
|
|||
|
||||
//Send the email
|
||||
smtp.Send(email);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("There was an error sending an email.");
|
||||
Logger.TraceException(ex.Message, ex);
|
||||
return false;
|
||||
Logger.ErrorException("There was an error sending an email.", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Ninject;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Repository;
|
||||
using PetaPoco;
|
||||
|
||||
namespace NzbDrone.Core.Providers
|
||||
{
|
||||
public class StatsProvider
|
||||
{
|
||||
private readonly IDatabase _database;
|
||||
|
||||
[Inject]
|
||||
public StatsProvider(IDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public StatsProvider()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual StatsModel GetStats()
|
||||
{
|
||||
var series = _database.Fetch<Series>();
|
||||
var episodes = _database.Fetch<Episode>();
|
||||
var history = _database.Fetch<History>("WHERE Date <= @0", DateTime.Today.AddDays(-30));
|
||||
|
||||
var stats = new StatsModel();
|
||||
stats.SeriesTotal = series.Count;
|
||||
stats.SeriesContinuing = series.Count(s => s.Status == "Continuing");
|
||||
stats.SeriesEnded = series.Count(s => s.Status == "Ended");
|
||||
stats.EpisodesTotal = episodes.Count;
|
||||
stats.EpisodesOnDisk = episodes.Count(e => e.EpisodeFileId > 0);
|
||||
stats.EpisodesMissing = episodes.Count(e => e.Ignored == false && e.EpisodeFileId == 0);
|
||||
stats.DownloadedLastMonth = history.Count;
|
||||
stats.DownloadLastWeek = history.Count(h => h.Date <= DateTime.Today.AddDays(7));
|
||||
|
||||
return stats;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
using PetaPoco;
|
||||
|
||||
namespace NzbDrone.Core.Repository.Search
|
||||
{
|
||||
[PrimaryKey("Id", autoIncrement = true)]
|
||||
[TableName("SearchHistory")]
|
||||
public class SearchHistory
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
public int? SeasonNumber { get; set; }
|
||||
public int? EpisodeId { get; set; }
|
||||
public DateTime SearchTime { get; set; }
|
||||
public bool SuccessfulDownload { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public List<SearchHistoryItem> SearchHistoryItems { get; set; }
|
||||
|
||||
[Ignore]
|
||||
public List<int> Successes { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public string SeriesTitle { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public bool IsDaily { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public int? EpisodeNumber { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public string EpisodeTitle { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public DateTime AirDate { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public int TotalItems { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public int SuccessfulCount { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
using PetaPoco;
|
||||
|
||||
namespace NzbDrone.Core.Repository.Search
|
||||
{
|
||||
[PrimaryKey("Id", autoIncrement = true)]
|
||||
[TableName("SearchHistoryItems")]
|
||||
public class SearchHistoryItem
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int SearchHistoryId { get; set; }
|
||||
public string ReportTitle { get; set; }
|
||||
public string Indexer { get; set; }
|
||||
public string NzbUrl { get; set; }
|
||||
public string NzbInfoUrl { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public ReportRejectionType SearchError { get; set; }
|
||||
public QualityTypes Quality { get; set; }
|
||||
public bool Proper { get; set; }
|
||||
public int Age { get; set; }
|
||||
public LanguageType Language { get; set; }
|
||||
public long Size { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{0} - {1} - {2}", ReportTitle, Quality, SearchError);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
<package id="Growl" version="0.6" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" />
|
||||
<package id="MiniProfiler" version="1.9" />
|
||||
<package id="Newtonsoft.Json" version="4.0.8" />
|
||||
<package id="Newtonsoft.Json" version="4.5.3" />
|
||||
<package id="Ninject" version="2.2.1.4" />
|
||||
<package id="NLog" version="2.0.0.2000" />
|
||||
<package id="SignalR.Hosting.AspNet" version="0.4.0.0" />
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
using MongoDB.Driver;
|
||||
using NzbDrone.Services.Service.Datastore;
|
||||
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
|
||||
using Ninject;
|
||||
using Ninject.Web.Mvc;
|
||||
using NzbDrone.Services.Service.Datastore;
|
||||
using NzbDrone.Services.Service.Migrations;
|
||||
using Services.PetaPoco;
|
||||
|
||||
|
@ -33,8 +32,6 @@ namespace NzbDrone.Services.Service.App_Start
|
|||
var kernel = new StandardKernel();
|
||||
MigrationsHelper.Run(Connection.GetConnectionString);
|
||||
kernel.Bind<IDatabase>().ToMethod(c => Connection.GetPetaPocoDb());
|
||||
kernel.Bind<MongoDatabase>().ToConstant(Connection.GetMongoDb());
|
||||
|
||||
|
||||
return kernel;
|
||||
}
|
||||
|
|
|
@ -1,153 +1,23 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using MongoDB.Driver;
|
||||
using NLog;
|
||||
using Ninject;
|
||||
using NzbDrone.Common.Contract;
|
||||
using NzbDrone.Services.Service.Exceptions;
|
||||
using NzbDrone.Services.Service.Repository.Reporting;
|
||||
using Services.PetaPoco;
|
||||
using ExceptionInstance = NzbDrone.Services.Service.Repository.Reporting.ExceptionInstance;
|
||||
using ExceptionReport = NzbDrone.Common.Contract.ExceptionReport;
|
||||
|
||||
namespace NzbDrone.Services.Service.Controllers
|
||||
{
|
||||
public class ExceptionController : Controller
|
||||
{
|
||||
private readonly IDatabase _database;
|
||||
private readonly ExceptionRepository _exceptionRepository;
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
[Inject]
|
||||
public ExceptionController(IDatabase database, ExceptionRepository exceptionRepository)
|
||||
{
|
||||
_database = database;
|
||||
_exceptionRepository = exceptionRepository;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public EmptyResult ReportExisting(ExistingExceptionReport existingExceptionReport)
|
||||
public EmptyResult ReportExisting()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ExceptionHashExists(existingExceptionReport.Hash))
|
||||
{
|
||||
|
||||
var exceptionInstance = new ExceptionInstance
|
||||
{
|
||||
ExceptionHash = existingExceptionReport.Hash,
|
||||
IsProduction = existingExceptionReport.IsProduction,
|
||||
LogMessage = existingExceptionReport.LogMessage,
|
||||
UGuid = existingExceptionReport.UGuid,
|
||||
Timestamp = DateTime.Now
|
||||
};
|
||||
|
||||
_database.Insert(exceptionInstance);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn("Invalid exception hash '{0}'", existingExceptionReport.Hash);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.FatalException("Error has occurred while saving exception", e);
|
||||
throw;
|
||||
}
|
||||
|
||||
return new EmptyResult();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public JsonResult ReportNew(ExceptionReport exceptionReport)
|
||||
public JsonResult ReportNew()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
var report = new Exceptions.ExceptionReport();
|
||||
report.AppVersion = exceptionReport.Version;
|
||||
report.ApplicationId = "NzbDrone";
|
||||
report.ExceptionMessage = exceptionReport.ExceptionMessage;
|
||||
report.ExceptionType = exceptionReport.Type;
|
||||
report.Location = exceptionReport.Logger;
|
||||
report.Message = exceptionReport.LogMessage;
|
||||
report.Stack = exceptionReport.Stack;
|
||||
report.Uid = exceptionReport.UGuid.ToString();
|
||||
|
||||
_exceptionRepository.Store(report);
|
||||
|
||||
var exceptionHash = GetExceptionDetailId(exceptionReport);
|
||||
|
||||
var exceptionInstance = new ExceptionInstance
|
||||
{
|
||||
ExceptionHash = exceptionHash,
|
||||
IsProduction = exceptionReport.IsProduction,
|
||||
LogMessage = exceptionReport.LogMessage,
|
||||
Timestamp = DateTime.Now,
|
||||
UGuid = exceptionReport.UGuid
|
||||
};
|
||||
|
||||
_database.Insert(exceptionInstance);
|
||||
|
||||
return new JsonResult { Data = new ExceptionReportResponse { ExceptionHash = exceptionHash } };
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.FatalException("Error has occurred while saving exception", e);
|
||||
if (!exceptionReport.IsProduction)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return new JsonResult();
|
||||
}
|
||||
|
||||
private string GetExceptionDetailId(ExceptionReport exceptionReport)
|
||||
{
|
||||
var reportHash = Hash(String.Concat(exceptionReport.Version, exceptionReport.String, exceptionReport.Logger));
|
||||
|
||||
if (!ExceptionHashExists(reportHash))
|
||||
{
|
||||
var exeptionDetail = new ExceptionDetail();
|
||||
exeptionDetail.Hash = reportHash;
|
||||
exeptionDetail.Logger = exceptionReport.Logger;
|
||||
exeptionDetail.String = exceptionReport.String;
|
||||
exeptionDetail.Type = exceptionReport.Type;
|
||||
exeptionDetail.Version = exceptionReport.Version;
|
||||
|
||||
_database.Insert(exeptionDetail);
|
||||
}
|
||||
|
||||
return reportHash;
|
||||
}
|
||||
|
||||
private bool ExceptionHashExists(string reportHash)
|
||||
{
|
||||
return _database.Exists<ExceptionDetail>(reportHash);
|
||||
}
|
||||
|
||||
private static string Hash(string input)
|
||||
{
|
||||
uint mCrc = 0xffffffff;
|
||||
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(input);
|
||||
foreach (byte myByte in bytes)
|
||||
{
|
||||
mCrc ^= ((uint)(myByte) << 24);
|
||||
for (var i = 0; i < 8; i++)
|
||||
{
|
||||
if ((Convert.ToUInt32(mCrc) & 0x80000000) == 0x80000000)
|
||||
{
|
||||
mCrc = (mCrc << 1) ^ 0x04C11DB7;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCrc <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return String.Format("{0:x8}", mCrc);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -63,9 +63,9 @@ namespace NzbDrone.Services.Service.Controllers
|
|||
}
|
||||
|
||||
[HttpPost]
|
||||
public JsonResult ReportException(ExceptionReport exceptionReport)
|
||||
public JsonResult ReportException()
|
||||
{
|
||||
return _exceptionController.ReportNew(exceptionReport);
|
||||
return new JsonResult();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,5 @@
|
|||
using System;
|
||||
using System.Configuration;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using NzbDrone.Services.Service.Migrations;
|
||||
using Services.PetaPoco;
|
||||
|
||||
|
||||
|
@ -28,22 +24,6 @@ namespace NzbDrone.Services.Service.Datastore
|
|||
}
|
||||
|
||||
|
||||
public static MongoDatabase GetMongoDb()
|
||||
{
|
||||
var serverSettings = new MongoServerSettings()
|
||||
{
|
||||
ConnectionMode = ConnectionMode.Direct,
|
||||
ConnectTimeout = TimeSpan.FromSeconds(10),
|
||||
DefaultCredentials = new MongoCredentials("nzbdrone", "nzbdronepassword"),
|
||||
GuidRepresentation = GuidRepresentation.Standard,
|
||||
Server = new MongoServerAddress("ds031747.mongolab.com", 31747),
|
||||
SafeMode = new SafeMode(true) { J = true },
|
||||
};
|
||||
|
||||
|
||||
var server = MongoServer.Create(serverSettings);
|
||||
|
||||
return server.GetDatabase("nzbdrone_ex");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace NzbDrone.Services.Service.Exceptions
|
||||
{
|
||||
public class ExceptionInfo
|
||||
{
|
||||
public ExceptionInfo()
|
||||
{
|
||||
Instances = new ExceptionInstance[0];
|
||||
}
|
||||
|
||||
[BsonId]
|
||||
public string Hash { get; set; }
|
||||
|
||||
[BsonElement("xtype")]
|
||||
public string ExceptionType { get; set; }
|
||||
|
||||
[BsonElement("stk")]
|
||||
public string Stack { get; set; }
|
||||
|
||||
[BsonElement("loc")]
|
||||
public string Location { get; set; }
|
||||
|
||||
[BsonElement("inst")]
|
||||
public IEnumerable<ExceptionInstance> Instances { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
using System.Linq;
|
||||
using System;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace NzbDrone.Services.Service.Exceptions
|
||||
{
|
||||
public class ExceptionInstance
|
||||
{
|
||||
[BsonElement("ver")]
|
||||
public string AppVersion { get; set; }
|
||||
|
||||
[BsonElement("uid")]
|
||||
public string UserId { get; set; }
|
||||
|
||||
[BsonElement("xmsg")]
|
||||
public string ExceptionMessage { get; set; }
|
||||
|
||||
[BsonElement("msg")]
|
||||
public string Message { get; set; }
|
||||
|
||||
[BsonElement("time")]
|
||||
public DateTime Time { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Services.Service.Exceptions
|
||||
{
|
||||
public class ExceptionReport
|
||||
{
|
||||
public string ApplicationId { get; set; }
|
||||
public string AppVersion { get; set; }
|
||||
public string Uid { get; set; }
|
||||
public string ExceptionType { get; set; }
|
||||
public string ExceptionMessage { get; set; }
|
||||
public string Stack { get; set; }
|
||||
public string Location { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using MongoDB.Driver;
|
||||
using MongoDB.Driver.Builders;
|
||||
|
||||
namespace NzbDrone.Services.Service.Exceptions
|
||||
{
|
||||
public class ExceptionRepository
|
||||
{
|
||||
private readonly MongoDatabase _mongoDb;
|
||||
|
||||
public ExceptionRepository(MongoDatabase mongoDb)
|
||||
{
|
||||
_mongoDb = mongoDb;
|
||||
}
|
||||
|
||||
public ExceptionRepository()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual string Store(NzbDrone.Services.Service.Exceptions.ExceptionReport exceptionReport)
|
||||
{
|
||||
var hash = GetExceptionDetailId(exceptionReport);
|
||||
|
||||
var exceptionInstance = new NzbDrone.Services.Service.Exceptions.ExceptionInstance
|
||||
{
|
||||
AppVersion = exceptionReport.AppVersion,
|
||||
ExceptionMessage = exceptionReport.ExceptionMessage,
|
||||
Message = exceptionReport.Message,
|
||||
Time = DateTime.UtcNow,
|
||||
UserId = exceptionReport.Uid
|
||||
};
|
||||
|
||||
|
||||
|
||||
var applicationExceptions = _mongoDb.GetCollection(exceptionReport.ApplicationId);
|
||||
|
||||
applicationExceptions.Update(Query.EQ("_id", hash), Update.PushWrapped("inst", exceptionInstance));
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
private string GetExceptionDetailId(NzbDrone.Services.Service.Exceptions.ExceptionReport exceptionReport)
|
||||
{
|
||||
var hash = Hash(String.Concat(exceptionReport.AppVersion, exceptionReport.Location, exceptionReport.ExceptionType, exceptionReport.Stack));
|
||||
|
||||
if (!ExceptionInfoExists(exceptionReport.ApplicationId, hash))
|
||||
{
|
||||
var exceptionInfo = new NzbDrone.Services.Service.Exceptions.ExceptionInfo
|
||||
{
|
||||
Hash = hash,
|
||||
Stack = exceptionReport.Stack,
|
||||
ExceptionType = exceptionReport.ExceptionType,
|
||||
Location = exceptionReport.Location
|
||||
};
|
||||
|
||||
_mongoDb.GetCollection(exceptionReport.ApplicationId).Insert(exceptionInfo);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public bool ExceptionInfoExists(string applicationId, string hash)
|
||||
{
|
||||
var appCollection = _mongoDb.GetCollection(applicationId);
|
||||
return appCollection.FindAs<NzbDrone.Services.Service.Exceptions.ExceptionInfo>(Query.EQ("_id", hash)).Any();
|
||||
}
|
||||
|
||||
private static string Hash(string input)
|
||||
{
|
||||
uint mCrc = 0xffffffff;
|
||||
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(input);
|
||||
foreach (byte myByte in bytes)
|
||||
{
|
||||
mCrc ^= ((uint)(myByte) << 24);
|
||||
for (var i = 0; i < 8; i++)
|
||||
{
|
||||
if ((Convert.ToUInt32(mCrc) & 0x80000000) == 0x80000000)
|
||||
{
|
||||
mCrc = (mCrc << 1) ^ 0x04C11DB7;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCrc <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return String.Format("{0:x8}", mCrc);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,8 @@
|
|||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>4.0</OldToolsVersion>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -41,9 +43,6 @@
|
|||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="AutoMapper">
|
||||
<HintPath>..\..\packages\AutoMapper.2.0.0\lib\net40-client\AutoMapper.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Elmah">
|
||||
<HintPath>..\..\packages\elmah.corelibrary.1.2.1\lib\Elmah.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -64,14 +63,9 @@
|
|||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Libraries\Migrator.NET\Migrator.Providers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MongoDB.Bson">
|
||||
<HintPath>..\..\packages\mongocsharpdriver.1.4\lib\net35\MongoDB.Bson.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MongoDB.Driver">
|
||||
<HintPath>..\..\packages\mongocsharpdriver.1.4\lib\net35\MongoDB.Driver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.0.8.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.4.0.8\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.4.5.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Ninject, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll</HintPath>
|
||||
|
@ -100,8 +94,6 @@
|
|||
<Reference Include="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Configuration" />
|
||||
|
@ -222,15 +214,9 @@
|
|||
<Compile Include="App_Start\Logging.cs" />
|
||||
<Compile Include="App_Start\NinjectMVC3.cs" />
|
||||
<Compile Include="Controllers\ExceptionController.cs" />
|
||||
<Compile Include="Exceptions\ExceptionInfo.cs" />
|
||||
<Compile Include="Exceptions\ExceptionInstance.cs" />
|
||||
<Compile Include="Exceptions\ExceptionReport.cs" />
|
||||
<Compile Include="Exceptions\ExceptionRepository.cs" />
|
||||
<Compile Include="Helpers\HtmlIncludeExtentions.cs" />
|
||||
<Compile Include="Migrations\Migration20120226.cs" />
|
||||
<Compile Include="Migrations\Migration20120229.cs" />
|
||||
<Compile Include="Repository\Reporting\ExceptionDetail.cs" />
|
||||
<Compile Include="Repository\Reporting\ExceptionInstance.cs" />
|
||||
<Compile Include="Services.PetaPoco.cs" />
|
||||
<Compile Include="Datastore\Connection.cs" />
|
||||
<Compile Include="Controllers\DailySeriesController.cs" />
|
||||
|
@ -252,7 +238,6 @@
|
|||
<Compile Include="Providers\SceneMappingProvider.cs" />
|
||||
<Compile Include="Repository\DailySeries.cs" />
|
||||
<Compile Include="Repository\PendingSceneMapping.cs" />
|
||||
<Compile Include="Repository\Reporting\ExceptionRow.cs" />
|
||||
<Compile Include="Repository\Reporting\ParseErrorRow.cs" />
|
||||
<Compile Include="Repository\Reporting\ReportRowBase.cs" />
|
||||
<Compile Include="Repository\SceneMapping.cs" />
|
||||
|
@ -308,6 +293,7 @@
|
|||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
using System.Linq;
|
||||
using Services.PetaPoco;
|
||||
|
||||
namespace NzbDrone.Services.Service.Repository.Reporting
|
||||
{
|
||||
[TableName("Exceptions")]
|
||||
[PrimaryKey("Hash", autoIncrement = false)]
|
||||
public class ExceptionDetail
|
||||
{
|
||||
public string Hash { get; set; }
|
||||
public string Logger { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string String { get; set; }
|
||||
public string Version { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Services.PetaPoco;
|
||||
|
||||
namespace NzbDrone.Services.Service.Repository.Reporting
|
||||
{
|
||||
[TableName("ExceptionInstances")]
|
||||
public class ExceptionInstance
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string ExceptionHash { get; set; }
|
||||
public string LogMessage { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
public bool IsProduction { get; set; }
|
||||
public Guid UGuid { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
using System.Linq;
|
||||
using Services.PetaPoco;
|
||||
|
||||
namespace NzbDrone.Services.Service.Repository.Reporting
|
||||
{
|
||||
[TableName("ExceptionReports")]
|
||||
public class ExceptionRow : ReportRowBase
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public string Logger { get; set; }
|
||||
public string LogMessage { get; set; }
|
||||
public string String { get; set; }
|
||||
}
|
||||
}
|
|
@ -74,7 +74,7 @@
|
|||
{ sWidth: 'auto', "mDataProp": "Title", "bSortable": false }, //Title
|
||||
{ sWidth: '40px', "mDataProp": "Commands", "bSortable": false, "fnRender": function (row) {
|
||||
var promoteImage = "<img src=\"../../Content/Images/Promote.png\" alt=\"Promote\" title=\Promote to Active\" class=\"gridAction\" onclick=\"promoteMapping(this.parentNode.parentNode, " + row.aData["MappingId"] + ")\">";
|
||||
var deleteImage = "<img src=\"../../Content/Images/X.png\" alt=\"Delete\" title=\"Delete\" class=\"gridAction\" onclick=\"deleteMapping(this.parentNode.parentNode, " + row.aData["MappingId"] + ")\">";
|
||||
var deleteImage = "<img src=\"../../Content/Images/close.png\" alt=\"Delete\" title=\"Delete\" class=\"gridAction\" onclick=\"deleteMapping(this.parentNode.parentNode, " + row.aData["MappingId"] + ")\">";
|
||||
|
||||
return promoteImage + deleteImage;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.8.0" newVersion="4.0.8.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="4.5.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="AutoMapper" version="2.0.0" />
|
||||
<package id="elmah" version="1.2.0.1" />
|
||||
<package id="elmah.corelibrary" version="1.2.1" />
|
||||
<package id="elmah.sqlserver" version="1.2" />
|
||||
|
@ -9,8 +8,7 @@
|
|||
<package id="jQuery.UI.Combined" version="1.8.17" />
|
||||
<package id="jQuery.Validation" version="1.9" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" />
|
||||
<package id="mongocsharpdriver" version="1.4" />
|
||||
<package id="Newtonsoft.Json" version="4.0.8" />
|
||||
<package id="Newtonsoft.Json" version="4.5.3" />
|
||||
<package id="Ninject" version="2.2.1.4" />
|
||||
<package id="Ninject.MVC3" version="2.2.2.0" />
|
||||
<package id="NLog" version="2.0.0.2000" />
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Contract;
|
||||
using NzbDrone.Services.Service.Repository.Reporting;
|
||||
using NzbDrone.Services.Tests.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Services.Tests.ExceptionControllerTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ReportExistingFixture : ServicesTestBase
|
||||
{
|
||||
|
||||
Service.Controllers.ExceptionController Controller
|
||||
{
|
||||
get
|
||||
{
|
||||
return Mocker.Resolve<Service.Controllers.ExceptionController>();
|
||||
}
|
||||
}
|
||||
|
||||
private static ExistingExceptionReport CreateExceptionReport()
|
||||
{
|
||||
return new ExistingExceptionReport
|
||||
{
|
||||
IsProduction = true,
|
||||
Version = "1.1.2.323456",
|
||||
UGuid = Guid.NewGuid(),
|
||||
LogMessage = @"Log message",
|
||||
Hash = "ABC123"
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_log_warn_if_hash_doesnt_exist()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
Controller.ReportExisting(CreateExceptionReport());
|
||||
|
||||
Db.Fetch<ExceptionDetail>().Should().BeEmpty();
|
||||
Db.Fetch<ExceptionInstance>().Should().BeEmpty();
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_save_instance_if_hash_is_valid()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var existing = CreateExceptionReport();
|
||||
|
||||
|
||||
Db.Insert(Builder<ExceptionDetail>.CreateNew().With(c => c.Hash = existing.Hash).Build());
|
||||
|
||||
Controller.ReportExisting(existing);
|
||||
|
||||
Db.Fetch<ExceptionDetail>().Should().HaveCount(1);
|
||||
var exceptionInstance = Db.Fetch<ExceptionInstance>();
|
||||
exceptionInstance.Should().HaveCount(1);
|
||||
exceptionInstance.Single().Id.Should().BeGreaterThan(0);
|
||||
exceptionInstance.Single().ExceptionHash.Should().NotBeBlank();
|
||||
exceptionInstance.Single().IsProduction.Should().Be(existing.IsProduction);
|
||||
exceptionInstance.Single().Timestamp.Should().BeWithin(TimeSpan.FromSeconds(4)).Before(DateTime.Now);
|
||||
exceptionInstance.Single().LogMessage.Should().Be(existing.LogMessage);
|
||||
exceptionInstance.Single().UGuid.Should().Be(existing.UGuid);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,213 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Contract;
|
||||
using NzbDrone.Services.Service.Repository.Reporting;
|
||||
using NzbDrone.Services.Tests.Framework;
|
||||
|
||||
namespace NzbDrone.Services.Tests.ExceptionControllerTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ReportNewFixture : ServicesTestBase
|
||||
{
|
||||
|
||||
Service.Controllers.ExceptionController Controller
|
||||
{
|
||||
get
|
||||
{
|
||||
return Mocker.Resolve<Service.Controllers.ExceptionController>();
|
||||
}
|
||||
}
|
||||
|
||||
private static ExceptionReport CreateExceptionReport()
|
||||
{
|
||||
return new ExceptionReport
|
||||
{
|
||||
IsProduction = true,
|
||||
Version = "1.1.2.323456",
|
||||
UGuid = Guid.NewGuid(),
|
||||
Logger = "NzbDrone.Logger.Name",
|
||||
LogMessage = @"Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message",
|
||||
String = @"Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message",
|
||||
|
||||
Type = typeof(InvalidOperationException).Name
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void ReportNew_should_save_instance()
|
||||
{
|
||||
var exceptionReport = CreateExceptionReport();
|
||||
|
||||
WithRealDb();
|
||||
|
||||
Controller.ReportNew(exceptionReport);
|
||||
|
||||
var exceptionInstance = Db.Fetch<ExceptionInstance>();
|
||||
exceptionInstance.Should().HaveCount(1);
|
||||
exceptionInstance.Single().Id.Should().BeGreaterThan(0);
|
||||
exceptionInstance.Single().ExceptionHash.Should().NotBeBlank();
|
||||
exceptionInstance.Single().IsProduction.Should().Be(exceptionReport.IsProduction);
|
||||
exceptionInstance.Single().Timestamp.Should().BeWithin(TimeSpan.FromSeconds(4)).Before(DateTime.Now);
|
||||
exceptionInstance.Single().LogMessage.Should().Be(exceptionReport.LogMessage);
|
||||
exceptionInstance.Single().UGuid.Should().Be(exceptionReport.UGuid);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReportNew_should_save_detail()
|
||||
{
|
||||
var exceptionReport = CreateExceptionReport();
|
||||
|
||||
WithRealDb();
|
||||
|
||||
Controller.ReportNew(exceptionReport);
|
||||
|
||||
var exceptionDetails = Db.Fetch<ExceptionDetail>();
|
||||
exceptionDetails.Should().HaveCount(1);
|
||||
exceptionDetails.Single().Hash.Should().NotBeBlank();
|
||||
exceptionDetails.Single().Logger.Should().Be(exceptionReport.Logger);
|
||||
exceptionDetails.Single().Type.Should().Be(exceptionReport.Type);
|
||||
exceptionDetails.Single().String.Should().Be(exceptionReport.String);
|
||||
exceptionDetails.Single().Version.Should().Be(exceptionReport.Version);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReportNew_should_return_exception_id()
|
||||
{
|
||||
var exceptionReport = CreateExceptionReport();
|
||||
|
||||
WithRealDb();
|
||||
|
||||
var response = Controller.ReportNew(exceptionReport);
|
||||
|
||||
response.Data.Should().BeOfType<ExceptionReportResponse>();
|
||||
((ExceptionReportResponse)response.Data).ExceptionHash.Should().NotBeBlank();
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Reporting_exception_more_than_once_should_create_single_detail_with_multiple_instances()
|
||||
{
|
||||
var exceptionReport = CreateExceptionReport();
|
||||
|
||||
WithRealDb();
|
||||
|
||||
var response1 = Controller.ReportNew(exceptionReport);
|
||||
var response2 = Controller.ReportNew(exceptionReport);
|
||||
var response3 = Controller.ReportNew(exceptionReport);
|
||||
|
||||
var detail = Db.Fetch<ExceptionDetail>();
|
||||
var instances = Db.Fetch<ExceptionInstance>();
|
||||
|
||||
detail.Should().HaveCount(1);
|
||||
instances.Should().HaveCount(3);
|
||||
|
||||
instances.Should().OnlyContain(c => c.ExceptionHash == detail.Single().Hash);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Reporting_exception_with_diffrent_version_should_create_new_detail()
|
||||
{
|
||||
var exceptionReport1 = CreateExceptionReport();
|
||||
exceptionReport1.Version = "0.1.1";
|
||||
|
||||
var exceptionReport2 = CreateExceptionReport();
|
||||
exceptionReport2.Version = "0.2.1";
|
||||
|
||||
WithRealDb();
|
||||
|
||||
Controller.ReportNew(exceptionReport1);
|
||||
Controller.ReportNew(exceptionReport2);
|
||||
|
||||
var detail = Db.Fetch<ExceptionDetail>();
|
||||
var instances = Db.Fetch<ExceptionInstance>();
|
||||
|
||||
detail.Should().HaveCount(2);
|
||||
instances.Should().HaveCount(2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Reporting_exception_with_diffrent_strting_should_create_new_detail()
|
||||
{
|
||||
var exceptionReport1 = CreateExceptionReport();
|
||||
exceptionReport1.String = "Error1";
|
||||
|
||||
var exceptionReport2 = CreateExceptionReport();
|
||||
exceptionReport2.String = "Error2";
|
||||
|
||||
WithRealDb();
|
||||
|
||||
Controller.ReportNew(exceptionReport1);
|
||||
Controller.ReportNew(exceptionReport2);
|
||||
|
||||
var detail = Db.Fetch<ExceptionDetail>();
|
||||
var instances = Db.Fetch<ExceptionInstance>();
|
||||
|
||||
detail.Should().HaveCount(2);
|
||||
instances.Should().HaveCount(2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Reporting_exception_with_diffrent_logger_should_create_new_detail()
|
||||
{
|
||||
var exceptionReport1 = CreateExceptionReport();
|
||||
exceptionReport1.Logger = "logger1";
|
||||
|
||||
var exceptionReport2 = CreateExceptionReport();
|
||||
exceptionReport2.Logger = "logger2";
|
||||
|
||||
WithRealDb();
|
||||
|
||||
Controller.ReportNew(exceptionReport1);
|
||||
Controller.ReportNew(exceptionReport2);
|
||||
|
||||
var detail = Db.Fetch<ExceptionDetail>();
|
||||
var instances = Db.Fetch<ExceptionInstance>();
|
||||
|
||||
detail.Should().HaveCount(2);
|
||||
instances.Should().HaveCount(2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>NzbDrone.Services.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -68,8 +70,6 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ExceptionControllerTests\ReportExistingFixture.cs" />
|
||||
<Compile Include="ExceptionControllerTests\ReportNewFixture.cs" />
|
||||
<Compile Include="ReportingControllerFixture.cs" />
|
||||
<Compile Include="Framework\ServicesTestBase.cs" />
|
||||
<Compile Include="Framework\TestDbHelper.cs" />
|
||||
|
@ -100,6 +100,7 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -39,62 +39,6 @@ namespace NzbDrone.Services.Tests
|
|||
};
|
||||
}
|
||||
|
||||
private static ExceptionReport CreateExceptionReport()
|
||||
{
|
||||
return new ExceptionReport
|
||||
{
|
||||
IsProduction = true,
|
||||
Version = "1.1.2.323456",
|
||||
UGuid = Guid.NewGuid(),
|
||||
Logger = "NzbDrone.Logger.Name",
|
||||
LogMessage = @"Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message",
|
||||
String = @"Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message
|
||||
Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message",
|
||||
|
||||
Type = typeof(InvalidOperationException).Name
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void parse_report_should_be_saved()
|
||||
{
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>NzbDrone.Test.Common</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -82,6 +84,7 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -49,6 +49,8 @@ namespace NzbDrone.Test.Common
|
|||
|
||||
MockedRestProvider = new Mock<RestProvider>();
|
||||
ReportingService.RestProvider = MockedRestProvider.Object;
|
||||
ReportingService.SetupExceptronDriver();
|
||||
|
||||
|
||||
if (Directory.Exists(TempFolder))
|
||||
{
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
|
@ -47,6 +49,7 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
|
@ -87,6 +89,7 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
|
@ -61,6 +63,7 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace NzbDrone.Update
|
|||
private static void InitLoggers()
|
||||
{
|
||||
ReportingService.RestProvider = _kernel.Get<RestProvider>();
|
||||
ReportingService.SetupExceptronDriver();
|
||||
|
||||
LogConfiguration.RegisterRemote();
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
<AssemblyName>NzbDrone.Web.UI.Automation</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -39,8 +41,9 @@
|
|||
<Reference Include="Ionic.Zip, Version=1.9.1.8, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.0.6.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.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.4.5.1\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework">
|
||||
<HintPath>..\packages\NUnit.2.6.0.12054\lib\nunit.framework.dll</HintPath>
|
||||
|
@ -53,8 +56,9 @@
|
|||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WebDriver, Version=2.19.0.0, Culture=neutral, PublicKeyToken=1c2bd1631853048f, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Selenium.WebDriver.2.19.0\lib\net40\WebDriver.dll</HintPath>
|
||||
<Reference Include="WebDriver, Version=2.21.0.0, Culture=neutral, PublicKeyToken=1c2bd1631853048f, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Selenium.WebDriver.2.21.0\lib\net40\WebDriver.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -91,6 +95,7 @@
|
|||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(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">
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30AD4FE6B2A6AEED" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.8.0" newVersion="4.0.6.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="4.5.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<packages>
|
||||
<package id="DotNetZip" version="1.9.1.8" />
|
||||
<package id="FluentAssertions" version="1.7.0" />
|
||||
<package id="Newtonsoft.Json" version="4.0.6" />
|
||||
<package id="Newtonsoft.Json" version="4.5.1" />
|
||||
<package id="NUnit" version="2.6.0.12054" />
|
||||
<package id="Selenium.WebDriver" version="2.19.0" />
|
||||
<package id="Selenium.WebDriver" version="2.21.0" />
|
||||
</packages>
|
|
@ -0,0 +1,17 @@
|
|||
using DataTables.Mvc.Core.Helpers;
|
||||
using DataTables.Mvc.Core.Models;
|
||||
using System.Web.Mvc;
|
||||
|
||||
[assembly: WebActivator.PreApplicationStartMethod(typeof(NzbDrone.Web.App_Start.DataTablesModelBinderActivator), "Start")]
|
||||
|
||||
namespace NzbDrone.Web.App_Start
|
||||
{
|
||||
public static class DataTablesModelBinderActivator
|
||||
{
|
||||
public static void Start()
|
||||
{
|
||||
if (!ModelBinders.Binders.ContainsKey(typeof(DataTablesParams)))
|
||||
ModelBinders.Binders.Add(typeof(DataTablesParams), new DataTablesModelBinder());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
using System.Web.Mvc;
|
||||
using System.Web.WebPages;
|
||||
using NzbDrone.Web.Helpers;
|
||||
using NzbDrone.Web.Models;
|
||||
|
||||
[assembly: WebActivator.PreApplicationStartMethod(typeof(NzbDrone.Web.App_Start.RegisterDatatablesModelBinder), "Start")]
|
||||
|
||||
namespace NzbDrone.Web.App_Start {
|
||||
public static class RegisterDatatablesModelBinder {
|
||||
public static void Start() {
|
||||
if (!ModelBinders.Binders.ContainsKey(typeof(DataTablesParams)))
|
||||
ModelBinders.Binders.Add(typeof(DataTablesParams), new DataTablesModelBinder());
|
||||
}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
|
@ -4,6 +4,8 @@ using System.Linq;
|
|||
using System.Linq.Dynamic;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using DataTables.Mvc.Core;
|
||||
using DataTables.Mvc.Core.Models;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Instrumentation;
|
||||
using NzbDrone.Web.Models;
|
||||
|
@ -16,7 +18,8 @@ namespace NzbDrone.Web.Controllers
|
|||
private readonly EnvironmentProvider _environmentProvider;
|
||||
private readonly DiskProvider _diskProvider;
|
||||
|
||||
public LogController(LogProvider logProvider, EnvironmentProvider environmentProvider, DiskProvider diskProvider)
|
||||
public LogController(LogProvider logProvider, EnvironmentProvider environmentProvider,
|
||||
DiskProvider diskProvider)
|
||||
{
|
||||
_logProvider = logProvider;
|
||||
_environmentProvider = environmentProvider;
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using NzbDrone.Core;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Repository.Search;
|
||||
using NzbDrone.Web.Models;
|
||||
|
||||
namespace NzbDrone.Web.Controllers
|
||||
{
|
||||
public class SearchHistoryController : Controller
|
||||
{
|
||||
private readonly SearchHistoryProvider _searchHistoryProvider;
|
||||
|
||||
public SearchHistoryController(SearchHistoryProvider searchHistoryProvider)
|
||||
{
|
||||
_searchHistoryProvider = searchHistoryProvider;
|
||||
}
|
||||
|
||||
public ActionResult Index()
|
||||
{
|
||||
var results = _searchHistoryProvider.AllSearchHistory();
|
||||
|
||||
var model = results.Select(s => new SearchHistoryModel
|
||||
{
|
||||
Id = s.Id,
|
||||
SearchTime = s.SearchTime.ToString(),
|
||||
DisplayName = GetDisplayName(s),
|
||||
ReportCount = s.TotalItems,
|
||||
Successful = s.SuccessfulCount > 0
|
||||
});
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
public ActionResult Details(int searchId)
|
||||
{
|
||||
var searchResult = _searchHistoryProvider.GetSearchHistory(searchId);
|
||||
var model = new SearchDetailsModel
|
||||
{
|
||||
Id = searchResult.Id,
|
||||
DisplayName = GetDisplayName(searchResult),
|
||||
SearchHistoryItems =
|
||||
searchResult.SearchHistoryItems.Select(s => new SearchItemModel
|
||||
{
|
||||
Id = s.Id,
|
||||
ReportTitle = s.ReportTitle,
|
||||
Indexer = s.Indexer,
|
||||
NzbUrl = s.NzbUrl,
|
||||
NzbInfoUrl = s.NzbInfoUrl,
|
||||
Success = s.Success,
|
||||
SearchError = s.SearchError.AddSpacesToEnum().Replace("None", "Grabbed"),
|
||||
Quality = s.Quality.ToString(),
|
||||
QualityInt = (int)s.Quality,
|
||||
Proper = s.Proper,
|
||||
Age = s.Age,
|
||||
Size = s.Size.ToBestFileSize(1),
|
||||
Language = s.Language.ToString()
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
public JsonResult ForceDownload(int id)
|
||||
{
|
||||
_searchHistoryProvider.ForceDownload(id);
|
||||
|
||||
return new JsonResult { Data = "ok", JsonRequestBehavior = JsonRequestBehavior.AllowGet };
|
||||
}
|
||||
|
||||
public string GetDisplayName(SearchHistory searchResult)
|
||||
{
|
||||
if (!searchResult.EpisodeNumber.HasValue)
|
||||
{
|
||||
return String.Format("{0} - Season {1}", searchResult.SeriesTitle, searchResult.SeasonNumber);
|
||||
}
|
||||
|
||||
string episodeString;
|
||||
|
||||
if (searchResult.IsDaily)
|
||||
episodeString = searchResult.AirDate.ToShortDateString().Replace('/', '-');
|
||||
|
||||
else
|
||||
episodeString = String.Format("S{0:00}E{1:00}", searchResult.SeasonNumber,
|
||||
searchResult.EpisodeNumber);
|
||||
|
||||
return String.Format("{0} - {1} - {2}", searchResult.SeriesTitle, episodeString, searchResult.EpisodeTitle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||
using System.Web.Mvc;
|
||||
using System.Web.Script.Serialization;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core;
|
||||
using NzbDrone.Core.Helpers;
|
||||
using NzbDrone.Core.Jobs;
|
||||
using NzbDrone.Core.Providers;
|
||||
|
@ -21,16 +22,18 @@ namespace NzbDrone.Web.Controllers
|
|||
private readonly ConfigProvider _configProvider;
|
||||
private readonly DiskProvider _diskProvider;
|
||||
private readonly BackupProvider _backupProvider;
|
||||
private readonly StatsProvider _statsProvider;
|
||||
|
||||
public SystemController(JobProvider jobProvider, IndexerProvider indexerProvider,
|
||||
ConfigProvider configProvider, DiskProvider diskProvider,
|
||||
BackupProvider backupProvider)
|
||||
BackupProvider backupProvider, StatsProvider statsProvider)
|
||||
{
|
||||
_jobProvider = jobProvider;
|
||||
_indexerProvider = indexerProvider;
|
||||
_configProvider = configProvider;
|
||||
_diskProvider = diskProvider;
|
||||
_backupProvider = backupProvider;
|
||||
_statsProvider = statsProvider;
|
||||
}
|
||||
|
||||
public ActionResult Jobs()
|
||||
|
@ -129,7 +132,7 @@ namespace NzbDrone.Web.Controllers
|
|||
foreach (var fileInfo in files)
|
||||
{
|
||||
fileResult += String.Format("<div><div style=\"width: 600px; display: inline-block;\">{0}</div><div style=\"display: inline-block;\">{1}</div></div>", fileInfo.Name,
|
||||
FileSizeFormatHelper.Format(fileInfo.Length, 1));
|
||||
fileInfo.Length.ToBestFileSize(1));
|
||||
}
|
||||
|
||||
model.Files = fileResult;
|
||||
|
@ -175,5 +178,12 @@ namespace NzbDrone.Web.Controllers
|
|||
|
||||
return File(fileInfo.FullName, "application/binary", fileInfo.Name);
|
||||
}
|
||||
|
||||
public ActionResult Stats()
|
||||
{
|
||||
var model = _statsProvider.GetStats();
|
||||
|
||||
return View(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using NzbDrone.Web.Models;
|
||||
|
||||
namespace NzbDrone.Web.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Model binder for datatables.js parameters a la http://geeksprogramando.blogspot.com/2011/02/jquery-datatables-plug-in-with-asp-mvc.html
|
||||
/// </summary>
|
||||
public class DataTablesModelBinder : IModelBinder
|
||||
{
|
||||
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
|
||||
{
|
||||
DataTablesParams obj = new DataTablesParams();
|
||||
var request = controllerContext.HttpContext.Request.Params;
|
||||
|
||||
obj.iDisplayStart = Convert.ToInt32(request["iDisplayStart"]);
|
||||
obj.iDisplayLength = Convert.ToInt32(request["iDisplayLength"]);
|
||||
obj.iColumns = Convert.ToInt32(request["iColumns"]);
|
||||
obj.sSearch = request["sSearch"];
|
||||
obj.bEscapeRegex = Convert.ToBoolean(request["bEscapeRegex"]);
|
||||
obj.iSortingCols = Convert.ToInt32(request["iSortingCols"]);
|
||||
obj.sEcho = int.Parse(request["sEcho"]);
|
||||
|
||||
for (int i = 0; i < obj.iColumns; i++)
|
||||
{
|
||||
obj.bSortable.Add(Convert.ToBoolean(request["bSortable_" + i]));
|
||||
obj.bSearchable.Add(Convert.ToBoolean(request["bSearchable_" + i]));
|
||||
obj.sSearchColumns.Add(request["sSearch_" + i]);
|
||||
obj.bEscapeRegexColumns.Add(Convert.ToBoolean(request["bEscapeRegex_" + i]));
|
||||
obj.iSortCol.Add(Convert.ToInt32(request["iSortCol_" + i]));
|
||||
obj.sSortDir.Add(request["sSortDir_" + i]);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace NzbDrone.Web.Models
|
||||
{
|
||||
public class DataTablesParams
|
||||
{
|
||||
public int iDisplayStart { get; set; }
|
||||
public int iDisplayLength { get; set; }
|
||||
public int iColumns { get; set; }
|
||||
public string sSearch { get; set; }
|
||||
public bool bEscapeRegex { get; set; }
|
||||
public int iSortingCols { get; set; }
|
||||
public int sEcho { get; set; }
|
||||
public List<bool> bSortable { get; set; }
|
||||
public List<bool> bSearchable { get; set; }
|
||||
public List<string> sSearchColumns { get; set; }
|
||||
public List<int> iSortCol { get; set; }
|
||||
public List<string> sSortDir { get; set; }
|
||||
public List<bool> bEscapeRegexColumns { get; set; }
|
||||
|
||||
public DataTablesParams()
|
||||
{
|
||||
bSortable = new List<bool>();
|
||||
bSearchable = new List<bool>();
|
||||
sSearchColumns = new List<string>();
|
||||
iSortCol = new List<int>();
|
||||
sSortDir = new List<string>();
|
||||
bEscapeRegexColumns = new List<bool>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Repository.Search;
|
||||
|
||||
namespace NzbDrone.Web.Models
|
||||
{
|
||||
public class SearchDetailsModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
public List<SearchItemModel> SearchHistoryItems { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace NzbDrone.Web.Models
|
||||
{
|
||||
public class SearchHistoryModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
public string SearchTime { get; set; }
|
||||
public int ReportCount { get; set; }
|
||||
public bool Successful { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
|
||||
namespace NzbDrone.Web.Models
|
||||
{
|
||||
public class SearchItemModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string ReportTitle { get; set; }
|
||||
public string Indexer { get; set; }
|
||||
public string NzbUrl { get; set; }
|
||||
public string NzbInfoUrl { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string SearchError { get; set; }
|
||||
public string Quality { get; set; }
|
||||
public int QualityInt { get; set; }
|
||||
public bool Proper { get; set; }
|
||||
public int Age { get; set; }
|
||||
public string Language { get; set; }
|
||||
public string Size { get; set; }
|
||||
public string Details { get; set; }
|
||||
}
|
||||
}
|
|
@ -23,6 +23,8 @@
|
|||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>4.0</OldToolsVersion>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -51,6 +53,10 @@
|
|||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="DataTables.Mvc.Core, Version=0.1.0.68, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\DataTables.Mvc.0.1.0.68\lib\DataTables.Mvc.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Dynamic">
|
||||
<HintPath>..\packages\DynamicQuery.1.0\lib\35\Dynamic.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -65,8 +71,9 @@
|
|||
<Reference Include="MvcMiniProfiler, Version=1.9.0.0, Culture=neutral, PublicKeyToken=b44f9351044011a3, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MiniProfiler.1.9\lib\net40\MvcMiniProfiler.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.0.8.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.0.8\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.4.5.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Ninject, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll</HintPath>
|
||||
|
@ -137,6 +144,8 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="App_Start\DataTablesMvc.cs" />
|
||||
<Compile Include="Controllers\SearchHistoryController.cs" />
|
||||
<Compile Include="Helpers\Validation\RequiredIfAnyAttribute.cs" />
|
||||
<Compile Include="Helpers\Validation\RequiredIfAttribute.cs" />
|
||||
<Content Include="Content\DataTables-1.9.0\media\css\jquery.dataTables.css" />
|
||||
|
@ -150,6 +159,7 @@
|
|||
<Content Include="Content\Images\AirsToday.png" />
|
||||
<Content Include="Content\Images\background.jpg" />
|
||||
<Content Include="Content\Images\blue.png" />
|
||||
<Content Include="Content\Images\False.png" />
|
||||
<Content Include="Content\Images\Gear.png" />
|
||||
<Content Include="Content\Images\green.png" />
|
||||
<Content Include="Content\Images\Indexers\FileSharingTalk.png" />
|
||||
|
@ -159,6 +169,7 @@
|
|||
<Content Include="Content\Images\Indexers\Nzbs.org.png" />
|
||||
<Content Include="Content\Images\Indexers\WomblesIndex.png" />
|
||||
<Content Include="Content\Images\logo.png" />
|
||||
<Content Include="Content\Images\logo_small.png" />
|
||||
<Content Include="Content\Images\pause.png" />
|
||||
<Content Include="Content\Images\play.png" />
|
||||
<Content Include="Content\Images\red.png" />
|
||||
|
@ -166,6 +177,7 @@
|
|||
<Content Include="Content\Images\settings.png" />
|
||||
<Content Include="Content\Images\stop.png" />
|
||||
<Content Include="Content\Images\thetvdb.png" />
|
||||
<Content Include="Content\Images\True.png" />
|
||||
<Content Include="Content\Images\yellow.png" />
|
||||
<Content Include="Content\IndexerSettings.css" />
|
||||
<Content Include="Content\jQueryUI\images\ui-bg_diagonals-thick_30_a32d00_40x40.png" />
|
||||
|
@ -204,7 +216,6 @@
|
|||
<Compile Include="App_Start\EntityFramework.SqlServerCompact.cs" />
|
||||
<Compile Include="App_Start\Logging.cs" />
|
||||
<Compile Include="App_Start\MiniProfiler.cs" />
|
||||
<Compile Include="App_Start\RegisterDataTablesModelBinder.cs" />
|
||||
<Compile Include="Filters\JsonErrorFilter.cs" />
|
||||
<Compile Include="Controllers\CommandController.cs" />
|
||||
<Compile Include="Controllers\DirectoryController.cs" />
|
||||
|
@ -224,7 +235,6 @@
|
|||
<Compile Include="Global.asax.cs">
|
||||
<DependentUpon>Global.asax</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Helpers\DataTablesModelBinder.cs" />
|
||||
<Compile Include="Helpers\HtmlIncludeExtentions.cs" />
|
||||
<Compile Include="Helpers\LinkHelper.cs" />
|
||||
<Compile Include="Helpers\ProfilerHelper.cs" />
|
||||
|
@ -232,10 +242,12 @@
|
|||
<Compile Include="Helpers\DescriptionExtension.cs" />
|
||||
<Compile Include="Helpers\HtmlPrefixScopeExtensions.cs" />
|
||||
<Compile Include="Helpers\IsCurrentActionHelper.cs" />
|
||||
<Compile Include="Models\DataTablesParams.cs" />
|
||||
<Compile Include="Models\SearchDetailsModel.cs" />
|
||||
<Compile Include="Models\JobModel.cs" />
|
||||
<Compile Include="Models\LogModel.cs" />
|
||||
<Compile Include="Models\PostUpgradeModel.cs" />
|
||||
<Compile Include="Models\SearchItemModel.cs" />
|
||||
<Compile Include="Models\SearchHistoryModel.cs" />
|
||||
<Compile Include="Models\UpcomingEpisodesModel.cs" />
|
||||
<Compile Include="Models\SeasonModel.cs" />
|
||||
<Compile Include="Models\SeriesDetailsModel.cs" />
|
||||
|
@ -279,7 +291,6 @@
|
|||
<Content Include="Content\Images\Indexers\Unknown.png" />
|
||||
<Content Include="Content\Images\Plus.png" />
|
||||
<Content Include="Content\Images\VideoFolder.png" />
|
||||
<Content Include="Content\Images\X.png" />
|
||||
<Content Include="Content\Settings.css" />
|
||||
<Content Include="Content\NzbDrone.css" />
|
||||
<Content Include="Content\Images\XbmcNotification.png" />
|
||||
|
@ -518,6 +529,15 @@
|
|||
<Content Include="Views\Shared\NoSeriesBanner.cshtml" />
|
||||
<Content Include="Views\Update\Post.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\SearchHistory\Index.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\SearchHistory\Details.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\System\Stats.cshtml" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
|
@ -550,4 +570,5 @@
|
|||
if not exist "$(TargetDir)x86" md "$(TargetDir)x86"
|
||||
xcopy /s /y "$(SolutionDir)packages\SqlServerCompact.4.0.8482.1\NativeBinaries\x86\*.*" "$(TargetDir)x86"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||
</Project>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue