New: Added Plex to Notifications, allowing notifications and library updates.

pull/6/head
Mark McDowall 13 years ago
parent d27f14d7aa
commit 6e767eafab

@ -115,6 +115,7 @@
<Compile Include="JobTests\RecentBacklogSearchJobTest.cs" />
<Compile Include="ProviderTests\AnalyticsProviderTests\AnalyticsProviderFixture.cs" />
<Compile Include="ProviderTests\ConfigProviderTests\ConfigCachingFixture.cs" />
<Compile Include="ProviderTests\PlexProviderTest.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\RetentionSpecificationFixture.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\QualityAllowedByProfileSpecificationFixtrue.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\UpgradeHistorySpecificationFixtrue.cs" />

@ -0,0 +1,102 @@
// ReSharper disable RedundantUsingDirective
using System;
using System.IO;
using System.Linq;
using System.Text;
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Model.Xbmc;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Xbmc;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.AutoMoq;
namespace NzbDrone.Core.Test.ProviderTests
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class PlexProviderTest : CoreTest
{
[Test]
public void GetSectionKeys_should_return_single_section_key_when_only_one_show_section()
{
//Setup
var response = "<MediaContainer size=\"1\" mediaTagPrefix=\"/system/bundle/media/flags/\" mediaTagVersion=\"1329809559\" title1=\"Plex Library\" identifier=\"com.plexapp.plugins.library\"><Directory refreshing=\"0\" key=\"5\" type=\"show\" title=\"TV Shows\" art=\"/:/resources/show-fanart.jpg\" agent=\"com.plexapp.agents.thetvdb\" scanner=\"Plex Series Scanner\" language=\"en\" updatedAt=\"1329810350\"><Location path=\"C:/Test/TV\"/></Directory></MediaContainer>";
Stream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(response));
Mocker.GetMock<HttpProvider>().Setup(s => s.DownloadStream("http://localhost:32400/library/sections", null))
.Returns(stream);
//Act
var result = Mocker.Resolve<PlexProvider>().GetSectionKeys("localhost:32400");
//Assert
result.Should().HaveCount(1);
result.First().Should().Be(5);
}
[Test]
public void GetSectionKeys_should_return_single_section_key_when_only_one_show_section_with_other_sections()
{
//Setup
var response = "<MediaContainer size=\"1\" mediaTagPrefix=\"/system/bundle/media/flags/\" mediaTagVersion=\"1329809559\" title1=\"Plex Library\" identifier=\"com.plexapp.plugins.library\"><Directory refreshing=\"0\" key=\"5\" type=\"show\" title=\"TV Shows\" art=\"/:/resources/show-fanart.jpg\" agent=\"com.plexapp.agents.thetvdb\" scanner=\"Plex Series Scanner\" language=\"en\" updatedAt=\"1329810350\"><Location path=\"C:/Test/TV\"/></Directory><Directory refreshing=\"0\" key=\"7\" type=\"movie\" title=\"TV Shows\" art=\"/:/resources/show-fanart.jpg\" agent=\"com.plexapp.agents.thetvdb\" scanner=\"Plex Series Scanner\" language=\"en\" updatedAt=\"1329810350\"><Location path=\"C:/Test/TV\"/></Directory></MediaContainer>";
Stream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(response));
Mocker.GetMock<HttpProvider>().Setup(s => s.DownloadStream("http://localhost:32400/library/sections", null))
.Returns(stream);
//Act
var result = Mocker.Resolve<PlexProvider>().GetSectionKeys("localhost:32400");
//Assert
result.Should().HaveCount(1);
result.First().Should().Be(5);
}
[Test]
public void GetSectionKeys_should_return_multiple_section_keys_when_there_are_multiple_show_sections()
{
//Setup
var response = "<MediaContainer size=\"1\" mediaTagPrefix=\"/system/bundle/media/flags/\" mediaTagVersion=\"1329809559\" title1=\"Plex Library\" identifier=\"com.plexapp.plugins.library\"><Directory refreshing=\"0\" key=\"5\" type=\"show\" title=\"TV Shows\" art=\"/:/resources/show-fanart.jpg\" agent=\"com.plexapp.agents.thetvdb\" scanner=\"Plex Series Scanner\" language=\"en\" updatedAt=\"1329810350\"><Location path=\"C:/Test/TV\"/></Directory><Directory refreshing=\"0\" key=\"6\" type=\"show\" title=\"TV Shows\" art=\"/:/resources/show-fanart.jpg\" agent=\"com.plexapp.agents.thetvdb\" scanner=\"Plex Series Scanner\" language=\"en\" updatedAt=\"1329810350\"><Location path=\"C:/Test/TV\"/></Directory></MediaContainer>";
Stream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(response));
Mocker.GetMock<HttpProvider>().Setup(s => s.DownloadStream("http://localhost:32400/library/sections", null))
.Returns(stream);
//Act
var result = Mocker.Resolve<PlexProvider>().GetSectionKeys("localhost:32400");
//Assert
result.Should().HaveCount(2);
result.First().Should().Be(5);
result.Last().Should().Be(6);
}
[Test]
public void UpdateSection_should_update_section()
{
//Setup
var response = "";
Stream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(response));
Mocker.GetMock<HttpProvider>().Setup(s => s.DownloadString("http://localhost:32400/library/sections/5/refresh"))
.Returns(response);
//Act
Mocker.Resolve<PlexProvider>().UpdateSection("localhost:32400", 5);
//Assert
}
}
}

@ -140,6 +140,7 @@ namespace NzbDrone.Core
Kernel.Bind<ExternalNotificationBase>().To<Twitter>();
Kernel.Bind<ExternalNotificationBase>().To<Providers.ExternalNotification.Growl>();
Kernel.Bind<ExternalNotificationBase>().To<Prowl>();
Kernel.Bind<ExternalNotificationBase>().To<Plex>();
var notifiers = Kernel.GetAll<ExternalNotificationBase>();
Kernel.Get<ExternalNotificationProvider>().InitializeNotifiers(notifiers.ToList());

@ -240,7 +240,6 @@
<Compile Include="Helpers\SabnzbdQueueTimeConverter.cs" />
<Compile Include="Jobs\CheckpointJob.cs" />
<Compile Include="Model\DownloadClientType.cs" />
<Compile Include="Providers\AnalyticsProvider.cs" />
<Compile Include="Instrumentation\LogDbContext.cs" />
<Compile Include="Instrumentation\LogProvider.cs" />
<Compile Include="Instrumentation\DatabaseTarget.cs" />
@ -268,61 +267,20 @@
<Compile Include="Model\Xbmc\TvShowResult.cs" />
<Compile Include="Model\Xbmc\ErrorResult.cs" />
<Compile Include="Model\Xbmc\IconType.cs" />
<Compile Include="Providers\BackupProvider.cs" />
<Compile Include="Providers\DecisionEngine\AlreadyInQueueSpecification.cs" />
<Compile Include="Providers\DecisionEngine\RetentionSpecification.cs" />
<Compile Include="Providers\DownloadClients\BlackholeProvider.cs" />
<Compile Include="Providers\Converting\AtomicParsleyProvider.cs" />
<Compile Include="Providers\Converting\HandbrakeProvider.cs" />
<Compile Include="Providers\DownloadClients\IDownloadClient.cs" />
<Compile Include="Providers\DecisionEngine\AcceptableSizeSpecification.cs" />
<Compile Include="Providers\DecisionEngine\UpgradeHistorySpecification.cs" />
<Compile Include="Providers\DecisionEngine\UpgradeDiskSpecification.cs" />
<Compile Include="Providers\DecisionEngine\QualityUpgradeSpecification.cs" />
<Compile Include="Providers\DecisionEngine\QualityAllowedByProfileSpecification.cs" />
<Compile Include="Providers\DecisionEngine\AllowedDownloadSpecification.cs" />
<Compile Include="Providers\DecisionEngine\UpgradePossibleSpecification.cs" />
<Compile Include="Providers\DecisionEngine\MonitoredEpisodeSpecification.cs" />
<Compile Include="Providers\Indexer\Newznab.cs" />
<Compile Include="Jobs\RecentBacklogSearchJob.cs" />
<Compile Include="Jobs\TrimLogsJob.cs" />
<Compile Include="Jobs\JobProvider.cs" />
<Compile Include="Jobs\RenameSeasonJob.cs" />
<Compile Include="Jobs\RenameSeriesJob.cs" />
<Compile Include="Providers\NewznzbProvider.cs" />
<Compile Include="Providers\ExternalNotification\Prowl.cs" />
<Compile Include="Jobs\AppUpdateJob.cs" />
<Compile Include="Providers\ProwlProvider.cs" />
<Compile Include="Providers\Core\UdpProvider.cs" />
<Compile Include="Providers\ExternalNotification\Growl.cs" />
<Compile Include="Providers\ExternalNotification\Twitter.cs" />
<Compile Include="Providers\ExternalNotification\Smtp.cs" />
<Compile Include="Providers\GrowlProvider.cs" />
<Compile Include="Jobs\BacklogSearchJob.cs" />
<Compile Include="Jobs\BannerDownloadJob.cs" />
<Compile Include="Jobs\ConvertEpisodeJob.cs" />
<Compile Include="Jobs\SeriesSearchJob.cs" />
<Compile Include="Jobs\SeasonSearchJob.cs" />
<Compile Include="Providers\MisnamedProvider.cs" />
<Compile Include="Providers\PostDownloadProvider.cs" />
<Compile Include="Providers\QualityTypeProvider.cs" />
<Compile Include="Providers\ReferenceDataProvider.cs" />
<Compile Include="Providers\SearchProvider.cs" />
<Compile Include="Providers\SignalRProvider.cs" />
<Compile Include="Providers\SmtpProvider.cs" />
<Compile Include="Providers\TwitterProvider.cs" />
<Compile Include="Providers\UpdateProvider.cs" />
<Compile Include="Providers\Xbmc\ResourceManager.cs" />
<Compile Include="Model\Xbmc\TvShowResponse.cs" />
<Compile Include="Model\Xbmc\TvShow.cs" />
<Compile Include="Model\Xbmc\VersionResult.cs" />
<Compile Include="Providers\DiskScanProvider.cs" />
<Compile Include="Providers\DownloadProvider.cs" />
<Compile Include="Providers\ExternalNotification\ExternalNotificationBase.cs" />
<Compile Include="Providers\ExternalNotification\Xbmc.cs" />
<Compile Include="Providers\Indexer\SyndicationFeedXmlReader.cs" />
<Compile Include="Providers\AutoConfigureProvider.cs" />
<Compile Include="Providers\Indexer\NzbMatrix.cs" />
<Compile Include="Jobs\UpdateSceneMappingsJob.cs" />
<Compile Include="Jobs\PostDownloadScanJob.cs" />
<Compile Include="Jobs\RenameEpisodeJob.cs" />
@ -330,13 +288,202 @@
<Compile Include="Jobs\DeleteSeriesJob.cs" />
<Compile Include="Jobs\DiskScanJob.cs" />
<Compile Include="Jobs\ImportNewSeriesJob.cs" />
<Compile Include="Providers\Indexer\Newzbin.cs" />
<Compile Include="Providers\Indexer\NzbsRUs.cs" />
<Compile Include="Jobs\IJob.cs" />
<Compile Include="Jobs\RssSyncJob.cs" />
<Compile Include="Jobs\UpdateInfoJob.cs" />
<Compile Include="Providers\SceneMappingProvider.cs" />
<Compile Include="Providers\Xbmc\EventClientProvider.cs" />
<Compile Include="Providers\AnalyticsProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\AutoConfigureProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\BackupProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Converting\AtomicParsleyProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Converting\HandbrakeProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Core\ArchiveProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Core\ConfigProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Core\UdpProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DecisionEngine\AcceptableSizeSpecification.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DecisionEngine\AllowedDownloadSpecification.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DecisionEngine\AlreadyInQueueSpecification.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DecisionEngine\MonitoredEpisodeSpecification.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DecisionEngine\QualityAllowedByProfileSpecification.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DecisionEngine\QualityUpgradeSpecification.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DecisionEngine\RetentionSpecification.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DecisionEngine\UpgradeDiskSpecification.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DecisionEngine\UpgradeHistorySpecification.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DecisionEngine\UpgradePossibleSpecification.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DiskScanProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DownloadClients\BlackholeProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DownloadClients\IDownloadClient.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DownloadClients\SabProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\DownloadProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\EpisodeProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\ExternalNotificationProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\ExternalNotification\ExternalNotificationBase.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\ExternalNotification\Growl.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\ExternalNotification\Plex.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\ExternalNotification\Prowl.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\ExternalNotification\Smtp.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\ExternalNotification\Twitter.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\ExternalNotification\Xbmc.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\GrowlProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\HistoryProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\IndexerProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Indexer\IndexerBase.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Indexer\Newzbin.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Indexer\Newznab.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Indexer\NzbMatrix.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Indexer\NzbsOrg.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Indexer\NzbsRUs.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Indexer\SyndicationFeedXmlReader.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\MediaFileProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\MisnamedProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\NewznzbProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\NotificationProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\PlexProvider.cs" />
<Compile Include="Providers\PostDownloadProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\ProwlProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\QualityProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\QualityTypeProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\ReferenceDataProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\RootDirProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\SceneMappingProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\SearchProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\SeriesProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\SignalRProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\SmtpProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\TvDbProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\TwitterProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\UpcomingEpisodesProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\UpdateProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\XbmcProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Xbmc\EventClientProvider.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Providers\Xbmc\ResourceManager.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Repository\NewznabDefinition.cs" />
<Compile Include="Repository\ExternalNotificationDefinition.cs" />
<Compile Include="Repository\JobDefinition.cs" />
@ -346,24 +493,10 @@
<Compile Include="Model\EpisodeStatusType.cs" />
<Compile Include="Model\Sabnzbd\SabPriorityType.cs" />
<Compile Include="Model\SeasonParseResult.cs" />
<Compile Include="Providers\Indexer\IndexerBase.cs" />
<Compile Include="Providers\ExternalNotificationProvider.cs" />
<Compile Include="Providers\Indexer\NzbsOrg.cs" />
<Compile Include="Providers\HistoryProvider.cs" />
<Compile Include="Providers\IndexerProvider.cs" />
<Compile Include="Providers\QualityProvider.cs" />
<Compile Include="Providers\RootDirProvider.cs" />
<Compile Include="Providers\UpcomingEpisodesProvider.cs" />
<Compile Include="Providers\XbmcProvider.cs" />
<Compile Include="Repository\EpisodeFile.cs" />
<Compile Include="Model\Notification\ProgressNotificationStatus.cs" />
<Compile Include="Parser.cs" />
<Compile Include="Providers\MediaFileProvider.cs" />
<Compile Include="Model\Notification\ProgressNotification.cs" />
<Compile Include="Providers\NotificationProvider.cs" />
<Compile Include="Providers\Core\ConfigProvider.cs" />
<Compile Include="Providers\EpisodeProvider.cs" />
<Compile Include="Providers\DownloadClients\SabProvider.cs" />
<Compile Include="Repository\Episode.cs" />
<Compile Include="Instrumentation\Log.cs" />
<Compile Include="Repository\History.cs" />
@ -376,9 +509,6 @@
<Compile Include="Repository\Series.cs" />
<Compile Include="CentralDispatch.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Providers\Core\ArchiveProvider.cs" />
<Compile Include="Providers\SeriesProvider.cs" />
<Compile Include="Providers\TvDbProvider.cs" />
<Compile Include="WebTimer.cs" />
</ItemGroup>
<ItemGroup>

@ -442,6 +442,51 @@ namespace NzbDrone.Core.Providers.Core
get { return "http://services.nzbdrone.com"; }
}
public virtual Boolean PlexNotifyOnGrab
{
get { return GetValueBoolean("PlexNotifyOnGrab"); }
set { SetValue("PlexNotifyOnGrab", value); }
}
public virtual Boolean PlexNotifyOnDownload
{
get { return GetValueBoolean("PlexNotifyOnDownload"); }
set { SetValue("PlexNotifyOnDownload", value); }
}
public virtual Boolean PlexUpdateLibrary
{
get { return GetValueBoolean("PlexUpdateLibrary"); }
set { SetValue("PlexUpdateLibrary", value); }
}
public virtual string PlexServerHost
{
get { return GetValue("PlexServerHost", "localhost:32400"); }
set { SetValue("PlexServerHost", value); }
}
public virtual string PlexClientHosts
{
get { return GetValue("PlexClientHosts", "localhost:3000"); }
set { SetValue("PlexClientHosts", value); }
}
public virtual string PlexUsername
{
get { return GetValue("PlexUsername"); }
set { SetValue("PlexUsername", value); }
}
public virtual string PlexPassword
{
get { return GetValue("PlexPassword"); }
set { SetValue("PlexPassword", value); }
}
private string GetValue(string key)
{
return GetValue(key, String.Empty);

@ -0,0 +1,66 @@
using System;
using NLog;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers.ExternalNotification
{
public class Plex : ExternalNotificationBase
{
private readonly PlexProvider _plexProvider;
public Plex(ConfigProvider configProvider, PlexProvider plexProvider)
: base(configProvider)
{
_plexProvider = plexProvider;
}
public override string Name
{
get { return "Plex"; }
}
public override void OnGrab(string message)
{
const string header = "NzbDrone [TV] - Grabbed";
if (_configProvider.PlexNotifyOnGrab)
{
_logger.Trace("Sending Notification to Plex Clients");
_plexProvider.Notify(header, message);
}
}
public override void OnDownload(string message, Series series)
{
const string header = "NzbDrone [TV] - Downloaded";
if (_configProvider.PlexNotifyOnDownload)
{
_logger.Trace("Sending Notification to Plex Clients");
_plexProvider.Notify(header, message);
}
UpdateIfEnabled();
}
public override void OnRename(string message, Series series)
{
}
public override void AfterRename(string message, Series series)
{
UpdateIfEnabled();
}
private void UpdateIfEnabled()
{
if (_configProvider.PlexUpdateLibrary)
{
_logger.Trace("Sending Update Request to Plex Server");
_plexProvider.UpdateLibrary();
}
}
}
}

@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using NLog;
using Ninject;
using NzbDrone.Common;
using NzbDrone.Core.Providers.Core;
namespace NzbDrone.Core.Providers
{
public class PlexProvider
{
private readonly HttpProvider _httpProvider;
private readonly ConfigProvider _configProvider;
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
[Inject]
public PlexProvider(HttpProvider httpProvider, ConfigProvider configProvider)
{
_httpProvider = httpProvider;
_configProvider = configProvider;
}
public PlexProvider()
{
}
public virtual void Notify(string header, string message)
{
//Foreach plex client send a notification
foreach(var host in _configProvider.PlexClientHosts.Split(','))
{
try
{
var command = String.Format("ExecBuiltIn(Notification({0}, {1}))", header, message);
SendCommand(host, command, _configProvider.PlexUsername, _configProvider.PlexPassword);
}
catch(Exception ex)
{
logger.WarnException("Failed to send notification to Plex Client: " + host, ex);
}
}
}
public virtual void UpdateLibrary()
{
var host = _configProvider.PlexServerHost;
try
{
var sections = GetSectionKeys(host);
sections.ForEach(s => UpdateSection(host, s));
}
catch(Exception ex)
{
logger.WarnException("Failed to Update Plex host: " + host, ex);
throw;
}
}
public List<int> GetSectionKeys(string host)
{
logger.Trace("Getting sections from Plex host: {0}", host);
var url = String.Format("http://{0}/library/sections", host);
var xmlStream = _httpProvider.DownloadStream(url, null);
var xDoc = XDocument.Load(xmlStream);
var mediaContainer = xDoc.Descendants("MediaContainer").FirstOrDefault();
var directories = mediaContainer.Descendants("Directory").Where(x => x.Attribute("type").Value == "show");
return directories.Select(d => Int32.Parse(d.Attribute("key").Value)).ToList();
}
public void UpdateSection(string host, int key)
{
logger.Trace("Updating Plex host: {0}, Section: {1}", host, key);
var url = String.Format("http://{0}/library/sections/{1}/refresh", host, key);
_httpProvider.DownloadString(url);
}
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);
}
}
}

@ -180,7 +180,15 @@ namespace NzbDrone.Web.Controllers
ProwlNotifyOnDownload = _configProvider.ProwlNotifyOnDownload,
ProwlApiKeys = _configProvider.ProwlApiKeys,
ProwlPriority = _configProvider.ProwlPriority,
ProwlPrioritySelectList = GetProwlPrioritySelectList()
ProwlPrioritySelectList = GetProwlPrioritySelectList(),
PlexEnabled = _externalNotificationProvider.GetSettings(typeof(Plex)).Enable,
PlexNotifyOnGrab = _configProvider.PlexNotifyOnGrab,
PlexNotifyOnDownload = _configProvider.PlexNotifyOnDownload,
PlexUpdateLibrary = _configProvider.PlexUpdateLibrary,
PlexServerHost = _configProvider.PlexServerHost,
PlexClientHosts = _configProvider.PlexClientHosts,
PlexUsername = _configProvider.PlexUsername,
PlexPassword = _configProvider.PlexPassword,
};
return View(model);
@ -530,6 +538,19 @@ namespace NzbDrone.Web.Controllers
_configProvider.ProwlApiKeys = data.ProwlApiKeys;
_configProvider.ProwlPriority = data.ProwlPriority;
//Plex
var plexSettings = _externalNotificationProvider.GetSettings(typeof(Plex));
plexSettings.Enable = data.PlexEnabled;
_externalNotificationProvider.SaveSettings(plexSettings);
_configProvider.PlexNotifyOnGrab = data.PlexNotifyOnGrab;
_configProvider.PlexNotifyOnDownload = data.PlexNotifyOnDownload;
_configProvider.PlexUpdateLibrary = data.PlexUpdateLibrary;
_configProvider.PlexServerHost = data.PlexServerHost;
_configProvider.PlexClientHosts = data.PlexClientHosts;
_configProvider.PlexUsername = data.PlexUsername;
_configProvider.PlexPassword = data.PlexPassword;
return GetSuccessResult();
}

@ -164,5 +164,46 @@ namespace NzbDrone.Web.Models
public int ProwlPriority { get; set; }
public SelectList ProwlPrioritySelectList { get; set; }
//Plex
[DisplayName("Enabled")]
[Description("Enable notifications for Plex?")]
public bool PlexEnabled { get; set; }
[DisplayName("Notify on Grab")]
[Description("Send notification when episode is sent to SABnzbd?")]
public bool PlexNotifyOnGrab { get; set; }
[DisplayName("Notify on Download")]
[Description("Send notification when episode is downloaded?")]
public bool PlexNotifyOnDownload { get; set; }
[DisplayName("Update on Download and Rename")]
[Description("Update Plex library after episode is downloaded or renamed?")]
public bool PlexUpdateLibrary { get; set; }
[DataType(DataType.Text)]
[DisplayName("Server Host")]
[Description("Plex Server host with port")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string PlexServerHost { get; set; }
[DataType(DataType.Text)]
[DisplayName("Client Hosts")]
[Description("Plex client hosts with port, comma separated for multiple clients")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string PlexClientHosts { get; set; }
[DataType(DataType.Text)]
[DisplayName("Username")]
[Description("Plex client webserver username")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string PlexUsername { get; set; }
[DataType(DataType.Text)]
[DisplayName("Password")]
[Description("Plex client webserver password")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string PlexPassword { get; set; }
}
}

@ -498,6 +498,7 @@
</ItemGroup>
<ItemGroup>
<None Include="Content\DataTables-1.9.0\media\images\Sorting icons.psd" />
<Content Include="Views\Settings\Plex.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

@ -34,21 +34,23 @@
@using (Html.BeginForm("SaveNotifications", "Settings", FormMethod.Post, new { id = "NotificationForm", name = "NotificationForm", @class = "settingsForm" }))
{
<div class="jquery-accordion">
<h3>
<a href="#">XBMC</a></h3>
<h3><a href="#">XBMC</a></h3>
@{Html.RenderPartial("Xbmc", Model);}
<h3>
<a href="#">SMTP</a></h3>
<h3><a href="#">SMTP</a></h3>
@{Html.RenderPartial("Smtp", Model);}
<h3>
<a href="#">Twitter</a></h3>
<h3><a href="#">Twitter</a></h3>
@{Html.RenderPartial("Twitter", Model);}
<h3>
<a href="#">Growl</a></h3>
<h3><a href="#">Growl</a></h3>
@{Html.RenderPartial("Growl", Model);}
<h3>
<a href="#">Prowl</a></h3>
<h3><a href="#">Prowl</a></h3>
@{Html.RenderPartial("Prowl", Model);}
<h3><a href="#">Plex</a></h3>
@{Html.RenderPartial("Plex", Model);}
</div>
<button type="submit" class="save_button" disabled="disabled">

@ -0,0 +1,48 @@
@using NzbDrone.Web.Helpers
@model NzbDrone.Web.Models.NotificationSettingsModel
@{
Layout = null;
}
<div class="notifier">
<label class="labelClass">@Html.LabelFor(m => m.PlexEnabled)
<span class="small">@Html.DescriptionFor(m => m.PlexEnabled)</span>
</label>
@Html.CheckBoxFor(m => m.PlexEnabled, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.PlexNotifyOnGrab)
<span class="small">@Html.DescriptionFor(m => m.PlexNotifyOnGrab)</span>
</label>
@Html.CheckBoxFor(m => m.PlexNotifyOnGrab, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.PlexNotifyOnDownload)
<span class="small">@Html.DescriptionFor(m => m.PlexNotifyOnDownload)</span>
</label>
@Html.CheckBoxFor(m => m.PlexNotifyOnDownload, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.PlexUpdateLibrary)
<span class="small">@Html.DescriptionFor(m => m.PlexUpdateLibrary)</span>
</label>
@Html.CheckBoxFor(m => m.PlexUpdateLibrary, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.PlexServerHost)
<span class="small">@Html.DescriptionFor(m => m.PlexServerHost)</span>
</label>
@Html.TextBoxFor(m => m.PlexServerHost, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.PlexClientHosts)
<span class="small">@Html.DescriptionFor(m => m.PlexClientHosts)</span>
</label>
@Html.TextBoxFor(m => m.PlexClientHosts, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.PlexUsername)
<span class="small">@Html.DescriptionFor(m => m.PlexUsername)</span>
</label>
@Html.TextBoxFor(m => m.PlexUsername, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.PlexPassword)
<span class="small">@Html.DescriptionFor(m => m.PlexPassword)</span>
</label>
@Html.TextBoxFor(m => m.PlexPassword, new { @class = "inputClass", type = "password" })
</div>
Loading…
Cancel
Save