You've already forked Sonarr
							
							
				mirror of
				https://github.com/Sonarr/Sonarr.git
				synced 2025-10-31 00:07:55 +02:00 
			
		
		
		
	Xbmc Refactored
This commit is contained in:
		| @@ -138,7 +138,7 @@ | ||||
|     <Compile Include="Messaging\TestCommandExecutor.cs" /> | ||||
|     <Compile Include="Reflection\ReflectionExtensions.cs" /> | ||||
|     <Compile Include="ServiceFactory.cs" /> | ||||
|     <Compile Include="StringExtention.cs" /> | ||||
|     <Compile Include="StringExtension.cs" /> | ||||
|     <Compile Include="HttpProvider.cs" /> | ||||
|     <Compile Include="ConsoleService.cs" /> | ||||
|     <Compile Include="Contract\ReportBase.cs" /> | ||||
| @@ -155,7 +155,6 @@ | ||||
|     <Compile Include="IServiceProvider.cs" /> | ||||
|     <Compile Include="TinyIoC.cs" /> | ||||
|     <Compile Include="TryParseExtension.cs" /> | ||||
|     <Compile Include="UdpProvider.cs" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <None Include="packages.config"> | ||||
|   | ||||
| @@ -1,191 +0,0 @@ | ||||
| using System.Linq; | ||||
| using System; | ||||
| using System.Net; | ||||
| using System.Net.Sockets; | ||||
| using NLog; | ||||
|  | ||||
| namespace NzbDrone.Common | ||||
| { | ||||
|     public class UdpProvider | ||||
|     { | ||||
|         private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); | ||||
|  | ||||
|         public UdpProvider() | ||||
|         { | ||||
|              | ||||
|         } | ||||
|  | ||||
|         private const int StandardPort = 9777; | ||||
|         private const int MaxPacketSize = 1024; | ||||
|         private const int HeaderSize = 32; | ||||
|         private const int MaxPayloadSize = MaxPacketSize - HeaderSize; | ||||
|         private const byte MajorVersion = 2; | ||||
|         private const byte MinorVersion = 0; | ||||
|  | ||||
|         public enum PacketType | ||||
|         { | ||||
|             Helo = 0x01, | ||||
|             Bye = 0x02, | ||||
|             Button = 0x03, | ||||
|             Mouse = 0x04, | ||||
|             Ping = 0x05, | ||||
|             Broadcast = 0x06,  //Currently not implemented | ||||
|             Notification = 0x07, | ||||
|             Blob = 0x08, | ||||
|             Log = 0x09, | ||||
|             Action = 0x0A, | ||||
|             Debug = 0xFF //Currently not implemented | ||||
|         } | ||||
|  | ||||
|         private byte[] Header(PacketType packetType, int numberOfPackets, int currentPacket, int payloadSize, uint uniqueToken) | ||||
|         { | ||||
|             byte[] header = new byte[HeaderSize]; | ||||
|  | ||||
|             header[0] = (byte)'X'; | ||||
|             header[1] = (byte)'B'; | ||||
|             header[2] = (byte)'M'; | ||||
|             header[3] = (byte)'C'; | ||||
|  | ||||
|             header[4] = MajorVersion; | ||||
|             header[5] = MinorVersion; | ||||
|  | ||||
|             if (currentPacket == 1) | ||||
|             { | ||||
|                 header[6] = (byte)(((ushort)packetType & 0xff00) >> 8); | ||||
|                 header[7] = (byte)((ushort)packetType & 0x00ff); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 header[6] = ((ushort)PacketType.Blob & 0xff00) >> 8; | ||||
|                 header[7] = (ushort)PacketType.Blob & 0x00ff; | ||||
|             } | ||||
|  | ||||
|             header[8] = (byte)((currentPacket & 0xff000000) >> 24); | ||||
|             header[9] = (byte)((currentPacket & 0x00ff0000) >> 16); | ||||
|             header[10] = (byte)((currentPacket & 0x0000ff00) >> 8); | ||||
|             header[11] = (byte)(currentPacket & 0x000000ff); | ||||
|  | ||||
|             header[12] = (byte)((numberOfPackets & 0xff000000) >> 24); | ||||
|             header[13] = (byte)((numberOfPackets & 0x00ff0000) >> 16); | ||||
|             header[14] = (byte)((numberOfPackets & 0x0000ff00) >> 8); | ||||
|             header[15] = (byte)(numberOfPackets & 0x000000ff); | ||||
|  | ||||
|             header[16] = (byte)((payloadSize & 0xff00) >> 8); | ||||
|             header[17] = (byte)(payloadSize & 0x00ff); | ||||
|  | ||||
|             header[18] = (byte)((uniqueToken & 0xff000000) >> 24); | ||||
|             header[19] = (byte)((uniqueToken & 0x00ff0000) >> 16); | ||||
|             header[20] = (byte)((uniqueToken & 0x0000ff00) >> 8); | ||||
|             header[21] = (byte)(uniqueToken & 0x000000ff); | ||||
|  | ||||
|             return header; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public virtual bool Send(string address, PacketType packetType, byte[] payload) | ||||
|         { | ||||
|             var uniqueToken = (uint)DateTime.Now.TimeOfDay.Milliseconds; | ||||
|  | ||||
|             var socket = Connect(address, StandardPort); | ||||
|  | ||||
|             if (socket == null || !socket.Connected) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 bool successfull = true; | ||||
|                 int packetCount = (payload.Length / MaxPayloadSize) + 1; | ||||
|                 int bytesToSend = 0; | ||||
|                 int bytesSent = 0; | ||||
|                 int bytesLeft = payload.Length; | ||||
|  | ||||
|                 for (int Package = 1; Package <= packetCount; Package++) | ||||
|                 { | ||||
|  | ||||
|                     if (bytesLeft > MaxPayloadSize) | ||||
|                     { | ||||
|                         bytesToSend = MaxPayloadSize; | ||||
|                         bytesLeft -= bytesToSend; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         bytesToSend = bytesLeft; | ||||
|                         bytesLeft = 0; | ||||
|                     } | ||||
|  | ||||
|                     byte[] header = Header(packetType, packetCount, Package, bytesToSend, uniqueToken); | ||||
|                     byte[] packet = new byte[MaxPacketSize]; | ||||
|  | ||||
|                     Array.Copy(header, 0, packet, 0, header.Length); | ||||
|                     Array.Copy(payload, bytesSent, packet, header.Length, bytesToSend); | ||||
|  | ||||
|                     int sendSize = socket.Send(packet, header.Length + bytesToSend, SocketFlags.None); | ||||
|  | ||||
|                     if (sendSize != (header.Length + bytesToSend)) | ||||
|                     { | ||||
|                         successfull = false; | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                     bytesSent += bytesToSend; | ||||
|                 } | ||||
|                 Disconnect(socket); | ||||
|                 return successfull; | ||||
|             } | ||||
|  | ||||
|             catch | ||||
|             { | ||||
|                 Disconnect(socket); | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private Socket Connect(string address, int port) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); | ||||
|  | ||||
|                 IPAddress ip; | ||||
|                 if (!IPAddress.TryParse(address, out ip)) | ||||
|                 { | ||||
|                     IPHostEntry ipHostEntry = Dns.GetHostEntry(address); | ||||
|                     foreach (IPAddress ipAddress in ipHostEntry.AddressList) | ||||
|                     { | ||||
|                         if (ipAddress.AddressFamily == AddressFamily.InterNetwork) | ||||
|                         { | ||||
|                             ip = ipAddress; | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 socket.Connect(new IPEndPoint(ip, port)); | ||||
|                 return socket; | ||||
|             } | ||||
|  | ||||
|             catch (Exception exc) | ||||
|             { | ||||
|                 Logger.TraceException(exc.Message, exc); | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void Disconnect(Socket socket) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 if (socket != null) | ||||
|                 { | ||||
|                     socket.Shutdown(SocketShutdown.Both); | ||||
|                     socket.Close(); | ||||
|                 } | ||||
|             } | ||||
|             catch | ||||
|             { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.NotificationTests | ||||
|         { | ||||
|             _notifications = new List<INotification>(); | ||||
|  | ||||
|             _notifications.Add(new Xbmc(null, null)); | ||||
|             _notifications.Add(new Notifications.Xbmc.Xbmc(null, null)); | ||||
|             _notifications.Add(new PlexClient(null)); | ||||
|             _notifications.Add(new PlexServer(null)); | ||||
|             _notifications.Add(new Email(null)); | ||||
| @@ -49,8 +49,8 @@ namespace NzbDrone.Core.Test.NotificationTests | ||||
|         { | ||||
|             Mocker.SetConstant<INotificationRepository>(Mocker.Resolve<NotificationRepository>()); | ||||
|  | ||||
|             Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof (Xbmc))) | ||||
|                   .Returns(new Xbmc(null, null)); | ||||
|             Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof(Notifications.Xbmc.Xbmc))) | ||||
|                   .Returns(new Notifications.Xbmc.Xbmc(null, null)); | ||||
|  | ||||
|             Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof(PlexClient))) | ||||
|                   .Returns(new PlexClient(null)); | ||||
|   | ||||
| @@ -0,0 +1,80 @@ | ||||
| using System; | ||||
| using System.Linq; | ||||
| using FizzWare.NBuilder; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Configuration; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Tv; | ||||
| using NzbDrone.Core.Model.Xbmc; | ||||
| using NzbDrone.Core.Providers; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
| using NzbDrone.Test.Common.AutoMoq; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class GetJsonVersionFixture : CoreTest<XbmcService> | ||||
|     { | ||||
|         private XbmcSettings _settings; | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             _settings = new XbmcSettings | ||||
|                             { | ||||
|                                 Host = "localhost", | ||||
|                                 Port = 8080, | ||||
|                                 Username = "xbmc", | ||||
|                                 Password = "xbmc", | ||||
|                                 AlwaysUpdate = false, | ||||
|                                 CleanLibrary = false, | ||||
|                                 UpdateLibrary = true | ||||
|                             }; | ||||
|         } | ||||
|  | ||||
|         [TestCase(3)] | ||||
|         [TestCase(2)] | ||||
|         [TestCase(0)] | ||||
|         public void should_get_version_from_major_only(int number) | ||||
|         { | ||||
|             var message = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"version\":" + number + "}}"; | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(message); | ||||
|  | ||||
|             Subject.GetJsonVersion(_settings).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 should_get_version_from_semantic_version(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<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(message); | ||||
|  | ||||
|             Subject.GetJsonVersion(_settings).Should().Be(new XbmcVersion(major, minor, patch)); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_get_version_zero_when_an_error_is_received() | ||||
|         { | ||||
|             var message = "{\"error\":{\"code\":-32601,\"message\":\"Method not found.\"},\"id\":10,\"jsonrpc\":\"2.0\"}"; | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(message); | ||||
|  | ||||
|             Subject.GetJsonVersion(_settings).Should().Be(new XbmcVersion(0)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,74 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Http | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class ActivePlayersFixture : CoreTest<HttpApiProvider> | ||||
|     { | ||||
|         private XbmcSettings _settings; | ||||
|         private string _expectedUrl; | ||||
|  | ||||
|         private void WithNoActivePlayers() | ||||
|         { | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.DownloadString(_expectedUrl, _settings.Username, _settings.Password)) | ||||
|                   .Returns("<html><li>Filename:[Nothing Playing]</html>"); | ||||
|         } | ||||
|  | ||||
|         private void WithVideoPlayerActive() | ||||
|         { | ||||
|             var activePlayers = @"<html><li>Filename:C:\Test\TV\2 Broke Girls\Season 01\2 Broke Girls - S01E01 - Pilot [SDTV].avi" + | ||||
|                               "<li>PlayStatus:Playing<li>VideoNo:0<li>Type:Video<li>Thumb:special://masterprofile/Thumbnails/Video/a/auto-a664d5a2.tbn" + | ||||
|                               "<li>Time:00:06<li>Duration:21:35<li>Percentage:0<li>File size:183182590<li>Changed:True</html>"; | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.DownloadString(_expectedUrl, _settings.Username, _settings.Password)) | ||||
|                   .Returns(activePlayers); | ||||
|         } | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             _settings = new XbmcSettings | ||||
|             { | ||||
|                 Host = "localhost", | ||||
|                 Port = 8080, | ||||
|                 Username = "xbmc", | ||||
|                 Password = "xbmc", | ||||
|                 AlwaysUpdate = false, | ||||
|                 CleanLibrary = false, | ||||
|                 UpdateLibrary = true | ||||
|             }; | ||||
|  | ||||
|             _expectedUrl = String.Format("http://{0}/xbmcCmds/xbmcHttp?command={1}", _settings.Address, "getcurrentlyplaying"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void _should_be_empty_when_no_active_players() | ||||
|         { | ||||
|             WithNoActivePlayers(); | ||||
|  | ||||
|             Subject.GetActivePlayers(_settings).Should().BeEmpty(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_have_active_video_player() | ||||
|         { | ||||
|             WithVideoPlayerActive(); | ||||
|  | ||||
|             var result = Subject.GetActivePlayers(_settings); | ||||
|  | ||||
|             result.Should().HaveCount(1); | ||||
|             result.First().Type.Should().Be("video"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,41 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Http | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class CheckForErrorFixture : CoreTest<HttpApiProvider> | ||||
|     { | ||||
|         [Test] | ||||
|         public void should_be_true_when_the_response_contains_an_error() | ||||
|         { | ||||
|             const string response = "html><li>Error:Unknown command</html>"; | ||||
|  | ||||
|             Subject.CheckForError(response).Should().BeTrue(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void JsonError_true_empty_response() | ||||
|         { | ||||
|             var response = String.Empty; | ||||
|  | ||||
|             Subject.CheckForError(response).Should().BeTrue(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void JsonError_false() | ||||
|         { | ||||
|             const string response = "html><li>Filename:[Nothing Playing]</html>"; | ||||
|  | ||||
|             Subject.CheckForError(response).Should().BeFalse(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,99 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
| using NzbDrone.Core.Tv; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Http | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class GetSeriesPathFixture : CoreTest<HttpApiProvider> | ||||
|     { | ||||
|         private XbmcSettings _settings; | ||||
|         private Series _series; | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             _settings = new XbmcSettings | ||||
|             { | ||||
|                 Host = "localhost", | ||||
|                 Port = 8080, | ||||
|                 Username = "xbmc", | ||||
|                 Password = "xbmc", | ||||
|                 AlwaysUpdate = false, | ||||
|                 CleanLibrary = false, | ||||
|                 UpdateLibrary = true | ||||
|             }; | ||||
|  | ||||
|             _series = new Series | ||||
|             { | ||||
|                 TvdbId = 79488, | ||||
|                 Title = "30 Rock" | ||||
|             }; | ||||
|  | ||||
|             const string setResponseUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=SetResponseFormat(webheader;false;webfooter;false;header;<xml>;footer;</xml>;opentag;<tag>;closetag;</tag>;closefinaltag;false)"; | ||||
|             const string resetResponseUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=SetResponseFormat()"; | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.DownloadString(setResponseUrl, _settings.Username, _settings.Password)) | ||||
|                   .Returns("<xml><tag>OK</xml>"); | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.DownloadString(resetResponseUrl, _settings.Username, _settings.Password)) | ||||
|                   .Returns(@"<html> | ||||
|                              <li>OK | ||||
|                              </html>"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_get_series_path() | ||||
|         { | ||||
|             const string queryResult = @"<xml><record><field>smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/</field></record></xml>"; | ||||
|             var query = String.Format("http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)"); | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.DownloadString(query, _settings.Username, _settings.Password)) | ||||
|                   .Returns(queryResult); | ||||
|  | ||||
|             Subject.GetSeriesPath(_settings, _series) | ||||
|                    .Should().Be("smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_get_null_for_series_path() | ||||
|         { | ||||
|             const string queryResult = @"<xml></xml>"; | ||||
|             var query = String.Format("http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)"); | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.DownloadString(query, _settings.Username, _settings.Password)) | ||||
|                   .Returns(queryResult); | ||||
|  | ||||
|  | ||||
|             Subject.GetSeriesPath(_settings, _series) | ||||
|                    .Should().BeNull(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_get_series_path_with_special_characters_in_it() | ||||
|         { | ||||
|             const string queryResult = @"<xml><record><field>smb://xbmc:xbmc@HOMESERVER/TV/Law & Order- Special Victims Unit/</field></record></xml>"; | ||||
|             var query = String.Format("http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)"); | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.DownloadString(query, _settings.Username, _settings.Password)) | ||||
|                   .Returns(queryResult); | ||||
|  | ||||
|  | ||||
|             Subject.GetSeriesPath(_settings, _series) | ||||
|                    .Should().Be("smb://xbmc:xbmc@HOMESERVER/TV/Law & Order- Special Victims Unit/"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,81 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FizzWare.NBuilder; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
| using NzbDrone.Core.Tv; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Http | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class UpdateFixture : CoreTest<HttpApiProvider> | ||||
|     { | ||||
|         private XbmcSettings _settings; | ||||
|         private string _seriesQueryUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)"; | ||||
|         private Series _fakeSeries; | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             _settings = new XbmcSettings | ||||
|             { | ||||
|                 Host = "localhost", | ||||
|                 Port = 8080, | ||||
|                 Username = "xbmc", | ||||
|                 Password = "xbmc", | ||||
|                 AlwaysUpdate = false, | ||||
|                 CleanLibrary = false, | ||||
|                 UpdateLibrary = true | ||||
|             }; | ||||
|  | ||||
|             _fakeSeries = Builder<Series>.CreateNew() | ||||
|                                          .With(s => s.TvdbId = 79488) | ||||
|                                          .With(s => s.Title = "30 Rock") | ||||
|                                          .Build(); | ||||
|         } | ||||
|  | ||||
|         private void WithSeriesPath() | ||||
|         { | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.DownloadString(_seriesQueryUrl, _settings.Username, _settings.Password)) | ||||
|                   .Returns("<xml><record><field>smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/</field></record></xml>"); | ||||
|         } | ||||
|  | ||||
|         private void WithoutSeriesPath() | ||||
|         { | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.DownloadString(_seriesQueryUrl, _settings.Username, _settings.Password)) | ||||
|                   .Returns("<xml></xml>"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_update_using_series_path() | ||||
|         { | ||||
|             WithSeriesPath(); | ||||
|             const string url = "http://localhost:8080/xbmcCmds/xbmcHttp?command=ExecBuiltIn(UpdateLibrary(video,smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/))"; | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>().Setup(s => s.DownloadString(url, _settings.Username, _settings.Password)); | ||||
|  | ||||
|             Subject.Update(_settings, _fakeSeries); | ||||
|             Mocker.VerifyAllMocks(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_update_all_paths_when_series_path_not_found() | ||||
|         { | ||||
|             WithoutSeriesPath(); | ||||
|             const string url = "http://localhost:8080/xbmcCmds/xbmcHttp?command=ExecBuiltIn(UpdateLibrary(video))"; | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>().Setup(s => s.DownloadString(url, _settings.Username, _settings.Password)); | ||||
|  | ||||
|             Subject.Update(_settings, _fakeSeries); | ||||
|             Mocker.VerifyAllMocks(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,34 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class HttpApiProviderFixture : CoreTest<HttpApiProvider> | ||||
|     { | ||||
|         private XbmcSettings _settings; | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             _settings = new XbmcSettings | ||||
|             { | ||||
|                 Host = "localhost", | ||||
|                 Port = 8080, | ||||
|                 Username = "xbmc", | ||||
|                 Password = "xbmc", | ||||
|                 AlwaysUpdate = false, | ||||
|                 CleanLibrary = false, | ||||
|                 UpdateLibrary = true | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,122 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Json | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class ActivePlayersFixture : CoreTest<JsonApiProvider> | ||||
|     { | ||||
|         private XbmcSettings _settings; | ||||
|  | ||||
|         private void WithNoActivePlayers() | ||||
|         { | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.PostCommand(_settings.Address, _settings.Username, _settings.Password, It.IsAny<string>())) | ||||
|                   .Returns("{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[]}"); | ||||
|         } | ||||
|  | ||||
|         private void WithVideoPlayerActive() | ||||
|         { | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.PostCommand(_settings.Address, _settings.Username, _settings.Password, It.IsAny<string>())) | ||||
|                   .Returns("{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"video\"}]}"); | ||||
|         } | ||||
|  | ||||
|         private void WithAudioPlayerActive() | ||||
|         { | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.PostCommand(_settings.Address, _settings.Username, _settings.Password, It.IsAny<string>())) | ||||
|                   .Returns("{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"audio\"}]}"); | ||||
|         } | ||||
|  | ||||
|         private void WithPicturePlayerActive() | ||||
|         { | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.PostCommand(_settings.Address, _settings.Username, _settings.Password, It.IsAny<string>())) | ||||
|                   .Returns("{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"picture\"}]}"); | ||||
|         } | ||||
|  | ||||
|         private void WithAllPlayersActive() | ||||
|         { | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.PostCommand(_settings.Address, _settings.Username, _settings.Password, It.IsAny<string>())) | ||||
|                   .Returns("{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"audio\"},{\"playerid\":2,\"type\":\"picture\"},{\"playerid\":3,\"type\":\"video\"}]}"); | ||||
|         } | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             _settings = new XbmcSettings | ||||
|             { | ||||
|                 Host = "localhost", | ||||
|                 Port = 8080, | ||||
|                 Username = "xbmc", | ||||
|                 Password = "xbmc", | ||||
|                 AlwaysUpdate = false, | ||||
|                 CleanLibrary = false, | ||||
|                 UpdateLibrary = true | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void _should_be_empty_when_no_active_players() | ||||
|         { | ||||
|             WithNoActivePlayers(); | ||||
|              | ||||
|             Subject.GetActivePlayers(_settings).Should().BeEmpty(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_have_active_video_player() | ||||
|         { | ||||
|             WithVideoPlayerActive(); | ||||
|  | ||||
|             var result = Subject.GetActivePlayers(_settings); | ||||
|  | ||||
|             result.Should().HaveCount(1); | ||||
|             result.First().Type.Should().Be("video"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_have_active_audio_player() | ||||
|         { | ||||
|             WithAudioPlayerActive(); | ||||
|              | ||||
|             var result = Subject.GetActivePlayers(_settings); | ||||
|  | ||||
|             result.Should().HaveCount(1); | ||||
|             result.First().Type.Should().Be("audio"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_have_active_picture_player() | ||||
|         { | ||||
|             WithPicturePlayerActive(); | ||||
|  | ||||
|             var result = Subject.GetActivePlayers(_settings); | ||||
|              | ||||
|             result.Should().HaveCount(1); | ||||
|             result.First().Type.Should().Be("picture"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_have_all_players_active() | ||||
|         { | ||||
|             WithAllPlayersActive(); | ||||
|  | ||||
|             var result = Subject.GetActivePlayers(_settings); | ||||
|  | ||||
|             result.Should().HaveCount(3); | ||||
|             result.Select(a => a.PlayerId).Distinct().Should().HaveCount(3); | ||||
|             result.Select(a => a.Type).Distinct().Should().HaveCount(3); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,39 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FluentAssertions; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Json | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class CheckForErrorFixture : CoreTest<JsonApiProvider> | ||||
|     { | ||||
|         [Test] | ||||
|         public void should_be_true_when_the_response_contains_an_error() | ||||
|         { | ||||
|             const string response = "{\"error\":{\"code\":-32601,\"message\":\"Method not found.\"},\"id\":10,\"jsonrpc\":\"2.0\"}"; | ||||
|  | ||||
|             Subject.CheckForError(response).Should().BeTrue(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void JsonError_true_empty_response() | ||||
|         { | ||||
|             var response = String.Empty; | ||||
|  | ||||
|             Subject.CheckForError(response).Should().BeTrue(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void JsonError_false() | ||||
|         { | ||||
|             const string response = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"version\":3}}"; | ||||
|  | ||||
|             Subject.CheckForError(response).Should().BeFalse(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,103 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
| using NzbDrone.Core.Tv; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Json | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class GetSeriesPathFixture : CoreTest<JsonApiProvider> | ||||
|     { | ||||
|         private XbmcSettings _settings; | ||||
|         private Series _series; | ||||
|         private string _response; | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             _settings = new XbmcSettings | ||||
|             { | ||||
|                 Host = "localhost", | ||||
|                 Port = 8080, | ||||
|                 Username = "xbmc", | ||||
|                 Password = "xbmc", | ||||
|                 AlwaysUpdate = false, | ||||
|                 CleanLibrary = false, | ||||
|                 UpdateLibrary = true | ||||
|             }; | ||||
|  | ||||
|             _response = "{\"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}]}}"; | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup( | ||||
|                       s => s.PostCommand(_settings.Address, _settings.Username, _settings.Password, It.IsAny<string>())) | ||||
|                   .Returns(_response); | ||||
|         } | ||||
|  | ||||
|         private void WithMatchingTvdbId() | ||||
|         { | ||||
|             _series = new Series | ||||
|                           { | ||||
|                               TvdbId = 78461, | ||||
|                               Title = "TV Show" | ||||
|                           }; | ||||
|         } | ||||
|  | ||||
|         private void WithMatchingTitle() | ||||
|         { | ||||
|             _series = new Series | ||||
|             { | ||||
|                 TvdbId = 1, | ||||
|                 Title = "30 Rock" | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         private void WithoutMatchingSeries() | ||||
|         { | ||||
|             _series = new Series | ||||
|             { | ||||
|                 TvdbId = 1, | ||||
|                 Title = "Does not exist" | ||||
|             };  | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_return_null_when_series_is_not_found() | ||||
|         { | ||||
|             WithoutMatchingSeries(); | ||||
|  | ||||
|             Subject.GetSeriesPath(_settings, _series).Should().BeNull(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_return_path_when_tvdbId_matches() | ||||
|         { | ||||
|             WithMatchingTvdbId(); | ||||
|  | ||||
|             Subject.GetSeriesPath(_settings, _series).Should().Be("smb://HOMESERVER/TV/8 Simple Rules/"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_return_path_when_title_matches() | ||||
|         { | ||||
|             WithMatchingTitle(); | ||||
|  | ||||
|             Subject.GetSeriesPath(_settings, _series).Should().Be("smb://HOMESERVER/TV/30 Rock/"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										104
									
								
								NzbDrone.Core.Test/NotificationTests/Xbmc/Json/UpdateFixture.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								NzbDrone.Core.Test/NotificationTests/Xbmc/Json/UpdateFixture.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FizzWare.NBuilder; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
| using NzbDrone.Core.Tv; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Json | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class UpdateFixture : CoreTest<JsonApiProvider> | ||||
|     { | ||||
|         private XbmcSettings _settings; | ||||
|         const string _expectedJson = "{\"jsonrpc\":\"2.0\",\"method\":\"VideoLibrary.GetTvShows\",\"params\":{\"properties\":[\"file\",\"imdbnumber\"]},\"id\":10}"; | ||||
|  | ||||
|         private const string _tvshowsResponse = "{\"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}]}}"; | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             _settings = new XbmcSettings | ||||
|             { | ||||
|                 Host = "localhost", | ||||
|                 Port = 8080, | ||||
|                 Username = "xbmc", | ||||
|                 Password = "xbmc", | ||||
|                 AlwaysUpdate = false, | ||||
|                 CleanLibrary = false, | ||||
|                 UpdateLibrary = true | ||||
|             }; | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                 .Setup(s => s.PostCommand(_settings.Address, _settings.Username, _settings.Password, | ||||
|                         It.Is<string>(e => e.Replace(" ", "").Replace("\r\n", "").Replace("\t", "") == _expectedJson.Replace(" ", "")))) | ||||
|                 .Returns(_tvshowsResponse); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_update_using_series_path() | ||||
|         { | ||||
|             var fakeSeries = Builder<Series>.CreateNew() | ||||
|                 .With(s => s.TvdbId = 79488) | ||||
|                 .With(s => s.Title = "30 Rock") | ||||
|                 .Build(); | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Setup(s => s.PostCommand(_settings.Address, _settings.Username, _settings.Password, It.Is<String>( | ||||
|                     e => e.Replace(" ", "") | ||||
|                       .Replace("\r\n", "") | ||||
|                       .Replace("\t", "") | ||||
|                       .Contains("\"params\":{\"directory\":\"smb://HOMESERVER/TV/30Rock/\"}")))) | ||||
|                   .Returns("{\"id\":55,\"jsonrpc\":\"2.0\",\"result\":\"OK\"}"); | ||||
|  | ||||
|             Subject.Update(_settings, fakeSeries); | ||||
|  | ||||
|             Mocker.GetMock<IHttpProvider>() | ||||
|                   .Verify(s => s.PostCommand(_settings.Address, _settings.Username, _settings.Password, It.Is<String>( | ||||
|                     e => e.Replace(" ", "") | ||||
|                       .Replace("\r\n", "") | ||||
|                       .Replace("\t", "") | ||||
|                       .Contains("\"params\":{\"directory\":\"smb://HOMESERVER/TV/30Rock/\"}"))), Times.Once()); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_update_all_paths_when_series_path_not_found() | ||||
|         { | ||||
|             var fakeSeries = Builder<Series>.CreateNew() | ||||
|                 .With(s => s.TvdbId = 1) | ||||
|                 .With(s => s.Title = "Not 30 Rock") | ||||
|                 .Build(); | ||||
|  | ||||
|              Mocker.GetMock<IHttpProvider>() | ||||
|                    .Setup(s => s.PostCommand(_settings.Address, _settings.Username, _settings.Password, It.Is<String>( | ||||
|                      e => !e.Replace(" ", "") | ||||
|                       .Replace("\r\n", "") | ||||
|                       .Replace("\t", "") | ||||
|                       .Contains("\"params\":{\"directory\":\"smb://HOMESERVER/TV/30Rock/\"}")))) | ||||
|                    .Returns("{\"id\":55,\"jsonrpc\":\"2.0\",\"result\":\"OK\"}"); | ||||
|  | ||||
|              Subject.Update(_settings, fakeSeries); | ||||
|  | ||||
|              Mocker.GetMock<IHttpProvider>() | ||||
|                    .Verify(s => s.PostCommand(_settings.Address, _settings.Username, _settings.Password, It.Is<String>( | ||||
|                      e => e.Replace(" ", "") | ||||
|                       .Replace("\r\n", "") | ||||
|                       .Replace("\t", "") | ||||
|                       .Contains("\"params\":{\"directory\":\"smb://HOMESERVER/TV/30Rock/\"}"))), Times.Never()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,32 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FluentAssertions; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class JsonApiProviderFixture : CoreTest<JsonApiProvider> | ||||
|     { | ||||
|         private XbmcSettings _settings; | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             _settings = new XbmcSettings | ||||
|             { | ||||
|                 Host = "localhost", | ||||
|                 Port = 8080, | ||||
|                 Username = "xbmc", | ||||
|                 Password = "xbmc", | ||||
|                 AlwaysUpdate = false, | ||||
|                 CleanLibrary = false, | ||||
|                 UpdateLibrary = true | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,40 @@ | ||||
|  | ||||
|  | ||||
| using System; | ||||
| using System.Linq; | ||||
| using FizzWare.NBuilder; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Configuration; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Tv; | ||||
| using NzbDrone.Core.Model.Xbmc; | ||||
| using NzbDrone.Core.Providers; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
| using NzbDrone.Test.Common.AutoMoq; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.NotificationTests.Xbmc | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class XbmcProviderTest : CoreTest | ||||
|     { | ||||
|         private XbmcSettings _settings; | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             _settings = new XbmcSettings | ||||
|                             { | ||||
|                                 Host = "localhost", | ||||
|                                 Port = 8080, | ||||
|                                 Username = "xbmc", | ||||
|                                 Password = "xbmc", | ||||
|                                 AlwaysUpdate = false, | ||||
|                                 CleanLibrary = false, | ||||
|                                 UpdateLibrary = true | ||||
|                             }; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -149,6 +149,17 @@ | ||||
|     <Compile Include="MediaFileTests\EpisodeFileMoverFixture.cs" /> | ||||
|     <Compile Include="MetadataSourceTests\TracktProxyFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\NotificationServiceFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\GetJsonVersionFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\HttpApiProviderFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\Http\ActivePlayersFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\Http\CheckForErrorFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\Http\GetSeriesPathFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\Http\UpdateFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\JsonApiProviderFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\Json\ActivePlayersFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\Json\CheckForErrorFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\Json\GetSeriesPathFixture.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\Json\UpdateFixture.cs" /> | ||||
|     <Compile Include="Qualities\QualitySizeRepositoryFixture.cs" /> | ||||
|     <Compile Include="Qualities\QualityProfileRepositoryFixture.cs" /> | ||||
|     <Compile Include="RootFolderTests\FreeSpaceOnDrivesFixture.cs" /> | ||||
| @@ -163,7 +174,7 @@ | ||||
|     <Compile Include="ProviderTests\RecycleBinProviderTests\EmptyFixture.cs" /> | ||||
|     <Compile Include="ProviderTests\RecycleBinProviderTests\DeleteFileFixture.cs" /> | ||||
|     <Compile Include="ProviderTests\RecycleBinProviderTests\DeleteDirectoryFixture.cs" /> | ||||
|     <Compile Include="ProviderTests\PlexProviderTest.cs" /> | ||||
|     <Compile Include="NotificationTests\PlexProviderTest.cs" /> | ||||
|     <Compile Include="TvTests\EpisodeRepositoryTests\EpisodesRepositoryReadFixture.cs" /> | ||||
|     <Compile Include="TvTests\EpisodeRepositoryTests\EpisodesWithoutFilesFixture.cs" /> | ||||
|     <Compile Include="TvTests\EpisodeRepositoryTests\EpisodesBetweenDatesFixture.cs" /> | ||||
| @@ -175,8 +186,8 @@ | ||||
|     <Compile Include="DecisionEngineTests\QualityUpgradeSpecificationFixture.cs" /> | ||||
|     <Compile Include="DecisionEngineTests\QualityUpgradableSpecificationFixture.cs" /> | ||||
|     <Compile Include="ProviderTests\DiskProviderTests\FreeDiskSpaceTest.cs" /> | ||||
|     <Compile Include="ProviderTests\ProwlProviderTest.cs" /> | ||||
|     <Compile Include="ProviderTests\GrowlProviderTest.cs" /> | ||||
|     <Compile Include="NotificationTests\ProwlProviderTest.cs" /> | ||||
|     <Compile Include="NotificationTests\GrowlProviderTest.cs" /> | ||||
|     <Compile Include="ProviderTests\DiskProviderTests\ExtractArchiveFixture.cs" /> | ||||
|     <Compile Include="ProviderTests\PostDownloadProviderTests\DropFolderImportServiceFixture.cs" /> | ||||
|     <Compile Include="SeriesStatsTests\SeriesStatisticsFixture.cs" /> | ||||
| @@ -187,8 +198,7 @@ | ||||
|     <Compile Include="HelperTests\SortHelperTest.cs" /> | ||||
|     <Compile Include="DecisionEngineTests\AcceptableSizeSpecificationFixture.cs" /> | ||||
|     <Compile Include="Qualities\QualitySizeServiceFixture.cs" /> | ||||
|     <Compile Include="ProviderTests\EventClientProviderTest.cs" /> | ||||
|     <Compile Include="ProviderTests\XbmcProviderTest.cs" /> | ||||
|     <Compile Include="NotificationTests\Xbmc\XbmcServiceFixture.cs" /> | ||||
|     <Compile Include="TvTests\EpisodeProviderTests\EpisodeProviderTest_GetEpisodesByParseResult.cs" /> | ||||
|     <Compile Include="ProviderTests\DiskScanProviderTests\ImportFileFixture.cs" /> | ||||
|     <Compile Include="FluentTest.cs" /> | ||||
|   | ||||
| @@ -1,98 +0,0 @@ | ||||
|  | ||||
|  | ||||
| using System; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Model.Xbmc; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
| using NzbDrone.Test.Common.AutoMoq; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.ProviderTests | ||||
| { | ||||
|     [TestFixture] | ||||
|      | ||||
|     public class EventClientProviderTest : CoreTest | ||||
|     { | ||||
|         [Test] | ||||
|         public void SendNotification_true() | ||||
|         { | ||||
|              | ||||
|              | ||||
|  | ||||
|             var header = "NzbDrone Test"; | ||||
|             var message = "Test Message!"; | ||||
|             var address = "localhost"; | ||||
|  | ||||
|             var fakeUdp = Mocker.GetMock<UdpProvider>(); | ||||
|             fakeUdp.Setup(s => s.Send(address, UdpProvider.PacketType.Notification, It.IsAny<byte[]>())).Returns(true); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<EventClientProvider>().SendNotification(header, message, IconType.Jpeg, "NzbDrone.jpg", address); | ||||
|  | ||||
|              | ||||
|             Assert.AreEqual(true, result); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void SendNotification_false() | ||||
|         { | ||||
|              | ||||
|              | ||||
|  | ||||
|             var header = "NzbDrone Test"; | ||||
|             var message = "Test Message!"; | ||||
|             var address = "localhost"; | ||||
|  | ||||
|             var fakeUdp = Mocker.GetMock<UdpProvider>(); | ||||
|             fakeUdp.Setup(s => s.Send(address, UdpProvider.PacketType.Notification, It.IsAny<byte[]>())).Returns(false); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<EventClientProvider>().SendNotification(header, message, IconType.Jpeg, "NzbDrone.jpg", address); | ||||
|  | ||||
|              | ||||
|             Assert.AreEqual(false, result); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void SendAction_Update_true() | ||||
|         { | ||||
|              | ||||
|              | ||||
|  | ||||
|             var path = @"C:\Test\TV\30 Rock"; | ||||
|             var command = String.Format("ExecBuiltIn(UpdateLibrary(video,{0}))", path); | ||||
|             var address = "localhost"; | ||||
|  | ||||
|             var fakeUdp = Mocker.GetMock<UdpProvider>(); | ||||
|             fakeUdp.Setup(s => s.Send(address, UdpProvider.PacketType.Action, It.IsAny<byte[]>())).Returns(true); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<EventClientProvider>().SendAction(address, ActionType.ExecBuiltin, command); | ||||
|  | ||||
|              | ||||
|             Assert.AreEqual(true, result); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void SendAction_Update_false() | ||||
|         { | ||||
|              | ||||
|              | ||||
|  | ||||
|             var path = @"C:\Test\TV\30 Rock"; | ||||
|             var command = String.Format("ExecBuiltIn(UpdateLibrary(video,{0}))", path); | ||||
|             var address = "localhost"; | ||||
|  | ||||
|             var fakeUdp = Mocker.GetMock<UdpProvider>(); | ||||
|             fakeUdp.Setup(s => s.Send(address, UdpProvider.PacketType.Action, It.IsAny<byte[]>())).Returns(false); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<EventClientProvider>().SendAction(address, ActionType.ExecBuiltin, command); | ||||
|  | ||||
|              | ||||
|             Assert.AreEqual(false, result); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,637 +0,0 @@ | ||||
|  | ||||
|  | ||||
| using System; | ||||
| using System.Linq; | ||||
| using FizzWare.NBuilder; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Configuration; | ||||
| using NzbDrone.Core.Notifications.Xbmc; | ||||
| using NzbDrone.Core.Tv; | ||||
| using NzbDrone.Core.Model.Xbmc; | ||||
| using NzbDrone.Core.Providers; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
| using NzbDrone.Test.Common.AutoMoq; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.ProviderTests | ||||
| { | ||||
|     [TestFixture] | ||||
|      | ||||
|     public class XbmcProviderTest : CoreTest | ||||
|     { | ||||
|         private XbmcSettings _settings; | ||||
|         private string EdenActivePlayers; | ||||
|  | ||||
|         private void WithNoActivePlayers() | ||||
|         { | ||||
|             EdenActivePlayers = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[]}"; | ||||
|         } | ||||
|  | ||||
|         private void WithVideoPlayerActive() | ||||
|         { | ||||
|             EdenActivePlayers = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"video\"}]}"; | ||||
|         } | ||||
|  | ||||
|         private void WithAudioPlayerActive() | ||||
|         { | ||||
|             EdenActivePlayers = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"audio\"}]}"; | ||||
|         } | ||||
|  | ||||
|         private void WithPicturePlayerActive() | ||||
|         { | ||||
|             EdenActivePlayers = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"picture\"}]}"; | ||||
|         } | ||||
|  | ||||
|         private void WithAllPlayersActive() | ||||
|         { | ||||
|             EdenActivePlayers = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"audio\"},{\"playerid\":2,\"type\":\"picture\"},{\"playerid\":3,\"type\":\"video\"}]}"; | ||||
|         } | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             _settings = new XbmcSettings | ||||
|                             { | ||||
|                                 Host = "localhost", | ||||
|                                 Port = 8080, | ||||
|                                 AlwaysUpdate = false, | ||||
|                                 CleanLibrary = false, | ||||
|                                 UpdateLibrary = true | ||||
|                             }; | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void JsonError_true() | ||||
|         { | ||||
|              | ||||
|              | ||||
|             var response = "{\"error\":{\"code\":-32601,\"message\":\"Method not found.\"},\"id\":10,\"jsonrpc\":\"2.0\"}"; | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().CheckForJsonError(response); | ||||
|  | ||||
|              | ||||
|             Assert.AreEqual(true, result); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void JsonError_true_empty_response() | ||||
|         { | ||||
|              | ||||
|              | ||||
|             var response = String.Empty; | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().CheckForJsonError(response); | ||||
|  | ||||
|              | ||||
|             Assert.AreEqual(true, result); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void JsonError_false() | ||||
|         { | ||||
|              | ||||
|              | ||||
|             var reposnse = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"version\":3}}"; | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().CheckForJsonError(reposnse); | ||||
|  | ||||
|              | ||||
|             Assert.AreEqual(false, result); | ||||
|         } | ||||
|  | ||||
|         [TestCase(3)] | ||||
|         [TestCase(2)] | ||||
|         [TestCase(0)] | ||||
|         public void GetJsonVersionIntOnly(int number) | ||||
|         { | ||||
|             var message = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"version\":" + number + "}}"; | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(message); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetJsonVersion("localhost:8080", "xbmc", "xbmc"); | ||||
|  | ||||
|              | ||||
|             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<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(message); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetJsonVersion("localhost:8080", "xbmc", "xbmc"); | ||||
|  | ||||
|              | ||||
|             result.Should().Be(new XbmcVersion(major, minor, patch)); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void GetJsonVersion_error() | ||||
|         { | ||||
|             var message = "{\"error\":{\"code\":-32601,\"message\":\"Method not found.\"},\"id\":10,\"jsonrpc\":\"2.0\"}"; | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(message); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetJsonVersion("localhost:8080", "xbmc", "xbmc"); | ||||
|  | ||||
|              | ||||
|             result.Should().Be(new XbmcVersion(0)); | ||||
|         } | ||||
|  | ||||
|         [TestCase(false, false, false)] | ||||
|         [TestCase(true, true, true)] | ||||
|         [TestCase(true, false, false)] | ||||
|         [TestCase(true, true, false)] | ||||
|         [TestCase(false, true, false)] | ||||
|         [TestCase(false, true, true)] | ||||
|         [TestCase(false, false, true)] | ||||
|         [TestCase(true, false, true)] | ||||
|         public void GetActivePlayersDharma(bool audio, bool picture, bool video) | ||||
|         { | ||||
|              | ||||
|             var message = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"audio\":" | ||||
|                 + audio.ToString().ToLower() | ||||
|                 + ",\"picture\":" | ||||
|                 + picture.ToString().ToLower() | ||||
|                 + ",\"video\":" | ||||
|                 + video.ToString().ToLower() | ||||
|                 + "}}"; | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(message); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetActivePlayersDharma("localhost:8080", "xbmc", "xbmc"); | ||||
|  | ||||
|              | ||||
|             Assert.AreEqual(audio, result["audio"]); | ||||
|             Assert.AreEqual(picture, result["picture"]); | ||||
|             Assert.AreEqual(video, result["video"]); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void GetActivePlayersEden_should_be_empty_when_no_active_players() | ||||
|         { | ||||
|              | ||||
|             WithNoActivePlayers(); | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(EdenActivePlayers); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetActivePlayersEden("localhost:8080", "xbmc", "xbmc"); | ||||
|  | ||||
|              | ||||
|             result.Should().BeEmpty(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void GetActivePlayersEden_should_have_active_video_player() | ||||
|         { | ||||
|              | ||||
|             WithVideoPlayerActive(); | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(EdenActivePlayers); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetActivePlayersEden("localhost:8080", "xbmc", "xbmc"); | ||||
|  | ||||
|              | ||||
|             result.Should().HaveCount(1); | ||||
|             result.First().Type.Should().Be("video"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void GetActivePlayersEden_should_have_active_audio_player() | ||||
|         { | ||||
|              | ||||
|             WithAudioPlayerActive(); | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(EdenActivePlayers); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetActivePlayersEden("localhost:8080", "xbmc", "xbmc"); | ||||
|  | ||||
|              | ||||
|             result.Should().HaveCount(1); | ||||
|             result.First().Type.Should().Be("audio"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void GetActivePlayersEden_should_have_active_picture_player() | ||||
|         { | ||||
|              | ||||
|             WithPicturePlayerActive(); | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(EdenActivePlayers); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetActivePlayersEden("localhost:8080", "xbmc", "xbmc"); | ||||
|  | ||||
|              | ||||
|             result.Should().HaveCount(1); | ||||
|             result.First().Type.Should().Be("picture"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void GetActivePlayersEden_should_have_all_players_active() | ||||
|         { | ||||
|              | ||||
|             WithAllPlayersActive(); | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(EdenActivePlayers); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetActivePlayersEden("localhost:8080", "xbmc", "xbmc"); | ||||
|  | ||||
|              | ||||
|             result.Should().HaveCount(3); | ||||
|             result.Select(a => a.PlayerId).Distinct().Should().HaveCount(3); | ||||
|             result.Select(a => a.Type).Distinct().Should().HaveCount(3); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void GetTvShowsJson() | ||||
|         { | ||||
|              | ||||
|              | ||||
|  | ||||
|             var message = "{\"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 fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny<string>())) | ||||
|                 .Returns(message); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetTvShowsJson("localhost:8080", "xbmc", "xbmc"); | ||||
|  | ||||
|              | ||||
|             Assert.AreEqual(5, result.Count); | ||||
|             result.Should().Contain(s => s.ImdbNumber == 79488); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void Notify_true() | ||||
|         { | ||||
|             var header = "NzbDrone Test"; | ||||
|             var message = "Test Message!"; | ||||
|  | ||||
|             var fakeEventClient = Mocker.GetMock<EventClientProvider>(); | ||||
|             fakeEventClient.Setup(s => s.SendNotification(header, message, IconType.Jpeg, "NzbDrone.jpg", "localhost")).Returns(true); | ||||
|  | ||||
|             Mocker.Resolve<XbmcProvider>().Notify(_settings, header, message); | ||||
|  | ||||
|              | ||||
|             Mocker.VerifyAllMocks(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void SendCommand() | ||||
|         { | ||||
|              | ||||
|              | ||||
|  | ||||
|             var host = "localhost:8080"; | ||||
|             var command = "ExecBuiltIn(CleanLibrary(video))"; | ||||
|             var username = "xbmc"; | ||||
|             var password = "xbmc"; | ||||
|  | ||||
|             var url = String.Format("http://localhost:8080/xbmcCmds/xbmcHttp?command=ExecBuiltIn(CleanLibrary(video))"); | ||||
|  | ||||
|             //var fakeUdpProvider = Mocker.GetMock<EventClient>(); | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.DownloadString(url, username, password)).Returns("Ok\n"); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().SendCommand(host, command, username, username); | ||||
|  | ||||
|              | ||||
|             Mocker.VerifyAllMocks(); | ||||
|             Assert.AreEqual("Ok\n", result); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void GetXbmcSeriesPath_true() | ||||
|         { | ||||
|              | ||||
|              | ||||
|  | ||||
|             var queryResult = @"<xml><record><field>smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/</field></record></xml>"; | ||||
|  | ||||
|             var host = "localhost:8080"; | ||||
|             var username = "xbmc"; | ||||
|             var password = "xbmc"; | ||||
|  | ||||
|             var setResponseUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=SetResponseFormat(webheader;false;webfooter;false;header;<xml>;footer;</xml>;opentag;<tag>;closetag;</tag>;closefinaltag;false)"; | ||||
|             var resetResponseUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=SetResponseFormat()"; | ||||
|             var query = String.Format("http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)"); | ||||
|  | ||||
|  | ||||
|             //var fakeUdpProvider = Mocker.GetMock<EventClient>(); | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.DownloadString(setResponseUrl, username, password)).Returns("<xml><tag>OK</xml>"); | ||||
|             fakeHttp.Setup(s => s.DownloadString(resetResponseUrl, username, password)).Returns(@"<html> | ||||
|                                                                                                     <li>OK | ||||
|                                                                                                     </html>"); | ||||
|             fakeHttp.Setup(s => s.DownloadString(query, username, password)).Returns(queryResult); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetXbmcSeriesPath(host, 79488, username, username); | ||||
|  | ||||
|              | ||||
|             Mocker.VerifyAllMocks(); | ||||
|             Assert.AreEqual("smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/", result); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void GetXbmcSeriesPath_false() | ||||
|         { | ||||
|              | ||||
|              | ||||
|  | ||||
|             var queryResult = @"<xml></xml>"; | ||||
|  | ||||
|             var host = "localhost:8080"; | ||||
|             var username = "xbmc"; | ||||
|             var password = "xbmc"; | ||||
|  | ||||
|             var setResponseUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=SetResponseFormat(webheader;false;webfooter;false;header;<xml>;footer;</xml>;opentag;<tag>;closetag;</tag>;closefinaltag;false)"; | ||||
|             var resetResponseUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=SetResponseFormat()"; | ||||
|             var query = String.Format("http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)"); | ||||
|  | ||||
|  | ||||
|             //var fakeUdpProvider = Mocker.GetMock<EventClient>(); | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.DownloadString(setResponseUrl, username, password)).Returns("<xml><tag>OK</xml>"); | ||||
|             fakeHttp.Setup(s => s.DownloadString(resetResponseUrl, username, password)).Returns(@"<html> | ||||
|                                                                                                     <li>OK | ||||
|                                                                                                     </html>"); | ||||
|             fakeHttp.Setup(s => s.DownloadString(query, username, password)).Returns(queryResult); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetXbmcSeriesPath(host, 79488, username, username); | ||||
|  | ||||
|              | ||||
|             Mocker.VerifyAllMocks(); | ||||
|             Assert.AreEqual("", result); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void GetXbmcSeriesPath_special_characters() | ||||
|         { | ||||
|              | ||||
|              | ||||
|  | ||||
|             var queryResult = @"<xml><record><field>smb://xbmc:xbmc@HOMESERVER/TV/Law & Order- Special Victims Unit/</field></record></xml>"; | ||||
|  | ||||
|             var host = "localhost:8080"; | ||||
|             var username = "xbmc"; | ||||
|             var password = "xbmc"; | ||||
|  | ||||
|             var setResponseUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=SetResponseFormat(webheader;false;webfooter;false;header;<xml>;footer;</xml>;opentag;<tag>;closetag;</tag>;closefinaltag;false)"; | ||||
|             var resetResponseUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=SetResponseFormat()"; | ||||
|             var query = String.Format("http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)"); | ||||
|  | ||||
|  | ||||
|             //var fakeUdpProvider = Mocker.GetMock<EventClient>(); | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.DownloadString(setResponseUrl, username, password)).Returns("<xml><tag>OK</xml>"); | ||||
|             fakeHttp.Setup(s => s.DownloadString(resetResponseUrl, username, password)).Returns(@"<html> | ||||
|                                                                                                     <li>OK | ||||
|                                                                                                     </html>"); | ||||
|             fakeHttp.Setup(s => s.DownloadString(query, username, password)).Returns(queryResult); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().GetXbmcSeriesPath(host, 79488, username, username); | ||||
|  | ||||
|              | ||||
|             Mocker.VerifyAllMocks(); | ||||
|             result.Should().Be("smb://xbmc:xbmc@HOMESERVER/TV/Law & Order- Special Victims Unit/"); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void Clean() | ||||
|         { | ||||
|             var fakeEventClient = Mocker.GetMock<EventClientProvider>(); | ||||
|             fakeEventClient.Setup(s => s.SendAction("localhost", ActionType.ExecBuiltin, "ExecBuiltIn(CleanLibrary(video))")).Returns(true); | ||||
|  | ||||
|             Mocker.Resolve<XbmcProvider>().Clean(_settings); | ||||
|             Mocker.VerifyAllMocks(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void UpdateWithHttp_Single() | ||||
|         { | ||||
|             var host = "localhost:8080"; | ||||
|             var username = "xbmc"; | ||||
|             var password = "xbmc"; | ||||
|             var queryResult = @"<xml><record><field>smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/</field></record></xml>"; | ||||
|             var queryUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)"; | ||||
|             var url = "http://localhost:8080/xbmcCmds/xbmcHttp?command=ExecBuiltIn(UpdateLibrary(video,smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/))"; | ||||
|  | ||||
|             var fakeSeries = Builder<Series>.CreateNew() | ||||
|                 .With(s => s.Id = 79488) | ||||
|                 .With(s => s.Title = "30 Rock") | ||||
|                 .Build(); | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.DownloadString(queryUrl, username, password)).Returns(queryResult); | ||||
|             fakeHttp.Setup(s => s.DownloadString(url, username, password)); | ||||
|  | ||||
|              | ||||
|             Mocker.Resolve<XbmcProvider>().UpdateWithHttp(fakeSeries, host, username, password); | ||||
|  | ||||
|              | ||||
|             Mocker.VerifyAllMocks(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void UpdateWithHttp_All() | ||||
|         { | ||||
|             var host = "localhost:8080"; | ||||
|             var username = "xbmc"; | ||||
|             var password = "xbmc"; | ||||
|             var queryResult = @"<xml></xml>"; | ||||
|             var queryUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)"; | ||||
|             var url = "http://localhost:8080/xbmcCmds/xbmcHttp?command=ExecBuiltIn(UpdateLibrary(video))"; | ||||
|  | ||||
|             var fakeSeries = Builder<Series>.CreateNew() | ||||
|                 .With(s => s.Id = 79488) | ||||
|                 .With(s => s.Title = "30 Rock") | ||||
|                 .Build(); | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.DownloadString(queryUrl, username, password)).Returns(queryResult); | ||||
|             fakeHttp.Setup(s => s.DownloadString(url, username, password)); | ||||
|  | ||||
|              | ||||
|             Mocker.Resolve<XbmcProvider>().UpdateWithHttp(fakeSeries, host, username, password); | ||||
|  | ||||
|              | ||||
|             Mocker.VerifyAllMocks(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void UpdateWithJsonBuiltIn_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<Series>.CreateNew() | ||||
|                 .With(s => s.Id = 79488) | ||||
|                 .With(s => s.Title = "30 Rock") | ||||
|                 .Build(); | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand(host, username, password, It.Is<string>(e => e.Replace(" ", "").Replace("\r\n", "").Replace("\t", "") == expectedJson.Replace(" ", "")))) | ||||
|                 .Returns(tvshows); | ||||
|  | ||||
|             var command = "ExecBuiltIn(UpdateLibrary(video,smb://HOMESERVER/TV/30 Rock/))"; | ||||
|             var url = String.Format("http://{0}/xbmcCmds/xbmcHttp?command={1}", host, command); | ||||
|  | ||||
|             fakeHttp.Setup(s => s.DownloadString(url, username, password)).Returns("<html><li>OK</html>"); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().UpdateWithJsonExecBuiltIn(fakeSeries, host, username, password); | ||||
|  | ||||
|              | ||||
|             result.Should().BeTrue(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void UpdateWithJsonBuiltIn_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<Series>.CreateNew() | ||||
|                 .With(s => s.Id = 79488) | ||||
|                 .With(s => s.Title = "30 Rock") | ||||
|                 .Build(); | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand(host, username, password, It.Is<string>(e => e.Replace(" ", "").Replace("\r\n", "").Replace("\t", "") == expectedJson.Replace(" ", "")))) | ||||
|                 .Returns(tvshows); | ||||
|  | ||||
|             var command = "ExecBuiltIn(UpdateLibrary(video))"; | ||||
|             var url = String.Format("http://{0}/xbmcCmds/xbmcHttp?command={1}", host, command); | ||||
|  | ||||
|             fakeHttp.Setup(s => s.DownloadString(url, username, password)).Returns("<html><li>OK</html>"); | ||||
|  | ||||
|             //var fakeEventClient = Mocker.GetMock<EventClientProvider>(); | ||||
|             //fakeEventClient.Setup(s => s.SendAction("localhost", ActionType.ExecBuiltin, "ExecBuiltIn(UpdateLibrary(video))")); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().UpdateWithJsonExecBuiltIn(fakeSeries, host, username, password); | ||||
|  | ||||
|              | ||||
|             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<Series>.CreateNew() | ||||
|                 .With(s => s.Id = 79488) | ||||
|                 .With(s => s.Title = "30 Rock") | ||||
|                 .Build(); | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand(host, username, password, It.Is<string>(e => e.Replace(" ", "").Replace("\r\n", "").Replace("\t", "") == expectedJson.Replace(" ", "")))) | ||||
|                 .Returns(tvshows); | ||||
|  | ||||
|             fakeHttp.Setup(s => s.PostCommand(host, username, password, It.Is<String>( | ||||
|                 e => e.Replace(" ", "") | ||||
|                       .Replace("\r\n", "") | ||||
|                       .Replace("\t", "") | ||||
|                       .Contains("\"params\":{\"directory\":\"smb://HOMESERVER/TV/30Rock/\"}")))) | ||||
|                       .Returns("{\"id\":55,\"jsonrpc\":\"2.0\",\"result\":\"OK\"}"); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().UpdateWithJsonVideoLibraryScan(fakeSeries, host, username, password); | ||||
|  | ||||
|              | ||||
|             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<Series>.CreateNew() | ||||
|                 .With(s => s.Id = 79488) | ||||
|                 .With(s => s.Title = "30 Rock") | ||||
|                 .Build(); | ||||
|  | ||||
|             var fakeHttp = Mocker.GetMock<IHttpProvider>(); | ||||
|             fakeHttp.Setup(s => s.PostCommand(host, username, password, It.Is<string>(e => e.Replace(" ", "").Replace("\r\n", "").Replace("\t", "") == expectedJson.Replace(" ", "")))) | ||||
|                 .Returns(tvshows); | ||||
|  | ||||
|             fakeHttp.Setup(s => s.PostCommand(host, username, password, It.Is<String>( | ||||
|                 e => !e.Replace(" ", "") | ||||
|                       .Replace("\r\n", "") | ||||
|                       .Replace("\t", "") | ||||
|                       .Contains("\"params\":{\"directory\":\"smb://HOMESERVER/TV/30Rock/\"}")))) | ||||
|                       .Returns("{\"id\":55,\"jsonrpc\":\"2.0\",\"result\":\"OK\"}"); | ||||
|  | ||||
|              | ||||
|             var result = Mocker.Resolve<XbmcProvider>().UpdateWithJsonVideoLibraryScan(fakeSeries, host, username, password); | ||||
|  | ||||
|              | ||||
|             result.Should().BeTrue(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Text; | ||||
|  | ||||
| namespace NzbDrone.Core.Model.Xbmc | ||||
| { | ||||
|     public enum ActionType | ||||
|     { | ||||
|         ExecBuiltin = 0x01, | ||||
|         Button = 0x02 | ||||
|     } | ||||
| } | ||||
| @@ -15,5 +15,11 @@ namespace NzbDrone.Core.Model.Xbmc | ||||
|     { | ||||
|         public int PlayerId { get; set; } | ||||
|         public string Type { get; set; } | ||||
|  | ||||
|         public ActivePlayer(int playerId, string type) | ||||
|         { | ||||
|             PlayerId = playerId; | ||||
|             Type = type; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,14 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Text; | ||||
|  | ||||
| namespace NzbDrone.Core.Model.Xbmc | ||||
| { | ||||
|     public enum IconType | ||||
|     { | ||||
|         None = 0x00, | ||||
|         Jpeg = 0x01, | ||||
|         Png = 0x02, | ||||
|         Gif = 0x03 | ||||
|     } | ||||
| } | ||||
| @@ -1,64 +0,0 @@ | ||||
| using System; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Model.Xbmc; | ||||
|  | ||||
| namespace NzbDrone.Core.Notifications.Xbmc | ||||
| { | ||||
|     public class EventClientProvider | ||||
|     { | ||||
|         private readonly UdpProvider _udpProvider; | ||||
|  | ||||
|         public EventClientProvider(UdpProvider udpProvider) | ||||
|         { | ||||
|             _udpProvider = udpProvider; | ||||
|         } | ||||
|  | ||||
|         public EventClientProvider() | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         public virtual bool SendNotification(string caption, string message, IconType iconType, string iconFile, string address) | ||||
|         { | ||||
|             byte[] icon = new byte[0]; | ||||
|             if (iconType != IconType.None) | ||||
|             { | ||||
|                 icon = ResourceManager.GetRawLogo(iconFile); | ||||
|             } | ||||
|  | ||||
|             byte[] payload = new byte[caption.Length + message.Length + 7 + icon.Length]; | ||||
|  | ||||
|             int offset = 0; | ||||
|  | ||||
|             for (int i = 0; i < caption.Length; i++) | ||||
|                 payload[offset++] = (byte)caption[i]; | ||||
|             payload[offset++] = (byte)'\0'; | ||||
|  | ||||
|             for (int i = 0; i < message.Length; i++) | ||||
|                 payload[offset++] = (byte)message[i]; | ||||
|             payload[offset++] = (byte)'\0'; | ||||
|  | ||||
|             payload[offset++] = (byte)iconType; | ||||
|  | ||||
|             for (int i = 0; i < 4; i++) | ||||
|                 payload[offset++] = 0; | ||||
|  | ||||
|             Array.Copy(icon, 0, payload, caption.Length + message.Length + 7, icon.Length); | ||||
|  | ||||
|             return _udpProvider.Send(address, UdpProvider.PacketType.Notification, payload); | ||||
|         } | ||||
|  | ||||
|         public virtual bool SendAction(string address, ActionType action, string messages) | ||||
|         { | ||||
|             var payload = new byte[messages.Length + 2]; | ||||
|             int offset = 0; | ||||
|             payload[offset++] = (byte)action; | ||||
|  | ||||
|             for (int i = 0; i < messages.Length; i++) | ||||
|                 payload[offset++] = (byte)messages[i]; | ||||
|  | ||||
|             payload[offset++] = (byte)'\0'; | ||||
|  | ||||
|             return _udpProvider.Send(address, UdpProvider.PacketType.Action, payload); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										190
									
								
								NzbDrone.Core/Notifications/Xbmc/HttpApiProvider.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								NzbDrone.Core/Notifications/Xbmc/HttpApiProvider.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Xml.Linq; | ||||
| using NLog; | ||||
| using Newtonsoft.Json; | ||||
| using Newtonsoft.Json.Linq; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Model.Xbmc; | ||||
| using NzbDrone.Core.Tv; | ||||
|  | ||||
| namespace NzbDrone.Core.Notifications.Xbmc | ||||
| { | ||||
|     public class HttpApiProvider : IApiProvider | ||||
|     { | ||||
|         private readonly IHttpProvider _httpProvider; | ||||
|         private readonly Logger _logger; | ||||
|  | ||||
|         public HttpApiProvider(IHttpProvider httpProvider, Logger logger) | ||||
|         { | ||||
|             _httpProvider = httpProvider; | ||||
|             _logger = logger; | ||||
|         } | ||||
|  | ||||
|         public void Notify(XbmcSettings settings, string title, string message) | ||||
|         { | ||||
|             var notification = String.Format("Notification({0},{1},{2},{3})", title, message, 5000, "https://raw.github.com/NzbDrone/NzbDrone/vnext/NzbDrone.Core/NzbDrone.jpg"); | ||||
|             var command = BuildExecBuiltInCommand(notification); | ||||
|  | ||||
|             SendCommand(settings, command); | ||||
|         } | ||||
|  | ||||
|         public void Update(XbmcSettings settings, Series series) | ||||
|         { | ||||
|             if (!settings.AlwaysUpdate) | ||||
|             { | ||||
|                 _logger.Trace("Determining if there are any active players on XBMC host: {0}", settings.Address); | ||||
|                 var activePlayers = GetActivePlayers(settings); | ||||
|  | ||||
|                 if (activePlayers.Any(a => a.Type.Equals("video"))) | ||||
|                 { | ||||
|                     _logger.Debug("Video is currently playing, skipping library update"); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             UpdateLibrary(settings, series); | ||||
|         } | ||||
|  | ||||
|         public void Clean(XbmcSettings settings) | ||||
|         { | ||||
|             const string cleanVideoLibrary = "CleanLibrary(video)"; | ||||
|             var command = BuildExecBuiltInCommand(cleanVideoLibrary); | ||||
|  | ||||
|             SendCommand(settings, command); | ||||
|         } | ||||
|  | ||||
|         public List<ActivePlayer> GetActivePlayers(XbmcSettings settings) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var result = new List<ActivePlayer>(); | ||||
|                 var response = SendCommand(settings, "getcurrentlyplaying"); | ||||
|  | ||||
|                 if (response.Contains("<li>Filename:[Nothing Playing]")) return new List<ActivePlayer>(); | ||||
|                 if (response.Contains("<li>Type:Video")) result.Add(new ActivePlayer(1, "video")); | ||||
|  | ||||
|                 return result; | ||||
|             } | ||||
|  | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 _logger.DebugException(ex.Message, ex); | ||||
|             } | ||||
|  | ||||
|             return new List<ActivePlayer>(); | ||||
|         } | ||||
|  | ||||
|         public bool CheckForError(string response) | ||||
|         { | ||||
|             _logger.Trace("Looking for error in response: {0}", response); | ||||
|  | ||||
|             if (String.IsNullOrWhiteSpace(response)) | ||||
|             { | ||||
|                 _logger.Debug("Invalid response from XBMC, the response is not valid JSON"); | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             var errorIndex = response.IndexOf("Error", StringComparison.InvariantCultureIgnoreCase); | ||||
|  | ||||
|             if (errorIndex > -1) | ||||
|             { | ||||
|                 var errorMessage = response.Substring(errorIndex + 6); | ||||
|                 errorMessage = errorMessage.Substring(0, errorMessage.IndexOfAny(new char[] { '<', ';' })); | ||||
|  | ||||
|                 _logger.Trace("Error found in response: {0}", errorMessage); | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         public string GetSeriesPath(XbmcSettings settings, Series series) | ||||
|         { | ||||
|             var query = | ||||
|                 String.Format( | ||||
|                     "select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = {0} and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath", | ||||
|                     series.TvdbId); | ||||
|             var command = String.Format("QueryVideoDatabase({0})", query); | ||||
|  | ||||
|             const string setResponseCommand = | ||||
|                 "SetResponseFormat(webheader;false;webfooter;false;header;<xml>;footer;</xml>;opentag;<tag>;closetag;</tag>;closefinaltag;false)"; | ||||
|             const string resetResponseCommand = "SetResponseFormat()"; | ||||
|  | ||||
|             SendCommand(settings, setResponseCommand); | ||||
|             var response = SendCommand(settings, command); | ||||
|             SendCommand(settings, resetResponseCommand); | ||||
|  | ||||
|             if (String.IsNullOrEmpty(response)) | ||||
|                 return String.Empty; | ||||
|  | ||||
|             var xDoc = XDocument.Load(new StringReader(response.Replace("&", "&"))); | ||||
|             var xml = (from x in xDoc.Descendants("xml") select x).FirstOrDefault(); | ||||
|  | ||||
|             if (xml == null) | ||||
|                 return null; | ||||
|  | ||||
|             var field = xml.Descendants("field").FirstOrDefault(); | ||||
|  | ||||
|             if (field == null) | ||||
|                 return null; | ||||
|  | ||||
|             return field.Value; | ||||
|         } | ||||
|  | ||||
|         public bool CanHandle(XbmcVersion version) | ||||
|         { | ||||
|             return version < new XbmcVersion(5); | ||||
|         } | ||||
|  | ||||
|         private void UpdateLibrary(XbmcSettings settings, Series series) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 _logger.Trace("Sending Update DB Request to XBMC Host: {0}", settings.Address); | ||||
|                 var xbmcSeriesPath = GetSeriesPath(settings, series); | ||||
|  | ||||
|                 //If the path is found update it, else update the whole library | ||||
|                 if (!String.IsNullOrEmpty(xbmcSeriesPath)) | ||||
|                 { | ||||
|                     _logger.Trace("Updating series [{0}] on XBMC host: {1}", series.Title, settings.Address); | ||||
|                     var command = BuildExecBuiltInCommand(String.Format("UpdateLibrary(video,{0})", xbmcSeriesPath)); | ||||
|                     SendCommand(settings, command); | ||||
|                 } | ||||
|  | ||||
|                 else | ||||
|                 { | ||||
|                     //Update the entire library | ||||
|                     _logger.Trace("Series [{0}] doesn't exist on XBMC host: {1}, Updating Entire Library", series.Title, settings.Address); | ||||
|                     var command = BuildExecBuiltInCommand("UpdateLibrary(video)"); | ||||
|                     SendCommand(settings, command); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 _logger.DebugException(ex.Message, ex); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private string SendCommand(XbmcSettings settings, string command) | ||||
|         { | ||||
|             var url = String.Format("http://{0}/xbmcCmds/xbmcHttp?command={1}", settings.Address, command); | ||||
|  | ||||
|             if (!String.IsNullOrEmpty(settings.Username)) | ||||
|             { | ||||
|                 return _httpProvider.DownloadString(url, settings.Username, settings.Password); | ||||
|             } | ||||
|  | ||||
|             return _httpProvider.DownloadString(url); | ||||
|         } | ||||
|  | ||||
|         private string BuildExecBuiltInCommand(string command) | ||||
|         { | ||||
|             return String.Format("ExecBuiltIn({0})", command); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										20
									
								
								NzbDrone.Core/Notifications/Xbmc/IApiProvider.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								NzbDrone.Core/Notifications/Xbmc/IApiProvider.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using NzbDrone.Core.Model.Xbmc; | ||||
| using NzbDrone.Core.Tv; | ||||
|  | ||||
| namespace NzbDrone.Core.Notifications.Xbmc | ||||
| { | ||||
|     public interface IApiProvider | ||||
|     { | ||||
|         void Notify(XbmcSettings settings, string title, string message); | ||||
|         void Update(XbmcSettings settings, Series series); | ||||
|         void Clean(XbmcSettings settings); | ||||
|         List<ActivePlayer> GetActivePlayers(XbmcSettings settings); | ||||
|         bool CheckForError(string response); | ||||
|         string GetSeriesPath(XbmcSettings settings, Series series); | ||||
|         bool CanHandle(XbmcVersion version); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,18 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
|  | ||||
| namespace NzbDrone.Core.Notifications.Xbmc | ||||
| { | ||||
|     public class InvalidXbmcVersionException : Exception | ||||
|     { | ||||
|         public InvalidXbmcVersionException() | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         public InvalidXbmcVersionException(string message) : base(message) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										225
									
								
								NzbDrone.Core/Notifications/Xbmc/JsonApiProvider.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								NzbDrone.Core/Notifications/Xbmc/JsonApiProvider.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,225 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using NLog; | ||||
| using Newtonsoft.Json; | ||||
| using Newtonsoft.Json.Linq; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Model.Xbmc; | ||||
| using NzbDrone.Core.Tv; | ||||
|  | ||||
| namespace NzbDrone.Core.Notifications.Xbmc | ||||
| { | ||||
|     public class JsonApiProvider : IApiProvider | ||||
|     { | ||||
|         private readonly IHttpProvider _httpProvider; | ||||
|         private readonly Logger _logger; | ||||
|  | ||||
|         public JsonApiProvider(IHttpProvider httpProvider, Logger logger) | ||||
|         { | ||||
|             _httpProvider = httpProvider; | ||||
|             _logger = logger; | ||||
|         } | ||||
|  | ||||
|         public void Notify(XbmcSettings settings, string title, string message) | ||||
|         { | ||||
|             var parameters = new JObject( | ||||
|                                         new JProperty("title", title), | ||||
|                                         new JProperty("message", message), | ||||
|                                         new JProperty("image", "https://raw.github.com/NzbDrone/NzbDrone/vnext/NzbDrone.Core/NzbDrone.jpg")); | ||||
|  | ||||
|             var postJson = BuildJsonRequest("GUI.ShowNotification", parameters); | ||||
|  | ||||
|             _httpProvider.PostCommand(settings.Address, settings.Username, settings.Password, postJson.ToString()); | ||||
|         } | ||||
|  | ||||
|         public void Update(XbmcSettings settings, Series series) | ||||
|         { | ||||
|             if (!settings.AlwaysUpdate) | ||||
|             { | ||||
|                 _logger.Trace("Determining if there are any active players on XBMC host: {0}", settings.Address); | ||||
|                 var activePlayers = GetActivePlayers(settings); | ||||
|  | ||||
|                 if (activePlayers.Any(a => a.Type.Equals("video"))) | ||||
|                 { | ||||
|                     _logger.Debug("Video is currently playing, skipping library update"); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             UpdateLibrary(settings, series); | ||||
|         } | ||||
|          | ||||
|         public void Clean(XbmcSettings settings) | ||||
|         { | ||||
|             var postJson = BuildJsonRequest("VideoLibrary.Clean"); | ||||
|  | ||||
|             _httpProvider.PostCommand(settings.Address, settings.Username, settings.Password, postJson.ToString()); | ||||
|         } | ||||
|  | ||||
|         public List<ActivePlayer> GetActivePlayers(XbmcSettings settings) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var postJson = new JObject(); | ||||
|                 postJson.Add(new JProperty("jsonrpc", "2.0")); | ||||
|                 postJson.Add(new JProperty("method", "Player.GetActivePlayers")); | ||||
|                 postJson.Add(new JProperty("id", 10)); | ||||
|  | ||||
|                 var response = _httpProvider.PostCommand(settings.Address, settings.Username, settings.Password, postJson.ToString()); | ||||
|  | ||||
|                 if (CheckForError(response)) | ||||
|                     return new List<ActivePlayer>(); | ||||
|  | ||||
|                 var result = JsonConvert.DeserializeObject<ActivePlayersEdenResult>(response); | ||||
|  | ||||
|                 return result.Result; | ||||
|             } | ||||
|  | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 _logger.DebugException(ex.Message, ex); | ||||
|             } | ||||
|  | ||||
|             return new List<ActivePlayer>(); | ||||
|         } | ||||
|  | ||||
|         public bool CheckForError(string response) | ||||
|         { | ||||
|             _logger.Trace("Looking for error in response: {0}", response); | ||||
|  | ||||
|             if (String.IsNullOrWhiteSpace(response)) | ||||
|             { | ||||
|                 _logger.Debug("Invalid response from XBMC, the response is not valid JSON"); | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             if (response.StartsWith("{\"error\"")) | ||||
|             { | ||||
|                 var error = JsonConvert.DeserializeObject<ErrorResult>(response); | ||||
|                 var code = error.Error["code"]; | ||||
|                 var message = error.Error["message"]; | ||||
|  | ||||
|                 _logger.Debug("XBMC Json Error. Code = {0}, Message: {1}", code, message); | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         public string GetSeriesPath(XbmcSettings settings, Series series) | ||||
|         { | ||||
|             var allSeries = GetSeries(settings); | ||||
|  | ||||
|             if (!allSeries.Any()) | ||||
|             { | ||||
|                 _logger.Trace("No TV shows returned from XBMC"); | ||||
|                 return null; | ||||
|             } | ||||
|  | ||||
|             else | ||||
|             { | ||||
|                 var matchingSeries = allSeries.FirstOrDefault(s => s.ImdbNumber == series.TvdbId || s.Label == series.Title); | ||||
|  | ||||
|                 if (matchingSeries != null) return matchingSeries.File; | ||||
|             } | ||||
|  | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         public bool CanHandle(XbmcVersion version) | ||||
|         { | ||||
|             return version >= new XbmcVersion(5); | ||||
|         } | ||||
|  | ||||
|         private void UpdateLibrary(XbmcSettings settings, Series series) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var seriesPath = GetSeriesPath(settings, series); | ||||
|  | ||||
|                 JObject postJson; | ||||
|  | ||||
|                 if (seriesPath != null) | ||||
|                 { | ||||
|                     _logger.Trace("Updating series [{0}] (Path: {1}) on XBMC host: {2}", series.Title, seriesPath, settings.Address); | ||||
|  | ||||
|                     var parameters = new JObject(new JObject(new JProperty("directory", seriesPath))); | ||||
|                     postJson = BuildJsonRequest("VideoLibrary.Scan", parameters); | ||||
|                 } | ||||
|  | ||||
|                 else | ||||
|                 { | ||||
|                     _logger.Trace("Series [{0}] doesn't exist on XBMC host: {1}, Updating Entire Library", series.Title, | ||||
|                                  settings.Address); | ||||
|  | ||||
|                     postJson = BuildJsonRequest("VideoLibrary.Scan"); | ||||
|                 } | ||||
|  | ||||
|                 var response = _httpProvider.PostCommand(settings.Address, settings.Username, settings.Password, postJson.ToString()); | ||||
|  | ||||
|                 if (CheckForError(response)) return; | ||||
|  | ||||
|                 _logger.Trace(" from response"); | ||||
|                 var result = JsonConvert.DeserializeObject<XbmcJsonResult<String>>(response); | ||||
|  | ||||
|                 if (!result.Result.Equals("OK", StringComparison.InvariantCultureIgnoreCase)) | ||||
|                 { | ||||
|                     _logger.Trace("Failed to update library for: {0}", settings.Address); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 _logger.DebugException(ex.Message, ex); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private List<TvShow> GetSeries(XbmcSettings settings) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var properties = new JObject { new JProperty("properties", new[] { "file", "imdbnumber" }) }; | ||||
|                 var postJson = BuildJsonRequest("VideoLibrary.GetTvShows", properties); | ||||
|  | ||||
|                 var response = _httpProvider.PostCommand(settings.Address, settings.Username, settings.Password, postJson.ToString()); | ||||
|  | ||||
|                 if (CheckForError(response)) | ||||
|                     return new List<TvShow>(); | ||||
|  | ||||
|                 var result = JsonConvert.DeserializeObject<TvShowResponse>(response); | ||||
|                 var shows = result.Result.TvShows; | ||||
|  | ||||
|                 return shows; | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 _logger.DebugException(ex.Message, ex); | ||||
|             } | ||||
|  | ||||
|             return new List<TvShow>(); | ||||
|         } | ||||
|  | ||||
|         private JObject BuildJsonRequest(string method) | ||||
|         { | ||||
|             return BuildJsonRequest(method, null); | ||||
|         } | ||||
|  | ||||
|         private JObject BuildJsonRequest(string method, JObject parameters) | ||||
|         { | ||||
|             var postJson = new JObject(); | ||||
|             postJson.Add(new JProperty("jsonrpc", "2.0")); | ||||
|             postJson.Add(new JProperty("method", method)); | ||||
|  | ||||
|             if (parameters != null) | ||||
|             { | ||||
|                 postJson.Add(new JProperty("params", parameters)); | ||||
|             } | ||||
|  | ||||
|             postJson.Add(new JProperty("id", 10)); | ||||
|  | ||||
|             return postJson; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										12
									
								
								NzbDrone.Core/Notifications/Xbmc/TestXbmcCommand.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								NzbDrone.Core/Notifications/Xbmc/TestXbmcCommand.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| using NzbDrone.Common.Messaging; | ||||
|  | ||||
| namespace NzbDrone.Core.Notifications.Xbmc | ||||
| { | ||||
|     public class TestXbmcCommand : ICommand | ||||
|     { | ||||
|         public string Host { get; set; } | ||||
|         public int Port { get; set; } | ||||
|         public string Username { get; set; } | ||||
|         public string Password { get; set; } | ||||
|     } | ||||
| } | ||||
| @@ -5,9 +5,9 @@ namespace NzbDrone.Core.Notifications.Xbmc | ||||
| { | ||||
|     public class Xbmc : NotificationBase<XbmcSettings> | ||||
|     { | ||||
|         private readonly XbmcProvider _xbmcProvider; | ||||
|         private readonly IXbmcService _xbmcProvider; | ||||
|  | ||||
|         public Xbmc(XbmcProvider xbmcProvider, Logger logger) | ||||
|         public Xbmc(IXbmcService xbmcProvider, Logger logger) | ||||
|         { | ||||
|             _xbmcProvider = xbmcProvider; | ||||
|         } | ||||
|   | ||||
| @@ -1,455 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Xml.Linq; | ||||
| using Newtonsoft.Json; | ||||
| using Newtonsoft.Json.Linq; | ||||
| using NLog; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.Tv; | ||||
| using NzbDrone.Core.Model.Xbmc; | ||||
|  | ||||
| namespace NzbDrone.Core.Notifications.Xbmc | ||||
| { | ||||
|     public class XbmcProvider | ||||
|     { | ||||
|         private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); | ||||
|         private readonly IHttpProvider _httpProvider; | ||||
|         private readonly EventClientProvider _eventClientProvider; | ||||
|  | ||||
|         public XbmcProvider(IHttpProvider httpProvider, EventClientProvider eventClientProvider) | ||||
|         { | ||||
|             _httpProvider = httpProvider; | ||||
|             _eventClientProvider = eventClientProvider; | ||||
|         } | ||||
|  | ||||
|         public virtual void Notify(XbmcSettings settings, string header, string message) | ||||
|         { | ||||
|             //Always use EventServer, until Json has real support for it | ||||
|             var host = settings.Host; | ||||
|             Logger.Trace("Sending Notifcation to XBMC Host: {0}", host); | ||||
|             _eventClientProvider.SendNotification(header, message, IconType.Jpeg, "NzbDrone.jpg", host); | ||||
|         } | ||||
|  | ||||
|         public virtual void Update(XbmcSettings settings, Series series) | ||||
|         { | ||||
|             //Use Json for Eden/Nightly or depricated HTTP for 10.x (Dharma) to get the proper path | ||||
|             //Perform update with EventServer (Json currently doesn't support updating a specific path only - July 2011) | ||||
|  | ||||
|             var username = settings.Username; | ||||
|             var password = settings.Password; | ||||
|             var address = String.Format("{0}:{1}", settings.Host, settings.Port); | ||||
|  | ||||
|             Logger.Trace("Determining version of XBMC Host: {0}", address); | ||||
|             var version = GetJsonVersion(address, username, password); | ||||
|  | ||||
|             //Dharma | ||||
|             if (version == new XbmcVersion(2)) | ||||
|             { | ||||
|                 //Check for active player only when we should skip updates when playing | ||||
|                 if (!settings.AlwaysUpdate) | ||||
|                 { | ||||
|                     Logger.Trace("Determining if there are any active players on XBMC host: {0}", address); | ||||
|                     var activePlayers = GetActivePlayersDharma(address, username, password); | ||||
|  | ||||
|                     //If video is currently playing, then skip update | ||||
|                     if (activePlayers["video"]) | ||||
|                     { | ||||
|                         Logger.Debug("Video is currently playing, skipping library update"); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|                 UpdateWithHttp(series, address, username, password); | ||||
|             } | ||||
|  | ||||
|             //Eden | ||||
|             else if (version == new XbmcVersion(3) || version == new XbmcVersion(4)) | ||||
|             { | ||||
|                 //Check for active player only when we should skip updates when playing | ||||
|                 if (!settings.AlwaysUpdate) | ||||
|                 { | ||||
|                     Logger.Trace("Determining if there are any active players on XBMC host: {0}", address); | ||||
|                     var activePlayers = GetActivePlayersEden(address, 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"); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 UpdateWithJsonExecBuiltIn(series, address, username, password); | ||||
|             } | ||||
|  | ||||
|             //Frodo or newer (attempting to make it future compatible) | ||||
|             else if (version >= new XbmcVersion(5)) | ||||
|             { | ||||
|                 //Check for active player only when we should skip updates when playing | ||||
|                 if (!settings.AlwaysUpdate) | ||||
|                 { | ||||
|                     Logger.Trace("Determining if there are any active players on XBMC host: {0}", address); | ||||
|                     var activePlayers = GetActivePlayersEden(address, 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"); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 UpdateWithJsonVideoLibraryScan(series, address, username, password); | ||||
|             } | ||||
|  | ||||
|                 //Log Version zero if check failed | ||||
|             else | ||||
|                 Logger.Trace("Unknown version: [{0}], skipping.", version); | ||||
|          | ||||
|         } | ||||
|  | ||||
|         public virtual bool UpdateWithJsonExecBuiltIn(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.Id || s.Label == series.Title); | ||||
|  | ||||
|                 //var hostOnly = GetHostWithoutPort(host); | ||||
|  | ||||
|                 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); | ||||
|                     SendCommand(host, command, username, password); | ||||
|                 } | ||||
|  | ||||
|                 else | ||||
|                 { | ||||
|                     Logger.Trace("Series [{0}] doesn't exist on XBMC host: {1}, Updating Entire Library", series.Title, host); | ||||
|                     SendCommand(host, "ExecBuiltIn(UpdateLibrary(video))", username, password); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.DebugException(ex.Message, ex); | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             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.TvdbId || 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<XbmcJsonResult<String>>(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 | ||||
|             { | ||||
|                 Logger.Trace("Sending Update DB Request to XBMC Host: {0}", host); | ||||
|                 var xbmcSeriesPath = GetXbmcSeriesPath(host, series.Id, username, password); | ||||
|  | ||||
|                 //If the path is found update it, else update the whole library | ||||
|                 if (!String.IsNullOrEmpty(xbmcSeriesPath)) | ||||
|                 { | ||||
|                     Logger.Trace("Updating series [{0}] on XBMC host: {1}", series.Title, host); | ||||
|                     var command = String.Format("ExecBuiltIn(UpdateLibrary(video,{0}))", xbmcSeriesPath); | ||||
|                     SendCommand(host, command, username, password); | ||||
|                 } | ||||
|  | ||||
|                 else | ||||
|                 { | ||||
|                     //Update the entire library | ||||
|                     Logger.Trace("Series [{0}] doesn't exist on XBMC host: {1}, Updating Entire Library", series.Title, host); | ||||
|                     SendCommand(host, "ExecBuiltIn(UpdateLibrary(video))", username, password); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.DebugException(ex.Message, ex); | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         public virtual void Clean(XbmcSettings settings) | ||||
|         { | ||||
|             //Use EventServer, once Dharma is extinct use Json? | ||||
|  | ||||
|             var host = settings.Host; | ||||
|             Logger.Trace("Sending DB Clean Request to XBMC Host: {0}", host); | ||||
|             var command = "ExecBuiltIn(CleanLibrary(video))"; | ||||
|             _eventClientProvider.SendAction(host, ActionType.ExecBuiltin, command); | ||||
|         } | ||||
|  | ||||
|         public virtual string SendCommand(string host, string command, string username, string password) | ||||
|         { | ||||
|             var url = String.Format("http://{0}/xbmcCmds/xbmcHttp?command={1}", host, command); | ||||
|  | ||||
|             if (!String.IsNullOrEmpty(username)) | ||||
|             { | ||||
|                 return _httpProvider.DownloadString(url, username, password); | ||||
|             } | ||||
|  | ||||
|             return _httpProvider.DownloadString(url); | ||||
|         } | ||||
|  | ||||
|         public virtual string GetXbmcSeriesPath(string host, int seriesId, string username, string password) | ||||
|         { | ||||
|             var query = | ||||
|                 String.Format( | ||||
|                     "select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = {0} and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath", | ||||
|                     seriesId); | ||||
|             var command = String.Format("QueryVideoDatabase({0})", query); | ||||
|  | ||||
|             const string setResponseCommand = | ||||
|                 "SetResponseFormat(webheader;false;webfooter;false;header;<xml>;footer;</xml>;opentag;<tag>;closetag;</tag>;closefinaltag;false)"; | ||||
|             const string resetResponseCommand = "SetResponseFormat()"; | ||||
|  | ||||
|             SendCommand(host, setResponseCommand, username, password); | ||||
|             var response = SendCommand(host, command, username, password); | ||||
|             SendCommand(host, resetResponseCommand, username, password); | ||||
|  | ||||
|             if (String.IsNullOrEmpty(response)) | ||||
|                 return String.Empty; | ||||
|  | ||||
|             var xDoc = XDocument.Load(new StringReader(response.Replace("&", "&"))); | ||||
|             var xml = (from x in xDoc.Descendants("xml") select x).FirstOrDefault(); | ||||
|  | ||||
|             if (xml == null) | ||||
|                 return String.Empty; | ||||
|  | ||||
|             var field = xml.Descendants("field").FirstOrDefault(); | ||||
|  | ||||
|             if (field == null) | ||||
|                 return String.Empty; | ||||
|  | ||||
|             return field.Value; | ||||
|         } | ||||
|  | ||||
|         public virtual XbmcVersion GetJsonVersion(string host, string username, string password) | ||||
|         { | ||||
|             //2 = Dharma | ||||
|             //3 & 4 = Eden | ||||
|             //5 & 6 = Frodo | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 var postJson = new JObject(); | ||||
|                 postJson.Add(new JProperty("jsonrpc", "2.0")); | ||||
|                 postJson.Add(new JProperty("method", "JSONRPC.Version")); | ||||
|                 postJson.Add(new JProperty("id", 10)); | ||||
|  | ||||
|                 var response = _httpProvider.PostCommand(host, username, password, postJson.ToString()); | ||||
|  | ||||
|                 if (CheckForJsonError(response)) | ||||
|                     return new XbmcVersion(); | ||||
|  | ||||
|                 Logger.Trace("Getting version from response"); | ||||
|                 var result = JsonConvert.DeserializeObject<XbmcJsonResult<JObject>>(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<XbmcVersion>(versionObject.Value.ToString()); | ||||
|  | ||||
|                 throw new InvalidCastException("Unknown Version structure!: " + versionObject); | ||||
|             } | ||||
|  | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.DebugException(ex.Message, ex); | ||||
|             } | ||||
|  | ||||
|             return new XbmcVersion(); | ||||
|         } | ||||
|  | ||||
|         public virtual Dictionary<string, bool> GetActivePlayersDharma(string host, string username, string password) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var postJson = new JObject(); | ||||
|                 postJson.Add(new JProperty("jsonrpc", "2.0")); | ||||
|                 postJson.Add(new JProperty("method", "Player.GetActivePlayers")); | ||||
|                 postJson.Add(new JProperty("id", 10)); | ||||
|  | ||||
|                 var response = _httpProvider.PostCommand(host, username, password, postJson.ToString()); | ||||
|  | ||||
|                 if (CheckForJsonError(response)) | ||||
|                     return null; | ||||
|  | ||||
|                 var result = JsonConvert.DeserializeObject<ActivePlayersDharmaResult>(response); | ||||
|  | ||||
|                 return result.Result; | ||||
|             } | ||||
|  | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.DebugException(ex.Message, ex); | ||||
|             } | ||||
|  | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         public virtual List<ActivePlayer> GetActivePlayersEden(string host, string username, string password) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var postJson = new JObject(); | ||||
|                 postJson.Add(new JProperty("jsonrpc", "2.0")); | ||||
|                 postJson.Add(new JProperty("method", "Player.GetActivePlayers")); | ||||
|                 postJson.Add(new JProperty("id", 10)); | ||||
|  | ||||
|                 var response = _httpProvider.PostCommand(host, username, password, postJson.ToString()); | ||||
|  | ||||
|                 if (CheckForJsonError(response)) | ||||
|                     return null; | ||||
|  | ||||
|                 var result = JsonConvert.DeserializeObject<ActivePlayersEdenResult>(response); | ||||
|  | ||||
|                 return result.Result; | ||||
|             } | ||||
|  | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.DebugException(ex.Message, ex); | ||||
|             } | ||||
|  | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         public virtual List<TvShow> GetTvShowsJson(string host, string username, string password) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var postJson = new JObject(); | ||||
|                 postJson.Add(new JProperty("jsonrpc", "2.0")); | ||||
|                 postJson.Add(new JProperty("method", "VideoLibrary.GetTvShows")); | ||||
|                 postJson.Add(new JProperty("params", new JObject { new JProperty("properties", new string[] { "file", "imdbnumber" }) })); | ||||
|                 postJson.Add(new JProperty("id", 10)); | ||||
|  | ||||
|                 var response = _httpProvider.PostCommand(host, username, password, postJson.ToString()); | ||||
|  | ||||
|                 if (CheckForJsonError(response)) | ||||
|                     return null; | ||||
|  | ||||
|                 var result = JsonConvert.DeserializeObject<TvShowResponse>(response); | ||||
|                 var shows = result.Result.TvShows; | ||||
|  | ||||
|                 return shows; | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.DebugException(ex.Message, ex); | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         public virtual bool CheckForJsonError(string response) | ||||
|         { | ||||
|             Logger.Trace("Looking for error in response: {0}", response); | ||||
|  | ||||
|             if (response.StartsWith("{\"error\"")) | ||||
|             { | ||||
|                 var error = JsonConvert.DeserializeObject<ErrorResult>(response); | ||||
|                 var code = error.Error["code"]; | ||||
|                 var message = error.Error["message"]; | ||||
|  | ||||
|                 Logger.Debug("XBMC Json Error. Code = {0}, Message: {1}", code, message); | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             if (String.IsNullOrWhiteSpace(response)) | ||||
|             { | ||||
|                 Logger.Debug("Invalid response from XBMC, the response is not valid JSON"); | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         public virtual void TestNotification(string hosts) | ||||
|         { | ||||
|             foreach (var host in hosts.Split(',')) | ||||
|             { | ||||
|                 Logger.Trace("Sending Test Notifcation to XBMC Host: {0}", host); | ||||
|                 _eventClientProvider.SendNotification("Test Notification", "Success! Notifications are setup correctly", IconType.Jpeg, "NzbDrone.jpg", host); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public virtual void TestJsonApi(string hosts, string username, string password) | ||||
|         { | ||||
|             foreach (var host in hosts.Split(',')) | ||||
|             { | ||||
|                 Logger.Trace("Sending Test Notifcation to XBMC Host: {0}", host); | ||||
|                 var version = GetJsonVersion(host, username, password); | ||||
|                 if (version == new XbmcVersion()) | ||||
|                     throw new Exception("Failed to get JSON version in test"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										118
									
								
								NzbDrone.Core/Notifications/Xbmc/XbmcService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								NzbDrone.Core/Notifications/Xbmc/XbmcService.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Xml.Linq; | ||||
| using Newtonsoft.Json; | ||||
| using Newtonsoft.Json.Linq; | ||||
| using NLog; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Common.Messaging; | ||||
| using NzbDrone.Core.Tv; | ||||
| using NzbDrone.Core.Model.Xbmc; | ||||
|  | ||||
| namespace NzbDrone.Core.Notifications.Xbmc | ||||
| { | ||||
|     public interface IXbmcService | ||||
|     { | ||||
|         void Notify(XbmcSettings settings, string title, string message); | ||||
|         void Update(XbmcSettings settings, Series series); | ||||
|         void Clean(XbmcSettings settings); | ||||
|         XbmcVersion GetJsonVersion(XbmcSettings settings); | ||||
|     } | ||||
|  | ||||
|     public class XbmcService : IXbmcService, IExecute<TestXbmcCommand> | ||||
|     { | ||||
|         private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); | ||||
|         private readonly IHttpProvider _httpProvider; | ||||
|         private readonly IEnumerable<IApiProvider> _apiProviders; | ||||
|  | ||||
|         public XbmcService(IHttpProvider httpProvider, IEnumerable<IApiProvider> apiProviders) | ||||
|         { | ||||
|             _httpProvider = httpProvider; | ||||
|             _apiProviders = apiProviders; | ||||
|         } | ||||
|  | ||||
|         public void Notify(XbmcSettings settings, string title, string message) | ||||
|         { | ||||
|             var provider = GetApiProvider(settings); | ||||
|             provider.Notify(settings, title, message); | ||||
|         } | ||||
|  | ||||
|         public void Update(XbmcSettings settings, Series series) | ||||
|         { | ||||
|             var provider = GetApiProvider(settings); | ||||
|             provider.Update(settings, series); | ||||
|         } | ||||
|  | ||||
|         public void Clean(XbmcSettings settings) | ||||
|         { | ||||
|             var provider = GetApiProvider(settings); | ||||
|             provider.Clean(settings); | ||||
|         } | ||||
|  | ||||
|         public XbmcVersion GetJsonVersion(XbmcSettings settings) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var postJson = new JObject(); | ||||
|                 postJson.Add(new JProperty("jsonrpc", "2.0")); | ||||
|                 postJson.Add(new JProperty("method", "JSONRPC.Version")); | ||||
|                 postJson.Add(new JProperty("id", 10)); | ||||
|  | ||||
|                 var response = _httpProvider.PostCommand(settings.Address, settings.Username, settings.Password, postJson.ToString()); | ||||
|  | ||||
|                 Logger.Trace("Getting version from response"); | ||||
|                 var result = JsonConvert.DeserializeObject<XbmcJsonResult<JObject>>(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<XbmcVersion>(versionObject.Value.ToString()); | ||||
|  | ||||
|                 throw new InvalidCastException("Unknown Version structure!: " + versionObject); | ||||
|             } | ||||
|  | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 Logger.DebugException(ex.Message, ex); | ||||
|             } | ||||
|  | ||||
|             return new XbmcVersion(); | ||||
|         } | ||||
|  | ||||
|         private IApiProvider GetApiProvider(XbmcSettings settings) | ||||
|         { | ||||
|             var version = GetJsonVersion(settings); | ||||
|             var apiProvider = _apiProviders.SingleOrDefault(a => a.CanHandle(version)); | ||||
|  | ||||
|             if (apiProvider == null) | ||||
|             { | ||||
|                 var message = String.Format("Invalid API Version: {0} for {1}", version, settings.Address); | ||||
|                 throw new InvalidXbmcVersionException(message); | ||||
|             } | ||||
|  | ||||
|             return apiProvider; | ||||
|         } | ||||
|  | ||||
|         public void Execute(TestXbmcCommand message) | ||||
|         { | ||||
|             var settings = new XbmcSettings | ||||
|                                { | ||||
|                                    Host = message.Host, | ||||
|                                    Port = message.Port, | ||||
|                                    Username = message.Username, | ||||
|                                    Password = message.Password | ||||
|                                }; | ||||
|  | ||||
|             Logger.Trace("Determining version of XBMC Host: {0}", settings.Address); | ||||
|             var version = GetJsonVersion(settings); | ||||
|             Logger.Trace("Version is: {0}", version); | ||||
|  | ||||
|             Notify(settings, "Test Notification", "Success! XBMC has been successfully configured!"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -2,6 +2,7 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using Newtonsoft.Json; | ||||
| using NzbDrone.Core.Annotations; | ||||
|  | ||||
| namespace NzbDrone.Core.Notifications.Xbmc | ||||
| @@ -32,6 +33,9 @@ namespace NzbDrone.Core.Notifications.Xbmc | ||||
|         [FieldDefinition(7, Label = "Always Update", HelpText = "Update Library even when a video is playing?", Type = FieldType.Checkbox)] | ||||
|         public Boolean AlwaysUpdate { get; set; } | ||||
|  | ||||
|         [JsonIgnore] | ||||
|         public String Address { get { return String.Format("{0}:{1}", Host, Port); } } | ||||
|          | ||||
|         public bool IsValid | ||||
|         { | ||||
|             get | ||||
|   | ||||
| @@ -329,6 +329,11 @@ | ||||
|     <Compile Include="Notifications\Plex\PlexServerSettings.cs" /> | ||||
|     <Compile Include="Notifications\Prowl\ProwlSettings.cs" /> | ||||
|     <Compile Include="Notifications\Email\EmailSettings.cs" /> | ||||
|     <Compile Include="Notifications\Xbmc\HttpApiProvider.cs" /> | ||||
|     <Compile Include="Notifications\Xbmc\IApiProvider.cs" /> | ||||
|     <Compile Include="Notifications\Xbmc\InvalidXbmcVersionException.cs" /> | ||||
|     <Compile Include="Notifications\Xbmc\JsonApiProvider.cs" /> | ||||
|     <Compile Include="Notifications\Xbmc\TestXbmcCommand.cs" /> | ||||
|     <Compile Include="Notifications\Xbmc\XbmcSettings.cs" /> | ||||
|     <Compile Include="Organizer\EpisodeSortingType.cs" /> | ||||
|     <Compile Include="Organizer\FileNameBuilder.cs" /> | ||||
| @@ -379,12 +384,10 @@ | ||||
|     <Compile Include="Download\Clients\Sabnzbd\SabModel.cs" /> | ||||
|     <Compile Include="Download\Clients\Sabnzbd\SabQueueItem.cs" /> | ||||
|     <Compile Include="Download\Clients\Sabnzbd\SabVersionModel.cs" /> | ||||
|     <Compile Include="Model\Xbmc\ActionType.cs" /> | ||||
|     <Compile Include="Model\Xbmc\ActivePlayersDharmaResult.cs" /> | ||||
|     <Compile Include="Model\Xbmc\ActivePlayersEdenResult.cs" /> | ||||
|     <Compile Include="Model\Xbmc\TvShowResult.cs" /> | ||||
|     <Compile Include="Model\Xbmc\ErrorResult.cs" /> | ||||
|     <Compile Include="Model\Xbmc\IconType.cs" /> | ||||
|     <Compile Include="Model\Xbmc\XbmcJsonResult.cs" /> | ||||
|     <Compile Include="Model\Xbmc\XbmcVersion.cs" /> | ||||
|     <Compile Include="Model\Xem\XemResult.cs" /> | ||||
| @@ -492,10 +495,7 @@ | ||||
|     <Compile Include="Notifications\Email\EmailProvider.cs"> | ||||
|       <SubType>Code</SubType> | ||||
|     </Compile> | ||||
|     <Compile Include="Notifications\Xbmc\XbmcProvider.cs"> | ||||
|       <SubType>Code</SubType> | ||||
|     </Compile> | ||||
|     <Compile Include="Notifications\Xbmc\EventClientProvider.cs"> | ||||
|     <Compile Include="Notifications\Xbmc\XbmcService.cs"> | ||||
|       <SubType>Code</SubType> | ||||
|     </Compile> | ||||
|     <Compile Include="Notifications\Xbmc\ResourceManager.cs"> | ||||
|   | ||||
							
								
								
									
										32
									
								
								UI/.idea/runConfigurations/Debug___Chrome.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										32
									
								
								UI/.idea/runConfigurations/Debug___Chrome.xml
									
									
									
										generated
									
									
									
								
							| @@ -3,22 +3,22 @@ | ||||
|     <JSRemoteDebuggerConfigurationSettings> | ||||
|       <option name="engineId" value="chrome" /> | ||||
|       <option name="fileUrl" value="http://localhost:8989" /> | ||||
|       <mapping url="http://localhost:8989/Calendar" local-file="$PROJECT_DIR$/Calendar" /> | ||||
|       <mapping url="http://localhost:8989/MainMenuView.js" local-file="$PROJECT_DIR$/MainMenuView.js" /> | ||||
|       <mapping url="http://localhost:8989/Settings" local-file="$PROJECT_DIR$/Settings" /> | ||||
|       <mapping url="http://localhost:8989/Upcoming" local-file="$PROJECT_DIR$/Upcoming" /> | ||||
|       <mapping url="http://localhost:8989/app.js" local-file="$PROJECT_DIR$/app.js" /> | ||||
|       <mapping url="http://localhost:8989/Mixins" local-file="$PROJECT_DIR$/Mixins" /> | ||||
|       <mapping url="http://localhost:8989/Missing" local-file="$PROJECT_DIR$/Missing" /> | ||||
|       <mapping url="http://localhost:8989/Quality" local-file="$PROJECT_DIR$/Quality" /> | ||||
|       <mapping url="http://localhost:8989/Config.js" local-file="$PROJECT_DIR$/Config.js" /> | ||||
|       <mapping url="http://localhost:8989/Shared" local-file="$PROJECT_DIR$/Shared" /> | ||||
|       <mapping url="http://localhost:8989/AddSeries" local-file="$PROJECT_DIR$/AddSeries" /> | ||||
|       <mapping url="http://localhost:8989/HeaderView.js" local-file="$PROJECT_DIR$/HeaderView.js" /> | ||||
|       <mapping url="http://localhost:8989" local-file="$PROJECT_DIR$" /> | ||||
|       <mapping url="http://localhost:8989/Routing.js" local-file="$PROJECT_DIR$/Routing.js" /> | ||||
|       <mapping url="http://localhost:8989/Controller.js" local-file="$PROJECT_DIR$/Controller.js" /> | ||||
|       <mapping url="http://localhost:8989/Series" local-file="$PROJECT_DIR$/Series" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Calendar" url="http://localhost:8989/Calendar" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/MainMenuView.js" url="http://localhost:8989/MainMenuView.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Settings" url="http://localhost:8989/Settings" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Upcoming" url="http://localhost:8989/Upcoming" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/app.js" url="http://localhost:8989/app.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Mixins" url="http://localhost:8989/Mixins" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Missing" url="http://localhost:8989/Missing" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Quality" url="http://localhost:8989/Quality" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Config.js" url="http://localhost:8989/Config.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Shared" url="http://localhost:8989/Shared" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/AddSeries" url="http://localhost:8989/AddSeries" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/HeaderView.js" url="http://localhost:8989/HeaderView.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$" url="http://localhost:8989" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Routing.js" url="http://localhost:8989/Routing.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Controller.js" url="http://localhost:8989/Controller.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Series" url="http://localhost:8989/Series" /> | ||||
|     </JSRemoteDebuggerConfigurationSettings> | ||||
|     <RunnerSettings RunnerId="JavascriptDebugRunner" /> | ||||
|     <ConfigurationWrapper RunnerId="JavascriptDebugRunner" /> | ||||
|   | ||||
							
								
								
									
										32
									
								
								UI/.idea/runConfigurations/Debug___Firefox.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										32
									
								
								UI/.idea/runConfigurations/Debug___Firefox.xml
									
									
									
										generated
									
									
									
								
							| @@ -3,22 +3,22 @@ | ||||
|     <JSRemoteDebuggerConfigurationSettings> | ||||
|       <option name="engineId" value="firefox" /> | ||||
|       <option name="fileUrl" value="http://localhost:8989" /> | ||||
|       <mapping url="http://localhost:8989/Calendar" local-file="$PROJECT_DIR$/Calendar" /> | ||||
|       <mapping url="http://localhost:8989/MainMenuView.js" local-file="$PROJECT_DIR$/MainMenuView.js" /> | ||||
|       <mapping url="http://localhost:8989/Settings" local-file="$PROJECT_DIR$/Settings" /> | ||||
|       <mapping url="http://localhost:8989/Upcoming" local-file="$PROJECT_DIR$/Upcoming" /> | ||||
|       <mapping url="http://localhost:8989/app.js" local-file="$PROJECT_DIR$/app.js" /> | ||||
|       <mapping url="http://localhost:8989/Mixins" local-file="$PROJECT_DIR$/Mixins" /> | ||||
|       <mapping url="http://localhost:8989/Missing" local-file="$PROJECT_DIR$/Missing" /> | ||||
|       <mapping url="http://localhost:8989/Config.js" local-file="$PROJECT_DIR$/Config.js" /> | ||||
|       <mapping url="http://localhost:8989/Quality" local-file="$PROJECT_DIR$/Quality" /> | ||||
|       <mapping url="http://localhost:8989/AddSeries" local-file="$PROJECT_DIR$/AddSeries" /> | ||||
|       <mapping url="http://localhost:8989/Shared" local-file="$PROJECT_DIR$/Shared" /> | ||||
|       <mapping url="http://localhost:8989/HeaderView.js" local-file="$PROJECT_DIR$/HeaderView.js" /> | ||||
|       <mapping url="http://localhost:8989" local-file="$PROJECT_DIR$" /> | ||||
|       <mapping url="http://localhost:8989/Routing.js" local-file="$PROJECT_DIR$/Routing.js" /> | ||||
|       <mapping url="http://localhost:8989/Controller.js" local-file="$PROJECT_DIR$/Controller.js" /> | ||||
|       <mapping url="http://localhost:8989/Series" local-file="$PROJECT_DIR$/Series" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Calendar" url="http://localhost:8989/Calendar" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/MainMenuView.js" url="http://localhost:8989/MainMenuView.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Settings" url="http://localhost:8989/Settings" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Upcoming" url="http://localhost:8989/Upcoming" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/app.js" url="http://localhost:8989/app.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Mixins" url="http://localhost:8989/Mixins" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Missing" url="http://localhost:8989/Missing" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Config.js" url="http://localhost:8989/Config.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Quality" url="http://localhost:8989/Quality" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/AddSeries" url="http://localhost:8989/AddSeries" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Shared" url="http://localhost:8989/Shared" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/HeaderView.js" url="http://localhost:8989/HeaderView.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$" url="http://localhost:8989" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Routing.js" url="http://localhost:8989/Routing.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Controller.js" url="http://localhost:8989/Controller.js" /> | ||||
|       <mapping local-file="$PROJECT_DIR$/Series" url="http://localhost:8989/Series" /> | ||||
|     </JSRemoteDebuggerConfigurationSettings> | ||||
|     <RunnerSettings RunnerId="JavascriptDebugRunner" /> | ||||
|     <ConfigurationWrapper RunnerId="JavascriptDebugRunner" /> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user