using System.Collections.Generic; using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Serializer; using NzbDrone.Core.Notifications.Xbmc.Model; using NzbDrone.Core.Rest; using RestSharp; using RestSharp.Authenticators; namespace NzbDrone.Core.Notifications.Xbmc { public interface IXbmcJsonApiProxy { string GetJsonVersion(XbmcSettings settings); void Notify(XbmcSettings settings, string title, string message); string UpdateLibrary(XbmcSettings settings, string path); void CleanLibrary(XbmcSettings settings); List GetActivePlayers(XbmcSettings settings); List GetMovies(XbmcSettings settings); } public class XbmcJsonApiProxy : IXbmcJsonApiProxy { private readonly IRestClientFactory _restClientFactory; private readonly Logger _logger; public XbmcJsonApiProxy(IRestClientFactory restClientFactory, Logger logger) { _restClientFactory = restClientFactory; _logger = logger; } public string GetJsonVersion(XbmcSettings settings) { var request = new RestRequest(); return ProcessRequest(request, settings, "JSONRPC.Version"); } public void Notify(XbmcSettings settings, string title, string message) { var request = new RestRequest(); var parameters = new Dictionary(); parameters.Add("title", title); parameters.Add("message", message); parameters.Add("image", "https://raw.github.com/Radarr/Radarr/develop/Logo/64.png"); parameters.Add("displaytime", settings.DisplayTime * 1000); ProcessRequest(request, settings, "GUI.ShowNotification", parameters); } public string UpdateLibrary(XbmcSettings settings, string path) { var request = new RestRequest(); var parameters = new Dictionary(); parameters.Add("directory", path); if (path.IsNullOrWhiteSpace()) { parameters = null; } var response = ProcessRequest(request, settings, "VideoLibrary.Scan", parameters); return Json.Deserialize>(response).Result; } public void CleanLibrary(XbmcSettings settings) { var request = new RestRequest(); ProcessRequest(request, settings, "VideoLibrary.Clean"); } public List GetActivePlayers(XbmcSettings settings) { var request = new RestRequest(); var response = ProcessRequest(request, settings, "Player.GetActivePlayers"); return Json.Deserialize(response).Result; } public List GetMovies(XbmcSettings settings) { var request = new RestRequest(); var parameters = new Dictionary(); parameters.Add("properties", new[] { "file", "imdbnumber" }); var response = ProcessRequest(request, settings, "VideoLibrary.GetMovies", parameters); return Json.Deserialize(response).Result.Movies; } private string ProcessRequest(IRestRequest request, XbmcSettings settings, string method, Dictionary parameters = null) { var client = BuildClient(settings); request.Method = Method.POST; request.RequestFormat = DataFormat.Json; request.JsonSerializer = new JsonNetSerializer(); request.AddBody(new { jsonrpc = "2.0", method = method, id = 10, @params = parameters }); var response = client.ExecuteAndValidate(request); _logger.Trace("Response: {0}", response.Content); CheckForError(response); return response.Content; } private IRestClient BuildClient(XbmcSettings settings) { var url = string.Format(@"http://{0}/jsonrpc", settings.Address); var client = _restClientFactory.BuildClient(url); if (!settings.Username.IsNullOrWhiteSpace()) { client.Authenticator = new HttpBasicAuthenticator(settings.Username, settings.Password); } return client; } private void CheckForError(IRestResponse response) { if (string.IsNullOrWhiteSpace(response.Content)) { throw new XbmcJsonException("Invalid response from XBMC, the response is not valid JSON"); } _logger.Trace("Looking for error in response, {0}", response.Content); if (response.Content.StartsWith("{\"error\"")) { var error = Json.Deserialize(response.Content); var code = error.Error["code"]; var message = error.Error["message"]; var errorMessage = string.Format("XBMC Json Error. Code = {0}, Message: {1}", code, message); throw new XbmcJsonException(errorMessage); } } } }