Fixed: Remove obsolete XBMC HTTP notification API
Co-Authored-By: ta264 <ta264@users.noreply.github.com>
This commit is contained in:
parent
91c9250d9c
commit
78eb8b0e6d
|
@ -1,70 +0,0 @@
|
|||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
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/");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
using FizzWare.NBuilder;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ using NzbDrone.Core.Tv;
|
|||
namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Json
|
||||
{
|
||||
[TestFixture]
|
||||
public class GetSeriesPathFixture : CoreTest<JsonApiProvider>
|
||||
public class GetSeriesPathFixture : CoreTest<XbmcService>
|
||||
{
|
||||
private const int TVDB_ID = 5;
|
||||
private XbmcSettings _settings;
|
||||
|
|
|
@ -11,7 +11,7 @@ using NzbDrone.Core.Tv;
|
|||
namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Json
|
||||
{
|
||||
[TestFixture]
|
||||
public class UpdateFixture : CoreTest<JsonApiProvider>
|
||||
public class UpdateFixture : CoreTest<XbmcService>
|
||||
{
|
||||
private const int TVDB_ID = 5;
|
||||
private XbmcSettings _settings;
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Notifications.Xbmc.Model;
|
||||
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 bool CanHandle(XbmcVersion version)
|
||||
{
|
||||
return version < new XbmcVersion(5);
|
||||
}
|
||||
|
||||
public void Notify(XbmcSettings settings, string title, string message)
|
||||
{
|
||||
var notification = string.Format("Notification({0},{1},{2},{3})", title, message, settings.DisplayTime * 1000, "https://raw.github.com/Sonarr/Sonarr/develop/Logo/64.png");
|
||||
var command = BuildExecBuiltInCommand(notification);
|
||||
|
||||
SendCommand(settings, command);
|
||||
}
|
||||
|
||||
public void Update(XbmcSettings settings, Series series)
|
||||
{
|
||||
if (!settings.AlwaysUpdate)
|
||||
{
|
||||
_logger.Debug("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)
|
||||
{
|
||||
if (!settings.AlwaysUpdate)
|
||||
{
|
||||
_logger.Debug("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 cleaning");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const string cleanVideoLibrary = "CleanLibrary(video)";
|
||||
var command = BuildExecBuiltInCommand(cleanVideoLibrary);
|
||||
|
||||
SendCommand(settings, command);
|
||||
}
|
||||
|
||||
internal 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.Debug(ex, ex.Message);
|
||||
}
|
||||
|
||||
return new List<ActivePlayer>();
|
||||
}
|
||||
|
||||
internal 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 = xDoc.Descendants("xml").Select(x => x).FirstOrDefault();
|
||||
|
||||
if (xml == null)
|
||||
return null;
|
||||
|
||||
var field = xml.Descendants("field").FirstOrDefault();
|
||||
|
||||
if (field == null)
|
||||
return null;
|
||||
|
||||
return field.Value;
|
||||
}
|
||||
|
||||
internal bool CheckForError(string response)
|
||||
{
|
||||
_logger.Debug("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.Debug("Error found in response: {0}", errorMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void UpdateLibrary(XbmcSettings settings, Series series)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Debug("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.Debug("Updating series [{0}] on XBMC host: {1}", series, settings.Address);
|
||||
var command = BuildExecBuiltInCommand(string.Format("UpdateLibrary(video,{0})", xbmcSeriesPath));
|
||||
SendCommand(settings, command);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//Update the entire library
|
||||
_logger.Debug("Series [{0}] doesn't exist on XBMC host: {1}, Updating Entire Library", series, settings.Address);
|
||||
var command = BuildExecBuiltInCommand("UpdateLibrary(video)");
|
||||
SendCommand(settings, command);
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Debug(ex, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private string SendCommand(XbmcSettings settings, string command)
|
||||
{
|
||||
var url = HttpRequestBuilder.BuildBaseUrl(settings.UseSsl, settings.Host, settings.Port, $"xbmcCmds/xbmcHttp?command={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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
using NzbDrone.Core.Notifications.Xbmc.Model;
|
||||
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);
|
||||
bool CanHandle(XbmcVersion version);
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Xbmc
|
||||
{
|
||||
public class InvalidXbmcVersionException : Exception
|
||||
{
|
||||
public InvalidXbmcVersionException()
|
||||
{
|
||||
}
|
||||
|
||||
public InvalidXbmcVersionException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Notifications.Xbmc.Model;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Xbmc
|
||||
{
|
||||
public class JsonApiProvider : IApiProvider
|
||||
{
|
||||
private readonly IXbmcJsonApiProxy _proxy;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public JsonApiProvider(IXbmcJsonApiProxy proxy, Logger logger)
|
||||
{
|
||||
_proxy = proxy;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public bool CanHandle(XbmcVersion version)
|
||||
{
|
||||
return version >= new XbmcVersion(5);
|
||||
}
|
||||
|
||||
public void Notify(XbmcSettings settings, string title, string message)
|
||||
{
|
||||
_proxy.Notify(settings, title, message);
|
||||
}
|
||||
|
||||
public void Update(XbmcSettings settings, Series series)
|
||||
{
|
||||
if (!settings.AlwaysUpdate)
|
||||
{
|
||||
_logger.Debug("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)
|
||||
{
|
||||
if (!settings.AlwaysUpdate)
|
||||
{
|
||||
_logger.Debug("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 cleaning");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_proxy.CleanLibrary(settings);
|
||||
}
|
||||
|
||||
public List<ActivePlayer> GetActivePlayers(XbmcSettings settings)
|
||||
{
|
||||
return _proxy.GetActivePlayers(settings);
|
||||
}
|
||||
|
||||
public string GetSeriesPath(XbmcSettings settings, Series series)
|
||||
{
|
||||
var allSeries = _proxy.GetSeries(settings);
|
||||
|
||||
if (!allSeries.Any())
|
||||
{
|
||||
_logger.Debug("No TV shows returned from XBMC");
|
||||
return null;
|
||||
}
|
||||
|
||||
var matchingSeries = allSeries.FirstOrDefault(s =>
|
||||
{
|
||||
var tvdbId = 0;
|
||||
int.TryParse(s.ImdbNumber, out tvdbId);
|
||||
|
||||
return tvdbId == series.TvdbId || s.Label == series.Title;
|
||||
});
|
||||
|
||||
if (matchingSeries != null) return matchingSeries.File;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void UpdateLibrary(XbmcSettings settings, Series series)
|
||||
{
|
||||
try
|
||||
{
|
||||
var seriesPath = GetSeriesPath(settings, series);
|
||||
|
||||
if (seriesPath != null)
|
||||
{
|
||||
_logger.Debug("Updating series {0} (Path: {1}) on XBMC host: {2}", series, seriesPath, settings.Address);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
_logger.Debug("Series {0} doesn't exist on XBMC host: {1}, Updating Entire Library", series,
|
||||
settings.Address);
|
||||
}
|
||||
|
||||
var response = _proxy.UpdateLibrary(settings, seriesPath);
|
||||
|
||||
if (!response.Equals("OK", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
_logger.Debug("Failed to update library for: {0}", settings.Address);
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Debug(ex, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Xbmc.Model
|
||||
{
|
||||
public class ActivePlayersDharmaResult
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string JsonRpc { get; set; }
|
||||
public Dictionary<string, bool> Result { get; set; }
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace NzbDrone.Core.Notifications.Xbmc.Model
|
||||
{
|
||||
public class ActivePlayersEdenResult
|
||||
public class ActivePlayersResult
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string JsonRpc { get; set; }
|
|
@ -20,7 +20,7 @@ namespace NzbDrone.Core.Notifications.Xbmc
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public override string Link => "https://kodi.tv";
|
||||
public override string Link => "https://kodi.tv/";
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace NzbDrone.Core.Notifications.Xbmc
|
|||
{
|
||||
var response = ProcessRequest(settings, "Player.GetActivePlayers");
|
||||
|
||||
return Json.Deserialize<ActivePlayersEdenResult>(response).Result;
|
||||
return Json.Deserialize<ActivePlayersResult>(response).Result;
|
||||
}
|
||||
|
||||
public List<TvShow> GetSeries(XbmcSettings settings)
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using FluentValidation.Results;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.Notifications.Xbmc.Model;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
|
@ -22,95 +20,98 @@ namespace NzbDrone.Core.Notifications.Xbmc
|
|||
public class XbmcService : IXbmcService
|
||||
{
|
||||
private readonly IXbmcJsonApiProxy _proxy;
|
||||
private readonly IEnumerable<IApiProvider> _apiProviders;
|
||||
private readonly Logger _logger;
|
||||
|
||||
private readonly ICached<XbmcVersion> _xbmcVersionCache;
|
||||
|
||||
public XbmcService(IXbmcJsonApiProxy proxy,
|
||||
IEnumerable<IApiProvider> apiProviders,
|
||||
ICacheManager cacheManager,
|
||||
Logger logger)
|
||||
{
|
||||
_proxy = proxy;
|
||||
_apiProviders = apiProviders;
|
||||
_logger = logger;
|
||||
|
||||
_xbmcVersionCache = cacheManager.GetCache<XbmcVersion>(GetType());
|
||||
}
|
||||
|
||||
public void Notify(XbmcSettings settings, string title, string message)
|
||||
{
|
||||
var provider = GetApiProvider(settings);
|
||||
provider.Notify(settings, title, message);
|
||||
_proxy.Notify(settings, title, message);
|
||||
}
|
||||
|
||||
public void Update(XbmcSettings settings, Series series)
|
||||
{
|
||||
var provider = GetApiProvider(settings);
|
||||
provider.Update(settings, series);
|
||||
if (!settings.AlwaysUpdate)
|
||||
{
|
||||
_logger.Debug("Determining if there are any active players on XBMC host: {0}", settings.Address);
|
||||
var activePlayers = _proxy.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 provider = GetApiProvider(settings);
|
||||
provider.Clean(settings);
|
||||
_proxy.CleanLibrary(settings);
|
||||
}
|
||||
|
||||
private XbmcVersion GetJsonVersion(XbmcSettings settings)
|
||||
public string GetSeriesPath(XbmcSettings settings, Series series)
|
||||
{
|
||||
return _xbmcVersionCache.Get(settings.Address, () =>
|
||||
var allSeries = _proxy.GetSeries(settings);
|
||||
|
||||
if (!allSeries.Any())
|
||||
{
|
||||
var response = _proxy.GetJsonVersion(settings);
|
||||
|
||||
_logger.Debug("Getting version from response: " + response);
|
||||
var result = Json.Deserialize<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 Json.Deserialize<XbmcVersion>(versionObject.Value.ToString());
|
||||
}
|
||||
|
||||
throw new InvalidCastException("Unknown Version structure!: " + versionObject);
|
||||
}, TimeSpan.FromHours(12));
|
||||
}
|
||||
|
||||
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);
|
||||
_logger.Debug("No TV shows returned from XBMC");
|
||||
return null;
|
||||
}
|
||||
|
||||
return apiProvider;
|
||||
var matchingSeries = allSeries.FirstOrDefault(s =>
|
||||
{
|
||||
var tvdbId = 0;
|
||||
int.TryParse(s.ImdbNumber, out tvdbId);
|
||||
|
||||
return tvdbId == series.TvdbId || s.Label == series.Title;
|
||||
});
|
||||
|
||||
if (matchingSeries != null) return matchingSeries.File;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void UpdateLibrary(XbmcSettings settings, Series series)
|
||||
{
|
||||
try
|
||||
{
|
||||
var moviePath = GetSeriesPath(settings, series);
|
||||
|
||||
if (moviePath != null)
|
||||
{
|
||||
moviePath = new OsPath(moviePath).Directory.FullPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
_logger.Debug("Updating series {0} (Path: {1}) on XBMC host: {2}", series, moviePath, settings.Address);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("Series {0} doesn't exist on XBMC host: {1}, Updating Entire Library", series, settings.Address);
|
||||
}
|
||||
|
||||
var response = _proxy.UpdateLibrary(settings, moviePath);
|
||||
|
||||
if (!response.Equals("OK", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
_logger.Debug("Failed to update library for: {0}", settings.Address);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Debug(ex, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public ValidationFailure Test(XbmcSettings settings, string message)
|
||||
{
|
||||
_xbmcVersionCache.Clear();
|
||||
|
||||
try
|
||||
{
|
||||
_logger.Debug("Determining version of Host: {0}", settings.Address);
|
||||
var version = GetJsonVersion(settings);
|
||||
_logger.Debug("Version is: {0}", version);
|
||||
|
||||
if (version == new XbmcVersion(0))
|
||||
{
|
||||
throw new InvalidXbmcVersionException("Version received from XBMC is invalid, please correct your settings.");
|
||||
}
|
||||
|
||||
Notify(settings, "Test Notification", message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
Loading…
Reference in New Issue