From 500e9af6c3cf27ca5cc0fedb508f4bcb6d11fff1 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Mon, 23 May 2011 21:12:54 -0700 Subject: [PATCH] Fixed a bug where reports weren't being added to history --- NzbDrone.Core.Test/DownloadProviderTest.cs | 55 ++++++ NzbDrone.Core.Test/EpisodeProviderTest.cs | Bin 5794 -> 5800 bytes NzbDrone.Core.Test/IndexerProviderTest.cs | 17 +- NzbDrone.Core.Test/InventoryProviderTest.cs | 161 +++++++++++++----- NzbDrone.Core.Test/JobProviderTest.cs | 30 ++-- NzbDrone.Core.Test/MediaFileProviderTests.cs | 2 +- NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 1 + NzbDrone.Core.Test/ParserTest.cs | 18 +- NzbDrone.Core.Test/SabProviderTest.cs | 2 +- NzbDrone.Core/Model/EpisodeParseResult.cs | 12 +- NzbDrone.Core/Parser.cs | 4 +- NzbDrone.Core/Providers/DownloadProvider.cs | 26 ++- .../Providers/Indexer/IndexerBase.cs | 2 + .../Providers/Indexer/InventoryProvider.cs | 59 ++++--- NzbDrone.Core/Providers/MediaFileProvider.cs | 4 +- NzbDrone.Core/Providers/SabProvider.cs | 4 +- NzbDrone.Web/Controllers/SeriesController.cs | 85 +-------- NzbDrone.Web/Views/Series/Details.cshtml | 87 +++++----- 18 files changed, 344 insertions(+), 225 deletions(-) create mode 100644 NzbDrone.Core.Test/DownloadProviderTest.cs diff --git a/NzbDrone.Core.Test/DownloadProviderTest.cs b/NzbDrone.Core.Test/DownloadProviderTest.cs new file mode 100644 index 000000000..db2c8758f --- /dev/null +++ b/NzbDrone.Core.Test/DownloadProviderTest.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Text; +using AutoMoq; +using FizzWare.NBuilder; +using Gallio.Framework; +using MbUnit.Framework; +using MbUnit.Framework.ContractVerifiers; +using Moq; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Repository; + +// ReSharper disable InconsistentNaming +namespace NzbDrone.Core.Test +{ + [TestFixture] + public class DownloadProviderTest + { + [Test] + public void Download_report_should_send_to_sab_and_add_to_history() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + var parseResult = Builder.CreateNew() + .With(e => e.Episodes = Builder.CreateListOfSize(2) + .WhereTheFirst(1).Has(s => s.EpisodeId = 12) + .AndTheNext(1).Has(s => s.EpisodeId = 99) + .Build()) + .Build(); + + const string sabTitle = "My fake sab title"; + mocker.GetMock() + .Setup(s => s.IsInQueue(It.IsAny())) + .Returns(false); + + mocker.GetMock() + .Setup(s => s.AddByUrl(parseResult.NzbUrl, sabTitle)) + .Returns(true); + + mocker.GetMock() + .Setup(s => s.GetSabTitle(parseResult)) + .Returns(sabTitle); + + mocker.GetMock() + .Setup(s => s.Add(It.Is(h=>h.EpisodeId == 12))); + mocker.GetMock() + .Setup(s => s.Add(It.Is(h => h.EpisodeId == 99))); + + mocker.Resolve().DownloadReport(parseResult); + + + mocker.VerifyAllMocks(); + } + } +} diff --git a/NzbDrone.Core.Test/EpisodeProviderTest.cs b/NzbDrone.Core.Test/EpisodeProviderTest.cs index ca1f04183d2ad398154b3328c0203f5d4445bd98..36816c04c910b0c2a9a9b3f6eb5067a6d5b4466b 100644 GIT binary patch delta 19 bcmZ3ayFz!v6CO6d(%hufqRmfu_HhCLQQrt2 delta 12 UcmZ3XyGVD#6Q0elc=mAu04A6PwEzGB diff --git a/NzbDrone.Core.Test/IndexerProviderTest.cs b/NzbDrone.Core.Test/IndexerProviderTest.cs index 1eb820f59..b0ac3cae6 100644 --- a/NzbDrone.Core.Test/IndexerProviderTest.cs +++ b/NzbDrone.Core.Test/IndexerProviderTest.cs @@ -41,7 +41,8 @@ namespace NzbDrone.Core.Test .Setup(c => c.GetSettings(It.IsAny())) .Returns(fakeSettings); - var parseResults = mocker.Resolve().Fetch(); + var mockIndexer = mocker.Resolve(); + var parseResults = mockIndexer.Fetch(); foreach (var episodeParseResult in parseResults) { @@ -51,6 +52,11 @@ namespace NzbDrone.Core.Test Assert.IsNotEmpty(parseResults); + + Assert.ForAll(parseResults, s => Assert.AreEqual(mockIndexer.Name, s.Indexer)); + Assert.ForAll(parseResults, s => Assert.AreNotEqual("", s.NzbTitle)); + Assert.ForAll(parseResults, s => Assert.AreNotEqual(null, s.NzbTitle)); + ExceptionVerification.ExcpectedWarns(warns); } @@ -70,7 +76,8 @@ namespace NzbDrone.Core.Test .Setup(c => c.GetSettings(It.IsAny())) .Returns(fakeSettings); - var parseResults = mocker.Resolve().Fetch(); + var newzbinProvider = mocker.Resolve(); + var parseResults = newzbinProvider.Fetch(); foreach (var episodeParseResult in parseResults) { @@ -80,6 +87,10 @@ namespace NzbDrone.Core.Test Assert.IsNotEmpty(parseResults); + Assert.ForAll(parseResults, s => Assert.AreEqual(newzbinProvider.Name, s.Indexer)); + Assert.ForAll(parseResults, s => Assert.AreNotEqual("", s.NzbTitle)); + Assert.ForAll(parseResults, s => Assert.AreNotEqual(null, s.NzbTitle)); + ExceptionVerification.ExcpectedWarns(1); } @@ -111,7 +122,7 @@ namespace NzbDrone.Core.Test Assert.IsNotNull(result); Assert.AreEqual(summary, result.EpisodeTitle); Assert.AreEqual(season, result.SeasonNumber); - Assert.AreEqual(episode, result.Episodes[0]); + Assert.AreEqual(episode, result.EpisodeNumbers[0]); Assert.AreEqual(quality, result.Quality); } diff --git a/NzbDrone.Core.Test/InventoryProviderTest.cs b/NzbDrone.Core.Test/InventoryProviderTest.cs index bbf0113c6..0e6043f9c 100644 --- a/NzbDrone.Core.Test/InventoryProviderTest.cs +++ b/NzbDrone.Core.Test/InventoryProviderTest.cs @@ -23,37 +23,56 @@ namespace NzbDrone.Core.Test // ReSharper disable InconsistentNaming public class InventoryProviderTest : TestBase { - private EpisodeParseResult parseResult; + private EpisodeParseResult parseResultMulti; private Series series; private Episode episode; + private Episode episode2; + private EpisodeParseResult parseResultSingle; [SetUp] public new void Setup() { - parseResult = new EpisodeParseResult() + parseResultMulti = new EpisodeParseResult() { CleanTitle = "Title", EpisodeTitle = "EpisodeTitle", Language = LanguageType.English, Proper = true, Quality = QualityTypes.Bluray720, - Episodes = new List { 3 }, + EpisodeNumbers = new List { 3, 4 }, SeasonNumber = 12, AirDate = DateTime.Now.AddDays(-12).Date - }; + parseResultSingle = new EpisodeParseResult() + { + CleanTitle = "Title", + EpisodeTitle = "EpisodeTitle", + Language = LanguageType.English, + Proper = true, + Quality = QualityTypes.Bluray720, + EpisodeNumbers = new List { 3 }, + SeasonNumber = 12, + AirDate = DateTime.Now.AddDays(-12).Date + }; + series = Builder.CreateNew() .With(c => c.Monitored = true) - .With(d => d.CleanTitle = parseResult.CleanTitle) + .With(d => d.CleanTitle = parseResultMulti.CleanTitle) .Build(); episode = Builder.CreateNew() - .With(c => c.EpisodeNumber = parseResult.Episodes[0]) - .With(c => c.SeasonNumber = parseResult.SeasonNumber) - .With(c => c.AirDate = parseResult.AirDate) + .With(c => c.EpisodeNumber = parseResultMulti.EpisodeNumbers[0]) + .With(c => c.SeasonNumber = parseResultMulti.SeasonNumber) + .With(c => c.AirDate = parseResultMulti.AirDate) .Build(); + episode2 = Builder.CreateNew() + .With(c => c.EpisodeNumber = parseResultMulti.EpisodeNumbers[1]) + .With(c => c.SeasonNumber = parseResultMulti.SeasonNumber) + .With(c => c.AirDate = parseResultMulti.AirDate) + .Build(); + base.Setup(); } @@ -71,7 +90,7 @@ namespace NzbDrone.Core.Test .Returns(series); //Act - var result = mocker.Resolve().IsNeeded(parseResult); + var result = mocker.Resolve().IsNeeded(parseResultMulti); //Assert Assert.IsFalse(result); @@ -90,7 +109,7 @@ namespace NzbDrone.Core.Test .Returns(null); //Act - var result = mocker.Resolve().IsNeeded(parseResult); + var result = mocker.Resolve().IsNeeded(parseResultMulti); //Assert Assert.IsFalse(result); @@ -107,12 +126,12 @@ namespace NzbDrone.Core.Test .Returns(series); mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality)) + .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality)) .Returns(false); //Act - var result = mocker.Resolve().IsNeeded(parseResult); + var result = mocker.Resolve().IsNeeded(parseResultMulti); //Assert Assert.IsFalse(result); @@ -131,15 +150,15 @@ namespace NzbDrone.Core.Test .Returns(series); mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality)) + .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality)) .Returns(true); mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber)) + .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber)) .Returns(true); //Act - var result = mocker.Resolve().IsNeeded(parseResult); + var result = mocker.Resolve().IsNeeded(parseResultMulti); //Assert Assert.IsFalse(result); @@ -163,21 +182,29 @@ namespace NzbDrone.Core.Test .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) .Returns(episode); + mocker.GetMock() + .Setup(p => p.GetEpisode(episode2.SeriesId, episode2.SeasonNumber, episode2.EpisodeNumber)) + .Returns(episode2); + mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality)) + .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality)) .Returns(true); mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber)) + .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber)) + .Returns(false); + + mocker.GetMock() + .Setup(p => p.IsNeeded(parseResultMulti, episode)) .Returns(false); mocker.GetMock() - .Setup(p => p.IsNeeded(parseResult, episode)) + .Setup(p => p.IsNeeded(parseResultMulti, episode2)) .Returns(false); //Act - var result = mocker.Resolve().IsNeeded(parseResult); + var result = mocker.Resolve().IsNeeded(parseResultMulti); //Assert Assert.IsFalse(result); @@ -198,25 +225,24 @@ namespace NzbDrone.Core.Test .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) .Returns(episode); - mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality)) + .Setup(p => p.QualityWanted(series.SeriesId, parseResultSingle.Quality)) .Returns(true); mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber)) + .Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber)) .Returns(false); mocker.GetMock() - .Setup(p => p.IsNeeded(parseResult, episode)) + .Setup(p => p.IsNeeded(parseResultSingle, episode)) .Returns(true); mocker.GetMock() - .Setup(p => p.Exists(episode.EpisodeId, parseResult.Quality, parseResult.Proper)) + .Setup(p => p.Exists(episode.EpisodeId, parseResultSingle.Quality, parseResultSingle.Proper)) .Returns(true); //Act - var result = mocker.Resolve().IsNeeded(parseResult); + var result = mocker.Resolve().IsNeeded(parseResultSingle); //Assert Assert.IsFalse(result); @@ -242,19 +268,19 @@ namespace NzbDrone.Core.Test mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality)) + .Setup(p => p.QualityWanted(series.SeriesId, parseResultSingle.Quality)) .Returns(true); mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber)) + .Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber)) .Returns(false); mocker.GetMock() - .Setup(p => p.IsNeeded(parseResult, episode)) + .Setup(p => p.IsNeeded(parseResultSingle, episode)) .Returns(false); //Act - var result = mocker.Resolve().IsNeeded(parseResult); + var result = mocker.Resolve().IsNeeded(parseResultSingle); //Assert Assert.IsFalse(result); @@ -272,11 +298,11 @@ namespace NzbDrone.Core.Test .Returns(series); mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality)) + .Setup(p => p.QualityWanted(series.SeriesId, parseResultSingle.Quality)) .Returns(true); mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber)) + .Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber)) .Returns(false); mocker.GetMock() @@ -292,11 +318,11 @@ namespace NzbDrone.Core.Test .Returns(12); mocker.GetMock() - .Setup(p => p.IsNeeded(parseResult, It.IsAny())) + .Setup(p => p.IsNeeded(parseResultSingle, It.IsAny())) .Returns(false); //Act - var result = mocker.Resolve().IsNeeded(parseResult); + var result = mocker.Resolve().IsNeeded(parseResultSingle); //Assert Assert.IsFalse(result); @@ -305,7 +331,7 @@ namespace NzbDrone.Core.Test [Test] - public void file_needed_should_return_true() + public void first_file_needed_should_return_true() { var mocker = new AutoMoqer(MockBehavior.Strict); @@ -317,30 +343,83 @@ namespace NzbDrone.Core.Test .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) .Returns(episode); + mocker.GetMock() + .Setup(p => p.GetEpisode(episode2.SeriesId, episode2.SeasonNumber, episode2.EpisodeNumber)) + .Returns(episode2); mocker.GetMock() - .Setup(p => p.QualityWanted(series.SeriesId, parseResult.Quality)) + .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality)) .Returns(true); mocker.GetMock() - .Setup(p => p.IsIgnored(series.SeriesId, parseResult.SeasonNumber)) + .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber)) + .Returns(false); + + mocker.GetMock() + .Setup(p => p.IsNeeded(parseResultMulti, episode)) + .Returns(true); + + mocker.GetMock() + .Setup(p => p.Exists(episode.EpisodeId, parseResultMulti.Quality, parseResultMulti.Proper)) + .Returns(false); + + //Act + var result = mocker.Resolve().IsNeeded(parseResultMulti); + + //Assert + Assert.IsTrue(result); + Assert.Contains(parseResultMulti.Episodes, episode); + Assert.Contains(parseResultMulti.Episodes, episode2); + Assert.AreEqual(series, parseResultMulti.Series); + mocker.VerifyAllMocks(); + } + + [Test] + public void second_file_needed_should_return_true() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(p => p.FindSeries(It.IsAny())) + .Returns(series); + + mocker.GetMock() + .Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber)) + .Returns(episode); + + mocker.GetMock() + .Setup(p => p.GetEpisode(episode2.SeriesId, episode2.SeasonNumber, episode2.EpisodeNumber)) + .Returns(episode2); + + + mocker.GetMock() + .Setup(p => p.QualityWanted(series.SeriesId, parseResultMulti.Quality)) + .Returns(true); + + mocker.GetMock() + .Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber)) + .Returns(false); + + mocker.GetMock() + .Setup(p => p.IsNeeded(parseResultMulti, episode)) .Returns(false); mocker.GetMock() - .Setup(p => p.IsNeeded(parseResult, episode)) + .Setup(p => p.IsNeeded(parseResultMulti, episode2)) .Returns(true); mocker.GetMock() - .Setup(p => p.Exists(episode.EpisodeId, parseResult.Quality, parseResult.Proper)) + .Setup(p => p.Exists(episode2.EpisodeId, parseResultMulti.Quality, parseResultMulti.Proper)) .Returns(false); //Act - var result = mocker.Resolve().IsNeeded(parseResult); + var result = mocker.Resolve().IsNeeded(parseResultMulti); //Assert Assert.IsTrue(result); - Assert.IsNotNull(parseResult.Series); - Assert.AreEqual(series, parseResult.Series); + Assert.Contains(parseResultMulti.Episodes, episode); + Assert.Contains(parseResultMulti.Episodes, episode2); + Assert.AreEqual(series, parseResultMulti.Series); mocker.VerifyAllMocks(); } } diff --git a/NzbDrone.Core.Test/JobProviderTest.cs b/NzbDrone.Core.Test/JobProviderTest.cs index f1af906bc..51e585125 100644 --- a/NzbDrone.Core.Test/JobProviderTest.cs +++ b/NzbDrone.Core.Test/JobProviderTest.cs @@ -17,7 +17,7 @@ namespace NzbDrone.Core.Test [Test] public void Run_Jobs_Updates_Last_Execution() { - IEnumerable fakeJobs = new List { new FakeJob() }; + IList fakeJobs = new List { new FakeJob() }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); @@ -39,7 +39,7 @@ namespace NzbDrone.Core.Test public void Run_Jobs_Updates_Last_Execution_Mark_as_unsuccesful() { - IEnumerable fakeJobs = new List { new BrokenJob() }; + IList fakeJobs = new List { new BrokenJob() }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); @@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test //after execution so the job can successfully run. public void can_run_job_again() { - IEnumerable fakeJobs = new List { new FakeJob() }; + IList fakeJobs = new List { new FakeJob() }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); @@ -84,7 +84,7 @@ namespace NzbDrone.Core.Test //after execution so the job can successfully run. public void can_run_async_job_again() { - IEnumerable fakeJobs = new List { new FakeJob() }; + IList fakeJobs = new List { new FakeJob() }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); @@ -106,7 +106,7 @@ namespace NzbDrone.Core.Test //after execution so the job can successfully run. public void no_concurent_jobs() { - IEnumerable fakeJobs = new List { new SlowJob() }; + IList fakeJobs = new List { new SlowJob() }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); @@ -129,7 +129,7 @@ namespace NzbDrone.Core.Test //after execution so the job can successfully run. public void can_run_broken_async_job_again() { - IEnumerable fakeJobs = new List { new BrokenJob() }; + IList fakeJobs = new List { new BrokenJob() }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); @@ -152,7 +152,7 @@ namespace NzbDrone.Core.Test //after execution so the job can successfully run. public void can_run_two_jobs_at_the_same_time() { - IEnumerable fakeJobs = new List { new SlowJob() }; + IList fakeJobs = new List { new SlowJob() }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); @@ -186,7 +186,7 @@ namespace NzbDrone.Core.Test { var slowJob = new SlowJob(); - IEnumerable fakeJobs = new List { slowJob }; + IList fakeJobs = new List { slowJob }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); @@ -214,7 +214,7 @@ namespace NzbDrone.Core.Test public void Init_Jobs() { var fakeTimer = new FakeJob(); - IEnumerable fakeJobs = new List { fakeTimer }; + IList fakeJobs = new List { fakeTimer }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); @@ -245,7 +245,7 @@ namespace NzbDrone.Core.Test for (int i = 0; i < 2; i++) { var fakeTimer = new FakeJob(); - IEnumerable fakeJobs = new List { fakeTimer }; + IList fakeJobs = new List { fakeTimer }; var mocker = new AutoMoqer(); mocker.SetConstant(repo); @@ -276,7 +276,7 @@ namespace NzbDrone.Core.Test for (int i = 0; i < 2; i++) { var disabledJob = new DisabledJob(); - IEnumerable fakeJobs = new List { disabledJob }; + IList fakeJobs = new List { disabledJob }; var mocker = new AutoMoqer(); mocker.SetConstant(repo); @@ -302,7 +302,7 @@ namespace NzbDrone.Core.Test [Test] public void Get_Next_Execution_Time() { - IEnumerable fakeJobs = new List { new FakeJob() }; + IList fakeJobs = new List { new FakeJob() }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); @@ -327,7 +327,7 @@ namespace NzbDrone.Core.Test var disabledJob = new DisabledJob(); - IEnumerable fakeJobs = new List { disabledJob }; + IList fakeJobs = new List { disabledJob }; var mocker = new AutoMoqer(); mocker.SetConstant(repo); @@ -348,7 +348,7 @@ namespace NzbDrone.Core.Test [Test] public void SingleId_do_not_update_last_execution() { - IEnumerable fakeJobs = new List { new FakeJob() }; + IList fakeJobs = new List { new FakeJob() }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); @@ -369,7 +369,7 @@ namespace NzbDrone.Core.Test [Test] public void SingleId_do_not_set_success() { - IEnumerable fakeJobs = new List { new FakeJob() }; + IList fakeJobs = new List { new FakeJob() }; var mocker = new AutoMoqer(); mocker.SetConstant(MockLib.GetEmptyRepository()); diff --git a/NzbDrone.Core.Test/MediaFileProviderTests.cs b/NzbDrone.Core.Test/MediaFileProviderTests.cs index 75ef69a47..8ca8d2ba6 100644 --- a/NzbDrone.Core.Test/MediaFileProviderTests.cs +++ b/NzbDrone.Core.Test/MediaFileProviderTests.cs @@ -116,7 +116,7 @@ namespace NzbDrone.Core.Test //Currently can't verify this since the list of episodes are loaded //Dynamically by SubSonic - //Assert.AreEqual(fakeEpisode, result.Episodes[0]); + //Assert.AreEqual(fakeEpisode, result.EpisodeNumbers[0]); Assert.AreEqual(fakeEpisode.SeriesId, result.SeriesId); Assert.AreEqual(QualityTypes.HDTV, result.Quality); diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 64bf6f0b3..523d14b39 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -85,6 +85,7 @@ + diff --git a/NzbDrone.Core.Test/ParserTest.cs b/NzbDrone.Core.Test/ParserTest.cs index f113a5584..cd8c2bf64 100644 --- a/NzbDrone.Core.Test/ParserTest.cs +++ b/NzbDrone.Core.Test/ParserTest.cs @@ -46,9 +46,9 @@ namespace NzbDrone.Core.Test { var result = Parser.ParseEpisodeInfo(postTitle); Assert.AreEqual(season, result.SeasonNumber); - Assert.AreEqual(episode, result.Episodes[0]); + Assert.AreEqual(episode, result.EpisodeNumbers[0]); Assert.AreEqual(Parser.NormalizeTitle(title), result.CleanTitle); - Assert.AreEqual(1, result.Episodes.Count); + Assert.AreEqual(1, result.EpisodeNumbers.Count); } [Test] @@ -60,9 +60,9 @@ namespace NzbDrone.Core.Test public void file_path_parse(string path, int season, int episode) { var result = Parser.ParseEpisodeInfo(path); - Assert.Count(1, result.Episodes); + Assert.Count(1, result.EpisodeNumbers); Assert.AreEqual(season, result.SeasonNumber); - Assert.AreEqual(episode, result.Episodes[0]); + Assert.AreEqual(episode, result.EpisodeNumbers[0]); } @@ -110,10 +110,10 @@ namespace NzbDrone.Core.Test { var result = Parser.ParseEpisodeInfo(postTitle); Assert.AreEqual(season, result.SeasonNumber); - Assert.Count(episodes.Length, result.Episodes); - Assert.AreElementsEqualIgnoringOrder(episodes, result.Episodes); + Assert.Count(episodes.Length, result.EpisodeNumbers); + Assert.AreElementsEqualIgnoringOrder(episodes, result.EpisodeNumbers); Assert.AreEqual(Parser.NormalizeTitle(title), result.CleanTitle); - Assert.AreEqual(count, result.Episodes.Count); + Assert.AreEqual(count, result.EpisodeNumbers.Count); } [Test] @@ -129,7 +129,7 @@ namespace NzbDrone.Core.Test var airDate = new DateTime(year, month, day); Assert.AreEqual(Parser.NormalizeTitle(title), result.CleanTitle); Assert.AreEqual(airDate, result.AirDate); - Assert.IsNull(result.Episodes); + Assert.IsNull(result.EpisodeNumbers); } @@ -142,7 +142,7 @@ namespace NzbDrone.Core.Test var result = Parser.ParseEpisodeInfo(postTitle); Assert.AreEqual(season, result.SeasonNumber); Assert.AreEqual(Parser.NormalizeTitle(title), result.CleanTitle); - Assert.AreEqual(0, result.Episodes.Count); + Assert.AreEqual(0, result.EpisodeNumbers.Count); } [Test] diff --git a/NzbDrone.Core.Test/SabProviderTest.cs b/NzbDrone.Core.Test/SabProviderTest.cs index d48df6fe0..d5323f6a9 100644 --- a/NzbDrone.Core.Test/SabProviderTest.cs +++ b/NzbDrone.Core.Test/SabProviderTest.cs @@ -229,7 +229,7 @@ namespace NzbDrone.Core.Test var parsResult = new EpisodeParseResult() { AirDate = DateTime.Now, - Episodes = episodes.ToList(), + EpisodeNumbers = episodes.ToList(), Proper = proper, Quality = quality, SeasonNumber = seasons, diff --git a/NzbDrone.Core/Model/EpisodeParseResult.cs b/NzbDrone.Core/Model/EpisodeParseResult.cs index d5892dc9d..4452d8fa9 100644 --- a/NzbDrone.Core/Model/EpisodeParseResult.cs +++ b/NzbDrone.Core/Model/EpisodeParseResult.cs @@ -11,7 +11,7 @@ namespace NzbDrone.Core.Model internal int SeasonNumber { get; set; } - internal List Episodes { get; set; } + internal List EpisodeNumbers { get; set; } internal string EpisodeTitle { get; set; } @@ -25,15 +25,21 @@ namespace NzbDrone.Core.Model public string NzbUrl { get; set; } + public string NzbTitle { get; set; } + public Series Series { get; set; } + public IList Episodes { get; set; } + + public String Indexer { get; set; } + public override string ToString() { - if (Episodes == null) + if (EpisodeNumbers == null) return string.Format("{0} - {1}", CleanTitle, AirDate.Date); return string.Format("{0} - S{1:00}E{2}", CleanTitle, SeasonNumber, - String.Join("-", Episodes)); + String.Join("-", EpisodeNumbers)); } } diff --git a/NzbDrone.Core/Parser.cs b/NzbDrone.Core/Parser.cs index a2a3aef68..91b4e7a82 100644 --- a/NzbDrone.Core/Parser.cs +++ b/NzbDrone.Core/Parser.cs @@ -68,7 +68,7 @@ namespace NzbDrone.Core Proper = title.ToLower().Contains("proper"), CleanTitle = seriesName, SeasonNumber = season, - Episodes = new List() + EpisodeNumbers = new List() }; foreach (Match matchGroup in match) @@ -83,7 +83,7 @@ namespace NzbDrone.Core for (int i = first; i <= last; i++) { - parsedEpisode.Episodes.Add(i); + parsedEpisode.EpisodeNumbers.Add(i); } } } diff --git a/NzbDrone.Core/Providers/DownloadProvider.cs b/NzbDrone.Core/Providers/DownloadProvider.cs index f249b1c1e..1070eaded 100644 --- a/NzbDrone.Core/Providers/DownloadProvider.cs +++ b/NzbDrone.Core/Providers/DownloadProvider.cs @@ -13,11 +13,15 @@ namespace NzbDrone.Core.Providers public class DownloadProvider { private readonly SabProvider _sabProvider; + private readonly HistoryProvider _historyProvider; + private readonly EpisodeProvider _episodeProvider; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public DownloadProvider(SabProvider sabProvider) + public DownloadProvider(SabProvider sabProvider, HistoryProvider historyProvider, EpisodeProvider episodeProvider) { _sabProvider = sabProvider; + _historyProvider = historyProvider; + _episodeProvider = episodeProvider; } public DownloadProvider() @@ -34,7 +38,25 @@ namespace NzbDrone.Core.Providers return false; } - return _sabProvider.AddByUrl(parseResult.NzbUrl, sabTitle); + var addSuccess = _sabProvider.AddByUrl(parseResult.NzbUrl, sabTitle); + + if (addSuccess) + { + foreach (var episode in parseResult.Episodes) + { + var history = new History(); + history.Date = DateTime.Now; + history.Indexer = parseResult.Indexer; + history.IsProper = parseResult.Proper; + history.Quality = parseResult.Quality; + history.NzbTitle = parseResult.NzbTitle; + history.EpisodeId = episode.EpisodeId; + + _historyProvider.Add(history); + } + } + + return addSuccess; } } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/Indexer/IndexerBase.cs b/NzbDrone.Core/Providers/Indexer/IndexerBase.cs index 6e197b6c7..aeee9d96e 100644 --- a/NzbDrone.Core/Providers/Indexer/IndexerBase.cs +++ b/NzbDrone.Core/Providers/Indexer/IndexerBase.cs @@ -77,6 +77,8 @@ namespace NzbDrone.Core.Providers.Indexer if (parsedEpisode != null) { parsedEpisode.NzbUrl = NzbDownloadUrl(item); + parsedEpisode.Indexer = Name; + parsedEpisode.NzbTitle = item.Title.Text; result.Add(parsedEpisode); } } diff --git a/NzbDrone.Core/Providers/Indexer/InventoryProvider.cs b/NzbDrone.Core/Providers/Indexer/InventoryProvider.cs index 70e462a68..363a3332a 100644 --- a/NzbDrone.Core/Providers/Indexer/InventoryProvider.cs +++ b/NzbDrone.Core/Providers/Indexer/InventoryProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using NLog; using NzbDrone.Core.Model; @@ -36,32 +37,28 @@ namespace NzbDrone.Core.Providers.Indexer } parseResult.Series = series; + parseResult.Episodes = new List(); - foreach (var episodeNumber in parseResult.Episodes) + if (!series.Monitored) { - //Todo: How to handle full season files? Currently the episode list is completely empty for these releases - //Todo: Should we assume that the release contains all the episodes that belong to this season and add them from the DB? - //Todo: Fix this so it properly handles multi-epsiode releases (Currently as long as the first episode is needed we download it) - //Todo: for small releases this is less of an issue, but for Full Season Releases this could be an issue if we only need the first episode (or first few) - - if (!series.Monitored) - { - Logger.Debug("{0} is present in the DB but not tracked. skipping.", parseResult.CleanTitle); - return false; - } + Logger.Debug("{0} is present in the DB but not tracked. skipping.", parseResult.CleanTitle); + return false; + } - if (!_seriesProvider.QualityWanted(series.SeriesId, parseResult.Quality)) - { - Logger.Debug("Post doesn't meet the quality requirements [{0}]. skipping.", parseResult.Quality); - return false; - } + if (!_seriesProvider.QualityWanted(series.SeriesId, parseResult.Quality)) + { + Logger.Debug("Post doesn't meet the quality requirements [{0}]. skipping.", parseResult.Quality); + return false; + } - if (_seasonProvider.IsIgnored(series.SeriesId, parseResult.SeasonNumber)) - { - Logger.Debug("Season {0} is currently set to ignore. skipping.", parseResult.SeasonNumber); - return false; - } + if (_seasonProvider.IsIgnored(series.SeriesId, parseResult.SeasonNumber)) + { + Logger.Debug("Season {0} is currently set to ignore. skipping.", parseResult.SeasonNumber); + return false; + } + foreach (var episodeNumber in parseResult.EpisodeNumbers) + { var episodeInfo = _episodeProvider.GetEpisode(series.SeriesId, parseResult.SeasonNumber, episodeNumber); if (episodeInfo == null) { @@ -84,21 +81,33 @@ namespace NzbDrone.Core.Providers.Indexer _episodeProvider.AddEpisode(episodeInfo); } + parseResult.Episodes.Add(episodeInfo); + } - if (!_episodeProvider.IsNeeded(parseResult, episodeInfo)) + foreach (var episode in parseResult.Episodes) + { + //Todo: How to handle full season files? Currently the episode list is completely empty for these releases + //Todo: Should we assume that the release contains all the episodes that belong to this season and add them from the DB? + //Todo: Fix this so it properly handles multi-epsiode releases (Currently as long as the first episode is needed we download it) + //Todo: for small releases this is less of an issue, but for Full Season Releases this could be an issue if we only need the first episode (or first few) + + + + if (!_episodeProvider.IsNeeded(parseResult, episode)) { Logger.Debug("Episode {0} is not needed. skipping.", parseResult); - return false; + continue; } - if (_historyProvider.Exists(episodeInfo.EpisodeId, parseResult.Quality, parseResult.Proper)) + if (_historyProvider.Exists(episode.EpisodeId, parseResult.Quality, parseResult.Proper)) { Logger.Debug("Episode {0} is in history. skipping.", parseResult); - return false; + continue; } //Congragulations younge feed item! you have made it this far. you are truly special!!! Logger.Debug("Episode {0} is needed", parseResult); + return true; } diff --git a/NzbDrone.Core/Providers/MediaFileProvider.cs b/NzbDrone.Core/Providers/MediaFileProvider.cs index 56b3a433c..0879692e7 100644 --- a/NzbDrone.Core/Providers/MediaFileProvider.cs +++ b/NzbDrone.Core/Providers/MediaFileProvider.cs @@ -83,7 +83,7 @@ namespace NzbDrone.Core.Providers var episodes = new List(); //Check for daily shows - if (parseResult.Episodes == null) + if (parseResult.EpisodeNumbers == null) { var episode = _episodeProvider.GetEpisode(series.SeriesId, parseResult.AirDate.Date); @@ -98,7 +98,7 @@ namespace NzbDrone.Core.Providers } else { - foreach (var episodeNumber in parseResult.Episodes) + foreach (var episodeNumber in parseResult.EpisodeNumbers) { var episode = _episodeProvider.GetEpisode(series.SeriesId, parseResult.SeasonNumber, episodeNumber); diff --git a/NzbDrone.Core/Providers/SabProvider.cs b/NzbDrone.Core/Providers/SabProvider.cs index 6a7c52f0b..8417eef9b 100644 --- a/NzbDrone.Core/Providers/SabProvider.cs +++ b/NzbDrone.Core/Providers/SabProvider.cs @@ -92,13 +92,13 @@ namespace NzbDrone.Core.Providers _configProvider.SabPassword); } - public String GetSabTitle(EpisodeParseResult parseResult) + public virtual String GetSabTitle(EpisodeParseResult parseResult) { //Show Name - 1x01-1x02 - Episode Name //Show Name - 1x01 - Episode Name var episodeString = new List(); - foreach (var episode in parseResult.Episodes) + foreach (var episode in parseResult.EpisodeNumbers) { episodeString.Add(String.Format("{0}x{1}", parseResult.SeasonNumber, episode)); } diff --git a/NzbDrone.Web/Controllers/SeriesController.cs b/NzbDrone.Web/Controllers/SeriesController.cs index 247786d8a..b2a21a837 100644 --- a/NzbDrone.Web/Controllers/SeriesController.cs +++ b/NzbDrone.Web/Controllers/SeriesController.cs @@ -142,15 +142,14 @@ namespace NzbDrone.Web.Controllers return View(new GridModel(episodes)); } - [GridAction] - public ActionResult _CustomBinding(GridCommand command, int seasonId) + //Local Helpers + private string GetEpisodePath(EpisodeFile file) { - IEnumerable data = GetData(command); - return View(new GridModel - { - Data = data, - Total = data.Count() - }); + if (file == null) + return String.Empty; + + //Return the path relative to the Series' Folder + return file.Path.Replace(file.Series.Path, "").Trim(Path.DirectorySeparatorChar); } public ActionResult SearchForSeries(string seriesName) @@ -174,66 +173,6 @@ namespace NzbDrone.Web.Controllers return PartialView("SeriesSearchResults", model); } - private IEnumerable GetData(GridCommand command) - { - return null; - /* - IQueryable data = .Orders; - //Apply filtering - if (command.FilterDescriptors.Any()) - { - data = data.Where(ExpressionBuilder.Expression(command.FilterDescriptors)); - } - // Apply sorting - foreach (SortDescriptor sortDescriptor in command.SortDescriptors) - { - if (sortDescriptor.SortDirection == ListSortDirection.Ascending) - { - switch (sortDescriptor.Member) - { - case "OrderID": - data = data.OrderBy(ExpressionBuilder.Expression(sortDescriptor.Member)); - break; - case "Customer.ContactName": - data = data.OrderBy(order => order.Customer.ContactName); - break; - case "ShipAddress": - data = data.OrderBy(order => order.ShipAddress); - break; - case "OrderDate": - data = data.OrderBy(order => order.OrderDate); - break; - } - } - else - { - switch (sortDescriptor.Member) - { - case "OrderID": - data = data.OrderByDescending(order => order.OrderID); - break; - case "Customer.ContactName": - data = data.OrderByDescending(order => order.Customer.ContactName); - break; - case "ShipAddress": - data = data.OrderByDescending(order => order.ShipAddress); - break; - case "OrderDate": - data = data.OrderByDescending(order => order.OrderDate); - break; - } - } - } - count = data.Count(); - // ... and paging - if (command.PageSize > 0) - { - data = data.Skip((command.Page - 1) * command.PageSize); - } - data = data.Take(command.PageSize); - return data;*/ - } - [AcceptVerbs(HttpVerbs.Post)] [GridAction] public ActionResult _SaveAjaxEditing(string id) @@ -301,16 +240,6 @@ namespace NzbDrone.Web.Controllers return RedirectToAction("Index"); } - //Local Helpers - private string GetEpisodePath(EpisodeFile file) - { - if (file == null) - return String.Empty; - - //Return the path relative to the Series' Folder - return file.Path.Replace(file.Series.Path, "").Trim(Path.DirectorySeparatorChar); - } - private List GetSeriesModels(List seriesInDb) { var series = new List(); diff --git a/NzbDrone.Web/Views/Series/Details.cshtml b/NzbDrone.Web/Views/Series/Details.cshtml index 75aec3d94..d29f74dd1 100644 --- a/NzbDrone.Web/Views/Series/Details.cshtml +++ b/NzbDrone.Web/Views/Series/Details.cshtml @@ -58,45 +58,47 @@ {
-

Season @season.SeasonNumber

+

+ Season @season.SeasonNumber

@{Season season1 = season; - Html.Telerik().Grid().Name("seasons_" + season.SeasonNumber) - .TableHtmlAttributes(new { @class = "Grid" }) - .Columns(columns => - { - columns.Bound(o => o.EpisodeId) - .ClientTemplate( - "") - .Title("") - .Width(1) - .HtmlAttributes(new { style = "text-align:center" }); + Html.Telerik().Grid().Name("seasons_" + season.SeasonNumber) + .TableHtmlAttributes(new { @class = "Grid" }) + .Columns(columns => + { + columns.Bound(o => o.EpisodeId) + .ClientTemplate( + "") + .Title("") + .Width(1) + .HtmlAttributes(new { style = "text-align:center" }); - columns.Bound(c => c.EpisodeNumber).Width(10).Title("Episode"); - columns.Bound(c => c.Title).Title("Title").Width(300); - columns.Bound(c => c.AirDate).Format("{0:d}").Width(10); - columns.Bound(c => c.Quality).Width(10); - columns.Bound(c => c.Path); - columns.Bound(c => c.Status); - }) - .DetailView(detailView => detailView.ClientTemplate("
<#= Overview #>
<#= Path #>
")) - .ClientEvents(clientEvents => - { - clientEvents.OnDataBinding("grid_bind"); - clientEvents.OnDataBound("grid_bound"); - }) - .Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber).Descending()).Enabled(true)) - .Footer(true) - .DataBinding( - d => - d.Ajax().Select("_AjaxSeasonGrid", "Series", - new RouteValueDictionary { { "seasonId", season1.SeasonId.ToString() } })) - .ToolBar( - c => - c.Custom().Text("Rename Season").Action("RenameSeason", "Series", new { seasonId = season1.SeasonId }) - .ButtonType(GridButtonType.Text)) - .Render();} - Loading Loading... + columns.Bound(c => c.EpisodeNumber).Width(0).Title("Episode"); + columns.Bound(c => c.Title).Title("Title"); + columns.Bound(c => c.AirDate).Format("{0:d}").Width(0); + columns.Bound(c => c.Quality).Width(0); + columns.Bound(c => c.Status).Width(0); + }) + .DetailView(detailView => detailView.ClientTemplate("
<#= Overview #>
<#= Path #>
")) + .ClientEvents(clientEvents => + { + clientEvents.OnDataBinding("grid_bind"); + clientEvents.OnDataBound("grid_bound"); + }) + .Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber).Descending()).Enabled(true)) + .Footer(true) + .DataBinding( + d => + d.Ajax().Select("_AjaxSeasonGrid", "Series", + new RouteValueDictionary { { "seasonId", season1.SeasonId.ToString() } })) + .ToolBar( + c => + c.Custom().Text("Rename Season").Action("RenameSeason", "Series", new { seasonId = season1.SeasonId }) + .ButtonType(GridButtonType.Text)) + .Render();} + + Loading + Loading...
} @{var specialSeasons = Model.Seasons.Where(s => s.SeasonNumber == 0).FirstOrDefault();} @@ -104,10 +106,11 @@ {
-

Specials

+

+ Specials

@{Html.Telerik().Grid().Name("seasons_specials") - .TableHtmlAttributes(new {@class = "Grid"}) + .TableHtmlAttributes(new { @class = "Grid" }) .Columns(columns => { columns.Bound(o => o.EpisodeId) @@ -118,10 +121,10 @@ .HtmlAttributes(new { style = "text-align:center" }); columns.Bound(c => c.EpisodeNumber).Width(10).Title("Episode"); - columns.Bound(c => c.Title).Title("Title").Width(300); + columns.Bound(c => c.Title).Title("Title").Width(10000); columns.Bound(c => c.AirDate).Format("{0:d}").Width(10); columns.Bound(c => c.Quality).Width(10); - columns.Bound(c => c.Path); + columns.Bound(c => c.Status).Width(10); }) .DetailView(detailView => detailView.ClientTemplate("
<#= Overview #>
<#= Path #>
")) .ClientEvents(clientEvents => @@ -136,7 +139,9 @@ d.Ajax().Select("_AjaxSeasonGrid", "Series", new RouteValueDictionary { { "seasonId", specialSeasons.SeasonId.ToString() } })) .Render(); } - Loading Loading... + + Loading + Loading...
} }