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="Messaging\TestCommandExecutor.cs" /> | ||||||
|     <Compile Include="Reflection\ReflectionExtensions.cs" /> |     <Compile Include="Reflection\ReflectionExtensions.cs" /> | ||||||
|     <Compile Include="ServiceFactory.cs" /> |     <Compile Include="ServiceFactory.cs" /> | ||||||
|     <Compile Include="StringExtention.cs" /> |     <Compile Include="StringExtension.cs" /> | ||||||
|     <Compile Include="HttpProvider.cs" /> |     <Compile Include="HttpProvider.cs" /> | ||||||
|     <Compile Include="ConsoleService.cs" /> |     <Compile Include="ConsoleService.cs" /> | ||||||
|     <Compile Include="Contract\ReportBase.cs" /> |     <Compile Include="Contract\ReportBase.cs" /> | ||||||
| @@ -155,7 +155,6 @@ | |||||||
|     <Compile Include="IServiceProvider.cs" /> |     <Compile Include="IServiceProvider.cs" /> | ||||||
|     <Compile Include="TinyIoC.cs" /> |     <Compile Include="TinyIoC.cs" /> | ||||||
|     <Compile Include="TryParseExtension.cs" /> |     <Compile Include="TryParseExtension.cs" /> | ||||||
|     <Compile Include="UdpProvider.cs" /> |  | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="packages.config"> |     <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 = 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 PlexClient(null)); | ||||||
|             _notifications.Add(new PlexServer(null)); |             _notifications.Add(new PlexServer(null)); | ||||||
|             _notifications.Add(new Email(null)); |             _notifications.Add(new Email(null)); | ||||||
| @@ -49,8 +49,8 @@ namespace NzbDrone.Core.Test.NotificationTests | |||||||
|         { |         { | ||||||
|             Mocker.SetConstant<INotificationRepository>(Mocker.Resolve<NotificationRepository>()); |             Mocker.SetConstant<INotificationRepository>(Mocker.Resolve<NotificationRepository>()); | ||||||
|  |  | ||||||
|             Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof (Xbmc))) |             Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof(Notifications.Xbmc.Xbmc))) | ||||||
|                   .Returns(new Xbmc(null, null)); |                   .Returns(new Notifications.Xbmc.Xbmc(null, null)); | ||||||
|  |  | ||||||
|             Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof(PlexClient))) |             Mocker.GetMock<IContainer>().Setup(s => s.Resolve(typeof(PlexClient))) | ||||||
|                   .Returns(new PlexClient(null)); |                   .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="MediaFileTests\EpisodeFileMoverFixture.cs" /> | ||||||
|     <Compile Include="MetadataSourceTests\TracktProxyFixture.cs" /> |     <Compile Include="MetadataSourceTests\TracktProxyFixture.cs" /> | ||||||
|     <Compile Include="NotificationTests\NotificationServiceFixture.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\QualitySizeRepositoryFixture.cs" /> | ||||||
|     <Compile Include="Qualities\QualityProfileRepositoryFixture.cs" /> |     <Compile Include="Qualities\QualityProfileRepositoryFixture.cs" /> | ||||||
|     <Compile Include="RootFolderTests\FreeSpaceOnDrivesFixture.cs" /> |     <Compile Include="RootFolderTests\FreeSpaceOnDrivesFixture.cs" /> | ||||||
| @@ -163,7 +174,7 @@ | |||||||
|     <Compile Include="ProviderTests\RecycleBinProviderTests\EmptyFixture.cs" /> |     <Compile Include="ProviderTests\RecycleBinProviderTests\EmptyFixture.cs" /> | ||||||
|     <Compile Include="ProviderTests\RecycleBinProviderTests\DeleteFileFixture.cs" /> |     <Compile Include="ProviderTests\RecycleBinProviderTests\DeleteFileFixture.cs" /> | ||||||
|     <Compile Include="ProviderTests\RecycleBinProviderTests\DeleteDirectoryFixture.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\EpisodesRepositoryReadFixture.cs" /> | ||||||
|     <Compile Include="TvTests\EpisodeRepositoryTests\EpisodesWithoutFilesFixture.cs" /> |     <Compile Include="TvTests\EpisodeRepositoryTests\EpisodesWithoutFilesFixture.cs" /> | ||||||
|     <Compile Include="TvTests\EpisodeRepositoryTests\EpisodesBetweenDatesFixture.cs" /> |     <Compile Include="TvTests\EpisodeRepositoryTests\EpisodesBetweenDatesFixture.cs" /> | ||||||
| @@ -175,8 +186,8 @@ | |||||||
|     <Compile Include="DecisionEngineTests\QualityUpgradeSpecificationFixture.cs" /> |     <Compile Include="DecisionEngineTests\QualityUpgradeSpecificationFixture.cs" /> | ||||||
|     <Compile Include="DecisionEngineTests\QualityUpgradableSpecificationFixture.cs" /> |     <Compile Include="DecisionEngineTests\QualityUpgradableSpecificationFixture.cs" /> | ||||||
|     <Compile Include="ProviderTests\DiskProviderTests\FreeDiskSpaceTest.cs" /> |     <Compile Include="ProviderTests\DiskProviderTests\FreeDiskSpaceTest.cs" /> | ||||||
|     <Compile Include="ProviderTests\ProwlProviderTest.cs" /> |     <Compile Include="NotificationTests\ProwlProviderTest.cs" /> | ||||||
|     <Compile Include="ProviderTests\GrowlProviderTest.cs" /> |     <Compile Include="NotificationTests\GrowlProviderTest.cs" /> | ||||||
|     <Compile Include="ProviderTests\DiskProviderTests\ExtractArchiveFixture.cs" /> |     <Compile Include="ProviderTests\DiskProviderTests\ExtractArchiveFixture.cs" /> | ||||||
|     <Compile Include="ProviderTests\PostDownloadProviderTests\DropFolderImportServiceFixture.cs" /> |     <Compile Include="ProviderTests\PostDownloadProviderTests\DropFolderImportServiceFixture.cs" /> | ||||||
|     <Compile Include="SeriesStatsTests\SeriesStatisticsFixture.cs" /> |     <Compile Include="SeriesStatsTests\SeriesStatisticsFixture.cs" /> | ||||||
| @@ -187,8 +198,7 @@ | |||||||
|     <Compile Include="HelperTests\SortHelperTest.cs" /> |     <Compile Include="HelperTests\SortHelperTest.cs" /> | ||||||
|     <Compile Include="DecisionEngineTests\AcceptableSizeSpecificationFixture.cs" /> |     <Compile Include="DecisionEngineTests\AcceptableSizeSpecificationFixture.cs" /> | ||||||
|     <Compile Include="Qualities\QualitySizeServiceFixture.cs" /> |     <Compile Include="Qualities\QualitySizeServiceFixture.cs" /> | ||||||
|     <Compile Include="ProviderTests\EventClientProviderTest.cs" /> |     <Compile Include="NotificationTests\Xbmc\XbmcServiceFixture.cs" /> | ||||||
|     <Compile Include="ProviderTests\XbmcProviderTest.cs" /> |  | ||||||
|     <Compile Include="TvTests\EpisodeProviderTests\EpisodeProviderTest_GetEpisodesByParseResult.cs" /> |     <Compile Include="TvTests\EpisodeProviderTests\EpisodeProviderTest_GetEpisodesByParseResult.cs" /> | ||||||
|     <Compile Include="ProviderTests\DiskScanProviderTests\ImportFileFixture.cs" /> |     <Compile Include="ProviderTests\DiskScanProviderTests\ImportFileFixture.cs" /> | ||||||
|     <Compile Include="FluentTest.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 int PlayerId { get; set; } | ||||||
|         public string Type { 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> |     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; |             _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.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Text; | using System.Text; | ||||||
|  | using Newtonsoft.Json; | ||||||
| using NzbDrone.Core.Annotations; | using NzbDrone.Core.Annotations; | ||||||
|  |  | ||||||
| namespace NzbDrone.Core.Notifications.Xbmc | 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)] |         [FieldDefinition(7, Label = "Always Update", HelpText = "Update Library even when a video is playing?", Type = FieldType.Checkbox)] | ||||||
|         public Boolean AlwaysUpdate { get; set; } |         public Boolean AlwaysUpdate { get; set; } | ||||||
|  |  | ||||||
|  |         [JsonIgnore] | ||||||
|  |         public String Address { get { return String.Format("{0}:{1}", Host, Port); } } | ||||||
|  |          | ||||||
|         public bool IsValid |         public bool IsValid | ||||||
|         { |         { | ||||||
|             get |             get | ||||||
|   | |||||||
| @@ -329,6 +329,11 @@ | |||||||
|     <Compile Include="Notifications\Plex\PlexServerSettings.cs" /> |     <Compile Include="Notifications\Plex\PlexServerSettings.cs" /> | ||||||
|     <Compile Include="Notifications\Prowl\ProwlSettings.cs" /> |     <Compile Include="Notifications\Prowl\ProwlSettings.cs" /> | ||||||
|     <Compile Include="Notifications\Email\EmailSettings.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="Notifications\Xbmc\XbmcSettings.cs" /> | ||||||
|     <Compile Include="Organizer\EpisodeSortingType.cs" /> |     <Compile Include="Organizer\EpisodeSortingType.cs" /> | ||||||
|     <Compile Include="Organizer\FileNameBuilder.cs" /> |     <Compile Include="Organizer\FileNameBuilder.cs" /> | ||||||
| @@ -379,12 +384,10 @@ | |||||||
|     <Compile Include="Download\Clients\Sabnzbd\SabModel.cs" /> |     <Compile Include="Download\Clients\Sabnzbd\SabModel.cs" /> | ||||||
|     <Compile Include="Download\Clients\Sabnzbd\SabQueueItem.cs" /> |     <Compile Include="Download\Clients\Sabnzbd\SabQueueItem.cs" /> | ||||||
|     <Compile Include="Download\Clients\Sabnzbd\SabVersionModel.cs" /> |     <Compile Include="Download\Clients\Sabnzbd\SabVersionModel.cs" /> | ||||||
|     <Compile Include="Model\Xbmc\ActionType.cs" /> |  | ||||||
|     <Compile Include="Model\Xbmc\ActivePlayersDharmaResult.cs" /> |     <Compile Include="Model\Xbmc\ActivePlayersDharmaResult.cs" /> | ||||||
|     <Compile Include="Model\Xbmc\ActivePlayersEdenResult.cs" /> |     <Compile Include="Model\Xbmc\ActivePlayersEdenResult.cs" /> | ||||||
|     <Compile Include="Model\Xbmc\TvShowResult.cs" /> |     <Compile Include="Model\Xbmc\TvShowResult.cs" /> | ||||||
|     <Compile Include="Model\Xbmc\ErrorResult.cs" /> |     <Compile Include="Model\Xbmc\ErrorResult.cs" /> | ||||||
|     <Compile Include="Model\Xbmc\IconType.cs" /> |  | ||||||
|     <Compile Include="Model\Xbmc\XbmcJsonResult.cs" /> |     <Compile Include="Model\Xbmc\XbmcJsonResult.cs" /> | ||||||
|     <Compile Include="Model\Xbmc\XbmcVersion.cs" /> |     <Compile Include="Model\Xbmc\XbmcVersion.cs" /> | ||||||
|     <Compile Include="Model\Xem\XemResult.cs" /> |     <Compile Include="Model\Xem\XemResult.cs" /> | ||||||
| @@ -492,10 +495,7 @@ | |||||||
|     <Compile Include="Notifications\Email\EmailProvider.cs"> |     <Compile Include="Notifications\Email\EmailProvider.cs"> | ||||||
|       <SubType>Code</SubType> |       <SubType>Code</SubType> | ||||||
|     </Compile> |     </Compile> | ||||||
|     <Compile Include="Notifications\Xbmc\XbmcProvider.cs"> |     <Compile Include="Notifications\Xbmc\XbmcService.cs"> | ||||||
|       <SubType>Code</SubType> |  | ||||||
|     </Compile> |  | ||||||
|     <Compile Include="Notifications\Xbmc\EventClientProvider.cs"> |  | ||||||
|       <SubType>Code</SubType> |       <SubType>Code</SubType> | ||||||
|     </Compile> |     </Compile> | ||||||
|     <Compile Include="Notifications\Xbmc\ResourceManager.cs"> |     <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> |     <JSRemoteDebuggerConfigurationSettings> | ||||||
|       <option name="engineId" value="chrome" /> |       <option name="engineId" value="chrome" /> | ||||||
|       <option name="fileUrl" value="http://localhost:8989" /> |       <option name="fileUrl" value="http://localhost:8989" /> | ||||||
|       <mapping url="http://localhost:8989/Calendar" local-file="$PROJECT_DIR$/Calendar" /> |       <mapping local-file="$PROJECT_DIR$/Calendar" url="http://localhost:8989/Calendar" /> | ||||||
|       <mapping url="http://localhost:8989/MainMenuView.js" local-file="$PROJECT_DIR$/MainMenuView.js" /> |       <mapping local-file="$PROJECT_DIR$/MainMenuView.js" url="http://localhost:8989/MainMenuView.js" /> | ||||||
|       <mapping url="http://localhost:8989/Settings" local-file="$PROJECT_DIR$/Settings" /> |       <mapping local-file="$PROJECT_DIR$/Settings" url="http://localhost:8989/Settings" /> | ||||||
|       <mapping url="http://localhost:8989/Upcoming" local-file="$PROJECT_DIR$/Upcoming" /> |       <mapping local-file="$PROJECT_DIR$/Upcoming" url="http://localhost:8989/Upcoming" /> | ||||||
|       <mapping url="http://localhost:8989/app.js" local-file="$PROJECT_DIR$/app.js" /> |       <mapping local-file="$PROJECT_DIR$/app.js" url="http://localhost:8989/app.js" /> | ||||||
|       <mapping url="http://localhost:8989/Mixins" local-file="$PROJECT_DIR$/Mixins" /> |       <mapping local-file="$PROJECT_DIR$/Mixins" url="http://localhost:8989/Mixins" /> | ||||||
|       <mapping url="http://localhost:8989/Missing" local-file="$PROJECT_DIR$/Missing" /> |       <mapping local-file="$PROJECT_DIR$/Missing" url="http://localhost:8989/Missing" /> | ||||||
|       <mapping url="http://localhost:8989/Quality" local-file="$PROJECT_DIR$/Quality" /> |       <mapping local-file="$PROJECT_DIR$/Quality" url="http://localhost:8989/Quality" /> | ||||||
|       <mapping url="http://localhost:8989/Config.js" local-file="$PROJECT_DIR$/Config.js" /> |       <mapping local-file="$PROJECT_DIR$/Config.js" url="http://localhost:8989/Config.js" /> | ||||||
|       <mapping url="http://localhost:8989/Shared" local-file="$PROJECT_DIR$/Shared" /> |       <mapping local-file="$PROJECT_DIR$/Shared" url="http://localhost:8989/Shared" /> | ||||||
|       <mapping url="http://localhost:8989/AddSeries" local-file="$PROJECT_DIR$/AddSeries" /> |       <mapping local-file="$PROJECT_DIR$/AddSeries" url="http://localhost:8989/AddSeries" /> | ||||||
|       <mapping url="http://localhost:8989/HeaderView.js" local-file="$PROJECT_DIR$/HeaderView.js" /> |       <mapping local-file="$PROJECT_DIR$/HeaderView.js" url="http://localhost:8989/HeaderView.js" /> | ||||||
|       <mapping url="http://localhost:8989" local-file="$PROJECT_DIR$" /> |       <mapping local-file="$PROJECT_DIR$" url="http://localhost:8989" /> | ||||||
|       <mapping url="http://localhost:8989/Routing.js" local-file="$PROJECT_DIR$/Routing.js" /> |       <mapping local-file="$PROJECT_DIR$/Routing.js" url="http://localhost:8989/Routing.js" /> | ||||||
|       <mapping url="http://localhost:8989/Controller.js" local-file="$PROJECT_DIR$/Controller.js" /> |       <mapping local-file="$PROJECT_DIR$/Controller.js" url="http://localhost:8989/Controller.js" /> | ||||||
|       <mapping url="http://localhost:8989/Series" local-file="$PROJECT_DIR$/Series" /> |       <mapping local-file="$PROJECT_DIR$/Series" url="http://localhost:8989/Series" /> | ||||||
|     </JSRemoteDebuggerConfigurationSettings> |     </JSRemoteDebuggerConfigurationSettings> | ||||||
|     <RunnerSettings RunnerId="JavascriptDebugRunner" /> |     <RunnerSettings RunnerId="JavascriptDebugRunner" /> | ||||||
|     <ConfigurationWrapper 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> |     <JSRemoteDebuggerConfigurationSettings> | ||||||
|       <option name="engineId" value="firefox" /> |       <option name="engineId" value="firefox" /> | ||||||
|       <option name="fileUrl" value="http://localhost:8989" /> |       <option name="fileUrl" value="http://localhost:8989" /> | ||||||
|       <mapping url="http://localhost:8989/Calendar" local-file="$PROJECT_DIR$/Calendar" /> |       <mapping local-file="$PROJECT_DIR$/Calendar" url="http://localhost:8989/Calendar" /> | ||||||
|       <mapping url="http://localhost:8989/MainMenuView.js" local-file="$PROJECT_DIR$/MainMenuView.js" /> |       <mapping local-file="$PROJECT_DIR$/MainMenuView.js" url="http://localhost:8989/MainMenuView.js" /> | ||||||
|       <mapping url="http://localhost:8989/Settings" local-file="$PROJECT_DIR$/Settings" /> |       <mapping local-file="$PROJECT_DIR$/Settings" url="http://localhost:8989/Settings" /> | ||||||
|       <mapping url="http://localhost:8989/Upcoming" local-file="$PROJECT_DIR$/Upcoming" /> |       <mapping local-file="$PROJECT_DIR$/Upcoming" url="http://localhost:8989/Upcoming" /> | ||||||
|       <mapping url="http://localhost:8989/app.js" local-file="$PROJECT_DIR$/app.js" /> |       <mapping local-file="$PROJECT_DIR$/app.js" url="http://localhost:8989/app.js" /> | ||||||
|       <mapping url="http://localhost:8989/Mixins" local-file="$PROJECT_DIR$/Mixins" /> |       <mapping local-file="$PROJECT_DIR$/Mixins" url="http://localhost:8989/Mixins" /> | ||||||
|       <mapping url="http://localhost:8989/Missing" local-file="$PROJECT_DIR$/Missing" /> |       <mapping local-file="$PROJECT_DIR$/Missing" url="http://localhost:8989/Missing" /> | ||||||
|       <mapping url="http://localhost:8989/Config.js" local-file="$PROJECT_DIR$/Config.js" /> |       <mapping local-file="$PROJECT_DIR$/Config.js" url="http://localhost:8989/Config.js" /> | ||||||
|       <mapping url="http://localhost:8989/Quality" local-file="$PROJECT_DIR$/Quality" /> |       <mapping local-file="$PROJECT_DIR$/Quality" url="http://localhost:8989/Quality" /> | ||||||
|       <mapping url="http://localhost:8989/AddSeries" local-file="$PROJECT_DIR$/AddSeries" /> |       <mapping local-file="$PROJECT_DIR$/AddSeries" url="http://localhost:8989/AddSeries" /> | ||||||
|       <mapping url="http://localhost:8989/Shared" local-file="$PROJECT_DIR$/Shared" /> |       <mapping local-file="$PROJECT_DIR$/Shared" url="http://localhost:8989/Shared" /> | ||||||
|       <mapping url="http://localhost:8989/HeaderView.js" local-file="$PROJECT_DIR$/HeaderView.js" /> |       <mapping local-file="$PROJECT_DIR$/HeaderView.js" url="http://localhost:8989/HeaderView.js" /> | ||||||
|       <mapping url="http://localhost:8989" local-file="$PROJECT_DIR$" /> |       <mapping local-file="$PROJECT_DIR$" url="http://localhost:8989" /> | ||||||
|       <mapping url="http://localhost:8989/Routing.js" local-file="$PROJECT_DIR$/Routing.js" /> |       <mapping local-file="$PROJECT_DIR$/Routing.js" url="http://localhost:8989/Routing.js" /> | ||||||
|       <mapping url="http://localhost:8989/Controller.js" local-file="$PROJECT_DIR$/Controller.js" /> |       <mapping local-file="$PROJECT_DIR$/Controller.js" url="http://localhost:8989/Controller.js" /> | ||||||
|       <mapping url="http://localhost:8989/Series" local-file="$PROJECT_DIR$/Series" /> |       <mapping local-file="$PROJECT_DIR$/Series" url="http://localhost:8989/Series" /> | ||||||
|     </JSRemoteDebuggerConfigurationSettings> |     </JSRemoteDebuggerConfigurationSettings> | ||||||
|     <RunnerSettings RunnerId="JavascriptDebugRunner" /> |     <RunnerSettings RunnerId="JavascriptDebugRunner" /> | ||||||
|     <ConfigurationWrapper RunnerId="JavascriptDebugRunner" /> |     <ConfigurationWrapper RunnerId="JavascriptDebugRunner" /> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user