Merge branch 'xem' into 'master'

Conflicts:
	NzbDrone.Common/DiskProvider.cs
	NzbDrone.Core.Test/ProviderTests/DiskScanProviderTests/ImportFileFixture.cs
	NzbDrone.Core/Providers/DecisionEngine/CustomStartDateSpecification.cs
	NzbDrone.Core/Providers/DiskScanProvider.cs
	NzbDrone.Core/Providers/DownloadProvider.cs
pull/4/head
Mark McDowall 12 years ago
commit 5bbe310af5

Binary file not shown.

Binary file not shown.

@ -175,6 +175,18 @@ namespace NzbDrone.Common.Test
Console.WriteLine(new DirectoryInfo(@"C:\DRIVERS").LastWriteTimeUtc); Console.WriteLine(new DirectoryInfo(@"C:\DRIVERS").LastWriteTimeUtc);
} }
[Test]
public void IsChildOfPath_should_return_true_when_it_is_a_child()
{
Mocker.Resolve<DiskProvider>().IsChildOfPath(@"C:\Test\TV", @"C:\Test").Should().BeTrue();
}
[Test]
public void IsChildOfPath_should_return_false_when_it_is_not_a_child()
{
Mocker.Resolve<DiskProvider>().IsChildOfPath(@"C:\NOT_Test\TV", @"C:\Test").Should().BeFalse();
}
private void VerifyCopy() private void VerifyCopy()
{ {
BinFolder.Refresh(); BinFolder.Refresh();

@ -268,5 +268,12 @@ namespace NzbDrone.Common
return false; return false;
} }
public virtual bool IsChildOfPath(string child, string parent)
{
if (Path.GetFullPath(child).StartsWith(Path.GetFullPath(parent)))
return true;
return false;
}
} }
} }

@ -0,0 +1,7 @@
{
"result": "failure",
"data": [ ],
"message": "no show with the tvdb_id 79488 found"
}

@ -0,0 +1,10 @@
{
"result": "success",
"data": [
"73141",
"79886",
],
"message": ""
}

@ -0,0 +1,32 @@
{
"result": "success",
"data": [
{
"scene": {
"season": 1,
"episode": 1,
"absolute": 1
},
"tvdb": {
"season": 1,
"episode": 1,
"absolute": 1
}
},
{
"scene": {
"season": 1,
"episode": 2,
"absolute": 2
},
"tvdb": {
"season": 1,
"episode": 2,
"absolute": 2
}
}
],
"message": "full mapping for 73388 on tvdb. this was a cached version"
}

@ -0,0 +1,24 @@
{
"result": "success",
"data": {
"220571": [
"Is This a Zombie? Of the Dead",
"Kore wa Zombie Desuka?",
"Kore wa Zombie Desuka? Of the Dead",
"Kore wa Zombie Desuka Of the Dead",
"Kore wa Zombie Desu ka - Of the Dead",
"Kore wa Zombie Desu ka of the Dead"
],
"79151": [
"Fate Stay Night",
"Fate/Zero",
"Fate Zero",
"Fate/Zero (2012)",
"Fate Zero S2",
"Fate Zero"
]
},
"message": ""
}

@ -42,13 +42,15 @@ namespace NzbDrone.Core.Test.JobTests
.Setup(j => j.Start(notification, It.Is<object>(d => d.GetPropertyValue<int>("SeriesId") == series[0].SeriesId))) .Setup(j => j.Start(notification, It.Is<object>(d => d.GetPropertyValue<int>("SeriesId") == series[0].SeriesId)))
.Callback(() => series[0].LastDiskSync = DateTime.Now); .Callback(() => series[0].LastDiskSync = DateTime.Now);
Mocker.GetMock<DiskScanJob>() Mocker.GetMock<DiskScanJob>()
.Setup(j => j.Start(notification, It.Is<object>(d => d.GetPropertyValue<int>("SeriesId") == series[1].SeriesId))) .Setup(j => j.Start(notification, It.Is<object>(d => d.GetPropertyValue<int>("SeriesId") == series[1].SeriesId)))
.Callback(() => series[1].LastDiskSync = DateTime.Now); .Callback(() => series[1].LastDiskSync = DateTime.Now);
Mocker.GetMock<BannerDownloadJob>() Mocker.GetMock<BannerDownloadJob>()
.Setup(j => j.Start(notification, It.Is<object>(d => d.GetPropertyValue<int>("SeriesId") >= 0))); .Setup(j => j.Start(notification, It.Is<object>(d => d.GetPropertyValue<int>("SeriesId") > 0)));
Mocker.GetMock<XemUpdateJob>()
.Setup(j => j.Start(notification, It.Is<object>(d => d.GetPropertyValue<int>("SeriesId") > 0)));
Mocker.GetMock<UpdateInfoJob>() Mocker.GetMock<UpdateInfoJob>()
.Setup(j => j.Start(notification, It.Is<object>(d => d.GetPropertyValue<int>("SeriesId") == series[0].SeriesId))) .Setup(j => j.Start(notification, It.Is<object>(d => d.GetPropertyValue<int>("SeriesId") == series[0].SeriesId)))
@ -121,6 +123,9 @@ namespace NzbDrone.Core.Test.JobTests
Mocker.GetMock<MediaFileProvider>() Mocker.GetMock<MediaFileProvider>()
.Setup(s => s.GetSeriesFiles(It.IsAny<int>())).Returns(new List<EpisodeFile>()); .Setup(s => s.GetSeriesFiles(It.IsAny<int>())).Returns(new List<EpisodeFile>());
Mocker.GetMock<XemUpdateJob>()
.Setup(j => j.Start(notification, It.Is<object>(d => d.GetPropertyValue<int>("SeriesId") == series[0].SeriesId)));
//Act //Act
Mocker.Resolve<ImportNewSeriesJob>().Start(notification, null); Mocker.Resolve<ImportNewSeriesJob>().Start(notification, null);

@ -129,13 +129,14 @@
<Reference Include="System.Transactions" /> <Reference Include="System.Transactions" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="TvdbLib, Version=0.8.8.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Libraries\TvdbLib.dll</HintPath>
</Reference>
<Reference Include="WebActivator, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="WebActivator, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\WebActivator.1.5\lib\net40\WebActivator.dll</HintPath> <HintPath>..\packages\WebActivator.1.5\lib\net40\WebActivator.dll</HintPath>
</Reference> </Reference>
<Reference Include="XemLib">
<HintPath>..\Libraries\XemLib\XemLib.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="QualityTypesTest.cs" /> <Compile Include="QualityTypesTest.cs" />
@ -156,6 +157,7 @@
<Compile Include="ProviderTests\DiskScanProviderTests\GetVideoFilesFixture.cs" /> <Compile Include="ProviderTests\DiskScanProviderTests\GetVideoFilesFixture.cs" />
<Compile Include="ProviderTests\DiskScanProviderTests\ScanFixture.cs" /> <Compile Include="ProviderTests\DiskScanProviderTests\ScanFixture.cs" />
<Compile Include="ProviderTests\DownloadClientTests\PneumaticProviderFixture.cs" /> <Compile Include="ProviderTests\DownloadClientTests\PneumaticProviderFixture.cs" />
<Compile Include="ProviderTests\EpisodeProviderTests\GetEpisodeBySceneNumberFixture.cs" />
<Compile Include="ProviderTests\Metadata\Xbmc_ForEpisodeFile_Fixture.cs" /> <Compile Include="ProviderTests\Metadata\Xbmc_ForEpisodeFile_Fixture.cs" />
<Compile Include="ProviderTests\Metadata\Xbmc_ForSeries_Fixture.cs" /> <Compile Include="ProviderTests\Metadata\Xbmc_ForSeries_Fixture.cs" />
<Compile Include="ProviderTests\PostDownloadProviderTests\ProcessDropDirectoryFixture.cs" /> <Compile Include="ProviderTests\PostDownloadProviderTests\ProcessDropDirectoryFixture.cs" />
@ -194,9 +196,11 @@
<Compile Include="JobTests\AppUpdateJobFixture.cs" /> <Compile Include="JobTests\AppUpdateJobFixture.cs" />
<Compile Include="ProviderTests\UpdateProviderTests\GetUpdateLogFixture.cs" /> <Compile Include="ProviderTests\UpdateProviderTests\GetUpdateLogFixture.cs" />
<Compile Include="ProviderTests\UpdateProviderTests\GetAvilableUpdateFixture.cs" /> <Compile Include="ProviderTests\UpdateProviderTests\GetAvilableUpdateFixture.cs" />
<Compile Include="ProviderTests\XemCommunicationProviderTests\GetSceneTvdbMappingsFixture.cs" />
<Compile Include="ProviderTests\XemCommunicationProviderTests\GetXemSeriesIdsFixture.cs" />
<Compile Include="Services\ParseErrorServiceFixture.cs" /> <Compile Include="Services\ParseErrorServiceFixture.cs" />
<Compile Include="SortHelperTest.cs" /> <Compile Include="SortHelperTest.cs" />
<Compile Include="ProviderTests\EpisodeProviderTest_DeleteInvalidEpisodes.cs" /> <Compile Include="ProviderTests\EpisodeProviderTests\EpisodeProviderTest_DeleteInvalidEpisodes.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\AcceptableSizeSpecificationFixture.cs" /> <Compile Include="ProviderTests\DecisionEngineTests\AcceptableSizeSpecificationFixture.cs" />
<Compile Include="ProviderTests\QualityTypeProviderTest.cs" /> <Compile Include="ProviderTests\QualityTypeProviderTest.cs" />
<Compile Include="ProviderTests\MisnamedProviderTest.cs" /> <Compile Include="ProviderTests\MisnamedProviderTest.cs" />
@ -206,7 +210,7 @@
<Compile Include="CentralDispatchFixture.cs" /> <Compile Include="CentralDispatchFixture.cs" />
<Compile Include="ProviderTests\XbmcProviderTest.cs" /> <Compile Include="ProviderTests\XbmcProviderTest.cs" />
<Compile Include="ProviderTests\DiskScanProviderTests\MoveEpisodeFileFixture.cs" /> <Compile Include="ProviderTests\DiskScanProviderTests\MoveEpisodeFileFixture.cs" />
<Compile Include="ProviderTests\EpisodeProviderTest_GetEpisodesByParseResult.cs" /> <Compile Include="ProviderTests\EpisodeProviderTests\EpisodeProviderTest_GetEpisodesByParseResult.cs" />
<Compile Include="ProviderTests\DiskScanProviderTests\ImportFileFixture.cs" /> <Compile Include="ProviderTests\DiskScanProviderTests\ImportFileFixture.cs" />
<Compile Include="FluentTest.cs" /> <Compile Include="FluentTest.cs" />
<Compile Include="ProviderTests\LogProviderTests\LogProviderFixture.cs" /> <Compile Include="ProviderTests\LogProviderTests\LogProviderFixture.cs" />
@ -228,7 +232,7 @@
<Compile Include="ProviderTests\HistoryProviderTest.cs" /> <Compile Include="ProviderTests\HistoryProviderTest.cs" />
<Compile Include="ProviderTests\MediaFileProviderTest.cs" /> <Compile Include="ProviderTests\MediaFileProviderTest.cs" />
<Compile Include="ProviderTests\ConfigProviderTests\ConfigProviderFixture.cs" /> <Compile Include="ProviderTests\ConfigProviderTests\ConfigProviderFixture.cs" />
<Compile Include="ProviderTests\EpisodeProviderTest.cs" /> <Compile Include="ProviderTests\EpisodeProviderTests\EpisodeProviderTest.cs" />
<Compile Include="Framework\TestDbHelper.cs" /> <Compile Include="Framework\TestDbHelper.cs" />
<Compile Include="ParserFixture\ParserTest.cs" /> <Compile Include="ParserFixture\ParserTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
@ -335,6 +339,18 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<Content Include="Files\Xem\Ids.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\Xem\Failure.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\Xem\Names.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\Xem\Mappings.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="log.config"> <Content Include="log.config">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>

@ -32,6 +32,9 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
{ {
_customStartDateSpecification = Mocker.Resolve<CustomStartDateSpecification>(); _customStartDateSpecification = Mocker.Resolve<CustomStartDateSpecification>();
firstEpisode = new Episode { AirDate = DateTime.Today };
secondEpisode = new Episode { AirDate = DateTime.Today };
fakeSeries = Builder<Series>.CreateNew() fakeSeries = Builder<Series>.CreateNew()
.With(c => c.Monitored = true) .With(c => c.Monitored = true)
.With(c => c.CustomStartDate = null) .With(c => c.CustomStartDate = null)
@ -43,6 +46,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Series = fakeSeries, Series = fakeSeries,
EpisodeNumbers = new List<int> { 3, 4 }, EpisodeNumbers = new List<int> { 3, 4 },
SeasonNumber = 12, SeasonNumber = 12,
Episodes = new List<Episode> { firstEpisode, secondEpisode }
}; };
parseResultSingle = new EpisodeParseResult parseResultSingle = new EpisodeParseResult
@ -51,16 +55,8 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Series = fakeSeries, Series = fakeSeries,
EpisodeNumbers = new List<int> { 3 }, EpisodeNumbers = new List<int> { 3 },
SeasonNumber = 12, SeasonNumber = 12,
Episodes = new List<Episode> { firstEpisode }
}; };
firstEpisode = new Episode { AirDate = DateTime.Today };
secondEpisode = new Episode { AirDate = DateTime.Today };
var singleEpisodeList = new List<Episode> { firstEpisode };
var doubleEpisodeList = new List<Episode> { firstEpisode, secondEpisode };
Mocker.GetMock<EpisodeProvider>().Setup(c => c.GetEpisodesByParseResult(parseResultSingle)).Returns(singleEpisodeList);
Mocker.GetMock<EpisodeProvider>().Setup(c => c.GetEpisodesByParseResult(parseResultMulti)).Returns(doubleEpisodeList);
} }
private void WithFirstEpisodeLastYear() private void WithFirstEpisodeLastYear()

@ -31,6 +31,12 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Mocker.Resolve<QualityUpgradeSpecification>(); Mocker.Resolve<QualityUpgradeSpecification>();
_upgradeDisk = Mocker.Resolve<UpgradeDiskSpecification>(); _upgradeDisk = Mocker.Resolve<UpgradeDiskSpecification>();
firstFile = new EpisodeFile { Quality = QualityTypes.Bluray1080p, Proper = true };
secondFile = new EpisodeFile { Quality = QualityTypes.Bluray1080p, Proper = true };
var singleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = null } };
var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = secondFile }, new Episode { EpisodeFile = null } };
var fakeSeries = Builder<Series>.CreateNew() var fakeSeries = Builder<Series>.CreateNew()
.With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p }) .With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p })
.Build(); .Build();
@ -41,6 +47,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Quality = new QualityModel(QualityTypes.DVD, true), Quality = new QualityModel(QualityTypes.DVD, true),
EpisodeNumbers = new List<int> { 3, 4 }, EpisodeNumbers = new List<int> { 3, 4 },
SeasonNumber = 12, SeasonNumber = 12,
Episodes = doubleEpisodeList
}; };
parseResultSingle = new EpisodeParseResult parseResultSingle = new EpisodeParseResult
@ -49,17 +56,8 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Quality = new QualityModel(QualityTypes.DVD, true), Quality = new QualityModel(QualityTypes.DVD, true),
EpisodeNumbers = new List<int> { 3 }, EpisodeNumbers = new List<int> { 3 },
SeasonNumber = 12, SeasonNumber = 12,
Episodes = singleEpisodeList
}; };
firstFile = new EpisodeFile { Quality = QualityTypes.Bluray1080p, Proper = true };
secondFile = new EpisodeFile { Quality = QualityTypes.Bluray1080p, Proper = true };
var singleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = null } };
var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = secondFile }, new Episode { EpisodeFile = null } };
Mocker.GetMock<EpisodeProvider>().Setup(c => c.GetEpisodesByParseResult(parseResultSingle)).Returns(singleEpisodeList);
Mocker.GetMock<EpisodeProvider>().Setup(c => c.GetEpisodesByParseResult(parseResultMulti)).Returns(doubleEpisodeList);
} }
private void WithFirstFileUpgradable() private void WithFirstFileUpgradable()
@ -73,9 +71,9 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
} }
[Test] [Test]
public void should_return_false_if_single_episode_doesnt_exist_on_disk() public void should_return_true_if_single_episode_doesnt_exist_on_disk()
{ {
Mocker.GetMock<EpisodeProvider>().Setup(c => c.GetEpisodesByParseResult(parseResultSingle)).Returns(new List<Episode>()); parseResultSingle.Episodes = new List<Episode>();
_upgradeDisk.IsSatisfiedBy(parseResultSingle).Should().BeTrue(); _upgradeDisk.IsSatisfiedBy(parseResultSingle).Should().BeTrue();
} }

@ -31,6 +31,13 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Mocker.Resolve<QualityUpgradeSpecification>(); Mocker.Resolve<QualityUpgradeSpecification>();
_upgradeHistory = Mocker.Resolve<UpgradeHistorySpecification>(); _upgradeHistory = Mocker.Resolve<UpgradeHistorySpecification>();
var singleEpisodeList = new List<Episode> { new Episode { SeasonNumber = 12, EpisodeNumber = 3 } };
var doubleEpisodeList = new List<Episode> {
new Episode { SeasonNumber = 12, EpisodeNumber = 3 },
new Episode { SeasonNumber = 12, EpisodeNumber = 4 },
new Episode { SeasonNumber = 12, EpisodeNumber = 5 }
};
var fakeSeries = Builder<Series>.CreateNew() var fakeSeries = Builder<Series>.CreateNew()
.With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p }) .With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p })
.Build(); .Build();
@ -41,6 +48,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Quality = new QualityModel(QualityTypes.DVD, true), Quality = new QualityModel(QualityTypes.DVD, true),
EpisodeNumbers = new List<int> { 3, 4 }, EpisodeNumbers = new List<int> { 3, 4 },
SeasonNumber = 12, SeasonNumber = 12,
Episodes = doubleEpisodeList
}; };
parseResultSingle = new EpisodeParseResult parseResultSingle = new EpisodeParseResult
@ -49,21 +57,12 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Quality = new QualityModel(QualityTypes.DVD, true), Quality = new QualityModel(QualityTypes.DVD, true),
EpisodeNumbers = new List<int> { 3 }, EpisodeNumbers = new List<int> { 3 },
SeasonNumber = 12, SeasonNumber = 12,
Episodes = singleEpisodeList
}; };
firstQuality = new QualityModel(QualityTypes.Bluray1080p, true); firstQuality = new QualityModel(QualityTypes.Bluray1080p, true);
secondQuality = new QualityModel(QualityTypes.Bluray1080p, true); secondQuality = new QualityModel(QualityTypes.Bluray1080p, true);
var singleEpisodeList = new List<Episode> { new Episode { SeasonNumber = 12, EpisodeNumber = 3 } };
var doubleEpisodeList = new List<Episode> {
new Episode { SeasonNumber = 12, EpisodeNumber = 3 },
new Episode { SeasonNumber = 12, EpisodeNumber = 4 },
new Episode { SeasonNumber = 12, EpisodeNumber = 5 }
};
Mocker.GetMock<EpisodeProvider>().Setup(c => c.GetEpisodesByParseResult(parseResultSingle)).Returns(singleEpisodeList);
Mocker.GetMock<EpisodeProvider>().Setup(c => c.GetEpisodesByParseResult(parseResultMulti)).Returns(doubleEpisodeList);
Mocker.GetMock<HistoryProvider>().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 3)).Returns(firstQuality); Mocker.GetMock<HistoryProvider>().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 3)).Returns(firstQuality);
Mocker.GetMock<HistoryProvider>().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 4)).Returns(secondQuality); Mocker.GetMock<HistoryProvider>().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 4)).Returns(secondQuality);
Mocker.GetMock<HistoryProvider>().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 5)).Returns<QualityModel>(null); Mocker.GetMock<HistoryProvider>().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 5)).Returns<QualityModel>(null);

@ -175,6 +175,9 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
.Setup(p => p.Exists(It.IsAny<String>())) .Setup(p => p.Exists(It.IsAny<String>()))
.Returns(false); .Returns(false);
Mocker.GetMock<DiskProvider>(MockBehavior.Strict)
.Setup(e => e.IsChildOfPath(fileName, fakeSeries.Path)).Returns(false);
Mocker.GetMock<EpisodeProvider>() Mocker.GetMock<EpisodeProvider>()
.Setup(c => c.GetEpisodesByParseResult(It.IsAny<EpisodeParseResult>())) .Setup(c => c.GetEpisodesByParseResult(It.IsAny<EpisodeParseResult>()))
.Returns(new List<Episode>()); .Returns(new List<Episode>());
@ -392,5 +395,47 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
Mocker.GetMock<EpisodeProvider>().Verify(p => p.UpdateEpisode(It.IsAny<Episode>()), Times.Never()); Mocker.GetMock<EpisodeProvider>().Verify(p => p.UpdateEpisode(It.IsAny<Episode>()), Times.Never());
Mocker.GetMock<DiskProvider>().Verify(p => p.DeleteFile(It.IsAny<string>()), Times.Never()); Mocker.GetMock<DiskProvider>().Verify(p => p.DeleteFile(It.IsAny<string>()), Times.Never());
} }
[Test]
public void should_set_parseResult_SceneSource_if_not_in_series_Path()
{
var series = Builder<Series>
.CreateNew()
.With(s => s.Path == @"C:\Test\TV\30 Rock")
.Build();
const string path = @"C:\Test\Unsorted TV\30 Rock\30.rock.s01e01.pilot.mkv";
Mocker.GetMock<EpisodeProvider>().Setup(s => s.GetEpisodesByParseResult(It.IsAny<EpisodeParseResult>()))
.Returns(new List<Episode>());
Mocker.GetMock<DiskProvider>().Setup(s => s.IsChildOfPath(path, series.Path))
.Returns(false);
Mocker.Resolve<DiskScanProvider>().ImportFile(series, path);
Mocker.Verify<EpisodeProvider>(s => s.GetEpisodesByParseResult(It.Is<EpisodeParseResult>(p => p.SceneSource)), Times.Once());
}
[Test]
public void should_not_set_parseResult_SceneSource_if_in_series_Path()
{
var series = Builder<Series>
.CreateNew()
.With(s => s.Path == @"C:\Test\TV\30 Rock")
.Build();
const string path = @"C:\Test\TV\30 Rock\30.rock.s01e01.pilot.mkv";
Mocker.GetMock<EpisodeProvider>().Setup(s => s.GetEpisodesByParseResult(It.IsAny<EpisodeParseResult>()))
.Returns(new List<Episode>());
Mocker.GetMock<DiskProvider>().Setup(s => s.IsChildOfPath(path, series.Path))
.Returns(true);
Mocker.Resolve<DiskScanProvider>().ImportFile(series, path);
Mocker.Verify<EpisodeProvider>(s => s.GetEpisodesByParseResult(It.Is<EpisodeParseResult>(p => p.SceneSource == false)), Times.Once());
}
} }
} }

@ -52,6 +52,7 @@ namespace NzbDrone.Core.Test.ProviderTests
.With(c => c.Quality = new QualityModel(QualityTypes.DVD, false)) .With(c => c.Quality = new QualityModel(QualityTypes.DVD, false))
.With(c => c.Series = Builder<Series>.CreateNew().Build()) .With(c => c.Series = Builder<Series>.CreateNew().Build())
.With(c => c.EpisodeNumbers = new List<int>{2}) .With(c => c.EpisodeNumbers = new List<int>{2})
.With(c => c.Episodes = episodes)
.Build(); .Build();
} }
@ -191,6 +192,15 @@ namespace NzbDrone.Core.Test.ProviderTests
.With(c => c.Title = "My Series Name") .With(c => c.Title = "My Series Name")
.Build(); .Build();
var fakeEpisodes = new List<Episode>();
foreach(var episode in episodes)
fakeEpisodes.Add(Builder<Episode>
.CreateNew()
.With(e => e.EpisodeNumber = episode)
.With(e => e.Title = title)
.Build());
var parsResult = new EpisodeParseResult() var parsResult = new EpisodeParseResult()
{ {
AirDate = DateTime.Now, AirDate = DateTime.Now,
@ -198,7 +208,8 @@ namespace NzbDrone.Core.Test.ProviderTests
Quality = new QualityModel(quality, proper), Quality = new QualityModel(quality, proper),
SeasonNumber = seasons, SeasonNumber = seasons,
Series = series, Series = series,
EpisodeTitle = title EpisodeTitle = title,
Episodes = fakeEpisodes
}; };
Mocker.Resolve<DownloadProvider>().GetDownloadTitle(parsResult).Should().Be(expected); Mocker.Resolve<DownloadProvider>().GetDownloadTitle(parsResult).Should().Be(expected);
@ -234,16 +245,49 @@ namespace NzbDrone.Core.Test.ProviderTests
.With(c => c.Title = "My Series Name") .With(c => c.Title = "My Series Name")
.Build(); .Build();
var episode = Builder<Episode>.CreateNew()
.With(e => e.Title = "My Episode Title")
.Build();
var parsResult = new EpisodeParseResult var parsResult = new EpisodeParseResult
{ {
AirDate = new DateTime(2011, 12, 1), AirDate = new DateTime(2011, 12, 1),
Quality = new QualityModel(QualityTypes.Bluray720p, proper), Quality = new QualityModel(QualityTypes.Bluray720p, proper),
Series = series, Series = series,
EpisodeTitle = "My Episode Title", EpisodeTitle = "My Episode Title",
Episodes = new List<Episode>{ episode }
}; };
return Mocker.Resolve<DownloadProvider>().GetDownloadTitle(parsResult); return Mocker.Resolve<DownloadProvider>().GetDownloadTitle(parsResult);
} }
[Test]
public void should_not_repeat_the_same_episode_title()
{
var series = Builder<Series>.CreateNew()
.With(c => c.Title = "My Series Name")
.Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(2)
.All()
.With(e => e.SeasonNumber = 5)
.TheFirst(1)
.With(e => e.Title = "My Episode Title (1)")
.TheLast(1)
.With(e => e.Title = "My Episode Title (2)")
.Build();
var parsResult = new EpisodeParseResult
{
AirDate = DateTime.Now,
EpisodeNumbers = new List<int>{ 10, 11 },
Quality = new QualityModel(QualityTypes.HDTV, false),
SeasonNumber = 35,
Series = series,
Episodes = fakeEpisodes
};
Mocker.Resolve<DownloadProvider>().GetDownloadTitle(parsResult).Should().Be("My Series Name - 5x01-5x02 - My Episode Title [HDTV]");
}
} }
} }

@ -2,9 +2,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using Moq; using Moq;
@ -15,11 +13,10 @@ using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality; using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq;
using PetaPoco; using PetaPoco;
using XemLib.Data; using TvdbLib.Data;
namespace NzbDrone.Core.Test.ProviderTests namespace NzbDrone.Core.Test.ProviderTests.EpisodeProviderTests
{ {
[TestFixture] [TestFixture]
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
@ -161,7 +158,7 @@ namespace NzbDrone.Core.Test.ProviderTests
c => c.Episodes = c => c.Episodes =
new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount). new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount).
All() All()
.With(l => l.Language = "en") .With(l => l.Language = new TvdbLanguage(0, "eng", "a"))
.Build()) .Build())
).With(c => c.Id = seriesId).Build(); ).With(c => c.Id = seriesId).Build();
@ -172,7 +169,7 @@ namespace NzbDrone.Core.Test.ProviderTests
Db.Insert(fakeSeries); Db.Insert(fakeSeries);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(fakeEpisodes); .Returns(fakeEpisodes);
//Act //Act
@ -195,7 +192,7 @@ namespace NzbDrone.Core.Test.ProviderTests
c => c.Episodes = c => c.Episodes =
new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(10). new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(10).
All() All()
.With(l => l.Language = "en").And(e => e.FirstAired = DateTime.Now) .With(l => l.Language = new TvdbLanguage(0, "eng", "a")).And(e => e.FirstAired = DateTime.Now)
.TheFirst(7).With(e => e.FirstAired = new DateTime(1800, 1, 1)) .TheFirst(7).With(e => e.FirstAired = new DateTime(1800, 1, 1))
.Build()) .Build())
).With(c => c.Id = seriesId).Build(); ).With(c => c.Id = seriesId).Build();
@ -207,7 +204,7 @@ namespace NzbDrone.Core.Test.ProviderTests
Db.Insert(fakeSeries); Db.Insert(fakeSeries);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(fakeEpisodes); .Returns(fakeEpisodes);
@ -236,7 +233,7 @@ namespace NzbDrone.Core.Test.ProviderTests
c => c.Episodes = c => c.Episodes =
new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(1) new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(1)
.All() .All()
.With(l => l.Language = "en").And(e => e.FirstAired = DateTime.Now) .With(l => l.Language = new TvdbLanguage(0, "eng", "a")).And(e => e.FirstAired = DateTime.Now)
.TheFirst(1).With(e => e.FirstAired = new DateTime(1800, 1, 1)) .TheFirst(1).With(e => e.FirstAired = new DateTime(1800, 1, 1))
.Build()) .Build())
).With(c => c.Id = seriesId).Build(); ).With(c => c.Id = seriesId).Build();
@ -248,7 +245,7 @@ namespace NzbDrone.Core.Test.ProviderTests
Db.Insert(fakeEpisode); Db.Insert(fakeEpisode);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(fakeTvDbEpisodes); .Returns(fakeTvDbEpisodes);
//Act //Act
@ -271,7 +268,7 @@ namespace NzbDrone.Core.Test.ProviderTests
c => c.Episodes = c => c.Episodes =
new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount). new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount).
All() All()
.With(l => l.Language = "en") .With(l => l.Language = new TvdbLanguage(0, "eng", "a"))
.TheFirst(1) .TheFirst(1)
.With(e => e.EpisodeNumber = 0) .With(e => e.EpisodeNumber = 0)
.With(e => e.SeasonNumber = 15) .With(e => e.SeasonNumber = 15)
@ -285,7 +282,7 @@ namespace NzbDrone.Core.Test.ProviderTests
Db.Insert(fakeSeries); Db.Insert(fakeSeries);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(fakeEpisodes); .Returns(fakeEpisodes);
@ -324,7 +321,7 @@ namespace NzbDrone.Core.Test.ProviderTests
Db.Insert(fakeSeries); Db.Insert(fakeSeries);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(fakeEpisodes); .Returns(fakeEpisodes);
@ -362,7 +359,7 @@ namespace NzbDrone.Core.Test.ProviderTests
Db.Insert(fakeSeries); Db.Insert(fakeSeries);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(fakeEpisodes); .Returns(fakeEpisodes);
@ -395,7 +392,7 @@ namespace NzbDrone.Core.Test.ProviderTests
Db.Insert(fakeSeries); Db.Insert(fakeSeries);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(fakeEpisodes); .Returns(fakeEpisodes);
@ -428,7 +425,7 @@ namespace NzbDrone.Core.Test.ProviderTests
Db.Insert(fakeSeries); Db.Insert(fakeSeries);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(fakeEpisodes); .Returns(fakeEpisodes);
@ -451,7 +448,7 @@ namespace NzbDrone.Core.Test.ProviderTests
c => c.Episodes = c => c.Episodes =
new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount). new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount).
All() All()
.With(l => l.Language = "en") .With(l => l.Language = new TvdbLanguage(0, "eng", "a"))
.With(e => e.SeasonNumber = 0) .With(e => e.SeasonNumber = 0)
.Build()) .Build())
).With(c => c.Id = seriesId).Build(); ).With(c => c.Id = seriesId).Build();
@ -463,7 +460,7 @@ namespace NzbDrone.Core.Test.ProviderTests
Db.Insert(fakeSeries); Db.Insert(fakeSeries);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(fakeEpisodes); .Returns(fakeEpisodes);
Mocker.GetMock<SeasonProvider>() Mocker.GetMock<SeasonProvider>()
@ -493,7 +490,7 @@ namespace NzbDrone.Core.Test.ProviderTests
var currentEpisodes = new List<Episode>(); var currentEpisodes = new List<Episode>();
Mocker.GetMock<TvDbProvider>(MockBehavior.Strict) Mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(tvdbSeries); .Returns(tvdbSeries);
Mocker.GetMock<IDatabase>() Mocker.GetMock<IDatabase>()
@ -528,7 +525,7 @@ namespace NzbDrone.Core.Test.ProviderTests
} }
Mocker.GetMock<TvDbProvider>(MockBehavior.Strict) Mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(tvdbSeries); .Returns(tvdbSeries);
Mocker.GetMock<IDatabase>() Mocker.GetMock<IDatabase>()
@ -565,7 +562,7 @@ namespace NzbDrone.Core.Test.ProviderTests
.Returns(fakeEpisodeList); .Returns(fakeEpisodeList);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(fakeTvDbResult); .Returns(fakeTvDbResult);
//Act //Act
@ -602,7 +599,7 @@ namespace NzbDrone.Core.Test.ProviderTests
var fakeSeries = Builder<Series>.CreateNew().With(c => c.SeriesId = seriesId).Build(); var fakeSeries = Builder<Series>.CreateNew().With(c => c.SeriesId = seriesId).Build();
Mocker.GetMock<TvDbProvider>(MockBehavior.Strict) Mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(tvdbSeries); .Returns(tvdbSeries);
Mocker.GetMock<IDatabase>() Mocker.GetMock<IDatabase>()
@ -643,7 +640,7 @@ namespace NzbDrone.Core.Test.ProviderTests
} }
Mocker.GetMock<TvDbProvider>(MockBehavior.Strict) Mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(tvdbSeries); .Returns(tvdbSeries);
var updatedEpisodes = new List<Episode>(); var updatedEpisodes = new List<Episode>();
@ -692,7 +689,7 @@ namespace NzbDrone.Core.Test.ProviderTests
} }
Mocker.GetMock<TvDbProvider>(MockBehavior.Strict) Mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(tvdbSeries); .Returns(tvdbSeries);
var updatedEpisodes = new List<Episode>(); var updatedEpisodes = new List<Episode>();
@ -738,7 +735,7 @@ namespace NzbDrone.Core.Test.ProviderTests
} }
Mocker.GetMock<TvDbProvider>(MockBehavior.Strict) Mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(tvdbSeries); .Returns(tvdbSeries);
var updatedEpisodes = new List<Episode>(); var updatedEpisodes = new List<Episode>();
@ -777,7 +774,7 @@ namespace NzbDrone.Core.Test.ProviderTests
c => c.Episodes = c => c.Episodes =
new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount). new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount).
All() All()
.With(l => l.Language = "en") .With(l => l.Language = new TvdbLanguage(0, "eng", "a"))
.With(e => e.SeasonNumber = 5) .With(e => e.SeasonNumber = 5)
.TheFirst(1) .TheFirst(1)
.With(e => e.EpisodeNumber = 1) .With(e => e.EpisodeNumber = 1)
@ -796,7 +793,7 @@ namespace NzbDrone.Core.Test.ProviderTests
Db.Insert(fakeEpisode); Db.Insert(fakeEpisode);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(tvdbSeries); .Returns(tvdbSeries);
Mocker.GetMock<SeasonProvider>() Mocker.GetMock<SeasonProvider>()
@ -1487,7 +1484,7 @@ namespace NzbDrone.Core.Test.ProviderTests
c => c.Episodes = c => c.Episodes =
new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount). new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount).
All() All()
.With(l => l.Language = "en") .With(l => l.Language = new TvdbLanguage(0, "eng", "a"))
.With(e => e.EpisodeNumber = 0) .With(e => e.EpisodeNumber = 0)
.TheFirst(1) .TheFirst(1)
.With(e => e.SeasonNumber = 1) .With(e => e.SeasonNumber = 1)
@ -1509,7 +1506,7 @@ namespace NzbDrone.Core.Test.ProviderTests
Db.Insert(fakeSeries); Db.Insert(fakeSeries);
Mocker.GetMock<TvDbProvider>() Mocker.GetMock<TvDbProvider>()
.Setup(c => c.GetSeries(seriesId, true, false, false)) .Setup(c => c.GetSeries(seriesId, true, false))
.Returns(tvdbSeries); .Returns(tvdbSeries);
//Act //Act

@ -2,17 +2,15 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq; using TvdbLib.Data;
using XemLib.Data;
namespace NzbDrone.Core.Test.ProviderTests namespace NzbDrone.Core.Test.ProviderTests.EpisodeProviderTests
{ {
[TestFixture] [TestFixture]
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
@ -27,7 +25,7 @@ namespace NzbDrone.Core.Test.ProviderTests
var tvDbSeries = Builder<TvdbEpisode>.CreateListOfSize(episodeCount). var tvDbSeries = Builder<TvdbEpisode>.CreateListOfSize(episodeCount).
All() All()
.With(l => l.Language = "en") .With(l => l.Language = new TvdbLanguage(0, "eng", "a"))
.Build(); .Build();
@ -65,7 +63,7 @@ namespace NzbDrone.Core.Test.ProviderTests
var tvDbSeries = Builder<TvdbEpisode>.CreateListOfSize(episodeCount). var tvDbSeries = Builder<TvdbEpisode>.CreateListOfSize(episodeCount).
All() All()
.With(l => l.Language = "en") .With(l => l.Language = new TvdbLanguage(0, "eng", "a"))
.Build(); .Build();
var fakeSeries = Builder<Series>.CreateNew() var fakeSeries = Builder<Series>.CreateNew()
@ -102,7 +100,7 @@ namespace NzbDrone.Core.Test.ProviderTests
var tvDbSeries = Builder<TvdbEpisode>.CreateListOfSize(episodeCount). var tvDbSeries = Builder<TvdbEpisode>.CreateListOfSize(episodeCount).
All() All()
.With(l => l.Language = "en") .With(l => l.Language = new TvdbLanguage(0, "eng", "a"))
.Build(); .Build();
var fakeSeries = Builder<Series>.CreateNew() var fakeSeries = Builder<Series>.CreateNew()
@ -139,7 +137,7 @@ namespace NzbDrone.Core.Test.ProviderTests
var tvDbSeries = Builder<TvdbEpisode>.CreateListOfSize(episodeCount). var tvDbSeries = Builder<TvdbEpisode>.CreateListOfSize(episodeCount).
All() All()
.With(l => l.Language = "en") .With(l => l.Language = new TvdbLanguage(0, "eng", "a"))
.Build(); .Build();
var fakeSeries = Builder<Series>.CreateNew() var fakeSeries = Builder<Series>.CreateNew()
@ -179,7 +177,7 @@ namespace NzbDrone.Core.Test.ProviderTests
var tvDbSeries = Builder<TvdbEpisode>.CreateListOfSize(episodeCount). var tvDbSeries = Builder<TvdbEpisode>.CreateListOfSize(episodeCount).
All() All()
.With(l => l.Language = "en") .With(l => l.Language = new TvdbLanguage(0, "eng", "a"))
.Build(); .Build();
var fakeSeries = Builder<Series>.CreateNew() var fakeSeries = Builder<Series>.CreateNew()

@ -5,17 +5,14 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Model; using NzbDrone.Core.Model;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
using NzbDrone.Test.Common.AutoMoq;
using PetaPoco;
namespace NzbDrone.Core.Test.ProviderTests namespace NzbDrone.Core.Test.ProviderTests.EpisodeProviderTests
{ {
[TestFixture] [TestFixture]
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming

@ -0,0 +1,77 @@
// ReSharper disable RedundantUsingDirective
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ProviderTests.EpisodeProviderTests
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class GetEpisodeBySceneNumberFixture : CoreTest
{
private Series _series;
private Episode _episode;
[SetUp]
public void Setup()
{
WithRealDb();
_series = Builder<Series>
.CreateNew()
.Build();
Db.Insert(_series);
}
public void WithNullSceneNumbering()
{
_episode = Builder<Episode>
.CreateNew()
.With(e => e.SeriesId = _series.SeriesId)
.Build();
Db.Insert(_episode);
Db.Execute("UPDATE Episodes SET SceneSeasonNumber = NULL, SceneEpisodeNumber = NULL");
}
public void WithSceneNumbering()
{
_episode = Builder<Episode>
.CreateNew()
.With(e => e.SeriesId = _series.SeriesId)
.Build();
Db.Insert(_episode);
}
[Test]
public void should_return_null_if_no_episodes_in_db()
{
Mocker.Resolve<EpisodeProvider>().GetEpisodeBySceneNumbering(_series.SeriesId, 1, 1).Should().BeNull();
}
[Test]
public void should_return_null_if_no_matching_episode_is_found()
{
WithNullSceneNumbering();
Mocker.Resolve<EpisodeProvider>().GetEpisodeBySceneNumbering(_series.SeriesId, 1, 1).Should().BeNull();
}
[Test]
public void should_return_episode_if_matching_episode_is_found()
{
WithSceneNumbering();
var result = Mocker.Resolve<EpisodeProvider>()
.GetEpisodeBySceneNumbering(_series.SeriesId, _episode.SceneSeasonNumber, _episode.SceneEpisodeNumber);
result.EpisodeId.Should().Be(_episode.EpisodeId);
}
}
}

@ -699,5 +699,43 @@ namespace NzbDrone.Core.Test.ProviderTests.MediaFileProviderTests
//Assert //Assert
result.Should().Be("30 Rock - S06E06-E07 - Hello + World"); result.Should().Be("30 Rock - S06E06-E07 - Hello + World");
} }
[Test]
public void should_have_two_episodeTitles_when_distinct_count_is_two()
{
//Setup
var fakeConfig = Mocker.GetMock<ConfigProvider>();
fakeConfig.SetupGet(c => c.SortingIncludeSeriesName).Returns(true);
fakeConfig.SetupGet(c => c.SortingIncludeEpisodeTitle).Returns(true);
fakeConfig.SetupGet(c => c.SortingAppendQuality).Returns(false);
fakeConfig.SetupGet(c => c.SortingSeparatorStyle).Returns(0);
fakeConfig.SetupGet(c => c.SortingNumberStyle).Returns(2);
fakeConfig.SetupGet(c => c.SortingReplaceSpaces).Returns(false);
fakeConfig.SetupGet(c => c.SortingMultiEpisodeStyle).Returns(3);
var episode = Builder<Episode>.CreateNew()
.With(e => e.Title = "Hello (3)")
.With(e => e.SeasonNumber = 6)
.With(e => e.EpisodeNumber = 6)
.Build();
var episode2 = Builder<Episode>.CreateNew()
.With(e => e.Title = "Hello (2)")
.With(e => e.SeasonNumber = 6)
.With(e => e.EpisodeNumber = 7)
.Build();
var episode3 = Builder<Episode>.CreateNew()
.With(e => e.Title = "World")
.With(e => e.SeasonNumber = 6)
.With(e => e.EpisodeNumber = 8)
.Build();
//Act
string result = Mocker.Resolve<MediaFileProvider>().GetNewFilename(new List<Episode> { episode, episode2, episode3 }, "30 Rock", QualityTypes.HDTV, false, new EpisodeFile());
//Assert
result.Should().Be("30 Rock - S06E06-E07-E08 - Hello + World");
}
} }
} }

@ -17,8 +17,8 @@ using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq; using NzbDrone.Test.Common.AutoMoq;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
using XemLib.Data; using TvdbLib.Data;
using XemLib.Data.Banner; using TvdbLib.Data.Banner;
namespace NzbDrone.Core.Test.ProviderTests.Metadata namespace NzbDrone.Core.Test.ProviderTests.Metadata
{ {
@ -52,30 +52,31 @@ namespace NzbDrone.Core.Test.ProviderTests.Metadata
.With(e => e.SeriesId = 79488) .With(e => e.SeriesId = 79488)
.With(e => e.SeasonNumber = 1) .With(e => e.SeasonNumber = 1)
.With(e => e.Directors = new List<string>{ "Fake Director" }) .With(e => e.Directors = new List<string>{ "Fake Director" })
.With(e => e.Writers = new List<string>{ "Fake Writer" }) .With(e => e.Writer = new List<string>{ "Fake Writer" })
.With(e => e.GuestStars = new List<string> { "Guest Star 1", "Guest Star 2", "Guest Star 3", "" }) .With(e => e.GuestStars = new List<string> { "Guest Star 1", "Guest Star 2", "Guest Star 3", "" })
.Build(); .Build();
var seasonBanners = Builder<TvdbSeasonBanner> var seasonBanners = Builder<TvdbSeasonBanner>
.CreateListOfSize(4) .CreateListOfSize(4)
.TheFirst(2) .TheFirst(2)
.With(b => b.SeasonNumber = 1) .With(b => b.Season = 1)
.TheLast(2) .TheLast(2)
.With(b => b.SeasonNumber = 2) .With(b => b.Season = 2)
.TheFirst(1) .TheFirst(1)
.With(b => b.BannerType = TvdbSeasonBanner.Type.Poster) .With(b => b.BannerType = TvdbSeasonBanner.Type.season)
.With(b => b.BannerPath = "seasons/79488-1-1.jpg") .With(b => b.BannerPath = "seasons/79488-1-1.jpg")
.TheNext(2) .TheNext(2)
.With(b => b.BannerType = TvdbSeasonBanner.Type.Banner) .With(b => b.BannerType = TvdbSeasonBanner.Type.seasonwide)
.With(b => b.BannerPath = "banners/seasons/79488-test.jpg") .With(b => b.BannerPath = "banners/seasons/79488-test.jpg")
.TheLast(1) .TheLast(1)
.With(b => b.BannerType = TvdbSeasonBanner.Type.Poster) .With(b => b.BannerType = TvdbSeasonBanner.Type.season)
.With(b => b.BannerPath = "seasons/79488-2-1.jpg") .With(b => b.BannerPath = "seasons/79488-2-1.jpg")
.Build(); .Build();
var seriesActors = Builder<TvdbActor> var seriesActors = Builder<TvdbActor>
.CreateListOfSize(5) .CreateListOfSize(5)
.All() .All()
.With(a => a.ActorImage = Builder<TvdbActorBanner>.CreateNew().Build())
.Build(); .Build();
tvdbSeries = Builder<TvdbSeries> tvdbSeries = Builder<TvdbSeries>
@ -84,10 +85,9 @@ namespace NzbDrone.Core.Test.ProviderTests.Metadata
.With(s => s.SeriesName = "30 Rock") .With(s => s.SeriesName = "30 Rock")
.With(s => s.TvdbActors = seriesActors.ToList()) .With(s => s.TvdbActors = seriesActors.ToList())
.With(s => s.Episodes = tvdbEpisodes.ToList()) .With(s => s.Episodes = tvdbEpisodes.ToList())
.With(s => s.Banners = new TvdbBanners())
.Build(); .Build();
tvdbSeries.Banners.SeasonBanners.AddRange(seasonBanners); tvdbSeries.Banners.AddRange(seasonBanners);
} }
private void WithUseBanners() private void WithUseBanners()
@ -128,7 +128,7 @@ namespace NzbDrone.Core.Test.ProviderTests.Metadata
private void WithNoWriters() private void WithNoWriters()
{ {
tvdbSeries.Episodes.ForEach(e => e.Writers = new List<string>()); tvdbSeries.Episodes.ForEach(e => e.Writer = new List<string>());
} }
[Test] [Test]
@ -159,7 +159,7 @@ namespace NzbDrone.Core.Test.ProviderTests.Metadata
{ {
WithSingleEpisodeFile(); WithSingleEpisodeFile();
Mocker.Resolve<Xbmc>().CreateForEpisodeFile(episodeFile, tvdbSeries); Mocker.Resolve<Xbmc>().CreateForEpisodeFile(episodeFile, tvdbSeries);
Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.Episodes.First().Banner, episodeFile.Path.Replace("avi", "tbn")), Times.Once()); Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.Episodes.First().BannerPath, episodeFile.Path.Replace("avi", "tbn")), Times.Once());
} }
[Test] [Test]

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@ -17,8 +16,8 @@ using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq; using NzbDrone.Test.Common.AutoMoq;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
using XemLib.Data; using TvdbLib.Data;
using XemLib.Data.Banner; using TvdbLib.Data.Banner;
namespace NzbDrone.Core.Test.ProviderTests.Metadata namespace NzbDrone.Core.Test.ProviderTests.Metadata
{ {
@ -43,23 +42,24 @@ namespace NzbDrone.Core.Test.ProviderTests.Metadata
var seasonBanners = Builder<TvdbSeasonBanner> var seasonBanners = Builder<TvdbSeasonBanner>
.CreateListOfSize(4) .CreateListOfSize(4)
.TheFirst(2) .TheFirst(2)
.With(b => b.SeasonNumber = 1) .With(b => b.Season = 1)
.TheLast(2) .TheLast(2)
.With(b => b.SeasonNumber = 2) .With(b => b.Season = 2)
.TheFirst(1) .TheFirst(1)
.With(b => b.BannerType = TvdbSeasonBanner.Type.Poster) .With(b => b.BannerType = TvdbSeasonBanner.Type.season)
.With(b => b.BannerPath = "seasons/79488-1-1.jpg") .With(b => b.BannerPath = "seasons/79488-1-1.jpg")
.TheNext(2) .TheNext(2)
.With(b => b.BannerType = TvdbSeasonBanner.Type.Banner) .With(b => b.BannerType = TvdbSeasonBanner.Type.seasonwide)
.With(b => b.BannerPath = "banners/seasons/79488-test.jpg") .With(b => b.BannerPath = "banners/seasons/79488-test.jpg")
.TheLast(1) .TheLast(1)
.With(b => b.BannerType = TvdbSeasonBanner.Type.Poster) .With(b => b.BannerType = TvdbSeasonBanner.Type.season)
.With(b => b.BannerPath = "seasons/79488-2-1.jpg") .With(b => b.BannerPath = "seasons/79488-2-1.jpg")
.Build(); .Build();
var seriesActors = Builder<TvdbActor> var seriesActors = Builder<TvdbActor>
.CreateListOfSize(5) .CreateListOfSize(5)
.All() .All()
.With(a => a.ActorImage = Builder<TvdbActorBanner>.CreateNew().Build())
.Build(); .Build();
tvdbSeries = Builder<TvdbSeries> tvdbSeries = Builder<TvdbSeries>
@ -67,10 +67,9 @@ namespace NzbDrone.Core.Test.ProviderTests.Metadata
.With(s => s.Id = 79488) .With(s => s.Id = 79488)
.With(s => s.SeriesName = "30 Rock") .With(s => s.SeriesName = "30 Rock")
.With(s => s.TvdbActors = seriesActors.ToList()) .With(s => s.TvdbActors = seriesActors.ToList())
.With(s => s.Banners = new TvdbBanners())
.Build(); .Build();
tvdbSeries.Banners.SeasonBanners.AddRange(seasonBanners); tvdbSeries.Banners.AddRange(seasonBanners);
} }
private void WithUseBanners() private void WithUseBanners()
@ -83,18 +82,19 @@ namespace NzbDrone.Core.Test.ProviderTests.Metadata
var seasonBanners = Builder<TvdbSeasonBanner> var seasonBanners = Builder<TvdbSeasonBanner>
.CreateListOfSize(2) .CreateListOfSize(2)
.All() .All()
.With(b => b.SeasonNumber = 0) .With(b => b.Season = 0)
.TheFirst(1) .TheFirst(1)
.With(b => b.BannerType = TvdbSeasonBanner.Type.Poster) .With(b => b.BannerType = TvdbSeasonBanner.Type.season)
.With(b => b.BannerPath = "seasons/79488-0-1.jpg") .With(b => b.BannerPath = "seasons/79488-0-1.jpg")
.TheLast(1) .TheLast(1)
.With(b => b.BannerType = TvdbSeasonBanner.Type.Banner) .With(b => b.BannerType = TvdbSeasonBanner.Type.seasonwide)
.With(b => b.BannerPath = "banners/seasons/79488-0-1.jpg") .With(b => b.BannerPath = "banners/seasons/79488-0-1.jpg")
.Build(); .Build();
var seriesActors = Builder<TvdbActor> var seriesActors = Builder<TvdbActor>
.CreateListOfSize(5) .CreateListOfSize(5)
.All() .All()
.With(a => a.ActorImage = Builder<TvdbActorBanner>.CreateNew().Build())
.Build(); .Build();
tvdbSeries = Builder<TvdbSeries> tvdbSeries = Builder<TvdbSeries>
@ -102,11 +102,9 @@ namespace NzbDrone.Core.Test.ProviderTests.Metadata
.With(s => s.Id = 79488) .With(s => s.Id = 79488)
.With(s => s.SeriesName = "30 Rock") .With(s => s.SeriesName = "30 Rock")
.With(s => s.TvdbActors = seriesActors.ToList()) .With(s => s.TvdbActors = seriesActors.ToList())
.With(s => s.Banners = new TvdbBanners())
.With(s => s.Genres = new List<String> { "Comedy" })
.Build(); .Build();
tvdbSeries.Banners.SeasonBanners.AddRange(seasonBanners); tvdbSeries.Banners.AddRange(seasonBanners);
} }
[Test] [Test]
@ -126,14 +124,14 @@ namespace NzbDrone.Core.Test.ProviderTests.Metadata
public void should_download_fanart() public void should_download_fanart()
{ {
Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries); Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries);
Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.Fanart, Path.Combine(series.Path, "fanart.jpg")), Times.Once()); Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.FanartPath, Path.Combine(series.Path, "fanart.jpg")), Times.Once());
} }
[Test] [Test]
public void should_download_poster_when_useBanners_is_false() public void should_download_poster_when_useBanners_is_false()
{ {
Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries); Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries);
Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.Poster, Path.Combine(series.Path, "folder.jpg")), Times.Once()); Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.PosterPath, Path.Combine(series.Path, "folder.jpg")), Times.Once());
} }
[Test] [Test]
@ -141,7 +139,7 @@ namespace NzbDrone.Core.Test.ProviderTests.Metadata
{ {
WithUseBanners(); WithUseBanners();
Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries); Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries);
Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.Banner, Path.Combine(series.Path, "folder.jpg")), Times.Once()); Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.BannerPath, Path.Combine(series.Path, "folder.jpg")), Times.Once());
} }
[Test] [Test]

@ -18,6 +18,7 @@ using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq; using NzbDrone.Test.Common.AutoMoq;
using PetaPoco; using PetaPoco;
using TvdbLib.Data;
namespace NzbDrone.Core.Test.ProviderTests.RecycleBinProviderTests namespace NzbDrone.Core.Test.ProviderTests.RecycleBinProviderTests
{ {

@ -18,6 +18,7 @@ using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq; using NzbDrone.Test.Common.AutoMoq;
using PetaPoco; using PetaPoco;
using TvdbLib.Data;
namespace NzbDrone.Core.Test.ProviderTests.RecycleBinProviderTests namespace NzbDrone.Core.Test.ProviderTests.RecycleBinProviderTests
{ {

@ -18,6 +18,7 @@ using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq; using NzbDrone.Test.Common.AutoMoq;
using PetaPoco; using PetaPoco;
using TvdbLib.Data;
namespace NzbDrone.Core.Test.ProviderTests.RecycleBinProviderTests namespace NzbDrone.Core.Test.ProviderTests.RecycleBinProviderTests
{ {

@ -18,6 +18,7 @@ using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq; using NzbDrone.Test.Common.AutoMoq;
using PetaPoco; using PetaPoco;
using TvdbLib.Data;
namespace NzbDrone.Core.Test.ProviderTests.RecycleBinProviderTests namespace NzbDrone.Core.Test.ProviderTests.RecycleBinProviderTests
{ {

@ -185,7 +185,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests
} }
[Test] [Test]
public void EpisodeSearch_should_skip_if_air_date_is_null() public void EpisodeSearch_should_skip_if_air_date_is_null_and_is_a_daily_series()
{ {
//Setup //Setup
_series.IsDaily = true; _series.IsDaily = true;

@ -16,6 +16,7 @@ using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq; using NzbDrone.Test.Common.AutoMoq;
using PetaPoco; using PetaPoco;
using TvdbLib.Data;
namespace NzbDrone.Core.Test.ProviderTests namespace NzbDrone.Core.Test.ProviderTests
{ {

@ -10,8 +10,8 @@ using NzbDrone.Common;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
using XemLib.Data; using TvdbLib.Data;
using XemLib.Exceptions; using TvdbLib.Exceptions;
namespace NzbDrone.Core.Test.ProviderTests namespace NzbDrone.Core.Test.ProviderTests
{ {
@ -30,7 +30,7 @@ namespace NzbDrone.Core.Test.ProviderTests
[TearDown] [TearDown]
public void TearDown() public void TearDown()
{ {
ExceptionVerification.MarkInconclusive(typeof(TheTvbdbUnavailableException)); ExceptionVerification.MarkInconclusive(typeof(TvdbNotAvailableException));
} }
[TestCase("The Simpsons")] [TestCase("The Simpsons")]

@ -0,0 +1,77 @@
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.Notification;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ProviderTests.XemCommunicationProviderTests
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class GetSceneTvdbMappingsFixture : CoreTest
{
private void WithFailureJson()
{
Mocker.GetMock<HttpProvider>().Setup(s => s.DownloadString(It.IsAny<String>()))
.Returns(File.ReadAllText(@".\Files\Xem\Failure.txt"));
}
private void WithIdsJson()
{
Mocker.GetMock<HttpProvider>().Setup(s => s.DownloadString(It.IsAny<String>()))
.Returns(File.ReadAllText(@".\Files\Xem\Ids.txt"));
}
private void WithMappingsJson()
{
Mocker.GetMock<HttpProvider>().Setup(s => s.DownloadString(It.IsAny<String>()))
.Returns(File.ReadAllText(@".\Files\Xem\Mappings.txt"));
}
[Test]
public void should_throw_when_failure_is_found()
{
WithFailureJson();
Assert.Throws<Exception>(() => Mocker.Resolve<XemCommunicationProvider>().GetSceneTvdbMappings(12345));
}
[Test]
public void should_get_list_of_mappings()
{
WithMappingsJson();
Mocker.Resolve<XemCommunicationProvider>().GetSceneTvdbMappings(12345).Should().NotBeEmpty();
}
[Test]
public void should_have_two_mappings()
{
WithMappingsJson();
Mocker.Resolve<XemCommunicationProvider>().GetSceneTvdbMappings(12345).Should().HaveCount(2);
}
[Test]
public void should_have_expected_results()
{
WithMappingsJson();
var results = Mocker.Resolve<XemCommunicationProvider>().GetSceneTvdbMappings(12345);
var first = results.First();
first.Scene.Absolute.Should().Be(1);
first.Scene.Season.Should().Be(1);
first.Scene.Episode.Should().Be(1);
first.Tvdb.Absolute.Should().Be(1);
first.Tvdb.Season.Should().Be(1);
first.Tvdb.Episode.Should().Be(1);
}
}
}

@ -0,0 +1,63 @@
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.Notification;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ProviderTests.XemCommunicationProviderTests
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class GetXemSeriesIdsFixture : CoreTest
{
private void WithFailureJson()
{
Mocker.GetMock<HttpProvider>().Setup(s => s.DownloadString(It.IsAny<String>()))
.Returns(File.ReadAllText(@".\Files\Xem\Failure.txt"));
}
private void WithIdsJson()
{
Mocker.GetMock<HttpProvider>().Setup(s => s.DownloadString(It.IsAny<String>()))
.Returns(File.ReadAllText(@".\Files\Xem\Ids.txt"));
}
private void WithMappingsJson()
{
Mocker.GetMock<HttpProvider>().Setup(s => s.DownloadString(It.IsAny<String>()))
.Returns(File.ReadAllText(@".\Files\Xem\Mappings.txt"));
}
[Test]
public void should_throw_when_failure_is_found()
{
WithFailureJson();
Assert.Throws<Exception>(() => Mocker.Resolve<XemCommunicationProvider>().GetXemSeriesIds());
}
[Test]
public void should_get_list_of_int()
{
WithIdsJson();
Mocker.Resolve<XemCommunicationProvider>().GetXemSeriesIds().Should().NotBeEmpty();
}
[Test]
public void should_have_two_ids()
{
WithIdsJson();
Mocker.Resolve<XemCommunicationProvider>().GetXemSeriesIds().Should().HaveCount(2);
}
}
}

@ -137,6 +137,7 @@ namespace NzbDrone.Core
Kernel.Bind<IJob>().To<RefreshEpisodeMetadata>().InSingletonScope(); Kernel.Bind<IJob>().To<RefreshEpisodeMetadata>().InSingletonScope();
Kernel.Bind<IJob>().To<CleanupRecycleBinJob>().InSingletonScope(); Kernel.Bind<IJob>().To<CleanupRecycleBinJob>().InSingletonScope();
Kernel.Bind<IJob>().To<EmptyRecycleBinJob>().InSingletonScope(); Kernel.Bind<IJob>().To<EmptyRecycleBinJob>().InSingletonScope();
Kernel.Bind<IJob>().To<XemUpdateJob>().InSingletonScope();
Kernel.Get<JobProvider>().Initialize(); Kernel.Get<JobProvider>().Initialize();
Kernel.Get<WebTimer>().StartTimer(30); Kernel.Get<WebTimer>().StartTimer(30);

@ -0,0 +1,20 @@
using System;
using System.Data;
using Migrator.Framework;
using NzbDrone.Common;
namespace NzbDrone.Core.Datastore.Migrations
{
[Migration(20121016)]
public class Migration20121016 : NzbDroneMigration
{
protected override void MainDbUpgrade()
{
Database.AddColumn("Episodes", new Column("SceneAbsoluteEpisodeNumber", DbType.Int32, ColumnProperty.Null));
Database.AddColumn("Episodes", new Column("SceneSeasonNumber", DbType.Int32, ColumnProperty.Null));
Database.AddColumn("Episodes", new Column("SceneEpisodeNumber", DbType.Int32, ColumnProperty.Null));
Database.AddColumn("Series", new Column("UseSceneNumbering", DbType.Boolean, ColumnProperty.Null));
}
}
}

@ -22,6 +22,7 @@ namespace NzbDrone.Core.Jobs
private readonly DiskScanJob _diskScanJob; private readonly DiskScanJob _diskScanJob;
private readonly BannerDownloadJob _bannerDownloadJob; private readonly BannerDownloadJob _bannerDownloadJob;
private readonly SeasonProvider _seasonProvider; private readonly SeasonProvider _seasonProvider;
private readonly XemUpdateJob _xemUpdateJob;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
@ -30,7 +31,8 @@ namespace NzbDrone.Core.Jobs
[Inject] [Inject]
public ImportNewSeriesJob(SeriesProvider seriesProvider, EpisodeProvider episodeProvider, public ImportNewSeriesJob(SeriesProvider seriesProvider, EpisodeProvider episodeProvider,
MediaFileProvider mediaFileProvider, UpdateInfoJob updateInfoJob, MediaFileProvider mediaFileProvider, UpdateInfoJob updateInfoJob,
DiskScanJob diskScanJob, BannerDownloadJob bannerDownloadJob,SeasonProvider seasonProvider) DiskScanJob diskScanJob, BannerDownloadJob bannerDownloadJob,
SeasonProvider seasonProvider, XemUpdateJob xemUpdateJob)
{ {
_seriesProvider = seriesProvider; _seriesProvider = seriesProvider;
_episodeProvider = episodeProvider; _episodeProvider = episodeProvider;
@ -39,6 +41,7 @@ namespace NzbDrone.Core.Jobs
_diskScanJob = diskScanJob; _diskScanJob = diskScanJob;
_bannerDownloadJob = bannerDownloadJob; _bannerDownloadJob = bannerDownloadJob;
_seasonProvider = seasonProvider; _seasonProvider = seasonProvider;
_xemUpdateJob = xemUpdateJob;
} }
public string Name public string Name
@ -81,6 +84,9 @@ namespace NzbDrone.Core.Jobs
//Download the banner for the new series //Download the banner for the new series
_bannerDownloadJob.Start(notification, new { SeriesId = updatedSeries.SeriesId }); _bannerDownloadJob.Start(notification, new { SeriesId = updatedSeries.SeriesId });
//Get Scene Numbering if applicable
_xemUpdateJob.Start(notification, new { SeriesId = updatedSeries.SeriesId });
notification.CurrentMessage = String.Format("{0} was successfully imported", updatedSeries.Title); notification.CurrentMessage = String.Format("{0} was successfully imported", updatedSeries.Title);
} }

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using Ninject;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Jobs
{
public class XemUpdateJob : IJob
{
private readonly XemProvider _xemProvider;
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
[Inject]
public XemUpdateJob(XemProvider xemProvider)
{
_xemProvider = xemProvider;
}
public XemUpdateJob()
{
}
public string Name
{
get { return "XEM Update"; }
}
public TimeSpan DefaultInterval
{
get { return TimeSpan.FromHours(12); }
}
public virtual void Start(ProgressNotification notification, dynamic options)
{
if (options == null || options.SeriesId == 0)
{
_logger.Trace("Starting XEM Update for all series");
_xemProvider.UpdateMappings();
}
else
{
_logger.Trace("Starting XEM Update for series: {0}", options.SeriesId);
_xemProvider.UpdateMappings(options.SeriesId);
}
_logger.Trace("XEM Update complete");
}
}
}

@ -46,6 +46,10 @@ namespace NzbDrone.Core.Model
public string ReleaseGroup { get; set; } public string ReleaseGroup { get; set; }
public bool SceneSource { get; set; }
public IList<Episode> Episodes { get; set; }
public override string ToString() public override string ToString()
{ {

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.Model.Xem
{
public class XemResult<T>
{
public string Result { get; set; }
public T Data { get; set; }
public string Message { get; set; }
}
}

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.Model.Xem
{
public class XemSceneTvdbMapping
{
public XemValues Scene { get; set; }
public XemValues Tvdb { get; set; }
}
}

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.Model.Xem
{
public class XemValues
{
public int Season { get; set; }
public int Episode { get; set; }
public int Absolute { get; set; }
}
}

@ -206,6 +206,10 @@
<Reference Include="System.Web.Extensions" /> <Reference Include="System.Web.Extensions" />
<Reference Include="System.XML" /> <Reference Include="System.XML" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="TvdbLib, Version=0.8.8.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Libraries\TvdbLib.dll</HintPath>
</Reference>
<Reference Include="Twitterizer2, Version=2.4.0.26532, Culture=neutral, PublicKeyToken=69d1469eac671567, processorArchitecture=MSIL"> <Reference Include="Twitterizer2, Version=2.4.0.26532, Culture=neutral, PublicKeyToken=69d1469eac671567, processorArchitecture=MSIL">
<HintPath>..\packages\twitterizer.2.4.0.26532\lib\net40\Twitterizer2.dll</HintPath> <HintPath>..\packages\twitterizer.2.4.0.26532\lib\net40\Twitterizer2.dll</HintPath>
</Reference> </Reference>
@ -213,9 +217,6 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\WebActivator.1.5\lib\net40\WebActivator.dll</HintPath> <HintPath>..\packages\WebActivator.1.5\lib\net40\WebActivator.dll</HintPath>
</Reference> </Reference>
<Reference Include="XemLib">
<HintPath>..\Libraries\XemLib\XemLib.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\NzbDrone.Common\Properties\SharedAssemblyInfo.cs"> <Compile Include="..\NzbDrone.Common\Properties\SharedAssemblyInfo.cs">
@ -226,6 +227,7 @@
<Compile Include="Datastore\MigrationLogger.cs" /> <Compile Include="Datastore\MigrationLogger.cs" />
<Compile Include="Datastore\MigrationsHelper.cs" /> <Compile Include="Datastore\MigrationsHelper.cs" />
<Compile Include="Datastore\CustomeMapper.cs" /> <Compile Include="Datastore\CustomeMapper.cs" />
<Compile Include="Datastore\Migrations\Migration20121016.cs" />
<Compile Include="Datastore\Migrations\Migration20121012.cs" /> <Compile Include="Datastore\Migrations\Migration20121012.cs" />
<Compile Include="Datastore\Migrations\Migration20120919.cs" /> <Compile Include="Datastore\Migrations\Migration20120919.cs" />
<Compile Include="Datastore\Migrations\Migration20120918.cs" /> <Compile Include="Datastore\Migrations\Migration20120918.cs" />
@ -256,6 +258,7 @@
<Compile Include="Helpers\SortHelper.cs" /> <Compile Include="Helpers\SortHelper.cs" />
<Compile Include="Helpers\SabnzbdPriorityTypeConverter.cs" /> <Compile Include="Helpers\SabnzbdPriorityTypeConverter.cs" />
<Compile Include="Jobs\CleanupRecycleBinJob.cs" /> <Compile Include="Jobs\CleanupRecycleBinJob.cs" />
<Compile Include="Jobs\XemUpdateJob.cs" />
<Compile Include="Jobs\EmptyRecycleBinJob.cs" /> <Compile Include="Jobs\EmptyRecycleBinJob.cs" />
<Compile Include="Jobs\RefreshEpsiodeMetadata.cs" /> <Compile Include="Jobs\RefreshEpsiodeMetadata.cs" />
<Compile Include="Jobs\PastWeekBacklogSearchJob.cs" /> <Compile Include="Jobs\PastWeekBacklogSearchJob.cs" />
@ -291,6 +294,9 @@
<Compile Include="Model\Xbmc\TvShowResult.cs" /> <Compile Include="Model\Xbmc\TvShowResult.cs" />
<Compile Include="Model\Xbmc\ErrorResult.cs" /> <Compile Include="Model\Xbmc\ErrorResult.cs" />
<Compile Include="Model\Xbmc\IconType.cs" /> <Compile Include="Model\Xbmc\IconType.cs" />
<Compile Include="Model\Xem\XemResult.cs" />
<Compile Include="Model\Xem\XemSceneTvdbMapping.cs" />
<Compile Include="Model\Xem\XemValues.cs" />
<Compile Include="Providers\BannerProvider.cs" /> <Compile Include="Providers\BannerProvider.cs" />
<Compile Include="Providers\DecisionEngine\AllowedReleaseGroupSpecification.cs" /> <Compile Include="Providers\DecisionEngine\AllowedReleaseGroupSpecification.cs" />
<Compile Include="Providers\DecisionEngine\CustomStartDateSpecification.cs" /> <Compile Include="Providers\DecisionEngine\CustomStartDateSpecification.cs" />
@ -329,6 +335,8 @@
<Compile Include="Jobs\RssSyncJob.cs" /> <Compile Include="Jobs\RssSyncJob.cs" />
<Compile Include="Jobs\UpdateInfoJob.cs" /> <Compile Include="Jobs\UpdateInfoJob.cs" />
<Compile Include="Providers\StatsProvider.cs" /> <Compile Include="Providers\StatsProvider.cs" />
<Compile Include="Providers\XemCommunicationProvider.cs" />
<Compile Include="Providers\XemProvider.cs" />
<Compile Include="Repository\MetadataDefinition.cs" /> <Compile Include="Repository\MetadataDefinition.cs" />
<Compile Include="Repository\Quality\QualityTypes.cs" /> <Compile Include="Repository\Quality\QualityTypes.cs" />
<Compile Include="Repository\Search\SearchHistoryItem.cs" /> <Compile Include="Repository\Search\SearchHistoryItem.cs" />

@ -42,6 +42,7 @@ namespace NzbDrone.Core.Providers.DecisionEngine
} }
var episodes = _episodeProvider.GetEpisodesByParseResult(subject); var episodes = _episodeProvider.GetEpisodesByParseResult(subject);
subject.Episodes = episodes;
//return monitored if any of the episodes are monitored //return monitored if any of the episodes are monitored
if (episodes.Any(episode => !episode.Ignored)) if (episodes.Any(episode => !episode.Ignored))

@ -24,7 +24,7 @@ namespace NzbDrone.Core.Providers.DecisionEngine
public virtual bool IsSatisfiedBy(EpisodeParseResult subject) public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
{ {
foreach (var file in _episodeProvider.GetEpisodesByParseResult(subject).Select(c => c.EpisodeFile).Where(c => c != null)) foreach (var file in subject.Episodes.Select(c => c.EpisodeFile).Where(c => c != null))
{ {
logger.Trace("Comparing file quality with report. Existing file is {0} proper:{1}", file.Quality, file.Proper); logger.Trace("Comparing file quality with report. Existing file is {0} proper:{1}", file.Quality, file.Proper);
if (!_qualityUpgradeSpecification.IsSatisfiedBy(new QualityModel { Quality = file.Quality, Proper = file.Proper }, subject.Quality, subject.Series.QualityProfile.Cutoff)) if (!_qualityUpgradeSpecification.IsSatisfiedBy(new QualityModel { Quality = file.Quality, Proper = file.Proper }, subject.Quality, subject.Series.QualityProfile.Cutoff))

@ -27,7 +27,7 @@ namespace NzbDrone.Core.Providers.DecisionEngine
public virtual bool IsSatisfiedBy(EpisodeParseResult subject) public virtual bool IsSatisfiedBy(EpisodeParseResult subject)
{ {
foreach (var episode in _episodeProvider.GetEpisodesByParseResult(subject)) foreach (var episode in subject.Episodes)
{ {
var bestQualityInHistory = _historyProvider.GetBestQualityInHistory(subject.Series.SeriesId, episode.SeasonNumber, episode.EpisodeNumber); var bestQualityInHistory = _historyProvider.GetBestQualityInHistory(subject.Series.SeriesId, episode.SeasonNumber, episode.EpisodeNumber);
if (bestQualityInHistory != null) if (bestQualityInHistory != null)

@ -122,6 +122,9 @@ namespace NzbDrone.Core.Providers
if (parseResult == null) if (parseResult == null)
return null; return null;
if (!_diskProvider.IsChildOfPath(filePath, series.Path))
parseResult.SceneSource = true;
parseResult.SeriesTitle = series.Title; //replaces the nasty path as title to help with logging parseResult.SeriesTitle = series.Title; //replaces the nasty path as title to help with logging
parseResult.Series = series; parseResult.Series = series;
@ -203,6 +206,7 @@ namespace NzbDrone.Core.Providers
var parseResult = Parser.ParsePath(episodeFile.Path); var parseResult = Parser.ParsePath(episodeFile.Path);
parseResult.Series = series; parseResult.Series = series;
parseResult.Quality = new QualityModel{ Quality = episodeFile.Quality, Proper = episodeFile.Proper }; parseResult.Quality = new QualityModel{ Quality = episodeFile.Quality, Proper = episodeFile.Proper };
parseResult.Episodes = episodes;
var message = _downloadProvider.GetDownloadTitle(parseResult); var message = _downloadProvider.GetDownloadTitle(parseResult);

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Ninject; using Ninject;
using NLog; using NLog;
using NzbDrone.Core.Model; using NzbDrone.Core.Model;
@ -48,13 +49,13 @@ namespace NzbDrone.Core.Providers
var provider = GetActiveDownloadClient(); var provider = GetActiveDownloadClient();
bool success = provider.DownloadNzb(parseResult.NzbUrl, GetDownloadTitle(parseResult)); bool success = provider.DownloadNzb(parseResult.NzbUrl, downloadTitle);
if (success) if (success)
{ {
logger.Trace("Download added to Queue: {0}", downloadTitle); logger.Trace("Download added to Queue: {0}", downloadTitle);
foreach (var episode in _episodeProvider.GetEpisodesByParseResult(parseResult)) foreach (var episode in parseResult.Episodes)
{ {
var history = new History var history = new History
{ {
@ -115,7 +116,7 @@ namespace NzbDrone.Core.Providers
if (parseResult.Series.IsDaily) if (parseResult.Series.IsDaily)
{ {
var dailyResult = String.Format("{0} - {1:yyyy-MM-dd} - {2} [{3}]", seriesTitle, var dailyResult = String.Format("{0} - {1:yyyy-MM-dd} - {2} [{3}]", seriesTitle,
parseResult.AirDate, parseResult.EpisodeTitle, parseResult.Quality.Quality); parseResult.AirDate, parseResult.Episodes.First().Title, parseResult.Quality.Quality);
if (parseResult.Quality.Proper) if (parseResult.Quality.Proper)
dailyResult += " [Proper]"; dailyResult += " [Proper]";
@ -126,15 +127,25 @@ namespace NzbDrone.Core.Providers
//Show Name - 1x01-1x02 - Episode Name //Show Name - 1x01-1x02 - Episode Name
//Show Name - 1x01 - Episode Name //Show Name - 1x01 - Episode Name
var episodeString = new List<String>(); var episodeString = new List<String>();
var episodeNames = new List<String>();
foreach (var episode in parseResult.EpisodeNumbers) foreach (var episode in parseResult.Episodes)
{ {
episodeString.Add(String.Format("{0}x{1:00}", parseResult.SeasonNumber, episode)); episodeString.Add(String.Format("{0}x{1:00}", episode.SeasonNumber, episode.EpisodeNumber));
episodeNames.Add(Parser.CleanupEpisodeTitle(episode.Title));
} }
var epNumberString = String.Join("-", episodeString); var epNumberString = String.Join("-", episodeString);
string episodeName;
var result = String.Format("{0} - {1} - {2} [{3}]", seriesTitle, epNumberString, parseResult.EpisodeTitle, parseResult.Quality.Quality);
if (episodeNames.Distinct().Count() == 1)
episodeName = episodeNames.First();
else
episodeName = String.Join(" + ", episodeNames.Distinct());
var result = String.Format("{0} - {1} - {2} [{3}]", seriesTitle, epNumberString, episodeName, parseResult.Quality.Quality);
if (parseResult.Quality.Proper) if (parseResult.Quality.Proper)
{ {

@ -7,7 +7,7 @@ using NLog;
using NzbDrone.Core.Model; using NzbDrone.Core.Model;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using PetaPoco; using PetaPoco;
using XemLib.Data; using TvdbLib.Data;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers
{ {
@ -188,11 +188,20 @@ namespace NzbDrone.Core.Providers
foreach (var episodeNumber in parseResult.EpisodeNumbers) foreach (var episodeNumber in parseResult.EpisodeNumbers)
{ {
var episodeInfo = GetEpisode(parseResult.Series.SeriesId, parseResult.SeasonNumber, episodeNumber); Episode episodeInfo = null;
if (episodeInfo == null && parseResult.AirDate != null)
if (parseResult.SceneSource && parseResult.Series.UseSceneNumbering)
episodeInfo = GetEpisodeBySceneNumbering(parseResult.Series.SeriesId, parseResult.SeasonNumber, episodeNumber);
if (episodeInfo == null)
{ {
episodeInfo = GetEpisode(parseResult.Series.SeriesId, parseResult.AirDate.Value); episodeInfo = GetEpisode(parseResult.Series.SeriesId, parseResult.SeasonNumber, episodeNumber);
if (episodeInfo == null && parseResult.AirDate != null)
{
episodeInfo = GetEpisode(parseResult.Series.SeriesId, parseResult.AirDate.Value);
}
} }
//if still null we should add the temp episode //if still null we should add the temp episode
if (episodeInfo == null && autoAddNew) if (episodeInfo == null && autoAddNew)
{ {
@ -217,6 +226,16 @@ namespace NzbDrone.Core.Providers
{ {
result.Add(episodeInfo); result.Add(episodeInfo);
if (parseResult.Series.UseSceneNumbering)
{
logger.Info("Using Scene to TVDB Mapping for: {0} - Scene: {1}x{2:00} - TVDB: {3}x{4:00}",
parseResult.Series.Title,
episodeInfo.SceneSeasonNumber,
episodeInfo.SceneEpisodeNumber,
episodeInfo.SeasonNumber,
episodeInfo.EpisodeNumber);
}
if (parseResult.EpisodeNumbers.Count == 1) if (parseResult.EpisodeNumbers.Count == 1)
{ {
parseResult.EpisodeTitle = episodeInfo.Title.Trim(); parseResult.EpisodeTitle = episodeInfo.Title.Trim();
@ -331,7 +350,7 @@ namespace NzbDrone.Core.Providers
episodeToUpdate.TvDbEpisodeId = episode.Id; episodeToUpdate.TvDbEpisodeId = episode.Id;
episodeToUpdate.EpisodeNumber = episode.EpisodeNumber; episodeToUpdate.EpisodeNumber = episode.EpisodeNumber;
episodeToUpdate.SeasonNumber = episode.SeasonNumber; episodeToUpdate.SeasonNumber = episode.SeasonNumber;
episodeToUpdate.AbsoluteEpisodeNumber = episode.AbsoluteEpisodeNumber; episodeToUpdate.AbsoluteEpisodeNumber = episode.AbsoluteNumber;
episodeToUpdate.Title = episode.EpisodeName; episodeToUpdate.Title = episode.EpisodeName;
episodeToUpdate.Overview = episode.Overview.Truncate(3500); episodeToUpdate.Overview = episode.Overview.Truncate(3500);
@ -435,5 +454,26 @@ namespace NzbDrone.Core.Providers
logger.Trace("Updating PostDownloadStatus for all episodeIds in {0}", episodeIdString); logger.Trace("Updating PostDownloadStatus for all episodeIds in {0}", episodeIdString);
_database.Execute(episodeIdQuery); _database.Execute(episodeIdQuery);
} }
public virtual void UpdateEpisodes(List<Episode> episodes)
{
_database.UpdateMany(episodes);
}
public virtual Episode GetEpisodeBySceneNumbering(int seriesId, int seasonNumber, int episodeNumber)
{
var episode = _database.Fetch<Episode, Series, EpisodeFile>(@"SELECT * FROM Episodes
INNER JOIN Series ON Episodes.SeriesId = Series.SeriesId
LEFT JOIN EpisodeFiles ON Episodes.EpisodeFileId = EpisodeFiles.EpisodeFileId
WHERE Episodes.SeriesId = @0 AND Episodes.SceneSeasonNumber = @1 AND Episodes.SceneEpisodeNumber = @2", seriesId, seasonNumber, episodeNumber).SingleOrDefault();
if (episode == null)
return null;
if (episode.EpisodeFileId == 0)
episode.EpisodeFile = null;
return episode;
}
} }
} }

@ -247,6 +247,7 @@ namespace NzbDrone.Core.Providers.Indexer
{ {
episodeParseResult.Age = DateTime.Now.Date.Subtract(item.PublishDate.Date).Days; episodeParseResult.Age = DateTime.Now.Date.Subtract(item.PublishDate.Date).Days;
episodeParseResult.OriginalString = title; episodeParseResult.OriginalString = title;
episodeParseResult.SceneSource = true;
} }
_logger.Trace("Parsed: {0} from: {1}", episodeParseResult, item.Title.Text); _logger.Trace("Parsed: {0} from: {1}", episodeParseResult, item.Title.Text);

@ -208,7 +208,7 @@ namespace NzbDrone.Core.Providers
result += separatorStyle.Pattern + episodeNames.First(); result += separatorStyle.Pattern + episodeNames.First();
else else
result += separatorStyle.Pattern + String.Join(" + ", episodeNames); result += separatorStyle.Pattern + String.Join(" + ", episodeNames.Distinct());
} }
if (_configProvider.SortingAppendQuality) if (_configProvider.SortingAppendQuality)

@ -4,7 +4,7 @@ using NzbDrone.Common;
using NzbDrone.Core.Model; using NzbDrone.Core.Model;
using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using XemLib.Data; using TvdbLib.Data;
namespace NzbDrone.Core.Providers.Metadata namespace NzbDrone.Core.Providers.Metadata
{ {

@ -8,8 +8,8 @@ using NzbDrone.Common;
using NzbDrone.Core.Model; using NzbDrone.Core.Model;
using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using XemLib.Data; using TvdbLib.Data;
using XemLib.Data.Banner; using TvdbLib.Data.Banner;
namespace NzbDrone.Core.Providers.Metadata namespace NzbDrone.Core.Providers.Metadata
{ {
@ -48,16 +48,16 @@ namespace NzbDrone.Core.Providers.Metadata
tvShow.Add(new XElement("episodeguideurl", episodeGuideUrl)); tvShow.Add(new XElement("episodeguideurl", episodeGuideUrl));
tvShow.Add(new XElement("mpaa", tvDbSeries.ContentRating)); tvShow.Add(new XElement("mpaa", tvDbSeries.ContentRating));
tvShow.Add(new XElement("id", tvDbSeries.Id)); tvShow.Add(new XElement("id", tvDbSeries.Id));
tvShow.Add(new XElement("genre", tvDbSeries.Genres.FirstOrDefault())); tvShow.Add(new XElement("genre", tvDbSeries.GenreString.Trim('|').Split('|')[0]));
tvShow.Add(new XElement("premiered", tvDbSeries.FirstAired.ToString("yyyy-MM-dd"))); tvShow.Add(new XElement("premiered", tvDbSeries.FirstAired.ToString("yyyy-MM-dd")));
tvShow.Add(new XElement("studio", tvDbSeries.Network)); tvShow.Add(new XElement("studio", tvDbSeries.Network));
foreach(var actor in tvDbSeries.TvdbActors) foreach(var actor in tvDbSeries.TvdbActors)
{ {
tvShow.Add(new XElement("actor", tvShow.Add(new XElement("actor",
new XElement("name", actor.Name), new XElement("name", actor.Name),
new XElement("role", actor.Role), new XElement("role", actor.Role),
new XElement("thumb", "http://www.thetvdb.com/banners/" + actor.Image) new XElement("thumb", "http://www.thetvdb.com/banners/" + actor.ActorImage.BannerPath)
)); ));
} }
@ -71,7 +71,7 @@ namespace NzbDrone.Core.Providers.Metadata
if (!_diskProvider.FileExists(Path.Combine(series.Path, "fanart.jpg"))) if (!_diskProvider.FileExists(Path.Combine(series.Path, "fanart.jpg")))
{ {
_logger.Debug("Downloading fanart for: {0}", series.Title); _logger.Debug("Downloading fanart for: {0}", series.Title);
_bannerProvider.Download(tvDbSeries.Fanart, Path.Combine(series.Path, "fanart.jpg")); _bannerProvider.Download(tvDbSeries.FanartPath, Path.Combine(series.Path, "fanart.jpg"));
} }
if (!_diskProvider.FileExists(Path.Combine(series.Path, "folder.jpg"))) if (!_diskProvider.FileExists(Path.Combine(series.Path, "folder.jpg")))
@ -79,19 +79,19 @@ namespace NzbDrone.Core.Providers.Metadata
if(_configProvider.MetadataUseBanners) if(_configProvider.MetadataUseBanners)
{ {
_logger.Debug("Downloading series banner for: {0}", series.Title); _logger.Debug("Downloading series banner for: {0}", series.Title);
_bannerProvider.Download(tvDbSeries.Banner, Path.Combine(series.Path, "folder.jpg")); _bannerProvider.Download(tvDbSeries.BannerPath, Path.Combine(series.Path, "folder.jpg"));
_logger.Debug("Downloading Season banners for {0}", series.Title); _logger.Debug("Downloading Season banners for {0}", series.Title);
DownloadSeasonThumbnails(series, tvDbSeries, TvdbSeasonBanner.Type.Banner); DownloadSeasonThumbnails(series, tvDbSeries, TvdbSeasonBanner.Type.seasonwide);
} }
else else
{ {
_logger.Debug("Downloading series thumbnail for: {0}", series.Title); _logger.Debug("Downloading series thumbnail for: {0}", series.Title);
_bannerProvider.Download(tvDbSeries.Poster, Path.Combine(series.Path, "folder.jpg")); _bannerProvider.Download(tvDbSeries.PosterPath, Path.Combine(series.Path, "folder.jpg"));
_logger.Debug("Downloading Season posters for {0}", series.Title); _logger.Debug("Downloading Season posters for {0}", series.Title);
DownloadSeasonThumbnails(series, tvDbSeries, TvdbSeasonBanner.Type.Poster); DownloadSeasonThumbnails(series, tvDbSeries, TvdbSeasonBanner.Type.season);
} }
} }
} }
@ -112,7 +112,7 @@ namespace NzbDrone.Core.Providers.Metadata
e.SeasonNumber == episodeFile.SeasonNumber && e.SeasonNumber == episodeFile.SeasonNumber &&
e.EpisodeNumber == episodes.First().EpisodeNumber); e.EpisodeNumber == episodes.First().EpisodeNumber);
if (episodeFileThumbnail == null || String.IsNullOrWhiteSpace(episodeFileThumbnail.Banner)) if (episodeFileThumbnail == null || String.IsNullOrWhiteSpace(episodeFileThumbnail.BannerPath))
{ {
_logger.Debug("No thumbnail is available for this episode"); _logger.Debug("No thumbnail is available for this episode");
return; return;
@ -121,7 +121,7 @@ namespace NzbDrone.Core.Providers.Metadata
if (!_diskProvider.FileExists(episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".tbn"))) if (!_diskProvider.FileExists(episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".tbn")))
{ {
_logger.Debug("Downloading episode thumbnail for: {0}", episodeFile.EpisodeFileId); _logger.Debug("Downloading episode thumbnail for: {0}", episodeFile.EpisodeFileId);
_bannerProvider.Download(episodeFileThumbnail.Banner, _bannerProvider.Download(episodeFileThumbnail.BannerPath,
episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".tbn")); episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".tbn"));
} }
@ -165,9 +165,9 @@ namespace NzbDrone.Core.Providers.Metadata
details.Add(new XElement("plot", tvdbEpisode.Overview)); details.Add(new XElement("plot", tvdbEpisode.Overview));
details.Add(new XElement("displayseason")); details.Add(new XElement("displayseason"));
details.Add(new XElement("displayepisode")); details.Add(new XElement("displayepisode"));
details.Add(new XElement("thumb", "http://www.thetvdb.com/banners/" + tvdbEpisode.Banner)); details.Add(new XElement("thumb", "http://www.thetvdb.com/banners/" + tvdbEpisode.BannerPath));
details.Add(new XElement("watched", "false")); details.Add(new XElement("watched", "false"));
details.Add(new XElement("credits", tvdbEpisode.Writers.FirstOrDefault())); details.Add(new XElement("credits", tvdbEpisode.Writer.FirstOrDefault()));
details.Add(new XElement("director", tvdbEpisode.Directors.FirstOrDefault())); details.Add(new XElement("director", tvdbEpisode.Directors.FirstOrDefault()));
details.Add(new XElement("rating", tvdbEpisode.Rating)); details.Add(new XElement("rating", tvdbEpisode.Rating));
@ -186,7 +186,7 @@ namespace NzbDrone.Core.Providers.Metadata
details.Add(new XElement("actor", details.Add(new XElement("actor",
new XElement("name", actor.Name), new XElement("name", actor.Name),
new XElement("role", actor.Role), new XElement("role", actor.Role),
new XElement("thumb", "http://www.thetvdb.com/banners/" + actor.Image) new XElement("thumb", "http://www.thetvdb.com/banners/" + actor.ActorImage.BannerPath)
)); ));
} }
@ -235,11 +235,11 @@ namespace NzbDrone.Core.Providers.Metadata
private void DownloadSeasonThumbnails(Series series, TvdbSeries tvDbSeries, TvdbSeasonBanner.Type bannerType) private void DownloadSeasonThumbnails(Series series, TvdbSeries tvDbSeries, TvdbSeasonBanner.Type bannerType)
{ {
var seasons = tvDbSeries.Banners.SeasonBanners.Where(s => s.BannerType == bannerType).Select(s => s.SeasonNumber); var seasons = tvDbSeries.SeasonBanners.Where(s => s.BannerType == bannerType).Select(s => s.Season);
foreach (var season in seasons) foreach (var season in seasons)
{ {
var banner = tvDbSeries.Banners.SeasonBanners.FirstOrDefault(b => b.BannerType == bannerType && b.SeasonNumber == season); var banner = tvDbSeries.SeasonBanners.FirstOrDefault(b => b.BannerType == bannerType && b.Season == season);
_logger.Debug("Downloading banner for Season: {0} Series: {1}", season, series.Title); _logger.Debug("Downloading banner for Season: {0} Series: {1}", season, series.Title);
if (season == 0) if (season == 0)

@ -8,7 +8,7 @@ using NzbDrone.Core.Providers.ExternalNotification;
using NzbDrone.Core.Providers.Metadata; using NzbDrone.Core.Providers.Metadata;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using PetaPoco; using PetaPoco;
using XemLib.Data; using TvdbLib.Data;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers
{ {
@ -92,7 +92,7 @@ namespace NzbDrone.Core.Providers
public virtual void CreateForSeries(Series series) public virtual void CreateForSeries(Series series)
{ {
var tvDbSeries = _tvDbProvider.GetSeries(series.SeriesId, false, true, true); var tvDbSeries = _tvDbProvider.GetSeries(series.SeriesId, false, true);
CreateForSeries(series, tvDbSeries); CreateForSeries(series, tvDbSeries);
} }
@ -107,7 +107,7 @@ namespace NzbDrone.Core.Providers
public virtual void CreateForEpisodeFile(EpisodeFile episodeFile) public virtual void CreateForEpisodeFile(EpisodeFile episodeFile)
{ {
var tvDbSeries = _tvDbProvider.GetSeries(episodeFile.SeriesId, true, true, true); var tvDbSeries = _tvDbProvider.GetSeries(episodeFile.SeriesId, true, true);
CreateForEpisodeFile(episodeFile, tvDbSeries); CreateForEpisodeFile(episodeFile, tvDbSeries);
} }
@ -130,7 +130,7 @@ namespace NzbDrone.Core.Providers
Logger.Trace("Creating metadata for {0} files.", episodeFiles.Count); Logger.Trace("Creating metadata for {0} files.", episodeFiles.Count);
var tvDbSeries = _tvDbProvider.GetSeries(episodeFiles.First().SeriesId, true, true, true); var tvDbSeries = _tvDbProvider.GetSeries(episodeFiles.First().SeriesId, true, true);
foreach(var episodeFile in episodeFiles) foreach(var episodeFile in episodeFiles)
{ {

@ -112,6 +112,8 @@ namespace NzbDrone.Core.Providers
parseResult.NzbUrl = item.NzbUrl; parseResult.NzbUrl = item.NzbUrl;
parseResult.Series = series; parseResult.Series = series;
parseResult.Indexer = item.Indexer; parseResult.Indexer = item.Indexer;
parseResult.Episodes = _episodeProvider.GetEpisodesByParseResult(parseResult);
parseResult.SceneSource = true;
logger.Info("Forcing Download of: {0}", item.ReportTitle); logger.Info("Forcing Download of: {0}", item.ReportTitle);
_downloadProvider.DownloadReport(parseResult); _downloadProvider.DownloadReport(parseResult);

@ -25,7 +25,7 @@ namespace NzbDrone.Core.Providers
private readonly AllowedDownloadSpecification _allowedDownloadSpecification; private readonly AllowedDownloadSpecification _allowedDownloadSpecification;
private readonly SearchHistoryProvider _searchHistoryProvider; private readonly SearchHistoryProvider _searchHistoryProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
[Inject] [Inject]
public SearchProvider(EpisodeProvider episodeProvider, DownloadProvider downloadProvider, SeriesProvider seriesProvider, public SearchProvider(EpisodeProvider episodeProvider, DownloadProvider downloadProvider, SeriesProvider seriesProvider,
@ -60,7 +60,7 @@ namespace NzbDrone.Core.Providers
if (series == null) if (series == null)
{ {
Logger.Error("Unable to find an series {0} in database", seriesId); _logger.Error("Unable to find an series {0} in database", seriesId);
return new List<int>(); return new List<int>();
} }
@ -72,17 +72,17 @@ namespace NzbDrone.Core.Providers
var reports = PerformSearch(notification, series, seasonNumber); var reports = PerformSearch(notification, series, seasonNumber);
Logger.Debug("Finished searching all indexers. Total {0}", reports.Count); _logger.Debug("Finished searching all indexers. Total {0}", reports.Count);
if (reports.Count == 0) if (reports.Count == 0)
return new List<int>(); return new List<int>();
Logger.Debug("Getting episodes from database for series: {0} and season: {1}", seriesId, seasonNumber); _logger.Debug("Getting episodes from database for series: {0} and season: {1}", seriesId, seasonNumber);
var episodeNumbers = _episodeProvider.GetEpisodeNumbersBySeason(seriesId, seasonNumber); var episodeNumbers = _episodeProvider.GetEpisodeNumbersBySeason(seriesId, seasonNumber);
if (episodeNumbers == null || episodeNumbers.Count == 0) if (episodeNumbers == null || episodeNumbers.Count == 0)
{ {
Logger.Warn("No episodes in database found for series: {0} and season: {1}.", seriesId, seasonNumber); _logger.Warn("No episodes in database found for series: {0} and season: {1}.", seriesId, seasonNumber);
return new List<int>(); return new List<int>();
} }
@ -111,7 +111,7 @@ namespace NzbDrone.Core.Providers
if (series == null) if (series == null)
{ {
Logger.Error("Unable to find an series {0} in database", seriesId); _logger.Error("Unable to find an series {0} in database", seriesId);
return new List<int>(); return new List<int>();
} }
@ -122,7 +122,7 @@ namespace NzbDrone.Core.Providers
notification.CurrentMessage = String.Format("Searching for {0} Season {1}", series.Title, seasonNumber); notification.CurrentMessage = String.Format("Searching for {0} Season {1}", series.Title, seasonNumber);
var episodes = _episodeProvider.GetEpisodesBySeason(seriesId, seasonNumber); var episodes = _episodeProvider.GetEpisodesBySeason(seriesId, seasonNumber);
var reports = PerformSearch(notification, series, seasonNumber, episodes); var reports = PerformSearch(notification, series, seasonNumber, episodes);
Logger.Debug("Finished searching all indexers. Total {0}", reports.Count); _logger.Debug("Finished searching all indexers. Total {0}", reports.Count);
if (reports.Count == 0) if (reports.Count == 0)
return new List<int>(); return new List<int>();
@ -140,14 +140,14 @@ namespace NzbDrone.Core.Providers
if (episode == null) if (episode == null)
{ {
Logger.Error("Unable to find an episode {0} in database", episodeId); _logger.Error("Unable to find an episode {0} in database", episodeId);
return false; return false;
} }
//Check to see if an upgrade is possible before attempting //Check to see if an upgrade is possible before attempting
if (!_upgradePossibleSpecification.IsSatisfiedBy(episode)) if (!_upgradePossibleSpecification.IsSatisfiedBy(episode))
{ {
Logger.Info("Search for {0} was aborted, file in disk meets or exceeds Profile's Cutoff", 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}, the 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; return false;
} }
@ -156,7 +156,7 @@ namespace NzbDrone.Core.Providers
if (episode.Series.IsDaily && !episode.AirDate.HasValue) if (episode.Series.IsDaily && !episode.AirDate.HasValue)
{ {
Logger.Warn("AirDate is not Valid for: {0}", episode); _logger.Warn("AirDate is not Valid for: {0}", episode);
notification.CurrentMessage = String.Format("Search for {0} Failed, AirDate is invalid", episode); notification.CurrentMessage = String.Format("Search for {0} Failed, AirDate is invalid", episode);
return false; return false;
} }
@ -169,7 +169,7 @@ namespace NzbDrone.Core.Providers
var reports = PerformSearch(notification, episode.Series, episode.SeasonNumber, new List<Episode> { episode }); var reports = PerformSearch(notification, episode.Series, episode.SeasonNumber, new List<Episode> { episode });
Logger.Debug("Finished searching all indexers. Total {0}", reports.Count); _logger.Debug("Finished searching all indexers. Total {0}", reports.Count);
notification.CurrentMessage = "Processing search results"; notification.CurrentMessage = "Processing search results";
if (episode.Series.IsDaily) if (episode.Series.IsDaily)
@ -181,6 +181,34 @@ namespace NzbDrone.Core.Providers
return true; return true;
} }
else if (episode.Series.UseSceneNumbering)
{
searchResult.EpisodeId = episodeId;
var seasonNumber = episode.SceneSeasonNumber;
var episodeNumber = episode.SceneEpisodeNumber;
if (seasonNumber == 0 || episodeNumber == 0)
{
seasonNumber = episode.SeasonNumber;
episodeNumber = episode.EpisodeNumber;
}
searchResult.SearchHistoryItems = ProcessSearchResults(
notification,
reports,
searchResult,
episode.Series,
seasonNumber,
episodeNumber
);
_searchHistoryProvider.Add(searchResult);
if (searchResult.SearchHistoryItems.Any(r => r.Success))
return true;
}
else else
{ {
searchResult.EpisodeId = episodeId; searchResult.EpisodeId = episodeId;
@ -188,10 +216,10 @@ namespace NzbDrone.Core.Providers
_searchHistoryProvider.Add(searchResult); _searchHistoryProvider.Add(searchResult);
if (searchResult.SearchHistoryItems.Any(r => r.Success)) if (searchResult.SearchHistoryItems.Any(r => r.Success))
return true; return true;
} }
Logger.Warn("Unable to find {0} in any of indexers.", episode); _logger.Warn("Unable to find {0} in any of indexers.", episode);
if (reports.Any()) if (reports.Any())
{ {
@ -228,7 +256,12 @@ namespace NzbDrone.Core.Providers
//Treat as single episode //Treat as single episode
else if (episodes.Count == 1) else if (episodes.Count == 1)
{ {
if (!series.IsDaily) //Use SceneNumbering - Only if SceneSN and SceneEN are greater than zero
if (series.UseSceneNumbering && episodes.First().SceneSeasonNumber > 0 && episodes.First().SceneEpisodeNumber > 0)
reports.AddRange(indexer.FetchEpisode(title, episodes.First().SceneSeasonNumber, episodes.First().SceneEpisodeNumber));
//Standard
else if (!series.IsDaily)
reports.AddRange(indexer.FetchEpisode(title, seasonNumber, episodes.First().EpisodeNumber)); reports.AddRange(indexer.FetchEpisode(title, seasonNumber, episodes.First().EpisodeNumber));
//Daily Episode //Daily Episode
@ -250,7 +283,7 @@ namespace NzbDrone.Core.Providers
catch (Exception e) catch (Exception e)
{ {
Logger.ErrorException("An error has occurred while fetching items from " + indexer.Name, e); _logger.ErrorException("An error has occurred while fetching items from " + indexer.Name, e);
} }
}); });
@ -268,7 +301,7 @@ namespace NzbDrone.Core.Providers
{ {
try try
{ {
Logger.Trace("Analysing report " + episodeParseResult); _logger.Trace("Analysing report " + episodeParseResult);
var item = new SearchHistoryItem var item = new SearchHistoryItem
{ {
@ -290,7 +323,7 @@ namespace NzbDrone.Core.Providers
//If series is null or doesn't match the series we're looking for return //If series is null or doesn't match the series we're looking for return
if (episodeParseResult.Series == null || episodeParseResult.Series.SeriesId != series.SeriesId) if (episodeParseResult.Series == null || episodeParseResult.Series.SeriesId != series.SeriesId)
{ {
Logger.Trace("Unexpected series for search: {0}. Skipping.", episodeParseResult.CleanTitle); _logger.Trace("Unexpected series for search: {0}. Skipping.", episodeParseResult.CleanTitle);
item.SearchError = ReportRejectionType.WrongSeries; item.SearchError = ReportRejectionType.WrongSeries;
continue; continue;
} }
@ -298,7 +331,7 @@ namespace NzbDrone.Core.Providers
//If SeasonNumber doesn't match or episode is not in the in the list in the parse result, skip the report. //If SeasonNumber doesn't match or episode is not in the in the list in the parse result, skip the report.
if (episodeParseResult.SeasonNumber != seasonNumber) if (episodeParseResult.SeasonNumber != seasonNumber)
{ {
Logger.Trace("Season number does not match searched season number, skipping."); _logger.Trace("Season number does not match searched season number, skipping.");
item.SearchError = ReportRejectionType.WrongSeason; item.SearchError = ReportRejectionType.WrongSeason;
continue; continue;
} }
@ -306,7 +339,7 @@ namespace NzbDrone.Core.Providers
//If the EpisodeNumber was passed in and it is not contained in the parseResult, skip the report. //If the EpisodeNumber was passed in and it is not contained in the parseResult, skip the report.
if (episodeNumber.HasValue && !episodeParseResult.EpisodeNumbers.Contains(episodeNumber.Value)) if (episodeNumber.HasValue && !episodeParseResult.EpisodeNumbers.Contains(episodeNumber.Value))
{ {
Logger.Trace("Searched episode number is not contained in post, skipping."); _logger.Trace("Searched episode number is not contained in post, skipping.");
item.SearchError = ReportRejectionType.WrongEpisode; item.SearchError = ReportRejectionType.WrongEpisode;
continue; continue;
} }
@ -314,15 +347,17 @@ namespace NzbDrone.Core.Providers
//Make sure we haven't already downloaded a report with this episodenumber, if we have, skip the report. //Make sure we haven't already downloaded a report with this episodenumber, if we have, skip the report.
if (searchResult.Successes.Intersect(episodeParseResult.EpisodeNumbers).Any()) if (searchResult.Successes.Intersect(episodeParseResult.EpisodeNumbers).Any())
{ {
Logger.Trace("Episode has already been downloaded in this search, skipping."); _logger.Trace("Episode has already been downloaded in this search, skipping.");
item.SearchError = ReportRejectionType.Skipped; item.SearchError = ReportRejectionType.Skipped;
continue; continue;
} }
episodeParseResult.Episodes = _episodeProvider.GetEpisodesByParseResult(episodeParseResult);
item.SearchError = _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult); item.SearchError = _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult);
if (item.SearchError == ReportRejectionType.None) if (item.SearchError == ReportRejectionType.None)
{ {
Logger.Debug("Found '{0}'. Adding to download queue.", episodeParseResult); _logger.Debug("Found '{0}'. Adding to download queue.", episodeParseResult);
try try
{ {
if (_downloadProvider.DownloadReport(episodeParseResult)) if (_downloadProvider.DownloadReport(episodeParseResult))
@ -340,7 +375,7 @@ namespace NzbDrone.Core.Providers
} }
catch (Exception e) catch (Exception e)
{ {
Logger.ErrorException("Unable to add report to download queue." + episodeParseResult, 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); notification.CurrentMessage = String.Format("Unable to add report to download queue. {0}", episodeParseResult);
item.SearchError = ReportRejectionType.DownloadClientFailure; item.SearchError = ReportRejectionType.DownloadClientFailure;
} }
@ -348,7 +383,7 @@ namespace NzbDrone.Core.Providers
} }
catch (Exception e) catch (Exception e)
{ {
Logger.ErrorException("An error has occurred while processing parse result items from " + episodeParseResult, e); _logger.ErrorException("An error has occurred while processing parse result items from " + episodeParseResult, e);
} }
} }
@ -384,7 +419,7 @@ namespace NzbDrone.Core.Providers
continue; continue;
} }
Logger.Trace("Analysing report " + episodeParseResult); _logger.Trace("Analysing report " + episodeParseResult);
//Get the matching series //Get the matching series
episodeParseResult.Series = _seriesProvider.FindSeries(episodeParseResult.CleanTitle); episodeParseResult.Series = _seriesProvider.FindSeries(episodeParseResult.CleanTitle);
@ -403,10 +438,12 @@ namespace NzbDrone.Core.Providers
continue; continue;
} }
episodeParseResult.Episodes = _episodeProvider.GetEpisodesByParseResult(episodeParseResult);
item.SearchError = _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult); item.SearchError = _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult);
if (item.SearchError == ReportRejectionType.None) if (item.SearchError == ReportRejectionType.None)
{ {
Logger.Debug("Found '{0}'. Adding to download queue.", episodeParseResult); _logger.Debug("Found '{0}'. Adding to download queue.", episodeParseResult);
try try
{ {
if (_downloadProvider.DownloadReport(episodeParseResult)) if (_downloadProvider.DownloadReport(episodeParseResult))
@ -425,7 +462,7 @@ namespace NzbDrone.Core.Providers
} }
catch (Exception e) catch (Exception e)
{ {
Logger.ErrorException("Unable to add report to download queue." + episodeParseResult, 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); notification.CurrentMessage = String.Format("Unable to add report to download queue. {0}", episodeParseResult);
item.SearchError = ReportRejectionType.DownloadClientFailure; item.SearchError = ReportRejectionType.DownloadClientFailure;
} }
@ -433,7 +470,7 @@ namespace NzbDrone.Core.Providers
} }
catch (Exception e) catch (Exception e)
{ {
Logger.ErrorException("An error has occurred while processing parse result items from " + episodeParseResult, e); _logger.ErrorException("An error has occurred while processing parse result items from " + episodeParseResult, e);
} }
} }

@ -97,11 +97,11 @@ namespace NzbDrone.Core.Providers
series.AirsDayOfWeek = tvDbSeries.AirsDayOfWeek; series.AirsDayOfWeek = tvDbSeries.AirsDayOfWeek;
series.Overview = tvDbSeries.Overview; series.Overview = tvDbSeries.Overview;
series.Status = tvDbSeries.Status; series.Status = tvDbSeries.Status;
series.Language = tvDbSeries.Language != null ? tvDbSeries.Language : string.Empty; series.Language = tvDbSeries.Language != null ? tvDbSeries.Language.Abbriviation : string.Empty;
series.CleanTitle = Parser.NormalizeTitle(tvDbSeries.SeriesName); series.CleanTitle = Parser.NormalizeTitle(tvDbSeries.SeriesName);
series.LastInfoSync = DateTime.Now; series.LastInfoSync = DateTime.Now;
series.Runtime = (int)tvDbSeries.Runtime; series.Runtime = (int)tvDbSeries.Runtime;
series.BannerUrl = tvDbSeries.Banner; series.BannerUrl = tvDbSeries.BannerPath;
series.Network = tvDbSeries.Network; series.Network = tvDbSeries.Network;
UpdateSeries(series); UpdateSeries(series);

@ -5,8 +5,9 @@ using System.Text.RegularExpressions;
using NLog; using NLog;
using Ninject; using Ninject;
using NzbDrone.Common; using NzbDrone.Common;
using XemLib; using TvdbLib;
using XemLib.Data; using TvdbLib.Cache;
using TvdbLib.Data;
namespace NzbDrone.Core.Providers namespace NzbDrone.Core.Providers
{ {
@ -16,13 +17,13 @@ namespace NzbDrone.Core.Providers
public const string TVDB_APIKEY = "5D2D188E86E07F4F"; public const string TVDB_APIKEY = "5D2D188E86E07F4F";
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly XemClient _xemClient; private readonly TvdbHandler _handler;
[Inject] [Inject]
public TvDbProvider(EnvironmentProvider environmentProvider) public TvDbProvider(EnvironmentProvider environmentProvider)
{ {
_environmentProvider = environmentProvider; _environmentProvider = environmentProvider;
_xemClient = new XemClient(TVDB_APIKEY); _handler = new TvdbHandler(new XmlCacheProvider(_environmentProvider.GetCacheFolder()), TVDB_APIKEY);
} }
public TvDbProvider() public TvDbProvider()
@ -32,27 +33,33 @@ namespace NzbDrone.Core.Providers
public virtual IList<TvdbSearchResult> SearchSeries(string title) public virtual IList<TvdbSearchResult> SearchSeries(string title)
{ {
Logger.Debug("Searching TVDB for '{0}'", title); lock (_handler)
{
Logger.Debug("Searching TVDB for '{0}'", title);
var result = _xemClient.SearchSeries(title); var result = _handler.SearchSeries(title);
Logger.Debug("Search for '{0}' returned {1} possible results", title, result.Count); Logger.Debug("Search for '{0}' returned {1} possible results", title, result.Count);
return result; return result;
}
} }
public virtual TvdbSeries GetSeries(int id, bool loadEpisodes, bool loadActors = false, bool loadBanners = false) public virtual TvdbSeries GetSeries(int id, bool loadEpisodes, bool loadActors = false)
{ {
Logger.Debug("Fetching SeriesId'{0}' from tvdb", id); lock (_handler)
var result = _xemClient.GetSeries(id, loadEpisodes, loadActors, true, TvdbLanguage.Default); {
Logger.Debug("Fetching SeriesId'{0}' from tvdb", id);
var result = _handler.GetSeries(id, TvdbLanguage.DefaultLanguage, loadEpisodes, loadActors, true, true);
//Remove duplicated episodes //Remove duplicated episodes
var episodes = result.Episodes.OrderByDescending(e => e.FirstAired).ThenByDescending(e => e.EpisodeName) var episodes = result.Episodes.OrderByDescending(e => e.FirstAired).ThenByDescending(e => e.EpisodeName)
.GroupBy(e => e.SeriesId.ToString("000000") + e.SeasonNumber.ToString("000") + e.EpisodeNumber.ToString("000")) .GroupBy(e => e.SeriesId.ToString("000000") + e.SeasonNumber.ToString("000") + e.EpisodeNumber.ToString("000"))
.Select(e => e.First()); .Select(e => e.First());
result.Episodes = episodes.ToList(); result.Episodes = episodes.ToList();
return result; return result;
}
} }
} }
} }

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NLog;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Ninject;
using NzbDrone.Common;
using NzbDrone.Core.Model.Xem;
namespace NzbDrone.Core.Providers
{
public class XemCommunicationProvider
{
private readonly HttpProvider _httpProvider;
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
private const string XEM_BASE_URL = "http://thexem.de/map/";
[Inject]
public XemCommunicationProvider(HttpProvider httpProvider)
{
_httpProvider = httpProvider;
}
public XemCommunicationProvider()
{
}
public virtual List<Int32> GetXemSeriesIds(string origin = "tvdb")
{
_logger.Trace("Fetching Series IDs from: {0}", origin);
var url = String.Format("{0}havemap?origin={1}", XEM_BASE_URL, origin);
var response =_httpProvider.DownloadString(url);
CheckForFailureResult(response);
var result = JsonConvert.DeserializeObject<XemResult<List<Int32>>>(response);
return result.Data.ToList();
}
public virtual List<XemSceneTvdbMapping> GetSceneTvdbMappings(int id)
{
_logger.Trace("Fetching Mappings for: {0}", id);
var url = String.Format("{0}all?id={1}&origin=tvdb", XEM_BASE_URL, id);
var response = _httpProvider.DownloadString(url);
CheckForFailureResult(response);
var result = JsonConvert.DeserializeObject<List<XemSceneTvdbMapping>>(JObject.Parse(response).SelectToken("data").ToString());
return result;
}
public virtual void CheckForFailureResult(string response)
{
var result = JsonConvert.DeserializeObject<XemResult<dynamic>>(response);
if (result != null && result.Result.Equals("failure", StringComparison.InvariantCultureIgnoreCase))
throw new Exception("Error response received from Xem: " + result.Message);
}
}
}

@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NLog;
using Ninject;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers
{
public class XemProvider
{
private readonly SeriesProvider _seriesProvider;
private readonly EpisodeProvider _episodeProvider;
private readonly XemCommunicationProvider _xemCommunicationProvider;
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
[Inject]
public XemProvider(SeriesProvider seriesProvider, EpisodeProvider episodeProvider,
XemCommunicationProvider xemCommunicationProvider)
{
_seriesProvider = seriesProvider;
_episodeProvider = episodeProvider;
_xemCommunicationProvider = xemCommunicationProvider;
}
public XemProvider()
{
}
public virtual void UpdateMappings()
{
_logger.Trace("Starting scene numbering update");
try
{
var ids = _xemCommunicationProvider.GetXemSeriesIds();
var series = _seriesProvider.GetAllSeries();
var wantedSeries = series.Where(s => ids.Contains(s.SeriesId)).ToList();
foreach(var ser in wantedSeries)
{
PerformUpdate(ser);
}
_logger.Trace("Completed scene numbering update");
}
catch(Exception ex)
{
_logger.WarnException("Error updating Scene Mappings", ex);
throw;
}
}
public virtual void UpdateMappings(int seriesId)
{
var series = _seriesProvider.GetSeries(seriesId);
if (series == null)
{
_logger.Trace("Series could not be found: {0}", seriesId);
return;
}
PerformUpdate(series);
}
public virtual void PerformUpdate(Series series)
{
_logger.Trace("Updating scene numbering mapping for: {0}", series.Title);
try
{
var episodesToUpdate = new List<Episode>();
var mappings = _xemCommunicationProvider.GetSceneTvdbMappings(series.SeriesId);
if (mappings == null)
{
_logger.Trace("Mappings for: {0} are null, skipping", series.Title);
return;
}
var episodes = _episodeProvider.GetEpisodeBySeries(series.SeriesId);
foreach (var mapping in mappings)
{
_logger.Trace("Setting scene numbering mappings for {0} S{1:00}E{2:00}", series.Title, mapping.Tvdb.Season, mapping.Tvdb.Episode);
var episode = episodes.SingleOrDefault(e => e.SeasonNumber == mapping.Tvdb.Season && e.EpisodeNumber == mapping.Tvdb.Episode);
if (episode == null)
{
_logger.Trace("Information hasn't been added to TheTVDB yet, skipping.");
continue;
}
episode.AbsoluteEpisodeNumber = mapping.Scene.Absolute;
episode.SceneSeasonNumber = mapping.Scene.Season;
episode.SceneEpisodeNumber = mapping.Scene.Episode;
episodesToUpdate.Add(episode);
}
_logger.Trace("Committing scene numbering mappings to database for: {0}", series.Title);
_episodeProvider.UpdateEpisodes(episodesToUpdate);
_logger.Trace("Setting UseSceneMapping for {0}", series.Title);
series.UseSceneNumbering = true;
_seriesProvider.UpdateSeries(series);
}
catch (Exception ex)
{
_logger.WarnException("Error updating scene numbering mappings for: " + series, ex);
}
}
}
}

@ -22,6 +22,9 @@ namespace NzbDrone.Core.Repository
public Boolean Ignored { get; set; } public Boolean Ignored { get; set; }
public PostDownloadStatusType PostDownloadStatus { get; set; } public PostDownloadStatusType PostDownloadStatus { get; set; }
public int AbsoluteEpisodeNumber { get; set; } public int AbsoluteEpisodeNumber { get; set; }
public int SceneAbsoluteEpisodeNumber { get; set; }
public int SceneSeasonNumber { get; set; }
public int SceneEpisodeNumber { get; set; }
/// <summary> /// <summary>
/// Gets or sets the grab date. /// Gets or sets the grab date.

@ -50,6 +50,8 @@ namespace NzbDrone.Core.Repository
public DateTime? CustomStartDate { get; set; } public DateTime? CustomStartDate { get; set; }
public bool UseSceneNumbering { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether this <see cref="Series"/> is hidden. /// Gets or sets a value indicating whether this <see cref="Series"/> is hidden.
/// </summary> /// </summary>

@ -12,7 +12,7 @@ using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using NzbDrone.Web.Filters; using NzbDrone.Web.Filters;
using NzbDrone.Web.Models; using NzbDrone.Web.Models;
using XemLib.Exceptions; using TvdbLib.Exceptions;
namespace NzbDrone.Web.Controllers namespace NzbDrone.Web.Controllers
{ {
@ -156,14 +156,14 @@ namespace NzbDrone.Web.Controllers
DisplayedTitle = r.FirstAired.Year > 1900 && !r.SeriesName.EndsWith("(" + r.FirstAired.Year + ")") DisplayedTitle = r.FirstAired.Year > 1900 && !r.SeriesName.EndsWith("(" + r.FirstAired.Year + ")")
? string.Format("{0} ({1})", r.SeriesName, r.FirstAired.Year) ? string.Format("{0} ({1})", r.SeriesName, r.FirstAired.Year)
: r.SeriesName, : r.SeriesName,
Banner = r.Banner, Banner = r.Banner.BannerPath,
Url = String.Format("http://www.thetvdb.com/?tab=series&id={0}", r.Id) Url = String.Format("http://www.thetvdb.com/?tab=series&id={0}", r.Id)
}).ToList(); }).ToList();
return Json(tvDbResults, JsonRequestBehavior.AllowGet); return Json(tvDbResults, JsonRequestBehavior.AllowGet);
} }
catch (TheTvbdbUnavailableException ex) catch(TvdbNotAvailableException ex)
{ {
logger.WarnException("Unable to lookup series on TheTVDB", ex); logger.WarnException("Unable to lookup series on TheTVDB", ex);
return JsonNotificationResult.Info("Lookup Failed", "TheTVDB is not available at this time."); return JsonNotificationResult.Info("Lookup Failed", "TheTVDB is not available at this time.");

@ -141,13 +141,13 @@
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="WebActivator, Version=1.5.1.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="TvdbLib, Version=0.8.8.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\WebActivator.1.5.1\lib\net40\WebActivator.dll</HintPath> <HintPath>..\Libraries\TvdbLib.dll</HintPath>
</Reference> </Reference>
<Reference Include="XemLib, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="WebActivator, Version=1.5.1.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\Libraries\XemLib\XemLib.dll</HintPath> <HintPath>..\packages\WebActivator.1.5.1\lib\net40\WebActivator.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

Loading…
Cancel
Save