Cleanup and updates for XEM

SceneSource added to signify to lookup via scene name
Use Episodes for naming instead of EpisodeNumbers (in ParseResult)
This commit is contained in:
Mark McDowall 2012-10-17 00:39:06 -07:00
parent c9c967fa1d
commit 9c6d78d479
22 changed files with 157 additions and 44 deletions

View File

@ -175,6 +175,18 @@ namespace NzbDrone.Common.Test
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()
{
BinFolder.Refresh();

View File

@ -235,5 +235,13 @@ namespace NzbDrone.Common
{
Directory.SetLastWriteTimeUtc(path, dateTime);
}
public virtual bool IsChildOfPath(string child, string parent)
{
if (Path.GetFullPath(child).StartsWith(Path.GetFullPath(parent)))
return true;
return false;
}
}
}

View File

@ -23,5 +23,8 @@
<NamedTestSelector>
<TestName>NzbDrone.Core.Test.Integeration.ServiceIntegerationFixture.should_be_able_to_submit_exceptions</TestName>
</NamedTestSelector>
<NamedTestSelector>
<TestName>NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests.ImportFileFixture.import_unparsable_file_should_skip</TestName>
</NamedTestSelector>
</IgnoredTests>
</ProjectConfiguration>

View File

@ -32,6 +32,9 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
{
_customStartDateSpecification = Mocker.Resolve<CustomStartDateSpecification>();
firstEpisode = new Episode { AirDate = DateTime.Today };
secondEpisode = new Episode { AirDate = DateTime.Today };
fakeSeries = Builder<Series>.CreateNew()
.With(c => c.Monitored = true)
.With(c => c.CustomStartDate = null)
@ -43,6 +46,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Series = fakeSeries,
EpisodeNumbers = new List<int> { 3, 4 },
SeasonNumber = 12,
Episodes = new List<Episode> { firstEpisode, secondEpisode }
};
parseResultSingle = new EpisodeParseResult
@ -51,16 +55,8 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Series = fakeSeries,
EpisodeNumbers = new List<int> { 3 },
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()

View File

@ -31,6 +31,12 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Mocker.Resolve<QualityUpgradeSpecification>();
_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()
.With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p })
.Build();
@ -41,6 +47,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Quality = new Quality(QualityTypes.DVD, true),
EpisodeNumbers = new List<int> { 3, 4 },
SeasonNumber = 12,
Episodes = doubleEpisodeList
};
parseResultSingle = new EpisodeParseResult
@ -49,17 +56,8 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Quality = new Quality(QualityTypes.DVD, true),
EpisodeNumbers = new List<int> { 3 },
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()
@ -73,9 +71,9 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
}
[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();
}

View File

@ -31,6 +31,13 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Mocker.Resolve<QualityUpgradeSpecification>();
_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()
.With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p })
.Build();
@ -41,6 +48,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Quality = new Quality(QualityTypes.DVD, true),
EpisodeNumbers = new List<int> { 3, 4 },
SeasonNumber = 12,
Episodes = doubleEpisodeList
};
parseResultSingle = new EpisodeParseResult
@ -49,21 +57,12 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests
Quality = new Quality(QualityTypes.DVD, true),
EpisodeNumbers = new List<int> { 3 },
SeasonNumber = 12,
Episodes = singleEpisodeList
};
firstQuality = new Quality(QualityTypes.Bluray1080p, true);
secondQuality = new Quality(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, 4)).Returns(secondQuality);
Mocker.GetMock<HistoryProvider>().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 5)).Returns<Quality>(null);

View File

@ -201,6 +201,9 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
Mocker.GetMock<DiskProvider>(MockBehavior.Strict)
.Setup(e => e.GetSize(fileName)).Returns(90000000000);
Mocker.GetMock<DiskProvider>(MockBehavior.Strict)
.Setup(e => e.IsChildOfPath(fileName, fakeSeries.Path)).Returns(false);
Mocker.GetMock<EpisodeProvider>()
.Setup(c => c.GetEpisodesByParseResult(It.IsAny<EpisodeParseResult>()))
.Returns(new List<Episode>());
@ -416,5 +419,47 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests
Mocker.GetMock<EpisodeProvider>().Verify(p => p.UpdateEpisode(It.IsAny<Episode>()), 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());
}
}
}

View File

@ -43,6 +43,7 @@ namespace NzbDrone.Core.Test.ProviderTests
.With(c => c.Quality = new Quality(QualityTypes.DVD, false))
.With(c => c.Series = Builder<Series>.CreateNew().Build())
.With(c => c.EpisodeNumbers = new List<int>{2})
.With(c => c.Episodes = episodes)
.Build();
}
@ -191,6 +192,11 @@ namespace NzbDrone.Core.Test.ProviderTests
.With(c => c.Title = "My Series Name")
.Build();
var fakeEpisodes = new List<Episode>();
foreach(var episode in episodes)
fakeEpisodes.Add(Builder<Episode>.CreateNew().With(e => e.EpisodeNumber = episode).Build());
var parsResult = new EpisodeParseResult()
{
AirDate = DateTime.Now,
@ -198,7 +204,8 @@ namespace NzbDrone.Core.Test.ProviderTests
Quality = new Quality(quality, proper),
SeasonNumber = seasons,
Series = series,
EpisodeTitle = title
EpisodeTitle = title,
Episodes = fakeEpisodes
};
return Mocker.Resolve<DownloadProvider>().GetDownloadTitle(parsResult);

View File

@ -13,6 +13,8 @@ namespace NzbDrone.Core.Datastore.Migrations
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));
}
}
}

View File

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

View File

@ -227,6 +227,7 @@
<Compile Include="Datastore\MigrationLogger.cs" />
<Compile Include="Datastore\MigrationsHelper.cs" />
<Compile Include="Datastore\CustomeMapper.cs" />
<Compile Include="Datastore\Migrations\Migration20121016.cs" />
<Compile Include="Datastore\Migrations\Migration20121012.cs" />
<Compile Include="Datastore\Migrations\Migration20120919.cs" />
<Compile Include="Datastore\Migrations\Migration20120918.cs" />
@ -334,6 +335,7 @@
<Compile Include="Jobs\UpdateInfoJob.cs" />
<Compile Include="Providers\StatsProvider.cs" />
<Compile Include="Providers\XemCommunicationProvider.cs" />
<Compile Include="Providers\XemProvider.cs" />
<Compile Include="Repository\MetadataDefinition.cs" />
<Compile Include="Repository\Search\SearchHistoryItem.cs" />
<Compile Include="Repository\Search\SearchHistory.cs" />

View File

@ -29,9 +29,7 @@ namespace NzbDrone.Core.Providers.DecisionEngine
return true;
}
var episodes = _episodeProvider.GetEpisodesByParseResult(subject);
if (episodes.Any(episode => episode.AirDate > subject.Series.CustomStartDate.Value))
if (subject.Episodes.Any(episode => episode.AirDate > subject.Series.CustomStartDate.Value))
{
logger.Debug("One or more episodes aired after cutoff, downloading.");
return true;

View File

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

View File

@ -24,7 +24,7 @@ namespace NzbDrone.Core.Providers.DecisionEngine
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);
if (!_qualityUpgradeSpecification.IsSatisfiedBy(new Quality { QualityType = file.Quality, Proper = file.Proper }, subject.Quality, subject.Series.QualityProfile.Cutoff))

View File

@ -27,7 +27,7 @@ namespace NzbDrone.Core.Providers.DecisionEngine
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);
if (bestQualityInHistory != null)

View File

@ -122,6 +122,9 @@ namespace NzbDrone.Core.Providers
if (parseResult == 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.Series = series;
@ -203,6 +206,7 @@ namespace NzbDrone.Core.Providers
var parseResult = Parser.ParsePath(episodeFile.Path);
parseResult.Series = series;
parseResult.Quality = new Quality{ QualityType = episodeFile.Quality, Proper = episodeFile.Proper };
parseResult.Episodes = episodes;
var message = _downloadProvider.GetDownloadTitle(parseResult);

View File

@ -48,13 +48,13 @@ namespace NzbDrone.Core.Providers
var provider = GetActiveDownloadClient();
bool success = provider.DownloadNzb(parseResult.NzbUrl, GetDownloadTitle(parseResult));
bool success = provider.DownloadNzb(parseResult.NzbUrl, downloadTitle);
if (success)
{
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
{
@ -127,9 +127,9 @@ namespace NzbDrone.Core.Providers
//Show Name - 1x01 - Episode Name
var episodeString = 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}", parseResult.SeasonNumber, episode.EpisodeNumber));
}
var epNumberString = String.Join("-", episodeString);

View File

@ -188,11 +188,20 @@ namespace NzbDrone.Core.Providers
foreach (var episodeNumber in parseResult.EpisodeNumbers)
{
var episodeInfo = GetEpisode(parseResult.Series.SeriesId, parseResult.SeasonNumber, episodeNumber);
if (episodeInfo == null && parseResult.AirDate != null)
Episode episodeInfo;
if (parseResult.SceneSource && parseResult.Series.UseSceneNumbering)
episodeInfo = GetEpisodeFromSceneNumbering(parseResult.Series.SeriesId, parseResult.SeasonNumber, episodeNumber);
else
{
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 (episodeInfo == null && autoAddNew)
{
@ -440,5 +449,21 @@ namespace NzbDrone.Core.Providers
{
_database.UpdateMany(episodes);
}
public virtual Episode GetEpisodeFromSceneNumbering(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;
}
}
}

View File

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

View File

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

View File

@ -319,6 +319,8 @@ namespace NzbDrone.Core.Providers
continue;
}
episodeParseResult.Episodes = _episodeProvider.GetEpisodesByParseResult(episodeParseResult);
item.SearchError = _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult);
if (item.SearchError == ReportRejectionType.None)
{
@ -403,6 +405,8 @@ namespace NzbDrone.Core.Providers
continue;
}
episodeParseResult.Episodes = _episodeProvider.GetEpisodesByParseResult(episodeParseResult);
item.SearchError = _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult);
if (item.SearchError == ReportRejectionType.None)
{

View File

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