diff --git a/NzbDrone.Core.Test/IndexerTests.cs b/NzbDrone.Core.Test/IndexerTests.cs index e46a369b7..fd71f1714 100644 --- a/NzbDrone.Core.Test/IndexerTests.cs +++ b/NzbDrone.Core.Test/IndexerTests.cs @@ -176,7 +176,7 @@ namespace NzbDrone.Core.Test WithConfiguredIndexers(); Mocker.GetMock() - .Setup(h => h.DownloadStream("http://www.nzbindex.nl/rss/alt.binaries.teevee/?sort=agedesc&minsize=100&complete=1&max=50&more=1&q=%23a.b.teevee%40EFNet", It.IsAny())) + .Setup(h => h.DownloadStream("http://www.nzbindex.nl/rss/alt.binaries.teevee/?sort=agedesc&minsize=100&complete=1&max=50&more=1&q=%23a.b.teevee", It.IsAny())) .Returns(File.OpenRead(".\\Files\\Rss\\SizeParsing\\nzbindex.xml")); Mocker.GetMock() @@ -195,7 +195,7 @@ namespace NzbDrone.Core.Test WithConfiguredIndexers(); Mocker.GetMock() - .Setup(h => h.DownloadStream("http://www.nzbclub.com/nzbfeed.aspx?ig=2&gid=102952&st=1&ns=1&q=%23a.b.teevee%40EFNet", It.IsAny())) + .Setup(h => h.DownloadStream("http://www.nzbclub.com/nzbfeed.aspx?ig=2&gid=102952&st=1&ns=1&q=%23a.b.teevee", It.IsAny())) .Returns(File.OpenRead(".\\Files\\Rss\\SizeParsing\\nzbclub.xml")); Mocker.GetMock() @@ -402,7 +402,7 @@ namespace NzbDrone.Core.Test const string expectedString = "release"; Mocker.GetMock() - .Setup(h => h.DownloadStream("http://www.nzbindex.nl/rss/alt.binaries.teevee/?sort=agedesc&minsize=100&complete=1&max=50&more=1&q=%23a.b.teevee%40EFNet", It.IsAny())) + .Setup(h => h.DownloadStream("http://www.nzbindex.nl/rss/alt.binaries.teevee/?sort=agedesc&minsize=100&complete=1&max=50&more=1&q=%23a.b.teevee", It.IsAny())) .Returns(File.OpenRead(".\\Files\\Rss\\nzbindex.xml")); Mocker.GetMock() @@ -426,7 +426,7 @@ namespace NzbDrone.Core.Test const string expectedString = "nzb_view"; Mocker.GetMock() - .Setup(h => h.DownloadStream("http://www.nzbclub.com/nzbfeed.aspx?ig=2&gid=102952&st=1&ns=1&q=%23a.b.teevee%40EFNet", It.IsAny())) + .Setup(h => h.DownloadStream("http://www.nzbclub.com/nzbfeed.aspx?ig=2&gid=102952&st=1&ns=1&q=%23a.b.teevee", It.IsAny())) .Returns(File.OpenRead(".\\Files\\Rss\\" + fileName)); Mocker.GetMock() diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index b49f1ba01..865e138b6 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -175,9 +175,9 @@ - - - + + + @@ -246,6 +246,7 @@ + diff --git a/NzbDrone.Core.Test/ParserFixture/ParserTest.cs b/NzbDrone.Core.Test/ParserFixture/ParserTest.cs index 18d4a621a..d7f65f732 100644 --- a/NzbDrone.Core.Test/ParserFixture/ParserTest.cs +++ b/NzbDrone.Core.Test/ParserFixture/ParserTest.cs @@ -71,6 +71,7 @@ namespace NzbDrone.Core.Test.ParserFixture [TestCase("Falling_Skies_-_1x1_-_Live_and_Learn_[HDTV]", "Falling Skies", 1, 1)] [TestCase("Top Gear - 07x03 - 2005.11.70", "Top Gear", 7, 3)] [TestCase("Hatfields and McCoys 2012 Part 1 REPACK 720p HDTV x264 2HD", "Hatfields and McCoys 2012", 1, 1)] + [TestCase("Glee.S04E09.Swan.Song.1080p.WEB-DL.DD5.1.H.264-ECI", "Glee", 4, 9)] public void ParseTitle_single(string postTitle, string title, int seasonNumber, int episodeNumber) { var result = Parser.ParseTitle(postTitle); diff --git a/NzbDrone.Core.Test/ParserFixture/QualityParserTests.cs b/NzbDrone.Core.Test/ParserFixture/QualityParserTests.cs index beadf999a..5b8334e79 100644 --- a/NzbDrone.Core.Test/ParserFixture/QualityParserTests.cs +++ b/NzbDrone.Core.Test/ParserFixture/QualityParserTests.cs @@ -61,7 +61,7 @@ namespace NzbDrone.Core.Test.ParserFixture new object[] { "Pawn Stars S04E87 REPACK 720p HDTV x264 aAF", QualityTypes.HDTV, true }, new object[] { "The Real Housewives of Vancouver S01E04 DSR x264 2HD", QualityTypes.SDTV, false }, new object[] { "Vanguard S01E04 Mexicos Death Train DSR x264 MiNDTHEGAP", QualityTypes.SDTV, false }, - new object[] { "Vanguard S01E04 Mexicos Death Train 720 WEB DL", QualityTypes.WEBDL720p, false }, + new object[] { "Vanguard S01E04 Mexicos Death Train 720p WEB DL", QualityTypes.WEBDL720p, false }, new object[] { "Hawaii Five 0 S02E21 720p WEB DL DD5 1 H 264", QualityTypes.WEBDL720p, false }, new object[] { "Castle S04E22 720p WEB DL DD5 1 H 264 NFHD", QualityTypes.WEBDL720p, false }, new object[] { "Fringe S04E22 720p WEB-DL DD5.1 H264-EbP.mkv", QualityTypes.WEBDL720p, false }, @@ -70,14 +70,20 @@ namespace NzbDrone.Core.Test.ParserFixture new object[] { "Criminal.Minds.S08E01.1080p.WEB-DL.DD5.1.H264-NFHD", QualityTypes.WEBDL1080p, false }, new object[] { "Its.Always.Sunny.in.Philadelphia.S08E01.1080p.WEB-DL.proper.AAC2.0.H.264", QualityTypes.WEBDL1080p, true }, new object[] { "Two and a Half Men S10E03 1080p WEB DL DD5 1 H 264 REPACK NFHD", QualityTypes.WEBDL1080p, true }, + new object[] { "Glee.S04E09.Swan.Song.1080p.WEB-DL.DD5.1.H.264-ECI", QualityTypes.WEBDL1080p, false }, + new object[] { "Elementary.S01E10.The.Leviathan.480p.WEB-DL.x264-mSD", QualityTypes.WEBDL480p, false }, + new object[] { "Glee.S04E10.Glee.Actually.480p.WEB-DL.x264-mSD", QualityTypes.WEBDL480p, false }, + new object[] { "The.Big.Bang.Theory.S06E11.The.Santa.Simulation.480p.WEB-DL.x264-mSD", QualityTypes.WEBDL480p, false } }; public static object[] SelfQualityParserCases = { new object[] { QualityTypes.SDTV }, new object[] { QualityTypes.DVD }, + new object[] { QualityTypes.WEBDL480p }, new object[] { QualityTypes.HDTV }, new object[] { QualityTypes.WEBDL720p }, + new object[] { QualityTypes.WEBDL1080p }, new object[] { QualityTypes.Bluray720p }, new object[] { QualityTypes.Bluray1080p } }; diff --git a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityAllowedByProfileSpecificationFixtrue.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityAllowedByProfileSpecificationFixture.cs similarity index 97% rename from NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityAllowedByProfileSpecificationFixtrue.cs rename to NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityAllowedByProfileSpecificationFixture.cs index 433af761b..2a47bfa9d 100644 --- a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityAllowedByProfileSpecificationFixtrue.cs +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityAllowedByProfileSpecificationFixture.cs @@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests { [TestFixture] // ReSharper disable InconsistentNaming - public class QualityAllowedByProfileSpecificationFixtrue : CoreTest + public class QualityAllowedByProfileSpecificationFixture : CoreTest { private QualityAllowedByProfileSpecification _qualityAllowedByProfile; private EpisodeParseResult parseResult; diff --git a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs index 07506badb..f6a7abb8b 100644 --- a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs @@ -23,7 +23,8 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests new object[] { QualityTypes.WEBDL720p, false, QualityTypes.HDTV, true, QualityTypes.Bluray720p, false }, new object[] { QualityTypes.WEBDL720p, false, QualityTypes.HDTV, true, QualityTypes.WEBDL720p, false }, new object[] { QualityTypes.WEBDL720p, false, QualityTypes.WEBDL720p, false, QualityTypes.WEBDL720p, false }, - new object[] { QualityTypes.SDTV, false, QualityTypes.SDTV, true, QualityTypes.SDTV, true } + new object[] { QualityTypes.SDTV, false, QualityTypes.SDTV, true, QualityTypes.SDTV, true }, + new object[] { QualityTypes.WEBDL1080p, false, QualityTypes.WEBDL1080p, false, QualityTypes.WEBDL1080p, false } }; [Test, TestCaseSource("IsUpgradeTestCases")] diff --git a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeDiskSpecificationFixtrue.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeDiskSpecificationFixture.cs similarity index 90% rename from NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeDiskSpecificationFixtrue.cs rename to NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeDiskSpecificationFixture.cs index 74eddef0a..df017e25a 100644 --- a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeDiskSpecificationFixtrue.cs +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeDiskSpecificationFixture.cs @@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests { [TestFixture] // ReSharper disable InconsistentNaming - public class UpgradeDiskSpecificationFixtrue : CoreTest + public class UpgradeDiskSpecificationFixture : CoreTest { private UpgradeDiskSpecification _upgradeDisk; @@ -112,5 +112,14 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests WithSecondFileUpgradable(); _upgradeDisk.IsSatisfiedBy(parseResultMulti).Should().BeFalse(); } + + [Test] + public void should_not_be_upgradable_if_qualities_are_the_same() + { + firstFile.Quality = QualityTypes.WEBDL1080p; + firstFile.Proper = false; + parseResultSingle.Quality = new QualityModel(QualityTypes.WEBDL1080p, false); + _upgradeDisk.IsSatisfiedBy(parseResultSingle).Should().BeFalse(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeHistorySpecificationFixtrue.cs b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeHistorySpecificationFixture.cs similarity index 85% rename from NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeHistorySpecificationFixtrue.cs rename to NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeHistorySpecificationFixture.cs index 898585aac..565ea6ed4 100644 --- a/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeHistorySpecificationFixtrue.cs +++ b/NzbDrone.Core.Test/ProviderTests/DecisionEngineTests/UpgradeHistorySpecificationFixture.cs @@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests { [TestFixture] // ReSharper disable InconsistentNaming - public class UpgradeHistorySpecificationFixtrue : CoreTest + public class UpgradeHistorySpecificationFixture : CoreTest { private UpgradeHistorySpecification _upgradeHistory; @@ -24,6 +24,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests private EpisodeParseResult parseResultSingle; private QualityModel firstQuality; private QualityModel secondQuality; + private Series fakeSeries; [SetUp] public void Setup() @@ -38,7 +39,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests new Episode { SeasonNumber = 12, EpisodeNumber = 5 } }; - var fakeSeries = Builder.CreateNew() + fakeSeries = Builder.CreateNew() .With(c => c.QualityProfile = new QualityProfile { Cutoff = QualityTypes.Bluray1080p }) .Build(); @@ -113,5 +114,17 @@ namespace NzbDrone.Core.Test.ProviderTests.DecisionEngineTests WithSecondReportUpgradable(); _upgradeHistory.IsSatisfiedBy(parseResultMulti).Should().BeFalse(); } + + [Test] + public void should_not_be_upgradable_if_episode_is_of_same_quality_as_existing() + { + fakeSeries.QualityProfile = new QualityProfile { Cutoff = QualityTypes.WEBDL1080p }; + parseResultSingle.Quality = new QualityModel(QualityTypes.WEBDL1080p, false); + firstQuality = new QualityModel(QualityTypes.WEBDL1080p, false); + + Mocker.GetMock().Setup(c => c.GetBestQualityInHistory(fakeSeries.SeriesId, 12, 3)).Returns(firstQuality); + + _upgradeHistory.IsSatisfiedBy(parseResultSingle).Should().BeFalse(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/NewznabProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/NewznabProviderTest.cs index ea296922d..64a9292bb 100644 --- a/NzbDrone.Core.Test/ProviderTests/NewznabProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/NewznabProviderTest.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Sockets; using FizzWare.NBuilder; using FluentAssertions; using Moq; @@ -304,10 +305,10 @@ namespace NzbDrone.Core.Test.ProviderTests } [Test] - [ExpectedException("System.Net.Sockets.SocketException")] public void CheckHostname_should_log_error_and_throw_exception_if_dnsHostname_is_invalid() { - Mocker.Resolve().CheckHostname("http://BadName"); + Assert.Throws(() => Mocker.Resolve().CheckHostname("http://BadName")); + ExceptionVerification.ExpectedErrors(1); } } diff --git a/NzbDrone.Core.Test/ProviderTests/QualityTypeProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/QualityTypeProviderTest.cs index 6a76de3cd..5135342fe 100644 --- a/NzbDrone.Core.Test/ProviderTests/QualityTypeProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/QualityTypeProviderTest.cs @@ -29,9 +29,10 @@ namespace NzbDrone.Core.Test.ProviderTests //Assert var types = Mocker.Resolve().All(); - types.Should().HaveCount(7); + types.Should().HaveCount(8); types.Should().Contain(e => e.Name == "SDTV" && e.QualityTypeId == 1); types.Should().Contain(e => e.Name == "DVD" && e.QualityTypeId == 2); + types.Should().Contain(e => e.Name == "WEBDL-480p" && e.QualityTypeId == 8); types.Should().Contain(e => e.Name == "HDTV" && e.QualityTypeId == 4); types.Should().Contain(e => e.Name == "WEBDL-720p" && e.QualityTypeId == 5); types.Should().Contain(e => e.Name == "WEBDL-1080p" && e.QualityTypeId == 3); @@ -54,7 +55,7 @@ namespace NzbDrone.Core.Test.ProviderTests //Assert var types = Mocker.Resolve().All(); - types.Should().HaveCount(7); + types.Should().HaveCount(8); } [Test] diff --git a/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs index 79a96ab33..9e4a7a19d 100644 --- a/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs @@ -93,11 +93,8 @@ namespace NzbDrone.Core.Test.ProviderTests [TestCase(3)] [TestCase(2)] [TestCase(0)] - public void GetJsonVersion(int number) + public void GetJsonVersionIntOnly(int number) { - //Setup - - var message = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"version\":" + number + "}}"; var fakeHttp = Mocker.GetMock(); @@ -108,15 +105,32 @@ namespace NzbDrone.Core.Test.ProviderTests var result = Mocker.Resolve().GetJsonVersion("localhost:8080", "xbmc", "xbmc"); //Assert - Assert.AreEqual(number, result); + result.Should().Be(new XbmcVersion(number)); + } + + [TestCase(5, 0, 0)] + [TestCase(6, 0, 0)] + [TestCase(6, 1, 0)] + [TestCase(6, 0, 23)] + [TestCase(0, 0, 0)] + public void GetJsonVersionFrodo(int major, int minor, int patch) + { + var message = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"version\":{\"major\":" + major + ",\"minor\":" + minor + ",\"patch\":" + patch + "}}}"; + + var fakeHttp = Mocker.GetMock(); + fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny())) + .Returns(message); + + //Act + var result = Mocker.Resolve().GetJsonVersion("localhost:8080", "xbmc", "xbmc"); + + //Assert + result.Should().Be(new XbmcVersion(major, minor, patch)); } [Test] public void GetJsonVersion_error() { - //Setup - - var message = "{\"error\":{\"code\":-32601,\"message\":\"Method not found.\"},\"id\":10,\"jsonrpc\":\"2.0\"}"; var fakeHttp = Mocker.GetMock(); @@ -127,7 +141,7 @@ namespace NzbDrone.Core.Test.ProviderTests var result = Mocker.Resolve().GetJsonVersion("localhost:8080", "xbmc", "xbmc"); //Assert - Assert.AreEqual(0, result); + result.Should().Be(new XbmcVersion(0)); } [TestCase(false, false, false)] @@ -491,7 +505,7 @@ namespace NzbDrone.Core.Test.ProviderTests } [Test] - public void UpdateWithJson_Single() + public void UpdateWithJsonBuiltIn_Single() { //Setup @@ -516,18 +530,15 @@ namespace NzbDrone.Core.Test.ProviderTests fakeHttp.Setup(s => s.DownloadString(url, username, password)).Returns("
  • OK"); - //var fakeEventClient = Mocker.GetMock(); - //fakeEventClient.Setup(s => s.SendAction("localhost", ActionType.ExecBuiltin, "ExecBuiltIn(UpdateLibrary(video,smb://HOMESERVER/TV/30 Rock/))")); - //Act - var result = Mocker.Resolve().UpdateWithJson(fakeSeries, host, username, password); + var result = Mocker.Resolve().UpdateWithJsonExecBuiltIn(fakeSeries, host, username, password); //Assert result.Should().BeTrue(); } [Test] - public void UpdateWithJson_All() + public void UpdateWithJsonBuiltIn_All() { //Setup @@ -556,7 +567,71 @@ namespace NzbDrone.Core.Test.ProviderTests //fakeEventClient.Setup(s => s.SendAction("localhost", ActionType.ExecBuiltin, "ExecBuiltIn(UpdateLibrary(video))")); //Act - var result = Mocker.Resolve().UpdateWithJson(fakeSeries, host, username, password); + var result = Mocker.Resolve().UpdateWithJsonExecBuiltIn(fakeSeries, host, username, password); + + //Assert + result.Should().BeTrue(); + } + + [Test] + public void UpdateWithJsonVideoLibraryScan_Single() + { + var host = "localhost:8080"; + var username = "xbmc"; + var password = "xbmc"; + var expectedJson = "{\"jsonrpc\":\"2.0\",\"method\":\"VideoLibrary.GetTvShows\",\"params\":{\"properties\":[\"file\",\"imdbnumber\"]},\"id\":10}"; + var tvshows = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"limits\":{\"end\":5,\"start\":0,\"total\":5},\"tvshows\":[{\"file\":\"smb://HOMESERVER/TV/7th Heaven/\",\"imdbnumber\":\"73928\",\"label\":\"7th Heaven\",\"tvshowid\":3},{\"file\":\"smb://HOMESERVER/TV/8 Simple Rules/\",\"imdbnumber\":\"78461\",\"label\":\"8 Simple Rules\",\"tvshowid\":4},{\"file\":\"smb://HOMESERVER/TV/24-7 Penguins-Capitals- Road to the NHL Winter Classic/\",\"imdbnumber\":\"213041\",\"label\":\"24/7 Penguins/Capitals: Road to the NHL Winter Classic\",\"tvshowid\":1},{\"file\":\"smb://HOMESERVER/TV/30 Rock/\",\"imdbnumber\":\"79488\",\"label\":\"30 Rock\",\"tvshowid\":2},{\"file\":\"smb://HOMESERVER/TV/90210/\",\"imdbnumber\":\"82716\",\"label\":\"90210\",\"tvshowid\":5}]}}"; + + var fakeSeries = Builder.CreateNew() + .With(s => s.SeriesId = 79488) + .With(s => s.Title = "30 Rock") + .Build(); + + var fakeHttp = Mocker.GetMock(); + fakeHttp.Setup(s => s.PostCommand(host, username, password, It.Is(e => e.Replace(" ", "").Replace("\r\n", "").Replace("\t", "") == expectedJson.Replace(" ", "")))) + .Returns(tvshows); + + fakeHttp.Setup(s => s.PostCommand(host, username, password, It.Is( + e => e.Replace(" ", "") + .Replace("\r\n", "") + .Replace("\t", "") + .Contains("\"params\":{\"directory\":\"smb://HOMESERVER/TV/30Rock/\"}")))) + .Returns("{\"id\":55,\"jsonrpc\":\"2.0\",\"result\":\"OK\"}"); + + //Act + var result = Mocker.Resolve().UpdateWithJsonVideoLibraryScan(fakeSeries, host, username, password); + + //Assert + result.Should().BeTrue(); + } + + [Test] + public void UpdateWithJsonVideoLibraryScan_All() + { + var host = "localhost:8080"; + var username = "xbmc"; + var password = "xbmc"; + var expectedJson = "{\"jsonrpc\":\"2.0\",\"method\":\"VideoLibrary.GetTvShows\",\"params\":{\"properties\":[\"file\",\"imdbnumber\"]},\"id\":10}"; + var tvshows = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"limits\":{\"end\":5,\"start\":0,\"total\":5},\"tvshows\":[{\"file\":\"smb://HOMESERVER/TV/7th Heaven/\",\"imdbnumber\":\"73928\",\"label\":\"7th Heaven\",\"tvshowid\":3},{\"file\":\"smb://HOMESERVER/TV/8 Simple Rules/\",\"imdbnumber\":\"78461\",\"label\":\"8 Simple Rules\",\"tvshowid\":4},{\"file\":\"smb://HOMESERVER/TV/24-7 Penguins-Capitals- Road to the NHL Winter Classic/\",\"imdbnumber\":\"213041\",\"label\":\"24/7 Penguins/Capitals: Road to the NHL Winter Classic\",\"tvshowid\":1},{\"file\":\"smb://HOMESERVER/TV/90210/\",\"imdbnumber\":\"82716\",\"label\":\"90210\",\"tvshowid\":5}]}}"; + + var fakeSeries = Builder.CreateNew() + .With(s => s.SeriesId = 79488) + .With(s => s.Title = "30 Rock") + .Build(); + + var fakeHttp = Mocker.GetMock(); + fakeHttp.Setup(s => s.PostCommand(host, username, password, It.Is(e => e.Replace(" ", "").Replace("\r\n", "").Replace("\t", "") == expectedJson.Replace(" ", "")))) + .Returns(tvshows); + + fakeHttp.Setup(s => s.PostCommand(host, username, password, It.Is( + e => !e.Replace(" ", "") + .Replace("\r\n", "") + .Replace("\t", "") + .Contains("\"params\":{\"directory\":\"smb://HOMESERVER/TV/30Rock/\"}")))) + .Returns("{\"id\":55,\"jsonrpc\":\"2.0\",\"result\":\"OK\"}"); + + //Act + var result = Mocker.Resolve().UpdateWithJsonVideoLibraryScan(fakeSeries, host, username, password); //Assert result.Should().BeTrue(); diff --git a/NzbDrone.Core.Test/XbmcVersionTests.cs b/NzbDrone.Core.Test/XbmcVersionTests.cs new file mode 100644 index 000000000..65b986400 --- /dev/null +++ b/NzbDrone.Core.Test/XbmcVersionTests.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Model.Xbmc; +using NzbDrone.Core.Repository.Quality; + +namespace NzbDrone.Core.Test +{ + public class XbmcVersionTests + { + [TestCase(6, 0, 0)] + [TestCase(5, 1, 0)] + [TestCase(5, 0, 1)] + public void Icomparer_greater_test(int major, int minor, int patch) + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(major, minor, patch); + + second.Should().BeGreaterThan(first); + } + + [TestCase(4, 5, 5)] + [TestCase(5, 4, 5)] + [TestCase(5, 5, 4)] + public void Icomparer_lesser_test(int major, int minor, int patch) + { + var first = new XbmcVersion(5, 5, 5); + var second = new XbmcVersion(major, minor, patch); + + second.Should().BeLessThan(first); + } + + [Test] + public void equal_operand() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(5, 0, 0); + + (first == second).Should().BeTrue(); + (first >= second).Should().BeTrue(); + (first <= second).Should().BeTrue(); + } + + [Test] + public void equal_operand_false() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(6, 0, 0); + + (first == second).Should().BeFalse(); + } + + [Test] + public void not_equal_operand_false() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(5, 0, 0); + + (first != second).Should().BeFalse(); + } + + [Test] + public void not_equal_operand_true() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(6, 0, 0); + + (first != second).Should().BeTrue(); + } + + [Test] + public void greater_operand() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(6, 0, 0); + + (first < second).Should().BeTrue(); + (first <= second).Should().BeTrue(); + } + + [Test] + public void lesser_operand() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(6, 0, 0); + + (second > first).Should().BeTrue(); + (second >= first).Should().BeTrue(); + } + } +} diff --git a/NzbDrone.Core/Model/Xbmc/XbmcJsonResult.cs b/NzbDrone.Core/Model/Xbmc/XbmcJsonResult.cs new file mode 100644 index 000000000..be4ed1d88 --- /dev/null +++ b/NzbDrone.Core/Model/Xbmc/XbmcJsonResult.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Model.Xbmc +{ + public class XbmcJsonResult + { + public string Id { get; set; } + public string JsonRpc { get; set; } + public T Result { get; set; } + } +} diff --git a/NzbDrone.Core/Model/Xbmc/XbmcVersion.cs b/NzbDrone.Core/Model/Xbmc/XbmcVersion.cs new file mode 100644 index 000000000..5b777844d --- /dev/null +++ b/NzbDrone.Core/Model/Xbmc/XbmcVersion.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Model.Xbmc +{ + public class XbmcVersion : IComparable + { + public XbmcVersion() + { + } + + public XbmcVersion(int major) + { + Major = major; + } + + public XbmcVersion(int major, int minor, int patch) + { + Major = major; + Minor = minor; + Patch = patch; + } + + public int Major { get; set; } + public int Minor { get; set; } + public int Patch { get; set; } + + public int CompareTo(XbmcVersion other) + { + if(other.Major > Major) + return -1; + + if(other.Major < Major) + return 1; + + if (other.Minor > Minor) + return -1; + + if (other.Minor < Minor) + return 1; + + if (other.Patch > Patch) + return -1; + + if (other.Patch < Patch) + return 1; + + return 0; + } + + public static bool operator !=(XbmcVersion x, XbmcVersion y) + { + return !(x == y); + } + + public static bool operator ==(XbmcVersion x, XbmcVersion y) + { + var xObj = (Object)x; + var yObj = (object)y; + + if (xObj == null || yObj == null) + { + return xObj == yObj; + } + + return x.CompareTo(y) == 0; + } + + public static bool operator >(XbmcVersion x, XbmcVersion y) + { + return x.CompareTo(y) > 0; + } + + public static bool operator <(XbmcVersion x, XbmcVersion y) + { + return x.CompareTo(y) < 0; + } + + public static bool operator <=(XbmcVersion x, XbmcVersion y) + { + return x.CompareTo(y) <= 0; + } + + public static bool operator >=(XbmcVersion x, XbmcVersion y) + { + return x.CompareTo(y) >= 0; + } + + public override string ToString() + { + return String.Format("{0}.{1}.{2}", Major, Minor, Patch); + } + + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hash = 17; + hash = hash * 23 + Major.GetHashCode(); + hash = hash * 23 + Minor.GetHashCode(); + hash = hash * 23 + Patch.GetHashCode(); + return hash; + } + } + + public bool Equals(XbmcVersion other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return (Equals(other.Major, Major) && Equals(other.Minor, Minor) && Equals(other.Patch, Patch)); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != typeof(XbmcVersion)) return false; + return Equals((XbmcVersion)obj); + } + + public static XbmcVersion NONE = new XbmcVersion(0, 0, 0); + public static XbmcVersion DHARMA = new XbmcVersion(2, 0, 0); + public static XbmcVersion EDEN = new XbmcVersion(4, 0, 0); + public static XbmcVersion FRODO = new XbmcVersion(6, 0, 0); + } +} diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index a891ffebc..1ad5b179e 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -300,6 +300,8 @@ + + diff --git a/NzbDrone.Core/Parser.cs b/NzbDrone.Core/Parser.cs index ea1890f49..44dc8128b 100644 --- a/NzbDrone.Core/Parser.cs +++ b/NzbDrone.Core/Parser.cs @@ -295,7 +295,20 @@ namespace NzbDrone.Core result.Quality = QualityTypes.WEBDL1080p; return result; } - result.Quality = QualityTypes.WEBDL720p; + + if (normalizedName.Contains("720p")) + { + result.Quality = QualityTypes.WEBDL720p; + return result; + } + + if(name.Contains("[WEBDL]")) + { + result.Quality = QualityTypes.WEBDL720p; + return result; + } + + result.Quality = QualityTypes.WEBDL480p; return result; } if (normalizedName.Contains("x264") || normalizedName.Contains("h264") || normalizedName.Contains("720p")) diff --git a/NzbDrone.Core/Providers/Indexer/NzbClub.cs b/NzbDrone.Core/Providers/Indexer/NzbClub.cs index ed21d4e14..eaba45b66 100644 --- a/NzbDrone.Core/Providers/Indexer/NzbClub.cs +++ b/NzbDrone.Core/Providers/Indexer/NzbClub.cs @@ -23,7 +23,7 @@ namespace NzbDrone.Core.Providers.Indexer { return new[] { - String.Format("http://www.nzbclub.com/nzbfeed.aspx?ig=2&gid=102952&st=1&ns=1&q=%23a.b.teevee%40EFNet"), + String.Format("http://www.nzbclub.com/nzbfeed.aspx?ig=2&gid=102952&st=1&ns=1&q=%23a.b.teevee"), String.Format("http://www.nzbclub.com/nzbfeed.aspx?ig=2&gid=5542&st=1&ns=1&q=") }; } diff --git a/NzbDrone.Core/Providers/Indexer/NzbIndex.cs b/NzbDrone.Core/Providers/Indexer/NzbIndex.cs index 4a7ebd847..8d6b41a59 100644 --- a/NzbDrone.Core/Providers/Indexer/NzbIndex.cs +++ b/NzbDrone.Core/Providers/Indexer/NzbIndex.cs @@ -23,7 +23,7 @@ namespace NzbDrone.Core.Providers.Indexer { return new[] { - String.Format("http://www.nzbindex.nl/rss/alt.binaries.teevee/?sort=agedesc&minsize=100&complete=1&max=50&more=1&q=%23a.b.teevee%40EFNet"), + String.Format("http://www.nzbindex.nl/rss/alt.binaries.teevee/?sort=agedesc&minsize=100&complete=1&max=50&more=1&q=%23a.b.teevee"), String.Format("http://www.nzbindex.nl/rss/alt.binaries.hdtv/?sort=agedesc&minsize=100&complete=1&max=50&more=1&q=") }; } diff --git a/NzbDrone.Core/Providers/XbmcProvider.cs b/NzbDrone.Core/Providers/XbmcProvider.cs index 6e7f6e867..62482e869 100644 --- a/NzbDrone.Core/Providers/XbmcProvider.cs +++ b/NzbDrone.Core/Providers/XbmcProvider.cs @@ -60,7 +60,7 @@ namespace NzbDrone.Core.Providers var version = GetJsonVersion(host, username, password); //If Dharma - if (version == 2) + if (version == new XbmcVersion(2)) { //Check for active player only when we should skip updates when playing if (!_configProvider.XbmcUpdateWhenPlaying) @@ -80,7 +80,7 @@ namespace NzbDrone.Core.Providers } //If Eden or newer (attempting to make it future compatible) - else if (version >= 3) + else if (version == new XbmcVersion(3) || version == new XbmcVersion(4)) { //Check for active player only when we should skip updates when playing if (!_configProvider.XbmcUpdateWhenPlaying) @@ -96,7 +96,26 @@ namespace NzbDrone.Core.Providers } } - UpdateWithJson(series, host, username, password); + UpdateWithJsonExecBuiltIn(series, host, username, password); + } + + else if (version >= new XbmcVersion(5)) + { + //Check for active player only when we should skip updates when playing + if (!_configProvider.XbmcUpdateWhenPlaying) + { + Logger.Trace("Determining if there are any active players on XBMC host: {0}", host); + var activePlayers = GetActivePlayersEden(host, username, password); + + //If video is currently playing, then skip update + if (activePlayers.Any(a => a.Type.Equals("video"))) + { + Logger.Debug("Video is currently playing, skipping library update"); + continue; + } + } + + UpdateWithJsonVideoLibraryScan(series, host, username, password); } //Log Version zero if check failed @@ -105,7 +124,7 @@ namespace NzbDrone.Core.Providers } } - public virtual bool UpdateWithJson(Series series, string host, string username, string password) + public virtual bool UpdateWithJsonExecBuiltIn(Series series, string host, string username, string password) { try { @@ -126,8 +145,6 @@ namespace NzbDrone.Core.Providers if (path != null) { Logger.Trace("Updating series [{0}] (Path: {1}) on XBMC host: {2}", series.Title, path.File, host); - //var command = String.Format("ExecBuiltIn(UpdateLibrary(video, {0}))", path.File); - //_eventClientProvider.SendAction(hostOnly, ActionType.ExecBuiltin, command); var command = String.Format("ExecBuiltIn(UpdateLibrary(video,{0}))", path.File); SendCommand(host, command, username, password); } @@ -135,8 +152,6 @@ namespace NzbDrone.Core.Providers else { Logger.Trace("Series [{0}] doesn't exist on XBMC host: {1}, Updating Entire Library", series.Title, host); - var command = String.Format("ExecBuiltIn(UpdateLibrary(video))"); - //_eventClientProvider.SendAction(hostOnly, ActionType.ExecBuiltin, command); SendCommand(host, "ExecBuiltIn(UpdateLibrary(video))", username, password); } } @@ -150,6 +165,57 @@ namespace NzbDrone.Core.Providers return true; } + public virtual bool UpdateWithJsonVideoLibraryScan(Series series, string host, string username, string password) + { + try + { + //Use Json! + var xbmcShows = GetTvShowsJson(host, username, password); + + TvShow path = null; + + //Log if response is null, otherwise try to find XBMC's path for series + if (xbmcShows == null) + Logger.Trace("Failed to get TV Shows from XBMC"); + + else + path = xbmcShows.FirstOrDefault(s => s.ImdbNumber == series.SeriesId || s.Label == series.Title); + + var postJson = new JObject(); + postJson.Add(new JProperty("jsonrpc", "2.0")); + postJson.Add(new JProperty("method", "VideoLibrary.Scan")); + postJson.Add(new JProperty("id", 55)); + + if (path != null) + { + Logger.Trace("Updating series [{0}] (Path: {1}) on XBMC host: {2}", series.Title, path.File, host); + postJson.Add(new JProperty("params", new JObject(new JObject(new JProperty("directory", path.File))))); + } + + else + Logger.Trace("Series [{0}] doesn't exist on XBMC host: {1}, Updating Entire Library", series.Title, host); + + var response = _httpProvider.PostCommand(host, username, password, postJson.ToString()); + + if (CheckForJsonError(response)) + return false; + + Logger.Trace(" from response"); + var result = JsonConvert.DeserializeObject>(response); + + if(!result.Result.Equals("OK", StringComparison.InvariantCultureIgnoreCase)) + return false; + } + + catch (Exception ex) + { + Logger.DebugException(ex.Message, ex); + return false; + } + + return true; + } + public virtual bool UpdateWithHttp(Series series, string host, string username, string password) { try @@ -239,12 +305,11 @@ namespace NzbDrone.Core.Providers return field.Value; } - public virtual int GetJsonVersion(string host, string username, string password) + public virtual XbmcVersion GetJsonVersion(string host, string username, string password) { //2 = Dharma - //3 = Eden/Nightly (as of July 2011) - - var version = 0; + //3 & 4 = Eden + //5 & 6 = Frodo try { @@ -256,11 +321,20 @@ namespace NzbDrone.Core.Providers var response = _httpProvider.PostCommand(host, username, password, postJson.ToString()); if (CheckForJsonError(response)) - return version; + return new XbmcVersion(); Logger.Trace("Getting version from response"); - var result = JsonConvert.DeserializeObject(response); - result.Result.TryGetValue("version", out version); + var result = JsonConvert.DeserializeObject>(response); + + var versionObject = result.Result.Property("version"); + + if (versionObject.Value.Type == JTokenType.Integer) + return new XbmcVersion((int)versionObject.Value); + + if(versionObject.Value.Type == JTokenType.Object) + return JsonConvert.DeserializeObject(versionObject.Value.ToString()); + + throw new InvalidCastException("Unknown Version structure!: " + versionObject); } catch (Exception ex) @@ -268,7 +342,7 @@ namespace NzbDrone.Core.Providers Logger.DebugException(ex.Message, ex); } - return version; + return new XbmcVersion(); } public virtual Dictionary GetActivePlayersDharma(string host, string username, string password) @@ -391,7 +465,7 @@ namespace NzbDrone.Core.Providers { Logger.Trace("Sending Test Notifcation to XBMC Host: {0}", host); var version = GetJsonVersion(host, username, password); - if (version == 0) + if (version == new XbmcVersion()) throw new Exception("Failed to get JSON version in test"); } } diff --git a/NzbDrone.Core/Repository/Quality/QualityTypes.cs b/NzbDrone.Core/Repository/Quality/QualityTypes.cs index e77c3f2cb..e055de8a4 100644 --- a/NzbDrone.Core/Repository/Quality/QualityTypes.cs +++ b/NzbDrone.Core/Repository/Quality/QualityTypes.cs @@ -94,11 +94,12 @@ namespace NzbDrone.Core.Repository.Quality public static QualityTypes Unknown = new QualityTypes { Id = 0, Name = "Unknown", Weight = 0 }; public static QualityTypes SDTV = new QualityTypes {Id = 1, Name = "SDTV", Weight = 1}; - public static QualityTypes DVD = new QualityTypes { Id = 2, Name = "DVD", Weight = 2 }; + public static QualityTypes WEBDL480p = new QualityTypes { Id = 8, Name = "WEBDL-480p", Weight = 2 }; + public static QualityTypes DVD = new QualityTypes { Id = 2, Name = "DVD", Weight = 3 }; public static QualityTypes HDTV = new QualityTypes { Id = 4, Name = "HDTV", Weight = 4 }; public static QualityTypes WEBDL720p = new QualityTypes { Id = 5, Name = "WEBDL-720p", Weight = 5 }; - public static QualityTypes WEBDL1080p = new QualityTypes { Id = 3, Name = "WEBDL-1080p", Weight = 7 }; public static QualityTypes Bluray720p = new QualityTypes { Id = 6, Name = "Bluray720p", Weight = 6 }; + public static QualityTypes WEBDL1080p = new QualityTypes { Id = 3, Name = "WEBDL-1080p", Weight = 7 }; public static QualityTypes Bluray1080p = new QualityTypes { Id = 7, Name = "Bluray1080p", Weight = 8 }; public static List All() @@ -107,6 +108,7 @@ namespace NzbDrone.Core.Repository.Quality { Unknown, SDTV, + WEBDL480p, DVD, HDTV, WEBDL720p,