Fixed notification issues

Added basic support for file scan
Major redactor of ReportTitle/File parsing
Updated Ninject/Ninject.MVC
Removed dependency from Microsoft.Web.Administration
reactored Episode repository structure
This commit is contained in:
Keivan 2010-10-20 18:49:23 -07:00
parent 41d9b0364f
commit c8a8fb4d62
57 changed files with 5569 additions and 320 deletions

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
IIS configuration sections. IIS configuration sections.
@ -17,9 +17,7 @@
%SYSTEMDRIVE% - The drive letter of %IIS_BIN% %SYSTEMDRIVE% - The drive letter of %IIS_BIN%
--> -->
<configuration> <configuration>
<!-- <!--
The <configSections> section controls the registration of sections. The <configSections> section controls the registration of sections.
@ -58,7 +56,6 @@
<section name="sites" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> <section name="sites" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
<section name="webLimits" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> <section name="webLimits" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
</sectionGroup> </sectionGroup>
<sectionGroup name="system.webServer"> <sectionGroup name="system.webServer">
<section name="asp" overrideModeDefault="Deny" /> <section name="asp" overrideModeDefault="Deny" />
<section name="caching" overrideModeDefault="Allow" /> <section name="caching" overrideModeDefault="Allow" />
@ -117,7 +114,6 @@
</sectionGroup> </sectionGroup>
</sectionGroup> </sectionGroup>
</configSections> </configSections>
<configProtectedData> <configProtectedData>
<providers> <providers>
<add name="IISWASOnlyRsaProvider" type="" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="iisWasKey" cspProviderName="" useMachineContainer="true" useOAEP="false" /> <add name="IISWASOnlyRsaProvider" type="" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="iisWasKey" cspProviderName="" useMachineContainer="true" useOAEP="false" />
@ -125,9 +121,7 @@
<add name="IISWASOnlyAesProvider" type="Microsoft.ApplicationHost.AesProtectedConfigurationProvider" description="Uses an AES session key to encrypt and decrypt" keyContainerName="iisWasKey" cspProviderName="" useOAEP="false" useMachineContainer="true" sessionKey="AQIAAA5mAAAApAAA4WoiRJ8KHwzAG8AgejPxEOO4/2Vhkolbwo/8gZeNdUDSD36m55hWv4uC9tr/MlKdnwRLL0NhT50Gccyftqz5xTZ0dg5FtvQhTw/he1NwexTKbV+I4Zrd+sZUqHZTsr7JiEr6OHGXL70qoISW5G2m9U8wKT3caPiDPNj2aAaYPLo=" /> <add name="IISWASOnlyAesProvider" type="Microsoft.ApplicationHost.AesProtectedConfigurationProvider" description="Uses an AES session key to encrypt and decrypt" keyContainerName="iisWasKey" cspProviderName="" useOAEP="false" useMachineContainer="true" sessionKey="AQIAAA5mAAAApAAA4WoiRJ8KHwzAG8AgejPxEOO4/2Vhkolbwo/8gZeNdUDSD36m55hWv4uC9tr/MlKdnwRLL0NhT50Gccyftqz5xTZ0dg5FtvQhTw/he1NwexTKbV+I4Zrd+sZUqHZTsr7JiEr6OHGXL70qoISW5G2m9U8wKT3caPiDPNj2aAaYPLo=" />
</providers> </providers>
</configProtectedData> </configProtectedData>
<system.applicationHost> <system.applicationHost>
<applicationPools> <applicationPools>
<!-- <add name="Clr4IntegratedAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" /> <!-- <add name="Clr4IntegratedAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
<add name="Clr4ClassicAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" /> <add name="Clr4ClassicAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
@ -139,7 +133,6 @@
<processModel /> <processModel />
</applicationPoolDefaults> </applicationPoolDefaults>
</applicationPools> </applicationPools>
<!-- <!--
The <listenerAdapters> section defines the protocols with which the The <listenerAdapters> section defines the protocols with which the
@ -149,14 +142,13 @@
<listenerAdapters> <listenerAdapters>
<add name="http" /> <add name="http" />
</listenerAdapters> </listenerAdapters>
<sites> <sites>
<site name="NZBDrone" id="1" serverAutoStart="true"> <site name="NZBDrone" id="1" serverAutoStart="true">
<application path="/"> <application path="/">
<virtualDirectory path="/" physicalPath="%NZBDRONE_PATH%\NZBDrone.Web" /> <virtualDirectory path="/" physicalPath="%NZBDRONE_PATH%\NZBDrone.Web" />
</application> </application>
<bindings> <bindings>
<binding protocol="http" bindingInformation="*:8981:" /> <binding protocol="http" bindingInformation="*:8989:" />
</bindings> </bindings>
</site> </site>
<siteDefaults> <siteDefaults>
@ -166,25 +158,16 @@
<applicationDefaults applicationPool="IISExpressAppPool" /> <applicationDefaults applicationPool="IISExpressAppPool" />
<virtualDirectoryDefaults allowSubDirConfig="true" /> <virtualDirectoryDefaults allowSubDirConfig="true" />
</sites> </sites>
<webLimits /> <webLimits />
</system.applicationHost> </system.applicationHost>
<system.webServer> <system.webServer>
<serverRuntime /> <serverRuntime />
<asp scriptErrorSentToBrowser="true"> <asp scriptErrorSentToBrowser="true">
<cache diskTemplateCacheDirectory="%TEMP%\iisexpress\ASP Compiled Templates" /> <cache diskTemplateCacheDirectory="%TEMP%\iisexpress\ASP Compiled Templates" />
<limits /> <limits />
</asp> </asp>
<caching enabled="true" enableKernelCache="true"></caching>
<caching enabled="true" enableKernelCache="true">
</caching>
<cgi /> <cgi />
<defaultDocument enabled="true"> <defaultDocument enabled="true">
<files> <files>
<add value="Default.htm" /> <add value="Default.htm" />
@ -194,11 +177,8 @@
<add value="default.aspx" /> <add value="default.aspx" />
</files> </files>
</defaultDocument> </defaultDocument>
<directoryBrowse enabled="false" /> <directoryBrowse enabled="false" />
<fastCgi /> <fastCgi />
<!-- <!--
The <globalModules> section defines all native-code modules. The <globalModules> section defines all native-code modules.
@ -244,7 +224,6 @@
<add name="ManagedEngine" image="%windir%\Microsoft.NET\Framework\v2.0.50727\webengine.dll" preCondition="integratedMode,runtimeVersionv2.0,bitness32" /> <add name="ManagedEngine" image="%windir%\Microsoft.NET\Framework\v2.0.50727\webengine.dll" preCondition="integratedMode,runtimeVersionv2.0,bitness32" />
<add name="ManagedEngineV4.0_32bit" image="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness32" /> <add name="ManagedEngineV4.0_32bit" image="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness32" />
</globalModules> </globalModules>
<httpCompression directory="%TEMP%\iisexpress\IIS Temporary Compressed Files"> <httpCompression directory="%TEMP%\iisexpress\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%IIS_BIN%\gzip.dll" /> <scheme name="gzip" dll="%IIS_BIN%\gzip.dll" />
<dynamicTypes> <dynamicTypes>
@ -262,7 +241,6 @@
<add mimeType="*/*" enabled="false" /> <add mimeType="*/*" enabled="false" />
</staticTypes> </staticTypes>
</httpCompression> </httpCompression>
<httpErrors lockAttributes="allowAbsolutePathsWhenDelegated,defaultPath"> <httpErrors lockAttributes="allowAbsolutePathsWhenDelegated,defaultPath">
<error statusCode="401" prefixLanguageFilePath="%IIS_BIN%\custerr" path="401.htm" /> <error statusCode="401" prefixLanguageFilePath="%IIS_BIN%\custerr" path="401.htm" />
<error statusCode="403" prefixLanguageFilePath="%IIS_BIN%\custerr" path="403.htm" /> <error statusCode="403" prefixLanguageFilePath="%IIS_BIN%\custerr" path="403.htm" />
@ -274,9 +252,7 @@
<error statusCode="501" prefixLanguageFilePath="%IIS_BIN%\custerr" path="501.htm" /> <error statusCode="501" prefixLanguageFilePath="%IIS_BIN%\custerr" path="501.htm" />
<error statusCode="502" prefixLanguageFilePath="%IIS_BIN%\custerr" path="502.htm" /> <error statusCode="502" prefixLanguageFilePath="%IIS_BIN%\custerr" path="502.htm" />
</httpErrors> </httpErrors>
<httpLogging dontLog="false" /> <httpLogging dontLog="false" />
<httpProtocol> <httpProtocol>
<customHeaders> <customHeaders>
<clear /> <clear />
@ -286,60 +262,39 @@
<clear /> <clear />
</redirectHeaders> </redirectHeaders>
</httpProtocol> </httpProtocol>
<httpRedirect enabled="false" /> <httpRedirect enabled="false" />
<httpTracing></httpTracing>
<httpTracing>
</httpTracing>
<isapiFilters> <isapiFilters>
<filter name="ASP.Net_2.0.50727.0" path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="bitness32,runtimeVersionv2.0" /> <filter name="ASP.Net_2.0.50727.0" path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="bitness32,runtimeVersionv2.0" />
<filter name="ASP.Net_2.0_for_v1.1" path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="runtimeVersionv1.1" /> <filter name="ASP.Net_2.0_for_v1.1" path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="runtimeVersionv1.1" />
<filter name="ASP.Net_4.0_32bit" path="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_filter.dll" enableCache="true" preCondition="bitness32,runtimeVersionv4.0" /> <filter name="ASP.Net_4.0_32bit" path="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_filter.dll" enableCache="true" preCondition="bitness32,runtimeVersionv4.0" />
</isapiFilters> </isapiFilters>
<odbcLogging /> <odbcLogging />
<security> <security>
<access sslFlags="None" /> <access sslFlags="None" />
<applicationDependencies> <applicationDependencies>
<application name="Active Server Pages" groupId="ASP" /> <application name="Active Server Pages" groupId="ASP" />
</applicationDependencies> </applicationDependencies>
<authentication> <authentication>
<anonymousAuthentication enabled="true" userName="" /> <anonymousAuthentication enabled="true" userName="" />
<basicAuthentication enabled="false" /> <basicAuthentication enabled="false" />
<clientCertificateMappingAuthentication enabled="false" /> <clientCertificateMappingAuthentication enabled="false" />
<digestAuthentication enabled="false" /> <digestAuthentication enabled="false" />
<iisClientCertificateMappingAuthentication enabled="false"></iisClientCertificateMappingAuthentication>
<iisClientCertificateMappingAuthentication enabled="false">
</iisClientCertificateMappingAuthentication>
<windowsAuthentication enabled="false"> <windowsAuthentication enabled="false">
<providers> <providers>
<add value="Negotiate" /> <add value="Negotiate" />
<add value="NTLM" /> <add value="NTLM" />
</providers> </providers>
</windowsAuthentication> </windowsAuthentication>
</authentication> </authentication>
<authorization> <authorization>
<add accessType="Allow" users="*" /> <add accessType="Allow" users="*" />
</authorization> </authorization>
<ipSecurity allowUnlisted="true" /> <ipSecurity allowUnlisted="true" />
<isapiCgiRestriction notListedIsapisAllowed="true" notListedCgisAllowed="true"> <isapiCgiRestriction notListedIsapisAllowed="true" notListedCgisAllowed="true">
<add path="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" allowed="true" groupId="ASP.NET_v4.0" description="ASP.NET_v4.0" /> <add path="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" allowed="true" groupId="ASP.NET_v4.0" description="ASP.NET_v4.0" />
</isapiCgiRestriction> </isapiCgiRestriction>
<requestFiltering> <requestFiltering>
<fileExtensions allowUnlisted="true" applyToWebDAV="true"> <fileExtensions allowUnlisted="true" applyToWebDAV="true">
<add fileExtension=".asa" allowed="false" /> <add fileExtension=".asa" allowed="false" />
@ -399,11 +354,8 @@
<add segment="App_Browsers" /> <add segment="App_Browsers" />
</hiddenSegments> </hiddenSegments>
</requestFiltering> </requestFiltering>
</security> </security>
<serverSideInclude ssiExecDisable="false" /> <serverSideInclude ssiExecDisable="false" />
<staticContent lockAttributes="isDocFooterFileName"> <staticContent lockAttributes="isDocFooterFileName">
<mimeMap fileExtension=".323" mimeType="text/h323" /> <mimeMap fileExtension=".323" mimeType="text/h323" />
<mimeMap fileExtension=".aaf" mimeType="application/octet-stream" /> <mimeMap fileExtension=".aaf" mimeType="application/octet-stream" />
@ -752,9 +704,7 @@
<mimeMap fileExtension=".z" mimeType="application/x-compress" /> <mimeMap fileExtension=".z" mimeType="application/x-compress" />
<mimeMap fileExtension=".zip" mimeType="application/x-zip-compressed" /> <mimeMap fileExtension=".zip" mimeType="application/x-zip-compressed" />
</staticContent> </staticContent>
<tracing> <tracing>
<traceProviderDefinitions> <traceProviderDefinitions>
<add name="WWW Server" guid="{3a2a4e84-4c21-4981-ae10-3fda0d9b0f83}"> <add name="WWW Server" guid="{3a2a4e84-4c21-4981-ae10-3fda0d9b0f83}">
<areas> <areas>
@ -791,7 +741,6 @@
</areas> </areas>
</add> </add>
</traceProviderDefinitions> </traceProviderDefinitions>
<traceFailedRequests> <traceFailedRequests>
<add path="*"> <add path="*">
<traceAreas> <traceAreas>
@ -803,11 +752,8 @@
<failureDefinitions statusCodes="200-999" /> <failureDefinitions statusCodes="200-999" />
</add> </add>
</traceFailedRequests> </traceFailedRequests>
</tracing> </tracing>
<urlCompression /> <urlCompression />
<validation /> <validation />
<webdav> <webdav>
<globalSettings> <globalSettings>
@ -817,14 +763,12 @@
<lockStores> <lockStores>
<add name="webdav_simple_lock" image="%IIS_BIN%\webdav_simple_lock.dll" image32="%windir%\syswow64\inetsrv\webdav_simple_lock.dll" /> <add name="webdav_simple_lock" image="%IIS_BIN%\webdav_simple_lock.dll" image32="%windir%\syswow64\inetsrv\webdav_simple_lock.dll" />
</lockStores> </lockStores>
</globalSettings> </globalSettings>
<authoring> <authoring>
<locks enabled="true" lockStore="webdav_simple_lock" /> <locks enabled="true" lockStore="webdav_simple_lock" />
</authoring> </authoring>
<authoringRules /> <authoringRules />
</webdav> </webdav>
</system.webServer> </system.webServer>
<location path="" overrideMode="Allow"> <location path="" overrideMode="Allow">
<system.webServer> <system.webServer>

View File

@ -5,8 +5,8 @@ using Gallio.Framework;
using MbUnit.Framework; using MbUnit.Framework;
using MbUnit.Framework.ContractVerifiers; using MbUnit.Framework.ContractVerifiers;
using Moq; using Moq;
using NzbDrone.Core.Entities;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using SubSonic.Repository; using SubSonic.Repository;
namespace NzbDrone.Core.Test namespace NzbDrone.Core.Test

View File

@ -21,11 +21,11 @@ namespace NzbDrone.Core.Test
public class EpisodeProviderTest public class EpisodeProviderTest
{ {
[Test] [Test]
public void BulkAddSpeedTest() public void RefreshEpisodeInfo()
{ {
//Arrange //Arrange
int seriesId = 71663; int seriesId = 71663;
int episodeCount = 500; int episodeCount = 10;
var fakeEpisodes = Builder<TvdbSeries>.CreateNew().With( var fakeEpisodes = Builder<TvdbSeries>.CreateNew().With(
c => c.Episodes = c => c.Episodes =
new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount). new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount).

Binary file not shown.

View File

@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Gallio.Framework;
using MbUnit.Framework;
using MbUnit.Framework.ContractVerifiers;
using Moq;
using Ninject;
using Ninject.Moq;
using NzbDrone.Core.Entities;
using NzbDrone.Core.Entities.Episode;
using NzbDrone.Core.Entities.Quality;
using NzbDrone.Core.Providers;
using SubSonic.Repository;
namespace NzbDrone.Core.Test
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class MediaFileProviderTests
{
[Test]
public void scan_test()
{
//Arrange
var repository = new Mock<IRepository>();
repository.Setup(c => c.Update(It.IsAny<EpisodeInfo>())).Verifiable();
var diskProvider = MockLib.GetStandardDisk(1, 2);
var kernel = new MockingKernel();
kernel.Bind<IDiskProvider>().ToConstant(diskProvider);
kernel.Bind<IRepository>().ToConstant(repository.Object);
kernel.Bind<IMediaFileProvider>().To<MediaFileProvider>();
var fakeSeries = new Series()
{
Path = MockLib.StandardSeries[0]
};
//Act
kernel.Get<IMediaFileProvider>().Scan(fakeSeries);
//Assert
repository.Verify(c => c.Update(It.IsAny<EpisodeInfo>()), Times.Exactly(1 * 2));
}
[Test]
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1)]
[Row("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", 1, 3)]
[Row("Chuck.4x05.HDTV.XviD-LOL", 4, 5)]
[Row("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", 3, 6)]
[Row("Degrassi.S10E27.WS.DSR.XviD-2HD", 10, 27)]
public void episode_parse(string path, int season, int episode)
{
var result = Parser.ParseBasicEpisode(path);
Assert.AreEqual(season, result.SeasonNumber);
Assert.AreEqual(episode, result.EpisodeNumber);
}
[Test]
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.DVD)]
[Row("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", QualityTypes.Bluray)]
[Row("Two.and.a.Half.Men.S08E05.720p.HDTV.X264-DIMENSION", QualityTypes.HDTV)]
[Row("Chuck.S04E05.HDTV.XviD-LOL", QualityTypes.TV)]
[Row("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", QualityTypes.DVD)]
[Row("Degrassi.S10E27.WS.DSR.XviD-2HD", QualityTypes.TV)]
[Row("Sonny.With.a.Chance.S02E15.720p.WEB-DL.DD5.1.H.264-SURFER", QualityTypes.WEBDL)]
[Row("Sonny.With.a.Chance.S02E15.720p", QualityTypes.HDTV)]
[Row("Sonny.With.a.Chance.S02E15.mkv", QualityTypes.HDTV)]
[Row("Sonny.With.a.Chance.S02E15.avi", QualityTypes.TV)]
[Row("Sonny.With.a.Chance.S02E15.xvid", QualityTypes.TV)]
[Row("Sonny.With.a.Chance.S02E15.divx", QualityTypes.TV)]
[Row("Sonny.With.a.Chance.S02E15", QualityTypes.Unknown)]
public void quality_parse(string path, object quality)
{
var result = Parser.ParseQuality(path);
Assert.AreEqual(quality, result);
}
[Test]
[Timeout(2)]
public void quality_parse()
{
var sw = Stopwatch.StartNew();
var name = "WEEDSawdawdadawdawd\\awdawdawdadadad.mkv";
var quality = QualityTypes.HDTV;
for (int i = 0; i < 100000; i++)
{
Assert.AreEqual(quality, Parser.ParseQuality(name));
}
Console.WriteLine(sw.Elapsed.ToString());
}
}
}

View File

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Text;
using Gallio.Framework;
using MbUnit.Framework;
using MbUnit.Framework.ContractVerifiers;
using Moq;
using Ninject;
using Ninject.Moq;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using SubSonic.Repository;
namespace NzbDrone.Core.Test
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class MediaFileProviderTests
{
[Test]
public void scan_test()
{
//Arrange
var repository = new Mock<IRepository>();
repository.Setup(c => c.Update(It.IsAny<Episode>())).Verifiable();
var diskProvider = MockLib.GetStandardDisk(1, 2);
var kernel = new MockingKernel();
kernel.Bind<IDiskProvider>().ToConstant(diskProvider);
kernel.Bind<IRepository>().ToConstant(repository.Object);
kernel.Bind<IMediaFileProvider>().To<MediaFileProvider>();
var fakeSeries = new Series()
{
Path = MockLib.StandardSeries[0]
};
//Act
kernel.Get<IMediaFileProvider>().Scan(fakeSeries);
//Assert
repository.Verify(c => c.Update(It.IsAny<Episode>()), Times.Exactly(1 * 2));
}
[Test]
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1)]
[Row("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", 1, 3)]
[Row("Chuck.4x05.HDTV.XviD-LOL", 4, 5)]
[Row("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", 3, 6)]
[Row("Degrassi.S10E27.WS.DSR.XviD-2HD", 10, 27)]
public void episode_parse(string path, int season, int episode)
{
var result = Parser.ParseEpisodeInfo(path);
Assert.Count(1, result);
Assert.AreEqual(season, result[0].SeasonNumber);
Assert.AreEqual(episode, result[0].EpisodeNumber);
}
[Test]
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.DVD)]
[Row("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", QualityTypes.Bluray)]
[Row("Two.and.a.Half.Men.S08E05.720p.HDTV.X264-DIMENSION", QualityTypes.HDTV)]
[Row("Chuck.S04E05.HDTV.XviD-LOL", QualityTypes.TV)]
[Row("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", QualityTypes.DVD)]
[Row("Degrassi.S10E27.WS.DSR.XviD-2HD", QualityTypes.TV)]
[Row("Sonny.With.a.Chance.S02E15.720p.WEB-DL.DD5.1.H.264-SURFER", QualityTypes.WEBDL)]
[Row("Sonny.With.a.Chance.S02E15.720p", QualityTypes.HDTV)]
[Row("Sonny.With.a.Chance.S02E15.mkv", QualityTypes.HDTV)]
[Row("Sonny.With.a.Chance.S02E15.avi", QualityTypes.TV)]
[Row("Sonny.With.a.Chance.S02E15.xvid", QualityTypes.TV)]
[Row("Sonny.With.a.Chance.S02E15.divx", QualityTypes.TV)]
[Row("Sonny.With.a.Chance.S02E15", QualityTypes.Unknown)]
public void quality_parse(string path, object quality)
{
var result = Parser.ParseQuality(path);
Assert.AreEqual(quality, result);
}
}
}

View File

@ -1,9 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using FizzWare.NBuilder;
using Moq; using Moq;
using NLog; using NLog;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
@ -50,11 +51,28 @@ namespace NzbDrone.Core.Test
} }
} }
public static IDiskProvider GetStandardDisk() public static IDiskProvider GetStandardDisk(int seasons, int episodes)
{ {
var mock = new Mock<IDiskProvider>(); var mock = new Mock<IDiskProvider>();
mock.Setup(c => c.GetDirectories(It.IsAny<String>())).Returns(StandardSeries); mock.Setup(c => c.GetDirectories(It.IsAny<String>())).Returns(StandardSeries);
mock.Setup(c => c.Exists(It.Is<String>(d => StandardSeries.Contains(d)))).Returns(true); mock.Setup(c => c.Exists(It.Is<String>(d => StandardSeries.Contains(d)))).Returns(true);
foreach (var series in StandardSeries)
{
var file = new List<String>();
for (int s = 0; s < seasons; s++)
{
for (int e = 0; e < episodes; e++)
{
file.Add(String.Format("{0}\\Seasons {1}\\myepname.S{1:00}E{2:00}.avi", series, s, e));
}
}
string series1 = series;
mock.Setup(c => c.GetFiles(series1, "*.avi", SearchOption.AllDirectories)).Returns(file.ToArray());
}
return mock.Object; return mock.Object;
} }
} }

View File

@ -31,16 +31,20 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Accessibility">
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="Castle.Core, Version=2.5.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="FizzWare.NBuilder, Version=2.1.9.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12, processorArchitecture=MSIL"> <Reference Include="FizzWare.NBuilder, Version=2.1.9.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>Libs\FizzWare.NBuilder.dll</HintPath> <HintPath>Libs\FizzWare.NBuilder.dll</HintPath>
</Reference> </Reference>
<Reference Include="Gallio, Version=3.2.0.0, Culture=neutral, PublicKeyToken=eb9cfa67ee6ab36e, processorArchitecture=MSIL" /> <Reference Include="Gallio, Version=3.2.0.0, Culture=neutral, PublicKeyToken=eb9cfa67ee6ab36e, processorArchitecture=MSIL" />
<Reference Include="MbUnit, Version=3.2.0.0, Culture=neutral, PublicKeyToken=eb9cfa67ee6ab36e, processorArchitecture=MSIL" /> <Reference Include="MbUnit, Version=3.2.0.0, Culture=neutral, PublicKeyToken=eb9cfa67ee6ab36e, processorArchitecture=MSIL" />
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL"> <Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL" />
<SpecificVersion>False</SpecificVersion>
<HintPath>Moq\Moq.dll</HintPath>
</Reference>
<Reference Include="Ninject, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL"> <Reference Include="Ninject, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\Ninject.dll</HintPath> <HintPath>..\NzbDrone.Core\Libraries\Ninject.dll</HintPath>
@ -62,6 +66,7 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="MediaFileProviderTests.cs" />
<Compile Include="DbConfigControllerTest.cs" /> <Compile Include="DbConfigControllerTest.cs" />
<Compile Include="EpisodeProviderTest.cs" /> <Compile Include="EpisodeProviderTest.cs" />
<Compile Include="Fixtures.cs" /> <Compile Include="Fixtures.cs" />
@ -84,8 +89,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Libs\FizzWare.NBuilder.dll" /> <Content Include="Libs\FizzWare.NBuilder.dll" />
<Content Include="Libs\Moq.dll" />
<Content Include="Libs\Moq.xml" />
<Content Include="Files\Queue.xml"> <Content Include="Files\Queue.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -95,6 +98,9 @@
<Content Include="Files\QueueError.xml"> <Content Include="Files\QueueError.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Libs\Moq.dll" />
<Content Include="Libs\Moq.pdb" />
<Content Include="Libs\Moq.xml" />
<Content Include="Libs\System.Data.SQLite.DLL"> <Content Include="Libs\System.Data.SQLite.DLL">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using MbUnit.Framework; using MbUnit.Framework;
using NzbDrone.Core.Entities.Quality; using NzbDrone.Core.Repository.Quality;
namespace NzbDrone.Core.Test namespace NzbDrone.Core.Test
{ {
@ -23,7 +23,7 @@ namespace NzbDrone.Core.Test
var repo = MockLib.GetEmptyRepository(); var repo = MockLib.GetEmptyRepository();
var testProfile = new QualityProfile var testProfile = new QualityProfile
{ {
Cutoff = QualityTypes.SDTV, Cutoff = QualityTypes.TV,
Allowed = new List<QualityTypes>() { QualityTypes.HDTV, QualityTypes.DVD }, Allowed = new List<QualityTypes>() { QualityTypes.HDTV, QualityTypes.DVD },
}; };

View File

@ -6,8 +6,8 @@ using FizzWare.NBuilder;
using Gallio.Framework; using Gallio.Framework;
using MbUnit.Framework; using MbUnit.Framework;
using MbUnit.Framework.ContractVerifiers; using MbUnit.Framework.ContractVerifiers;
using NzbDrone.Core.Entities; using NzbDrone.Core.Model;
using NzbDrone.Core.Entities.Episode; using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Test namespace NzbDrone.Core.Test
{ {
@ -20,7 +20,7 @@ namespace NzbDrone.Core.Test
{ {
//Arrange //Arrange
var fakeSeries = Builder<Series>.CreateNew().With(s => s.SeriesId = 69).Build(); var fakeSeries = Builder<Series>.CreateNew().With(s => s.SeriesId = 69).Build();
var fakeEpisode = Builder<EpisodeInfo>.CreateNew().With(c => c.SeriesId = 69).Build(); var fakeEpisode = Builder<Episode>.CreateNew().With(c => c.SeriesId = 69).Build();
//Act //Act
var repo = MockLib.GetEmptyRepository(); var repo = MockLib.GetEmptyRepository();
@ -55,5 +55,12 @@ namespace NzbDrone.Core.Test
Assert.IsNotEmpty(allSeries); Assert.IsNotEmpty(allSeries);
Assert.AreEqual(tvdbId, allSeries.First().SeriesId); Assert.AreEqual(tvdbId, allSeries.First().SeriesId);
} }
[Test]
public void enteties_toString()
{
Console.WriteLine(new Episode().ToString());
Console.WriteLine(new EpisodeModel().ToString());
}
} }
} }

View File

@ -10,8 +10,8 @@ using MbUnit.Framework.ContractVerifiers;
using Moq; using Moq;
using Ninject; using Ninject;
using Ninject.Moq; using Ninject.Moq;
using NzbDrone.Core.Entities;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using SubSonic.Repository; using SubSonic.Repository;
using TvdbLib.Data; using TvdbLib.Data;
using System.Linq; using System.Linq;
@ -59,10 +59,11 @@ namespace NzbDrone.Core.Test
[Row(new object[] { "Van.Duin.Op.Zn.Best.S02E05.DUTCH.WS.PDTV.XViD-DiFFERENT", "Van Duin Op Zn Best" })] [Row(new object[] { "Van.Duin.Op.Zn.Best.S02E05.DUTCH.WS.PDTV.XViD-DiFFERENT", "Van Duin Op Zn Best" })]
[Row(new object[] { "Dollhouse.S02E06.The.Left.Hand.720p.BluRay.x264-SiNNERS", "Dollhouse" })] [Row(new object[] { "Dollhouse.S02E06.The.Left.Hand.720p.BluRay.x264-SiNNERS", "Dollhouse" })]
[Row(new object[] { "Heroes.S02.COMPLETE.German.PROPER.DVDRip.XviD-Prim3time", "Heroes" })] [Row(new object[] { "Heroes.S02.COMPLETE.German.PROPER.DVDRip.XviD-Prim3time", "Heroes" })]
[Ignore("should be updated to validate agains a remote episode instance rather than just the title string")]
public void Test_Parse_Success(string postTitle, string title) public void Test_Parse_Success(string postTitle, string title)
{ {
var result = SeriesProvider.ParseTitle(postTitle); var result = Parser.ParseEpisodeInfo(postTitle);
Assert.AreEqual(title, result, postTitle); //Assert.AreEqual(title, result, postTitle);
} }
[Test] [Test]
@ -73,7 +74,8 @@ namespace NzbDrone.Core.Test
kernel.Bind<ISeriesProvider>().To<SeriesProvider>(); kernel.Bind<ISeriesProvider>().To<SeriesProvider>();
kernel.Bind<IDiskProvider>().ToConstant(MockLib.GetStandardDisk()); kernel.Bind<IDiskProvider>().ToConstant(MockLib.GetStandardDisk(0, 0));
kernel.Bind<IConfigProvider>().ToConstant(MockLib.StandardConfig);
var seriesController = kernel.Get<ISeriesProvider>(); var seriesController = kernel.Get<ISeriesProvider>();

View File

@ -5,10 +5,9 @@ using System.Web;
using Ninject; using Ninject;
using NLog.Config; using NLog.Config;
using NLog.Targets; using NLog.Targets;
using NzbDrone.Core.Entities;
using NzbDrone.Core.Entities.Episode;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Fakes; using NzbDrone.Core.Providers.Fakes;
using NzbDrone.Core.Repository;
using SubSonic.DataProviders; using SubSonic.DataProviders;
using SubSonic.Repository; using SubSonic.Repository;
using NLog; using NLog;
@ -76,7 +75,7 @@ namespace NzbDrone.Core
private static void ForceMigration(IRepository repository) private static void ForceMigration(IRepository repository)
{ {
repository.GetPaged<Series>(0, 1); repository.GetPaged<Series>(0, 1);
repository.GetPaged<EpisodeInfo>(0, 1); repository.GetPaged<Episode>(0, 1);
} }

View File

@ -1,14 +0,0 @@
using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Entities.Episode
{
public class BasicEpisode
{
public virtual int SeriesId { get; set; }
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
public virtual Series Series { get; private set; }
}
}

View File

@ -1,12 +0,0 @@
using System.ServiceModel.Syndication;
using NzbDrone.Core.Entities.Quality;
namespace NzbDrone.Core.Entities.Episode
{
public class RemoteEpisode : BasicEpisode
{
public QualityTypes Quality { get; set; }
public SyndicationItem Feed { get; set; }
public bool Proper { get; set; }
}
}

View File

@ -1,9 +0,0 @@
namespace NzbDrone.Core.Entities.Notification
{
public enum NotificationStatus
{
InProgress = 0,
Completed = 1,
Failed = 2
}
}

View File

@ -1,9 +0,0 @@
namespace NzbDrone.Core.Entities.Notification
{
public enum NotificationType
{
Info = 0,
Warrning = 1,
Error = 2
}
}

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
using NzbDrone.Core.Repository.Quality;
using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Model
{
public class EpisodeModel
{
public string SeriesTitle { get; set; }
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
public QualityTypes Quality { get; set; }
public string Path { get; set; }
public long Size { get; set; }
public bool Proper { get; set; }
}
}

View File

@ -0,0 +1,12 @@
using NzbDrone.Core.Repository.Quality;
using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Model
{
internal struct EpisodeParseResult
{
internal string SeriesTitle { get; set; }
internal int SeasonNumber { get; set; }
internal int EpisodeNumber { get; set; }
}
}

View File

@ -1,6 +1,6 @@
using System; using System;
namespace NzbDrone.Core.Entities.Notification namespace NzbDrone.Core.Model.Notification
{ {
public class BasicNotification public class BasicNotification
{ {
@ -17,7 +17,7 @@ namespace NzbDrone.Core.Entities.Notification
public String Title { get; set; } public String Title { get; set; }
public NotificationType Type { get; set; } public BasicNotificationType Type { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether or not this message should be automatically dismissed after a period of time. /// Gets or sets a value indicating whether or not this message should be automatically dismissed after a period of time.

View File

@ -0,0 +1,9 @@
namespace NzbDrone.Core.Model.Notification
{
public enum BasicNotificationType
{
Info = 0,
Warrning = 1,
Error = 2
}
}

View File

@ -1,7 +1,7 @@
using System; using System;
using NLog; using NLog;
namespace NzbDrone.Core.Entities.Notification namespace NzbDrone.Core.Model.Notification
{ {
public class ProgressNotification : IDisposable public class ProgressNotification : IDisposable
{ {
@ -63,14 +63,14 @@ namespace NzbDrone.Core.Entities.Notification
/// Gets or sets the status. /// Gets or sets the status.
/// </summary> /// </summary>
/// <value>The status.</value> /// <value>The status.</value>
public NotificationStatus Status { get; set; } public ProgressNotificationStatus Status { get; set; }
public void Dispose() public void Dispose()
{ {
if (Status == NotificationStatus.InProgress) if (Status == ProgressNotificationStatus.InProgress)
{ {
Logger.Error("Progress notification '{0}' was unexpectedly abandoned. ID:{1} Status:{2} CurrentStatus:{3} PercentComplete:{4}", Title, Id, Status, CurrentStatus, PercentComplete); Logger.Warn("Progress notification '{0}' was unexpectedly abandoned. ID:{1} Status:{2} CurrentStatus:{3} PercentComplete:{4}", Title, Id, Status, CurrentStatus, PercentComplete);
Status = NotificationStatus.Failed; Status = ProgressNotificationStatus.Failed;
} }
} }
} }

View File

@ -0,0 +1,9 @@
namespace NzbDrone.Core.Model.Notification
{
public enum ProgressNotificationStatus
{
InProgress = 0,
Completed = 1,
Failed = 2
}
}

View File

@ -121,6 +121,7 @@
<StartupObject /> <StartupObject />
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Castle.Core, Version=2.5.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL" />
<Reference Include="Exceptioneer.WindowsFormsClient, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Exceptioneer.WindowsFormsClient, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath> <HintPath>Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
@ -149,20 +150,25 @@
<Reference Include="UPnP, Version=1.0.3932.37442, Culture=neutral, processorArchitecture=MSIL" /> <Reference Include="UPnP, Version=1.0.3932.37442, Culture=neutral, processorArchitecture=MSIL" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Entities\MediaFile.cs" /> <Compile Include="Model\EpisodeParseResult.cs" />
<Compile Include="Entities\Notification\BasicNotification.cs" /> <Compile Include="Model\EpisodeModel.cs" />
<Compile Include="Entities\Notification\NotificationStatus.cs" /> <Compile Include="Repository\EpisodeFile.cs" />
<Compile Include="Entities\Notification\NotificationType.cs" /> <Compile Include="Model\Notification\BasicNotification.cs" />
<Compile Include="Model\Notification\ProgressNotificationStatus.cs" />
<Compile Include="Model\Notification\BasicNotificationType.cs" />
<Compile Include="Instrumentation.cs" /> <Compile Include="Instrumentation.cs" />
<Compile Include="Parser.cs" />
<Compile Include="Providers\Fakes\FakeNotificationProvider.cs" /> <Compile Include="Providers\Fakes\FakeNotificationProvider.cs" />
<Compile Include="Providers\IMediaFileProvider.cs" />
<Compile Include="Providers\INotificationProvider.cs" /> <Compile Include="Providers\INotificationProvider.cs" />
<Compile Include="Providers\IMediaDiscoveryProvider.cs" /> <Compile Include="Providers\IMediaDiscoveryProvider.cs" />
<Compile Include="Providers\IMediaProvider.cs" /> <Compile Include="Providers\IMediaProvider.cs" />
<Compile Include="Providers\ISyncProvider.cs" /> <Compile Include="Providers\ISyncProvider.cs" />
<Compile Include="Providers\MediaDiscoveryProvider.cs" /> <Compile Include="Providers\MediaDiscoveryProvider.cs" />
<Compile Include="Providers\MediaFileProvider.cs" />
<Compile Include="Providers\SyncProvider.cs" /> <Compile Include="Providers\SyncProvider.cs" />
<Compile Include="Providers\XBMCMediaProvider.cs" /> <Compile Include="Providers\XBMCMediaProvider.cs" />
<Compile Include="Entities\Notification\ProgressNotification.cs" /> <Compile Include="Model\Notification\ProgressNotification.cs" />
<Compile Include="Providers\NotificationProvider.cs" /> <Compile Include="Providers\NotificationProvider.cs" />
<Compile Include="Providers\ConfigProvider.cs" /> <Compile Include="Providers\ConfigProvider.cs" />
<Compile Include="Providers\EpisodeProvider.cs" /> <Compile Include="Providers\EpisodeProvider.cs" />
@ -175,15 +181,13 @@
<Compile Include="Providers\ITvDbProvider.cs" /> <Compile Include="Providers\ITvDbProvider.cs" />
<Compile Include="Providers\SabProvider.cs" /> <Compile Include="Providers\SabProvider.cs" />
<Compile Include="Providers\SeasonProvider.cs" /> <Compile Include="Providers\SeasonProvider.cs" />
<Compile Include="Entities\Episode\RemoteEpisode.cs" /> <Compile Include="Repository\Episode.cs" />
<Compile Include="Entities\Episode\EpisodeInfo.cs" /> <Compile Include="Repository\Quality\AllowedQuality.cs" />
<Compile Include="Entities\Quality\AllowedQuality.cs" /> <Compile Include="Repository\Config.cs" />
<Compile Include="Entities\Config.cs" /> <Compile Include="Repository\Quality\QualityProfile.cs" />
<Compile Include="Entities\Quality\QualityProfile.cs" /> <Compile Include="Repository\Season.cs" />
<Compile Include="Entities\Season.cs" /> <Compile Include="Repository\Quality\QualityTypes.cs" />
<Compile Include="Entities\Episode\BasicEpisode.cs" /> <Compile Include="Repository\Series.cs" />
<Compile Include="Entities\Quality\QualityTypes.cs" />
<Compile Include="Entities\Series.cs" />
<Compile Include="CentralDispatch.cs" /> <Compile Include="CentralDispatch.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Providers\DiskProvider.cs" /> <Compile Include="Providers\DiskProvider.cs" />
@ -215,6 +219,9 @@
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Libraries\Castle.Core.dll" />
<Content Include="Libraries\Castle.Core.pdb" />
<Content Include="Libraries\Castle.Core.xml" />
<Content Include="Libraries\Exceptioneer.WindowsFormsClient.dll" /> <Content Include="Libraries\Exceptioneer.WindowsFormsClient.dll" />
<Content Include="Libraries\Ninject.dll" /> <Content Include="Libraries\Ninject.dll" />
<Content Include="Libraries\Ninject.xml" /> <Content Include="Libraries\Ninject.xml" />

135
NzbDrone.Core/Parser.cs Normal file
View File

@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository.Quality;
namespace NzbDrone.Core
{
internal static class Parser
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static readonly Regex[] ReportTitleRegex = new[]
{
new Regex(@"(?<title>.+?)?\W(S)?(?<season>\d+)\w(?<episode>\d+)\W", RegexOptions.IgnoreCase | RegexOptions.Compiled)
};
private static readonly Regex NormalizeRegex = new Regex(@"((\s|^)the(\s|$))|((\s|^)and(\s|$))|[^a-z]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
/// <summary>
/// Parses a post title into list of episodes it contains
/// </summary>
/// <param name="title">Title of the report</param>
/// <returns>List of episodes contained to the post</returns>
internal static List<EpisodeParseResult> ParseEpisodeInfo(string title)
{
Logger.Trace("Parsing string '{0}'", title);
var result = new List<EpisodeParseResult>();
foreach (var regex in ReportTitleRegex)
{
var match = regex.Matches(title);
if (match.Count != 0)
{
var seriesName = NormalizeTitle(match[0].Groups["title"].Value);
foreach (Match matchGroup in match)
{
var tuple = new EpisodeParseResult
{
SeriesTitle = seriesName,
SeasonNumber = Convert.ToInt32(matchGroup.Groups["season"].Value),
EpisodeNumber = Convert.ToInt32(matchGroup.Groups["episode"].Value)
};
result.Add(tuple);
Logger.Trace("Episode Parsed. {0}", tuple);
}
}
}
Logger.Trace("{0} episodes parsed from string.", result.Count);
return result;
}
/// <summary>
/// Parses proper status out of a report title
/// </summary>
/// <param name="title">Title of the report</param>
/// <returns></returns>
internal static bool ParseProper(string title)
{
return title.ToLower().Contains("proper");
}
internal static QualityTypes ParseQuality(string name)
{
Logger.Trace("Trying to parse quality for {0}", name);
var result = QualityTypes.Unknown;
name = name.ToLowerInvariant();
if (name.Contains("dvd"))
return QualityTypes.DVD;
if (name.Contains("xvid") || name.Contains("divx"))
{
if (name.Contains("bluray") || name.Contains("bdrip"))
{
return QualityTypes.DVD;
}
return QualityTypes.TV;
}
if (name.Contains("bluray") || name.Contains("bdrip"))
return QualityTypes.Bluray;
if (name.Contains("web-dl"))
return QualityTypes.WEBDL;
if (name.Contains("x264") || name.Contains("h264") || name.Contains("720p"))
return QualityTypes.HDTV;
//Based on extension
if (result == QualityTypes.Unknown)
{
switch (new FileInfo(name).Extension.ToLower())
{
case ".avi":
case ".xvid":
case ".wmv":
{
result = QualityTypes.TV;
break;
}
case ".mkv":
{
result = QualityTypes.HDTV;
break;
}
}
}
Logger.Trace("Quality Parsed:{0} Title:", result, name);
return result;
}
/// <summary>
/// Normalizes the title. removing all non-word characters as well as common tokens
/// such as 'the' and 'and'
/// </summary>
/// <param name="title">title</param>
/// <returns></returns>
internal static string NormalizeTitle(string title)
{
return NormalizeRegex.Replace(title, String.Empty).ToLower();
}
}
}

View File

@ -13,6 +13,7 @@
// * // *
// */ // */
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
@ -50,3 +51,4 @@ using System.Runtime.InteropServices;
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.2.0.*")] [assembly: AssemblyVersion("0.2.0.*")]
[assembly: InternalsVisibleTo("NzbDrone.Core.Test")]

View File

@ -1,6 +1,6 @@
using System; using System;
using NLog; using NLog;
using NzbDrone.Core.Entities; using NzbDrone.Core.Repository;
using SubSonic.Repository; using SubSonic.Repository;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers

View File

@ -17,6 +17,11 @@ namespace NzbDrone.Core.Providers
return Directory.GetDirectories(path); return Directory.GetDirectories(path);
} }
public string[] GetFiles(string path, string pattern, SearchOption searchOption)
{
return Directory.GetFiles(path, pattern, searchOption);
}
public String CreateDirectory(string path) public String CreateDirectory(string path)
{ {
return Directory.CreateDirectory(path).FullName; return Directory.CreateDirectory(path).FullName;

View File

@ -3,8 +3,8 @@ using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using NLog; using NLog;
using NzbDrone.Core.Entities.Episode; using NzbDrone.Core.Model;
using NzbDrone.Core.Entities.Quality; using NzbDrone.Core.Repository;
using SubSonic.Repository; using SubSonic.Repository;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers
@ -12,21 +12,6 @@ namespace NzbDrone.Core.Providers
public class EpisodeProvider : IEpisodeProvider public class EpisodeProvider : IEpisodeProvider
{ {
//TODO: Remove parsing of the series name, it should be done in series provider //TODO: Remove parsing of the series name, it should be done in series provider
private static readonly Regex ParseRegex = new Regex(@"(?<showName>.*)
(?:
s(?<seasonNumber>\d+)e(?<episodeNumber>\d+)-?e(?<episodeNumber2>\d+)
| s(?<seasonNumber>\d+)e(?<episodeNumber>\d+)
| (?<seasonNumber>\d+)x(?<episodeNumber>\d+)
| (?<airDate>\d{4}.\d{2}.\d{2})
)
(?:
(?<episodeName>.*?)
(?<release>
(?:hdtv|pdtv|xvid|ws|720p|x264|bdrip|dvdrip|dsr|proper)
.*)
| (?<episodeName>.*)
)", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);
private readonly IRepository _sonicRepo; private readonly IRepository _sonicRepo;
private readonly ISeriesProvider _series; private readonly ISeriesProvider _series;
@ -43,35 +28,17 @@ namespace NzbDrone.Core.Providers
_seasons = seasonProvider; _seasons = seasonProvider;
} }
public EpisodeInfo GetEpisode(long id) public Episode GetEpisode(long id)
{ {
return _sonicRepo.Single<EpisodeInfo>(e => e.EpisodeId == id); return _sonicRepo.Single<Episode>(e => e.EpisodeId == id);
} }
public void UpdateEpisode(EpisodeInfo episode) public IList<Episode> GetEpisodeBySeries(long seriesId)
{ {
var episodeToUpdate = _sonicRepo.Single<EpisodeInfo>(e => e.EpisodeId == episode.EpisodeId); return _sonicRepo.Find<Episode>(e => e.SeriesId == seriesId);
episodeToUpdate.AirDate = episode.AirDate;
episodeToUpdate.Overview = episode.Overview;
episodeToUpdate.Title = episode.Title;
episodeToUpdate.EpisodeNumber = episode.EpisodeNumber;
episodeToUpdate.SeasonNumber = episode.SeasonNumber;
_sonicRepo.Update<EpisodeInfo>(episodeToUpdate);
} }
public IList<EpisodeInfo> GetEpisodesBySeason(long seasonId) public String GetSabTitle(Episode episode)
{
return _sonicRepo.Find<EpisodeInfo>(e => e.SeasonId == seasonId);
}
public IList<EpisodeInfo> GetEpisodeBySeries(long seriesId)
{
return _sonicRepo.Find<EpisodeInfo>(e => e.SeriesId == seriesId);
}
public String GetSabTitle(BasicEpisode episode)
{ {
var series = _series.GetSeries(episode.SeriesId); var series = _series.GetSeries(episode.SeriesId);
if (series == null) throw new ArgumentException("Unknown series. ID: " + episode.SeriesId); if (series == null) throw new ArgumentException("Unknown series. ID: " + episode.SeriesId);
@ -85,7 +52,7 @@ namespace NzbDrone.Core.Providers
/// </summary> /// </summary>
/// <param name="episode">Episode that needs to be checked</param> /// <param name="episode">Episode that needs to be checked</param>
/// <returns></returns> /// <returns></returns>
public bool IsNeeded(RemoteEpisode episode) public bool IsNeeded(EpisodeModel episode)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -97,8 +64,8 @@ namespace NzbDrone.Core.Providers
int failCount = 0; int failCount = 0;
var targetSeries = _tvDb.GetSeries(seriesId, true); var targetSeries = _tvDb.GetSeries(seriesId, true);
var updateList = new List<EpisodeInfo>(); var updateList = new List<Episode>();
var newList = new List<EpisodeInfo>(); var newList = new List<Episode>();
Logger.Debug("Updating season info for series:{0}", seriesId); Logger.Debug("Updating season info for series:{0}", seriesId);
targetSeries.Episodes.Select(e => new { e.SeasonId, e.SeasonNumber }) targetSeries.Episodes.Select(e => new { e.SeasonId, e.SeasonNumber })
@ -110,7 +77,7 @@ namespace NzbDrone.Core.Providers
try try
{ {
Logger.Debug("Updating info for series:{0} - episode:{1}", seriesId, episode.Id); Logger.Debug("Updating info for series:{0} - episode:{1}", seriesId, episode.Id);
var newEpisode = new EpisodeInfo() var newEpisode = new Episode()
{ {
AirDate = episode.FirstAired, AirDate = episode.FirstAired,
EpisodeId = episode.Id, EpisodeId = episode.Id,
@ -123,7 +90,7 @@ namespace NzbDrone.Core.Providers
Title = episode.EpisodeName Title = episode.EpisodeName
}; };
if (_sonicRepo.Exists<EpisodeInfo>(e => e.EpisodeId == newEpisode.EpisodeId)) if (_sonicRepo.Exists<Episode>(e => e.EpisodeId == newEpisode.EpisodeId))
{ {
updateList.Add(newEpisode); updateList.Add(newEpisode);
} }
@ -146,38 +113,5 @@ namespace NzbDrone.Core.Providers
Logger.Info("Finished episode refresh for series:{0}. Success:{1} - Fail:{2} ", seriesId, successCount, failCount); Logger.Info("Finished episode refresh for series:{0}. Success:{1} - Fail:{2} ", seriesId, successCount, failCount);
} }
/// <summary>
/// Parses a post title into list of episode objects
/// </summary>
/// <param name="title">Title of the report</param>
/// <returns>List of episodes relating to the post</returns>
public static List<RemoteEpisode> Parse(string title)
{
var match = ParseRegex.Match(title);
if (!match.Success)
throw new ArgumentException(String.Format("Title doesn't match any know patterns. [{0}]", title));
var result = new List<RemoteEpisode>();
result.Add(new RemoteEpisode { EpisodeNumber = Convert.ToInt32(match.Groups["episodeNumber"].Value) });
if (match.Groups["episodeNumber2"].Success)
{
result.Add(new RemoteEpisode { EpisodeNumber = Convert.ToInt32(match.Groups["episodeNumber2"].Value) });
}
foreach (var ep in result)
{
ep.SeasonNumber = Convert.ToInt32(match.Groups["seasonNumber"].Value);
ep.Proper = title.Contains("PROPER");
ep.Quality = QualityTypes.Unknown;
}
return result;
}
} }
} }

View File

@ -1,6 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.Entities.Notification; using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Providers.Fakes namespace NzbDrone.Core.Providers.Fakes
{ {
@ -33,8 +33,8 @@ namespace NzbDrone.Core.Providers.Fakes
get get
{ {
fakeNotification.Status = NotificationStatus.InProgress; fakeNotification.Status = ProgressNotificationStatus.InProgress;
fakeNotification.Status = NotificationStatus.InProgress; fakeNotification.Status = ProgressNotificationStatus.InProgress;
fakeNotification2.CurrentStatus = DateTime.UtcNow.ToString(); fakeNotification2.CurrentStatus = DateTime.UtcNow.ToString();
fakeNotification.CurrentStatus = DateTime.Now.ToString(); fakeNotification.CurrentStatus = DateTime.Now.ToString();
return new List<ProgressNotification> { fakeNotification }; return new List<ProgressNotification> { fakeNotification };

View File

@ -1,4 +1,5 @@
using System; using System;
using System.IO;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers
{ {
@ -7,5 +8,6 @@ namespace NzbDrone.Core.Providers
bool Exists(string path); bool Exists(string path);
string[] GetDirectories(string path); string[] GetDirectories(string path);
String CreateDirectory(string path); String CreateDirectory(string path);
string[] GetFiles(string path, string pattern, SearchOption searchOption);
} }
} }

View File

@ -1,23 +1,22 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.Entities.Episode; using NzbDrone.Core.Model;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers
{ {
public interface IEpisodeProvider public interface IEpisodeProvider
{ {
EpisodeInfo GetEpisode(long id); Episode GetEpisode(long id);
void UpdateEpisode(EpisodeInfo episode); IList<Episode> GetEpisodeBySeries(long seriesId);
IList<EpisodeInfo> GetEpisodesBySeason(long seasonId); String GetSabTitle(Episode episode);
IList<EpisodeInfo> GetEpisodeBySeries(long seriesId);
String GetSabTitle(BasicEpisode episode);
/// <summary> /// <summary>
/// Comprehensive check on whether or not this episode is needed. /// Comprehensive check on whether or not this episode is needed.
/// </summary> /// </summary>
/// <param name="episode">Episode that needs to be checked</param> /// <param name="episode">Episode that needs to be checked</param>
/// <returns></returns> /// <returns></returns>
bool IsNeeded(RemoteEpisode episode); bool IsNeeded(EpisodeModel episode);
void RefreshEpisodeInfo(int seriesId); void RefreshEpisodeInfo(int seriesId);
} }

View File

@ -0,0 +1,13 @@
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers
{
public interface IMediaFileProvider
{
/// <summary>
/// Scans the specified series folder for media files
/// </summary>
/// <param name="series">The series to be scanned</param>
void Scan(Series series);
}
}

View File

@ -1,6 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.Entities.Notification; using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers
{ {

View File

@ -1,5 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.Entities; using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers
{ {

View File

@ -1,7 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NzbDrone.Core.Entities; using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository;
using TvdbLib.Data; using TvdbLib.Data;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers
{
public class MediaFileProvider : IMediaFileProvider
{
private readonly IDiskProvider _diskProvider;
private readonly IEpisodeProvider _episodeProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static readonly string[] MediaExtentions = new[] { "*.mkv", "*.avi", "*.wmv" };
public MediaFileProvider(IDiskProvider diskProvider, IEpisodeProvider episodeProvider)
{
_diskProvider = diskProvider;
_episodeProvider = episodeProvider;
}
/// <summary>
/// Scans the specified series folder for media files
/// </summary>
/// <param name="series">The series to be scanned</param>
public void Scan(Series series)
{
var mediaFileList = new List<string>();
Logger.Info("Scanning '{0}'", series.Path);
foreach (var ext in MediaExtentions)
{
mediaFileList.AddRange(_diskProvider.GetFiles(series.Path, ext, SearchOption.AllDirectories));
}
Logger.Info("{0} media files were found", mediaFileList.Count);
foreach (var file in mediaFileList)
{
var episode = Parser.ParseEpisodeInfo(file);
}
}
}
}

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.Entities.Notification; using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers
{ {
@ -28,7 +28,7 @@ namespace NzbDrone.Core.Providers
public List<ProgressNotification> GetProgressNotifications public List<ProgressNotification> GetProgressNotifications
{ {
get { return new List<ProgressNotification>(_progressNotification.Values.Where(p => p.Status == NotificationStatus.InProgress)); } get { return new List<ProgressNotification>(_progressNotification.Values.Where(p => p.Status == ProgressNotificationStatus.InProgress)); }
} }
public void Dismiss(Guid notificationId) public void Dismiss(Guid notificationId)

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NLog; using NLog;
using NzbDrone.Core.Entities; using NzbDrone.Core.Repository;
using SubSonic.Repository; using SubSonic.Repository;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers

View File

@ -4,8 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using NLog; using NLog;
using NzbDrone.Core.Entities; using NzbDrone.Core.Repository;
using NzbDrone.Core.Entities.Notification;
using SubSonic.Repository; using SubSonic.Repository;
using TvdbLib.Data; using TvdbLib.Data;
@ -16,30 +15,12 @@ namespace NzbDrone.Core.Providers
//TODO: Remove parsing of rest of tv show info we just need the show name //TODO: Remove parsing of rest of tv show info we just need the show name
//Trims all white spaces and separators from the end of the title. //Trims all white spaces and separators from the end of the title.
private static readonly Regex CleanTitleRegex = new Regex(@"[\s.][^a-z]*$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex ParseRegex = new Regex(@"(?<showName>.*)
(?:
s(?<seasonNumber>\d+)e(?<episodeNumber>\d+)-?e(?<episodeNumber2>\d+)
| s(?<seasonNumber>\d+)e(?<episodeNumber>\d+)
| (?<seasonNumber>\d+)x(?<episodeNumber>\d+)
| (?<airDate>\d{4}.\d{2}.\d{2})
)
(?:
(?<episodeName>.*?)
(?<release>
(?:hdtv|pdtv|xvid|ws|720p|x264|bdrip|dvdrip|dsr|proper)
.*)
| (?<episodeName>.*)
)", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);
private readonly IConfigProvider _config; private readonly IConfigProvider _config;
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly IRepository _sonioRepo; private readonly IRepository _sonioRepo;
private readonly ITvDbProvider _tvDb; private readonly ITvDbProvider _tvDb;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static readonly Regex CleanUpRegex = new Regex(@"((\s|^)the(\s|$))|((\s|^)and(\s|$))|[^a-z]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public SeriesProvider(IDiskProvider diskProvider, IConfigProvider configProvider, IRepository dataRepository, ITvDbProvider tvDbProvider) public SeriesProvider(IDiskProvider diskProvider, IConfigProvider configProvider, IRepository dataRepository, ITvDbProvider tvDbProvider)
{ {
@ -71,21 +52,6 @@ namespace NzbDrone.Core.Providers
return _sonioRepo.Exists<Series>(c => c.SeriesId == id && c.Monitored); return _sonioRepo.Exists<Series>(c => c.SeriesId == id && c.Monitored);
} }
/// <summary>
/// Parses series name out of a post title
/// </summary>
/// <param name="postTitle">Title of the report</param>
/// <returns>Name series this report belongs to</returns>
public static string ParseTitle(string postTitle)
{
var match = ParseRegex.Match(postTitle);
if (!match.Success)
throw new ArgumentException(String.Format("Title doesn't match any know patterns. [{0}]", postTitle));
return CleanTitleRegex.Replace(match.Groups["showName"].Value, String.Empty).Replace(".", " ");
}
public List<String> GetUnmappedFolders() public List<String> GetUnmappedFolders()
{ {
Logger.Debug("Generating list of unmapped folders"); Logger.Debug("Generating list of unmapped folders");
@ -130,7 +96,7 @@ namespace NzbDrone.Core.Providers
repoSeries.Status = series.Status; repoSeries.Status = series.Status;
repoSeries.Language = series.Language != null ? series.Language.Abbriviation : string.Empty; repoSeries.Language = series.Language != null ? series.Language.Abbriviation : string.Empty;
repoSeries.Path = path; repoSeries.Path = path;
repoSeries.CleanTitle = CleanUpRegex.Replace(series.SeriesName, "").ToLower(); repoSeries.CleanTitle = Parser.NormalizeTitle(series.SeriesName);
_sonioRepo.Add(repoSeries); _sonioRepo.Add(repoSeries);
} }

View File

@ -6,7 +6,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using NLog; using NLog;
using NzbDrone.Core.Entities.Notification; using NzbDrone.Core.Model.Notification;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers
{ {
@ -58,7 +58,6 @@ namespace NzbDrone.Core.Providers
{ {
_notificationProvider.Register(_seriesSyncNotification); _notificationProvider.Register(_seriesSyncNotification);
_seriesSyncNotification.CurrentStatus = "Analysing Folder"; _seriesSyncNotification.CurrentStatus = "Analysing Folder";
Thread.Sleep(20000);
var unmappedFolders = _seriesProvider.GetUnmappedFolders(); var unmappedFolders = _seriesProvider.GetUnmappedFolders();
_seriesSyncNotification.ProgressMax = unmappedFolders.Count; _seriesSyncNotification.ProgressMax = unmappedFolders.Count;
@ -100,7 +99,7 @@ namespace NzbDrone.Core.Providers
_seriesSyncNotification.CurrentStatus = "Series Scan Completed"; _seriesSyncNotification.CurrentStatus = "Series Scan Completed";
Logger.Info("Series folders scan has successfully completed."); Logger.Info("Series folders scan has successfully completed.");
Thread.Sleep(3000); Thread.Sleep(3000);
_seriesSyncNotification.Status = NotificationStatus.Completed; _seriesSyncNotification.Status = ProgressNotificationStatus.Completed;
} }
} }
catch (Exception e) catch (Exception e)

View File

@ -1,6 +1,6 @@
using SubSonic.SqlGeneration.Schema; using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Entities namespace NzbDrone.Core.Repository
{ {
[SubSonicTableNameOverride("Config")] [SubSonicTableNameOverride("Config")]
public class Config public class Config

View File

@ -1,25 +1,29 @@
using System; using System;
using SubSonic.SqlGeneration.Schema; using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Entities.Episode namespace NzbDrone.Core.Repository
{ {
[SubSonicTableNameOverride("EpisodeInfo")] public class Episode
public class EpisodeInfo : BasicEpisode
{ {
[SubSonicPrimaryKey(false)] [SubSonicPrimaryKey(false)]
public virtual int EpisodeId { get; set; } public virtual int EpisodeId { get; set; }
public virtual int SeriesId { get; set; }
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
public int SeasonId { get; set; } public int SeasonId { get; set; }
public string Title { get; set; } public string Title { get; set; }
public DateTime AirDate { get; set; } public DateTime AirDate { get; set; }
[SubSonicLongString]
public string Overview { get; set; } public string Overview { get; set; }
public string Language { get; set; } public string Language { get; set; }
public int MediaFileId { get; set; }
[SubSonicNullString]
public string Path { get; set; }
public long? Size { get; set; }
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)] [SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
public virtual Season Season { get; set; } public virtual Season Season { get; set; }
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)] [SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
public virtual MediaFile File { get; set; } public virtual Series Series { get; private set; }
} }
} }

View File

@ -1,15 +1,21 @@
using NzbDrone.Core.Entities.Quality; using System;
using NzbDrone.Core.Repository.Quality;
using SubSonic.SqlGeneration.Schema; using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Entities namespace NzbDrone.Core.Repository
{ {
public class MediaFile class EpisodeFile
{ {
[SubSonicPrimaryKey] [SubSonicPrimaryKey]
public virtual int FileId { get; set; } public virtual int FileId { get; set; }
public int EpisodeId { get; set; }
public string Path { get; set; } public string Path { get; set; }
public QualityTypes Quality { get; set; } public QualityTypes Quality { get; set; }
public long Size { get; set; }
public bool Proper { get; set; } public bool Proper { get; set; }
public long Size { get; set; }
public DateTime DateAdded { get; set; }
[SubSonicToOneRelation]
public virtual Episode Episode { get; set; }
} }
} }

View File

@ -1,4 +1,4 @@
namespace NzbDrone.Core.Entities.Quality namespace NzbDrone.Core.Repository.Quality
{ {
public class AllowedQuality public class AllowedQuality
{ {

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using SubSonic.SqlGeneration.Schema; using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Entities.Quality namespace NzbDrone.Core.Repository.Quality
{ {
public class QualityProfile public class QualityProfile
{ {

View File

@ -1,4 +1,4 @@
namespace NzbDrone.Core.Entities.Quality namespace NzbDrone.Core.Repository.Quality
{ {
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
/// <summary> /// <summary>
@ -13,7 +13,7 @@ namespace NzbDrone.Core.Entities.Quality
/// <summary> /// <summary>
/// SD File (Source could be HD) /// SD File (Source could be HD)
/// </summary> /// </summary>
SDTV = 1, TV = 1,
/// <summary> /// <summary>
/// SD File (DVD Source) /// SD File (DVD Source)
/// </summary> /// </summary>

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using SubSonic.SqlGeneration.Schema; using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Entities namespace NzbDrone.Core.Repository
{ {
public class Season public class Season
{ {
@ -13,7 +13,7 @@ namespace NzbDrone.Core.Entities
public string Folder { get; set; } public string Folder { get; set; }
[SubSonicToManyRelation] [SubSonicToManyRelation]
public virtual List<Episode.BasicEpisode> Episodes { get; private set; } public virtual List<Episode> Episodes { get; private set; }
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)] [SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
public virtual Series Series { get; private set; } public virtual Series Series { get; private set; }

View File

@ -1,9 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.Entities.Episode;
using SubSonic.SqlGeneration.Schema; using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Entities namespace NzbDrone.Core.Repository
{ {
public class Series public class Series
{ {
@ -14,6 +13,7 @@ namespace NzbDrone.Core.Entities
public string CleanTitle { get; set; } public string CleanTitle { get; set; }
[SubSonicNullString]
public string Status { get; set; } public string Status { get; set; }
[SubSonicLongString] [SubSonicLongString]
@ -33,7 +33,7 @@ namespace NzbDrone.Core.Entities
public virtual List<Season> Seasons { get; private set; } public virtual List<Season> Seasons { get; private set; }
[SubSonicToManyRelation] [SubSonicToManyRelation]
public virtual List<EpisodeInfo> Episodes { get; private set; } public virtual List<Episode> Episodes { get; private set; }
} }

View File

@ -33,7 +33,7 @@ $(function () {
//set the message text //set the message text
$("#msgText").text(sMsg); $("#msgText").text(sMsg);
//show the message //show the message
$('#msgBox').slideUp(speed, null); $('#msgBox').slideDown(speed, null);
} }
function CloseMsg() { function CloseMsg() {

View File

@ -1,4 +1,4 @@
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NzbDrone.Core.Entities.Series>" %> <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NzbDrone.Core.Repository.Series>" %>
<%@ Import Namespace="Telerik.Web.Mvc.UI" %> <%@ Import Namespace="Telerik.Web.Mvc.UI" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">

View File

@ -1,4 +1,4 @@
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<NzbDrone.Core.Entities.Series>>" %> <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<NzbDrone.Core.Repository.Series>>" %>
<%@ Import Namespace="Telerik.Web.Mvc.UI" %> <%@ Import Namespace="Telerik.Web.Mvc.UI" %>
<%@ Import Namespace="System.Globalization" %> <%@ Import Namespace="System.Globalization" %>

View File

@ -1,10 +1,9 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Xml.Linq;
using Microsoft.Web.Administration; using System.Xml.XPath;
using NLog; using NLog;
namespace NzbDrone namespace NzbDrone
@ -46,7 +45,16 @@ namespace NzbDrone
//Set Variables for the config file. //Set Variables for the config file.
Environment.SetEnvironmentVariable("NZBDRONE_PATH", Config.ProjectRoot); Environment.SetEnvironmentVariable("NZBDRONE_PATH", Config.ProjectRoot);
try
{
UpdateIISConfig(); UpdateIISConfig();
}
catch (Exception e)
{
Logger.Error("An error has occured while trying to update the config file.", e);
}
Logger.Info("Starting process. [{0}]", IISProcess.StartInfo.FileName); Logger.Info("Starting process. [{0}]", IISProcess.StartInfo.FileName);
IISProcess.Start(); IISProcess.Start();
@ -101,10 +109,22 @@ namespace NzbDrone
private static void UpdateIISConfig() private static void UpdateIISConfig()
{ {
string configPath = Path.Combine(IISFolder, @"AppServer\applicationhost.config");
Logger.Info(@"Server configuration file: {0}", configPath);
Logger.Info(@"Configuring server to: [http://localhost:{0}]", Config.Port); Logger.Info(@"Configuring server to: [http://localhost:{0}]", Config.Port);
var serverManager = new ServerManager(Path.Combine(IISFolder, @"AppServer\applicationhost.config"));
serverManager.Sites["NZBDrone"].Bindings[0].BindingInformation = string.Format("*:{0}:", Config.Port); var configXml = XDocument.Load(configPath);
serverManager.CommitChanges();
var bindings = configXml.XPathSelectElement("configuration/system.applicationHost/sites").Elements("site").Where(d => d.Attribute("name").Value.ToLowerInvariant() == "nzbdrone").First().Element("bindings");
bindings.Descendants().Remove();
bindings.Add(
new XElement("binding",
new XAttribute("protocol", "http"),
new XAttribute("bindingInformation", String.Format("*:{0}:", Config.Port))
));
configXml.Save(configPath);
} }
private static string CleanPath(string path) private static string CleanPath(string path)

View File

@ -50,6 +50,9 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Accessibility">
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="EnvDTE, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <Reference Include="EnvDTE, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<EmbedInteropTypes>True</EmbedInteropTypes> <EmbedInteropTypes>True</EmbedInteropTypes>
</Reference> </Reference>
@ -60,9 +63,6 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath> <HintPath>..\NzbDrone.Core\Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Web.Administration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <Reference Include="NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\NLog.dll</HintPath> <HintPath>..\NzbDrone.Core\Libraries\NLog.dll</HintPath>

View File

@ -4,6 +4,6 @@
<supportedRuntime version="v4.0" /> <supportedRuntime version="v4.0" />
</startup> </startup>
<appSettings> <appSettings>
<add key="port" value="8981" /> <add key="port" value="8989" />
</appSettings> </appSettings>
</configuration> </configuration>