Add support for multiple server hosts to Plex server notifier.

Add support for multiple server hosts to the updated Plex server notifier.
Change Plex Media Server settings section for multi server(s) and improve the layout in the config/notifications page.
Add logic to Plex notifier to update a single server where its TV section path matches the downloaded show. All server libraries are updated if no single server has a download path match.
Change the ui notifications to show the Plex Media Server(s) actioned for library updating.
Fix issue where PMS text wasn't initialised on the config/notifications page and added info about Plex clients.
Add ability to test Plex Server(s) on config/notifications page.
This commit is contained in:
JackDandy 2015-02-14 02:28:24 +00:00
parent b8a4afc923
commit 47f1c8eaaf
6 changed files with 289 additions and 194 deletions

View file

@ -40,6 +40,13 @@
* Add sound selection for boxcar2 notifier
* Change boxcar2 notifier to use updated api scheme
* Update the Plex notifier from a port at midgetspy/sickbeard
* Add support for multiple server hosts to the updated Plex server notifier
* Change Plex Media Server settings section for multi server(s) and improve the layout in the config/notifications page
* Add logic to Plex notifier to update a single server where its TV section path matches the downloaded show. All server
libraries are updated if no single server has a download path match.
* Change the ui notifications to show the Plex Media Server(s) actioned for library updating
* Fix issue where PMS text wasn't initialised on the config/notifications page and added info about Plex clients
* Add ability to test Plex Server(s) on config/notifications page
[develop changelog]
* Change uT params from unicode to str.format as magnet URLs worked but sending files in POST bodies failed

View file

@ -1,4 +1,5 @@
#import sickbeard
#import re
#from sickbeard.helpers import anon_url
#set global $title = 'Config - Notifications'
@ -30,7 +31,7 @@
<div id="tabs-1">
<div class="component-group">
<div class="component-group-desc">
<img class="notifier-icon" src="$sbRoot/images/notifiers/xbmc.png" alt="" title="XBMC" />
<h3><a href="<%= anon_url('http://kodi.tv/') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">XBMC</a></h3>
@ -110,7 +111,7 @@
<p>only send library updates to the first active host ?</p>
</span>
</label>
</div>
</div>
<div class="field-pair">
<label for="xbmc_host">
<span class="component-title">XBMC IP:Port</span>
@ -123,7 +124,7 @@
<label>
<span class="component-title">&nbsp;</span>
<span class="component-desc">(multiple host strings must be separated by commas)</span>
</label>
</label>
</div>
<div class="field-pair">
<label for="xbmc_username">
@ -151,7 +152,7 @@
</div><!-- /content_use_xbmc //-->
</fieldset>
</div><!-- /xbmc component-group //-->
@ -160,103 +161,120 @@
<img class="notifier-icon" src="$sbRoot/images/notifiers/plex.png" alt="" title="Plex Media Server" />
<h3><a href="<%= anon_url('http://www.plexapp.com/') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">Plex Media Server</a></h3>
<p>Plex organizes all of your personal media, wherever you keep it, so you can enjoy it on any device</p>
<p class="plexinfo hide">For sending notifications to Plex Home Theater (PHT) clients, use the XBMC notifier with port <b>3005</b>.</p>
<p class="plexinfo hide"><span class="red-text">To send notifications to <span class="boldest">Plex Home Theater (PHT) clients</span>,</span> use the XBMC notifier with port <b>3005</b>.</p>
</div>
<fieldset class="component-group-list">
<div class="field-pair">
<label for="use_plex">
<span class="component-title">Enable</span>
<span class="component-desc">
<input type="checkbox" class="enabler" name="use_plex" id="use_plex" #if $sickbeard.USE_PLEX then "checked=\"checked\"" else ""# />
<input type="checkbox" class="enabler" name="use_plex" id="use_plex" #if $sickbeard.USE_PLEX then 'checked="checked" ' else ''# />
<p>should SickGear send Plex commands ?</p>
</span>
</label>
</div>
<div id="content_use_plex">
<div class="field-pair">
<label for="plex_notify_onsnatch">
<span class="component-title">Notify on snatch</span>
<span class="component-desc">
<input type="checkbox" name="plex_notify_onsnatch" id="plex_notify_onsnatch" #if $sickbeard.PLEX_NOTIFY_ONSNATCH then "checked=\"checked\"" else ""# />
<p>send a notification when a download starts ?</p>
</span>
</label>
<div class="component-group" style="padding: 0; min-height: 130px">
<div class="field-pair">
<label for="plex_username">
<span class="component-title">Server/client username</span>
<span class="component-desc">
<input type="text" name="plex_username" id="plex_username" value="$sickbeard.PLEX_USERNAME" class="form-control input-sm input250" />
<p>blank = no authentication</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="plex_password">
<span class="component-title">Server/client password</span>
<span class="component-desc">
<input type="password" name="plex_password" id="plex_password" value="$sickbeard.PLEX_PASSWORD" class="form-control input-sm input250" />
<p>blank = no authentication</p>
</span>
</label>
</div>
</div>
<div class="field-pair">
<label for="plex_notify_ondownload">
<span class="component-title">Notify on download</span>
<span class="component-desc">
<input type="checkbox" name="plex_notify_ondownload" id="plex_notify_ondownload" #if $sickbeard.PLEX_NOTIFY_ONDOWNLOAD then "checked=\"checked\"" else ""# />
<p>send a notification when a download finishes ?</p>
</span>
</label>
<div class="component-group" style="padding: 0; min-height: 50px">
<div class="field-pair">
<label for="plex_update_library">
<span class="component-title">Update server library</span>
<span class="component-desc">
<input type="checkbox" class="enabler" name="plex_update_library" id="plex_update_library" #if $sickbeard.PLEX_UPDATE_LIBRARY then 'checked="checked" ' else ''#/>
<p>update Plex Media Server library when a download finishes</p>
</span>
</label>
</div>
<div id="content_plex_update_library">
<div class="field-pair">
<label for="plex_server_host">
<span class="component-title">Plex Media Server IP:Port</span>
<span class="component-desc">
<input type="text" name="plex_server_host" id="plex_server_host" value="<%= re.sub(r'\b,\b', ', ', sickbeard.PLEX_SERVER_HOST) %>" class="form-control input-sm input350" />
<div class="clear-left">
<p>one or more hosts running Plex Media Server<br />(eg. 192.168.1.1:32400, 192.168.1.2:32400)</p>
</div>
</span>
</label>
</div>
<div class="field-pair">
<div class="testNotification" id="testPMS-result">Click below to test Plex server(s)</div>
<input class="btn" type="button" value="Test Plex Server" id="testPMS" />
<input type="submit" class="config_submitter btn" value="Save Changes" />
<div class="clear-left">&nbsp;</div>
</div>
</div>
</div>
<div class="field-pair">
<label for="plex_notify_onsubtitledownload">
<span class="component-title">Notify on subtitle download</span>
<span class="component-desc">
<input type="checkbox" name="plex_notify_onsubtitledownload" id="plex_notify_onsubtitledownload" #if $sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD then "checked=\"checked\"" else ""# />
<p>send a notification when subtitles are downloaded ?</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="plex_update_library">
<span class="component-title">Update library</span>
<span class="component-desc">
<input type="checkbox" name="plex_update_library" id="plex_update_library" #if $sickbeard.PLEX_UPDATE_LIBRARY then "checked=\"checked\"" else ""# />
<p>update Plex Media Server library when a download finishes ?</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="plex_server_host">
<span class="component-title">Plex Media Server IP:Port</span>
<input type="text" name="plex_server_host" id="plex_server_host" value="$sickbeard.PLEX_SERVER_HOST" class="form-control input-sm input250" />
</label>
<label>
<span class="component-title">&nbsp;</span>
<span class="component-desc">host running Plex Media Server (eg. 192.168.1.100:32400)</span>
</label>
</div>
<div class="field-pair">
<label for="plex_host">
<span class="component-title">Plex client IP:Port</span>
<input type="text" name="plex_host" id="plex_host" value="$sickbeard.PLEX_HOST" class="form-control input-sm input350" />
</label>
<label>
<span class="component-title">&nbsp;</span>
<span class="component-desc">host running Plex client (eg. 192.168.1.100:3000)</span>
</label>
<label>
<span class="component-title">&nbsp;</span>
<span class="component-desc">(multiple host strings must be separated by commas)</span>
</label>
</div>
<div class="field-pair">
<label for="plex_username">
<span class="component-title">Plex client username</span>
<input type="text" name="plex_username" id="plex_username" value="$sickbeard.PLEX_USERNAME" class="form-control input-sm input250" />
</label>
<label>
<span class="component-title">&nbsp;</span>
<span class="component-desc">needed if your client / server requires authentication (blank for none)</span>
</label>
</div>
<div class="field-pair">
<label for="plex_password">
<span class="component-title">Plex client password</span>
<input type="password" name="plex_password" id="plex_password" value="$sickbeard.PLEX_PASSWORD" class="form-control input-sm input250" />
</label>
<label>
<span class="component-title">&nbsp;</span>
<span class="component-desc">needed if your client / server requires authentication (blank for none)</span>
</label>
</div>
<div class="testNotification" id="testPLEX-result">Click below to test.</div>
<input class="btn" type="button" value="Test Plex Client" id="testPLEX" />
<input type="submit" class="config_submitter btn" value="Save Changes" />
<div>
<div class="field-pair">
<label for="plex_notify_onsnatch">
<span class="component-title">Notify on snatch</span>
<span class="component-desc">
<input type="checkbox" name="plex_notify_onsnatch" id="plex_notify_onsnatch" #if $sickbeard.PLEX_NOTIFY_ONSNATCH then "checked=\"checked\"" else ""# />
<p>download start notification</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="plex_notify_ondownload">
<span class="component-title">Notify on download</span>
<span class="component-desc">
<input type="checkbox" name="plex_notify_ondownload" id="plex_notify_ondownload" #if $sickbeard.PLEX_NOTIFY_ONDOWNLOAD then "checked=\"checked\"" else ""# />
<p>download finish notification</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="plex_notify_onsubtitledownload">
<span class="component-title">Notify on subtitle download</span>
<span class="component-desc">
<input type="checkbox" name="plex_notify_onsubtitledownload" id="plex_notify_onsubtitledownload" #if $sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD then "checked=\"checked\"" else ""# />
<p>subtitle downloaded notification</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="plex_host">
<span class="component-title">Plex client IP:Port</span>
<span class="component-desc">
<input type="text" name="plex_host" id="plex_host" value="<%= re.sub(r'\b,\b', ', ', sickbeard.PLEX_HOST) %>" class="form-control input-sm input350" />
<div class="clear-left">
<p>one or more hosts running Plex client<br />(eg. 192.168.1.100:3000, 192.168.1.101:3000)</p>
</div>
</span>
</label>
</div>
<div class="field-pair">
<div class="testNotification" id="testPMC-result">Click below to test Plex client(s)</div>
<input class="btn" type="button" value="Test Plex Client" id="testPMC" />
<input type="submit" class="config_submitter btn" value="Save Changes" />
<div class=clear-left><p>Note: some Plex clients <b class="boldest">do not</b> support notifications e.g. Plexapp for Samsung TVs</p></div>
</div>
</div><!-- /plex component-group -->
</div><!-- /content_use_plex -->
</fieldset>
@ -365,9 +383,9 @@
</label>
<label for="NMJV2_DBLOC_B">
<input type="radio" NAME="nmjv2_dbloc" VALUE="network" id="NMJV2_DBLOC_B" #if $sickbeard.NMJv2_DBLOC=="network" then "checked=\"checked\"" else ""#/>PCH Network Media
</label>
</label>
</span>
</div>
</div>
<div class="field-pair">
<label for="NMJv2db_instance">
<span class="component-title">Database instance</span>
@ -415,7 +433,7 @@
</fieldset>
</div><!-- /nmjv2 component-group //-->
<div class="component-group">
<div class="component-group-desc">
@ -430,7 +448,7 @@
<label for="use_synoindex">
<span class="component-title">Enable</span>
<span class="component-desc">
<input type="checkbox" class="enabler" name="use_synoindex" id="use_synoindex" #if $sickbeard.USE_SYNOINDEX then "checked=\"checked\"" else ""# />
<input type="checkbox" class="enabler" name="use_synoindex" id="use_synoindex" #if $sickbeard.USE_SYNOINDEX then "checked=\"checked\"" else ""# />
<p>should SickGear send Synology notifications ?</p>
</span>
</label>
@ -446,8 +464,8 @@
</fieldset>
</div><!-- /synoindex component-group //-->
<div class="component-group">
<div class="component-group-desc">
<img class="notifier-icon" src="$sbRoot/images/notifiers/synologynotifier.png" alt="" title="Synology Indexer" />
@ -563,7 +581,7 @@
</div>
<div id="tabs-2">
<div class="component-group">
<div class="component-group-desc">
@ -576,7 +594,7 @@
<label for="use_growl">
<span class="component-title">Enable</span>
<span class="component-desc">
<input type="checkbox" class="enabler" name="use_growl" id="use_growl" #if $sickbeard.USE_GROWL then "checked=\"checked\"" else ""# />
<input type="checkbox" class="enabler" name="use_growl" id="use_growl" #if $sickbeard.USE_GROWL then "checked=\"checked\"" else ""# />
<p>should SickGear send Growl notifications ?</p>
</span>
</label>
@ -587,7 +605,7 @@
<label for="growl_notify_onsnatch">
<span class="component-title">Notify on snatch</span>
<span class="component-desc">
<input type="checkbox" name="growl_notify_onsnatch" id="growl_notify_onsnatch" #if $sickbeard.GROWL_NOTIFY_ONSNATCH then "checked=\"checked\"" else ""# />
<input type="checkbox" name="growl_notify_onsnatch" id="growl_notify_onsnatch" #if $sickbeard.GROWL_NOTIFY_ONSNATCH then "checked=\"checked\"" else ""# />
<p>send a notification when a download starts ?</p>
</span>
</label>
@ -1172,7 +1190,7 @@
</div><!-- /pushbullet component-group //-->
</div>
<div id="tabs-3">
<div class="component-group">
<div class="component-group-desc">
@ -1350,7 +1368,7 @@
<span class="component-title">&nbsp;</span>
<span class="component-desc">method in which to download episodes for new show's.</span>
</label>
</div>
</div>
<div class="field-pair">
<label for="trakt_remove_watchlist">
<span class="component-title">Remove episode:</span>
@ -1359,8 +1377,8 @@
<p>remove an episode from your watchlist after it is downloaded.</p>
</span>
</label>
</div>
<div class="field-pair">
</div>
<div class="field-pair">
<label for="trakt_remove_serieslist">
<span class="component-title">Remove series:</span>
<span class="component-desc">

View file

@ -56,22 +56,41 @@ $(document).ready(function(){
});
});
$('#testPLEX').click(function () {
$('#testPMC').click(function () {
var plex_host = $.trim($('#plex_host').val());
var plex_username = $.trim($('#plex_username').val());
var plex_password = $.trim($('#plex_password').val());
if (!plex_host) {
$('#testPLEX-result').html('Please fill out the necessary fields above.');
$('#testPMC-result').html('Please fill out the necessary fields above.');
$('#plex_host').addClass('warning');
return;
}
$('#plex_host').removeClass('warning');
$(this).prop('disabled', true);
$('#testPLEX-result').html(loading);
$.get(sbRoot + '/home/testPLEX', {'host': plex_host, 'username': plex_username, 'password': plex_password})
$('#testPMC-result').html(loading);
$.get(sbRoot + '/home/testPMC', {'host': plex_host, 'username': plex_username, 'password': plex_password})
.done(function (data) {
$('#testPLEX-result').html(data);
$('#testPLEX').prop('disabled', false);
$('#testPMC-result').html(data);
$('#testPMC').prop('disabled', false);
});
});
$('#testPMS').click(function () {
var plex_server_host = $.trim($('#plex_server_host').val());
var plex_username = $.trim($('#plex_username').val());
var plex_password = $.trim($('#plex_password').val());
if (!plex_server_host) {
$('#testPMS-result').html('Please fill out the necessary fields above.');
$('#plex_server_host').addClass('warning');
return;
}
$('#plex_server_host').removeClass('warning');
$(this).prop('disabled', true);
$('#testPMS-result').html(loading);
$.get(sbRoot + '/home/testPMS', {'host': plex_server_host, 'username': plex_username, 'password': plex_password})
.done(function (data) {
$('#testPMS-result').html(data);
$('#testPMS').prop('disabled', false);
});
});
@ -158,7 +177,7 @@ $(document).ready(function(){
}
$('#testNMJ-result').html(loading);
var nmj_host = $('#nmj_host').val();
$.get(sbRoot + '/home/settingsNMJ', {'host': nmj_host},
function (data) {
if (data === null) {
@ -220,7 +239,7 @@ $(document).ready(function(){
}
var nmjv2_dbinstance=$('#NMJv2db_instance').val();
$.get(sbRoot + '/home/settingsNMJv2', {'host': nmjv2_host,'dbloc': nmjv2_dbloc,'instance': nmjv2_dbinstance},
$.get(sbRoot + '/home/settingsNMJv2', {'host': nmjv2_host,'dbloc': nmjv2_dbloc,'instance': nmjv2_dbinstance},
function (data){
if (data == null) {
$('#nmjv2_database').removeAttr('readonly');
@ -228,7 +247,7 @@ $(document).ready(function(){
var JSONData = $.parseJSON(data);
$('#testNMJv2-result').html(JSONData.message);
$('#nmjv2_database').val(JSONData.database);
if (JSONData.database)
$('#nmjv2_database').attr('readonly', true);
else
@ -379,7 +398,7 @@ $(document).ready(function(){
if(msg){
$('#testPushbullet-result').html(loading);
}
var pushbullet_api = $("#pushbullet_api").val();
if(!pushbullet_api) {
@ -417,7 +436,7 @@ $(document).ready(function(){
$('#getPushbulletDevices').click(function(){
get_pushbullet_devices("Device list updated. Please choose a device to push to.");
});
// we have to call this function on dom ready to create the devices select
get_pushbullet_devices();
@ -458,5 +477,5 @@ $(document).ready(function(){
$('.plexinfo').addClass('hide');
}
});
if ($('input[id="use_plex"]').is(':checked')) {$('.plexinfo').removeClass('hide')}
});

View file

@ -19,6 +19,7 @@
import urllib
import urllib2
import base64
import re
import sickbeard
@ -56,7 +57,7 @@ class PLEXNotifier:
password = sickbeard.PLEX_PASSWORD
if not host:
logger.log(u"PLEX: No host specified, check your settings", logger.ERROR)
logger.log(u'PLEX: No host specified, check your settings', logger.ERROR)
return False
for key in command:
@ -64,7 +65,7 @@ class PLEXNotifier:
command[key] = command[key].encode('utf-8')
enc_command = urllib.urlencode(command)
logger.log(u"PLEX: Encoded API command: " + enc_command, logger.DEBUG)
logger.log(u'PLEX: Encoded API command: ' + enc_command, logger.DEBUG)
url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command)
try:
@ -72,26 +73,26 @@ class PLEXNotifier:
# if we have a password, use authentication
if password:
base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
authheader = "Basic %s" % base64string
req.add_header("Authorization", authheader)
logger.log(u"PLEX: Contacting (with auth header) via url: " + url, logger.DEBUG)
authheader = 'Basic %s' % base64string
req.add_header('Authorization', authheader)
logger.log(u'PLEX: Contacting (with auth header) via url: ' + url, logger.DEBUG)
else:
logger.log(u"PLEX: Contacting via url: " + url, logger.DEBUG)
logger.log(u'PLEX: Contacting via url: ' + url, logger.DEBUG)
response = urllib2.urlopen(req)
result = response.read().decode(sickbeard.SYS_ENCODING)
response.close()
logger.log(u"PLEX: HTTP response: " + result.replace('\n', ''), logger.DEBUG)
logger.log(u'PLEX: HTTP response: ' + result.replace('\n', ''), logger.DEBUG)
# could return result response = re.compile('<html><li>(.+\w)</html>').findall(result)
return 'OK'
except (urllib2.URLError, IOError), e:
logger.log(u"PLEX: Warning: Couldn't contact Plex at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING)
logger.log(u'PLEX: Warning: Couldn\'t contact Plex at ' + fixStupidEncodings(url) + ' ' + ex(e), logger.WARNING)
return False
def _notify_pmc(self, message, title="SickGear", host=None, username=None, password=None, force=False):
def _notify_pmc(self, message, title='SickGear', host=None, username=None, password=None, force=False):
"""Internal wrapper for the notify_snatch and notify_download functions
Args:
@ -121,13 +122,13 @@ class PLEXNotifier:
password = sickbeard.PLEX_PASSWORD
result = ''
for curHost in [x.strip() for x in host.split(",")]:
logger.log(u"PLEX: Sending notification to '" + curHost + "' - " + message, logger.MESSAGE)
for curHost in [x.strip() for x in host.split(',')]:
logger.log(u'PLEX: Sending notification to \'%s\' - %s' % (curHost, message), logger.MESSAGE)
command = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' + title.encode("utf-8") + ',' + message.encode("utf-8") + ')'}
notifyResult = self._send_to_plex(command, curHost, username, password)
if notifyResult:
result += curHost + ':' + str(notifyResult)
command = {'command': 'ExecBuiltIn', 'parameter': 'Notification(%s,%s)' % (title.encode('utf-8'), message.encode('utf-8'))}
notify_result = self._send_to_plex(command, curHost, username, password)
if notify_result:
result += '%s:%s' % (curHost, str(notify_result))
return result
@ -145,89 +146,124 @@ class PLEXNotifier:
def notify_subtitle_download(self, ep_name, lang):
if sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD:
self._notify_pmc(ep_name + ": " + lang, common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD])
self._notify_pmc(ep_name + ': ' + lang, common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD])
def notify_git_update(self, new_version="??"):
def notify_git_update(self, new_version='??'):
if sickbeard.USE_PLEX:
update_text = common.notifyStrings[common.NOTIFY_GIT_UPDATE_TEXT]
title = common.notifyStrings[common.NOTIFY_GIT_UPDATE]
self._notify_pmc(update_text + new_version, title)
def test_notify(self, host, username, password):
return self._notify_pmc("This is a test notification from SickGear", "Test", host, username, password, force=True)
def test_notify_pmc(self, host, username, password):
return self._notify_pmc('This is a test notification from SickGear', 'Test', host, username, password, force=True)
def update_library(self, ep_obj=None, host=None, username=None, password=None):
def test_notify_pms(self, host, username, password):
return self.update_library(host=host, username=username, password=password, force=False)
def update_library(self, ep_obj=None, host=None, username=None, password=None, force=True):
"""Handles updating the Plex Media Server host via HTTP API
Plex Media Server currently only supports updating the whole video library and not a specific path.
Returns:
Returns True or False
Returns None for no issue, else a string of host with connection issues
"""
# fill in omitted parameters
if not host:
host = sickbeard.PLEX_SERVER_HOST
if not username:
username = sickbeard.PLEX_USERNAME
if not password:
password = sickbeard.PLEX_PASSWORD
if sickbeard.USE_PLEX and sickbeard.PLEX_UPDATE_LIBRARY:
if not sickbeard.PLEX_SERVER_HOST:
logger.log(u"PLEX: No Plex Media Server host specified, check your settings", logger.DEBUG)
logger.log(u'PLEX: No Plex Media Server host specified, check your settings', logger.DEBUG)
return False
logger.log(u"PLEX: Updating library for the Plex Media Server host: " + host, logger.MESSAGE)
if not host:
host = sickbeard.PLEX_SERVER_HOST
if not username:
username = sickbeard.PLEX_USERNAME
if not password:
password = sickbeard.PLEX_PASSWORD
# if username and password were provided, fetch the auth token from plex.tv
token_arg = ""
token_arg = ''
if username and password:
logger.log(u"PLEX: fetching credentials for Plex user: " + username, logger.DEBUG)
req = urllib2.Request("https://plex.tv/users/sign_in.xml", data="")
authheader = "Basic %s" % base64.encodestring('%s:%s' % (username, password))[:-1]
req.add_header("Authorization", authheader)
req.add_header("X-Plex-Device-Name", "SickGear")
req.add_header("X-Plex-Product", "SickGear Notifier")
req.add_header("X-Plex-Client-Identifier", "5f48c063eaf379a565ff56c9bb2b401e")
req.add_header("X-Plex-Version", "1.0")
logger.log(u'PLEX: fetching plex.tv credentials for user: ' + username, logger.DEBUG)
req = urllib2.Request('https://plex.tv/users/sign_in.xml', data='')
authheader = 'Basic %s' % base64.encodestring('%s:%s' % (username, password))[:-1]
req.add_header('Authorization', authheader)
req.add_header('X-Plex-Device-Name', 'SickGear')
req.add_header('X-Plex-Product', 'SickGear Notifier')
req.add_header('X-Plex-Client-Identifier', '5f48c063eaf379a565ff56c9bb2b401e')
req.add_header('X-Plex-Version', '1.0')
try:
response = urllib2.urlopen(req)
auth_tree = etree.parse(response)
token = auth_tree.findall(".//authentication-token")[0].text
token_arg = "?X-Plex-Token=" + token
token = auth_tree.findall('.//authentication-token')[0].text
token_arg = '?X-Plex-Token=' + token
except urllib2.URLError as e:
logger.log(u"PLEX: Error fetching credentials from from plex.tv for user %s: %s" % (username, ex(e)), logger.MESSAGE)
logger.log(u'PLEX: Error fetching credentials from from plex.tv for user %s: %s' % (username, ex(e)), logger.MESSAGE)
except (ValueError, IndexError) as e:
logger.log(u"PLEX: Error parsing plex.tv response: " + ex(e), logger.MESSAGE)
logger.log(u'PLEX: Error parsing plex.tv response: ' + ex(e), logger.MESSAGE)
url = "http://%s/library/sections%s" % (sickbeard.PLEX_SERVER_HOST, token_arg)
try:
xml_tree = etree.parse(urllib.urlopen(url))
media_container = xml_tree.getroot()
except IOError, e:
logger.log(u"PLEX: Error while trying to contact Plex Media Server: " + ex(e), logger.ERROR)
return False
file_location = '' if None is ep_obj else ep_obj.location
host_list = [x.strip() for x in host.split(',')]
hosts_all = {}
hosts_match = {}
hosts_failed = []
for cur_host in host_list:
sections = media_container.findall('.//Directory')
if not sections:
logger.log(u"PLEX: Plex Media Server not running on: " + sickbeard.PLEX_SERVER_HOST, logger.MESSAGE)
return False
url = 'http://%s/library/sections%s' % (cur_host, token_arg)
try:
xml_tree = etree.parse(urllib.urlopen(url))
media_container = xml_tree.getroot()
except IOError, e:
logger.log(u'PLEX: Error while trying to contact Plex Media Server: ' + ex(e), logger.ERROR)
hosts_failed.append(cur_host)
continue
for section in sections:
if section.attrib['type'] == "show":
url = "http://%s/library/sections/%s/refresh%s" % (sickbeard.PLEX_SERVER_HOST, section.attrib['key'], token_arg)
try:
urllib.urlopen(url)
except Exception, e:
logger.log(u"PLEX: Error updating library section for Plex Media Server: " + ex(e), logger.ERROR)
return False
sections = media_container.findall('.//Directory')
if not sections:
logger.log(u'PLEX: Plex Media Server not running on: ' + cur_host, logger.MESSAGE)
hosts_failed.append(cur_host)
continue
return True
for section in sections:
if 'show' == section.attrib['type']:
keyed_host = [(str(section.attrib['key']), cur_host)]
hosts_all.update(keyed_host)
if not file_location:
continue
for section_location in section.findall('.//Location'):
section_path = re.sub(r'[/\\]+', '/', section_location.attrib['path'].lower())
section_path = re.sub(r'^(.{,2})[/\\]', '', section_path)
location_path = re.sub(r'[/\\]+', '/', file_location.lower())
location_path = re.sub(r'^(.{,2})[/\\]', '', location_path)
if section_path in location_path:
hosts_match.update(keyed_host)
hosts_try = (hosts_all.copy(), hosts_match.copy())[len(hosts_match)]
host_list = []
for section_key, cur_host in hosts_try.items():
url = 'http://%s/library/sections/%s/refresh%s' % (cur_host, section_key, token_arg)
try:
force and urllib.urlopen(url)
host_list.append(cur_host)
except Exception, e:
logger.log(u'PLEX: Error updating library section for Plex Media Server: ' + ex(e), logger.ERROR)
hosts_failed.append(cur_host)
if len(hosts_match):
logger.log(u'PLEX: Updating hosts where TV section paths match the downloaded show: ' + ', '.join(set(host_list)), logger.MESSAGE)
else:
logger.log(u'PLEX: Updating all hosts with TV sections: ' + ', '.join(set(host_list)), logger.MESSAGE)
return (', '.join(set(hosts_failed)), None)[not len(hosts_failed)]
notifier = PLEXNotifier

View file

@ -1013,7 +1013,7 @@ class PostProcessor(object):
notifiers.xbmc_notifier.update_library(ep_obj.show.name)
# do the library update for Plex
notifiers.plex_notifier.update_library()
notifiers.plex_notifier.update_library(ep_obj)
# do the library update for NMJ
# nmj_notifier kicks off its library update when the notify_download is issued (inside notifiers)

View file

@ -2393,7 +2393,7 @@ class ConfigNotifications(MainHandler):
sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD = config.checkbox_to_value(plex_notify_onsubtitledownload)
sickbeard.PLEX_UPDATE_LIBRARY = config.checkbox_to_value(plex_update_library)
sickbeard.PLEX_HOST = config.clean_hosts(plex_host)
sickbeard.PLEX_SERVER_HOST = config.clean_host(plex_server_host)
sickbeard.PLEX_SERVER_HOST = config.clean_hosts(plex_server_host)
sickbeard.PLEX_USERNAME = plex_username
sickbeard.PLEX_PASSWORD = plex_password
@ -3412,21 +3412,37 @@ class Home(MainHandler):
return finalResult
def testPLEX(self, host=None, username=None, password=None):
def testPMC(self, host=None, username=None, password=None):
self.set_header('Cache-Control', 'max-age=0,no-cache,no-store')
finalResult = ''
for curHost in [x.strip() for x in host.split(",")]:
curResult = notifiers.plex_notifier.test_notify(urllib.unquote_plus(curHost), username, password)
if len(curResult.split(":")) > 2 and 'OK' in curResult.split(":")[2]:
finalResult += "Test Plex notice sent successfully to " + urllib.unquote_plus(curHost)
for curHost in [x.strip() for x in host.split(',')]:
curResult = notifiers.plex_notifier.test_notify_pmc(urllib.unquote_plus(curHost), username, password)
if len(curResult.split(':')) > 2 and 'OK' in curResult.split(':')[2]:
finalResult += 'Successful test notice sent to Plex client ... ' + urllib.unquote_plus(curHost)
else:
finalResult += "Test Plex notice failed to " + urllib.unquote_plus(curHost)
finalResult += "<br />\n"
finalResult += 'Test failed for Plex client ... ' + urllib.unquote_plus(curHost)
finalResult += '<br />' + "\n"
ui.notifications.message('Tested Plex client(s): ', urllib.unquote_plus(host.replace(',', ', ')))
return finalResult
def testPMS(self, host=None, username=None, password=None):
self.set_header('Cache-Control', 'max-age=0,no-cache,no-store')
finalResult = ''
curResult = notifiers.plex_notifier.test_notify_pms(urllib.unquote_plus(host), username, password)
if None is curResult:
finalResult += 'Successful test of Plex server(s) ... ' + urllib.unquote_plus(host.replace(',', ', '))
else:
finalResult += 'Test failed for Plex server(s) ... ' + urllib.unquote_plus(curResult.replace(',', ', '))
finalResult += '<br />' + "\n"
ui.notifications.message('Tested Plex Media Server host(s): ', urllib.unquote_plus(host.replace(',', ', ')))
return finalResult
def testLibnotify(self, *args, **kwargs):
self.set_header('Cache-Control', 'max-age=0,no-cache,no-store')
@ -4085,16 +4101,15 @@ class Home(MainHandler):
ui.notifications.error("Unable to contact one or more XBMC host(s): " + host)
redirect('/home/')
def updatePLEX(self, *args, **kwargs):
if notifiers.plex_notifier.update_library():
result = notifiers.plex_notifier.update_library()
if None is result:
ui.notifications.message(
"Library update command sent to Plex Media Server host: " + sickbeard.PLEX_SERVER_HOST)
'Library update command sent to', 'Plex Media Server host(s): ' + sickbeard.PLEX_SERVER_HOST.replace(',', ', '))
else:
ui.notifications.error("Unable to contact Plex Media Server host: " + sickbeard.PLEX_SERVER_HOST)
ui.notifications.error('Unable to contact', 'Plex Media Server host(s): ' + result.replace(',', ', '))
redirect('/home/')
def setStatus(self, show=None, eps=None, status=None, direct=False):
if show is None or eps is None or status is None: