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 * Add sound selection for boxcar2 notifier
* Change boxcar2 notifier to use updated api scheme * Change boxcar2 notifier to use updated api scheme
* Update the Plex notifier from a port at midgetspy/sickbeard * 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] [develop changelog]
* Change uT params from unicode to str.format as magnet URLs worked but sending files in POST bodies failed * 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 sickbeard
#import re
#from sickbeard.helpers import anon_url #from sickbeard.helpers import anon_url
#set global $title = 'Config - Notifications' #set global $title = 'Config - Notifications'
@ -160,26 +161,80 @@
<img class="notifier-icon" src="$sbRoot/images/notifiers/plex.png" alt="" title="Plex Media Server" /> <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> <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>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> </div>
<fieldset class="component-group-list"> <fieldset class="component-group-list">
<div class="field-pair"> <div class="field-pair">
<label for="use_plex"> <label for="use_plex">
<span class="component-title">Enable</span> <span class="component-title">Enable</span>
<span class="component-desc"> <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> <p>should SickGear send Plex commands ?</p>
</span> </span>
</label> </label>
</div> </div>
<div id="content_use_plex"> <div id="content_use_plex">
<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="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>
<div class="field-pair"> <div class="field-pair">
<label for="plex_notify_onsnatch"> <label for="plex_notify_onsnatch">
<span class="component-title">Notify on snatch</span> <span class="component-title">Notify on snatch</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="plex_notify_onsnatch" id="plex_notify_onsnatch" #if $sickbeard.PLEX_NOTIFY_ONSNATCH then "checked=\"checked\"" else ""# /> <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> <p>download start notification</p>
</span> </span>
</label> </label>
</div> </div>
@ -188,7 +243,7 @@
<span class="component-title">Notify on download</span> <span class="component-title">Notify on download</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="plex_notify_ondownload" id="plex_notify_ondownload" #if $sickbeard.PLEX_NOTIFY_ONDOWNLOAD then "checked=\"checked\"" else ""# /> <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> <p>download finish notification</p>
</span> </span>
</label> </label>
</div> </div>
@ -197,66 +252,29 @@
<span class="component-title">Notify on subtitle download</span> <span class="component-title">Notify on subtitle download</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="plex_notify_onsubtitledownload" id="plex_notify_onsubtitledownload" #if $sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD then "checked=\"checked\"" else ""# /> <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> <p>subtitle downloaded notification</p>
</span> </span>
</label> </label>
</div> </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"> <div class="field-pair">
<label for="plex_host"> <label for="plex_host">
<span class="component-title">Plex client IP:Port</span> <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" /> <span class="component-desc">
</label> <input type="text" name="plex_host" id="plex_host" value="<%= re.sub(r'\b,\b', ', ', sickbeard.PLEX_HOST) %>" class="form-control input-sm input350" />
<label> <div class="clear-left">
<span class="component-title">&nbsp;</span> <p>one or more hosts running Plex client<br />(eg. 192.168.1.100:3000, 192.168.1.101:3000)</p>
<span class="component-desc">host running Plex client (eg. 192.168.1.100:3000)</span> </div>
</label> </span>
<label>
<span class="component-title">&nbsp;</span>
<span class="component-desc">(multiple host strings must be separated by commas)</span>
</label> </label>
</div> </div>
<div class="field-pair"> <div class="field-pair">
<label for="plex_username"> <div class="testNotification" id="testPMC-result">Click below to test Plex client(s)</div>
<span class="component-title">Plex client username</span> <input class="btn" type="button" value="Test Plex Client" id="testPMC" />
<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" /> <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 --> </div><!-- /content_use_plex -->
</fieldset> </fieldset>

View file

@ -56,22 +56,41 @@ $(document).ready(function(){
}); });
}); });
$('#testPLEX').click(function () { $('#testPMC').click(function () {
var plex_host = $.trim($('#plex_host').val()); var plex_host = $.trim($('#plex_host').val());
var plex_username = $.trim($('#plex_username').val()); var plex_username = $.trim($('#plex_username').val());
var plex_password = $.trim($('#plex_password').val()); var plex_password = $.trim($('#plex_password').val());
if (!plex_host) { 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'); $('#plex_host').addClass('warning');
return; return;
} }
$('#plex_host').removeClass('warning'); $('#plex_host').removeClass('warning');
$(this).prop('disabled', true); $(this).prop('disabled', true);
$('#testPLEX-result').html(loading); $('#testPMC-result').html(loading);
$.get(sbRoot + '/home/testPLEX', {'host': plex_host, 'username': plex_username, 'password': plex_password}) $.get(sbRoot + '/home/testPMC', {'host': plex_host, 'username': plex_username, 'password': plex_password})
.done(function (data) { .done(function (data) {
$('#testPLEX-result').html(data); $('#testPMC-result').html(data);
$('#testPLEX').prop('disabled', false); $('#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);
}); });
}); });
@ -458,5 +477,5 @@ $(document).ready(function(){
$('.plexinfo').addClass('hide'); $('.plexinfo').addClass('hide');
} }
}); });
if ($('input[id="use_plex"]').is(':checked')) {$('.plexinfo').removeClass('hide')}
}); });

View file

@ -19,6 +19,7 @@
import urllib import urllib
import urllib2 import urllib2
import base64 import base64
import re
import sickbeard import sickbeard
@ -56,7 +57,7 @@ class PLEXNotifier:
password = sickbeard.PLEX_PASSWORD password = sickbeard.PLEX_PASSWORD
if not host: 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 return False
for key in command: for key in command:
@ -64,7 +65,7 @@ class PLEXNotifier:
command[key] = command[key].encode('utf-8') command[key] = command[key].encode('utf-8')
enc_command = urllib.urlencode(command) 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) url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command)
try: try:
@ -72,26 +73,26 @@ class PLEXNotifier:
# if we have a password, use authentication # if we have a password, use authentication
if password: if password:
base64string = base64.encodestring('%s:%s' % (username, password))[:-1] base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
authheader = "Basic %s" % base64string authheader = 'Basic %s' % base64string
req.add_header("Authorization", authheader) req.add_header('Authorization', authheader)
logger.log(u"PLEX: Contacting (with auth header) via url: " + url, logger.DEBUG) logger.log(u'PLEX: Contacting (with auth header) via url: ' + url, logger.DEBUG)
else: 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) response = urllib2.urlopen(req)
result = response.read().decode(sickbeard.SYS_ENCODING) result = response.read().decode(sickbeard.SYS_ENCODING)
response.close() 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) # could return result response = re.compile('<html><li>(.+\w)</html>').findall(result)
return 'OK' return 'OK'
except (urllib2.URLError, IOError), e: 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 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 """Internal wrapper for the notify_snatch and notify_download functions
Args: Args:
@ -121,13 +122,13 @@ class PLEXNotifier:
password = sickbeard.PLEX_PASSWORD password = sickbeard.PLEX_PASSWORD
result = '' result = ''
for curHost in [x.strip() for x in host.split(",")]: for curHost in [x.strip() for x in host.split(',')]:
logger.log(u"PLEX: Sending notification to '" + curHost + "' - " + message, logger.MESSAGE) 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") + ')'} command = {'command': 'ExecBuiltIn', 'parameter': 'Notification(%s,%s)' % (title.encode('utf-8'), message.encode('utf-8'))}
notifyResult = self._send_to_plex(command, curHost, username, password) notify_result = self._send_to_plex(command, curHost, username, password)
if notifyResult: if notify_result:
result += curHost + ':' + str(notifyResult) result += '%s:%s' % (curHost, str(notify_result))
return result return result
@ -145,28 +146,36 @@ class PLEXNotifier:
def notify_subtitle_download(self, ep_name, lang): def notify_subtitle_download(self, ep_name, lang):
if sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD: 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: if sickbeard.USE_PLEX:
update_text = common.notifyStrings[common.NOTIFY_GIT_UPDATE_TEXT] update_text = common.notifyStrings[common.NOTIFY_GIT_UPDATE_TEXT]
title = common.notifyStrings[common.NOTIFY_GIT_UPDATE] title = common.notifyStrings[common.NOTIFY_GIT_UPDATE]
self._notify_pmc(update_text + new_version, title) self._notify_pmc(update_text + new_version, title)
def test_notify(self, host, username, password): 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) 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 """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. Plex Media Server currently only supports updating the whole video library and not a specific path.
Returns: Returns:
Returns True or False Returns None for no issue, else a string of host with connection issues
""" """
# fill in omitted parameters 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)
return False
if not host: if not host:
host = sickbeard.PLEX_SERVER_HOST host = sickbeard.PLEX_SERVER_HOST
if not username: if not username:
@ -174,60 +183,87 @@ class PLEXNotifier:
if not password: if not password:
password = sickbeard.PLEX_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)
return False
logger.log(u"PLEX: Updating library for the Plex Media Server host: " + host, logger.MESSAGE)
# if username and password were provided, fetch the auth token from plex.tv # if username and password were provided, fetch the auth token from plex.tv
token_arg = "" token_arg = ''
if username and password: if username and password:
logger.log(u"PLEX: fetching credentials for Plex user: " + username, logger.DEBUG) logger.log(u'PLEX: fetching plex.tv credentials for user: ' + username, logger.DEBUG)
req = urllib2.Request("https://plex.tv/users/sign_in.xml", data="") req = urllib2.Request('https://plex.tv/users/sign_in.xml', data='')
authheader = "Basic %s" % base64.encodestring('%s:%s' % (username, password))[:-1] authheader = 'Basic %s' % base64.encodestring('%s:%s' % (username, password))[:-1]
req.add_header("Authorization", authheader) req.add_header('Authorization', authheader)
req.add_header("X-Plex-Device-Name", "SickGear") req.add_header('X-Plex-Device-Name', 'SickGear')
req.add_header("X-Plex-Product", "SickGear Notifier") req.add_header('X-Plex-Product', 'SickGear Notifier')
req.add_header("X-Plex-Client-Identifier", "5f48c063eaf379a565ff56c9bb2b401e") req.add_header('X-Plex-Client-Identifier', '5f48c063eaf379a565ff56c9bb2b401e')
req.add_header("X-Plex-Version", "1.0") req.add_header('X-Plex-Version', '1.0')
try: try:
response = urllib2.urlopen(req) response = urllib2.urlopen(req)
auth_tree = etree.parse(response) auth_tree = etree.parse(response)
token = auth_tree.findall(".//authentication-token")[0].text token = auth_tree.findall('.//authentication-token')[0].text
token_arg = "?X-Plex-Token=" + token token_arg = '?X-Plex-Token=' + token
except urllib2.URLError as e: 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: 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) 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:
url = 'http://%s/library/sections%s' % (cur_host, token_arg)
try: try:
xml_tree = etree.parse(urllib.urlopen(url)) xml_tree = etree.parse(urllib.urlopen(url))
media_container = xml_tree.getroot() media_container = xml_tree.getroot()
except IOError, e: except IOError, e:
logger.log(u"PLEX: Error while trying to contact Plex Media Server: " + ex(e), logger.ERROR) logger.log(u'PLEX: Error while trying to contact Plex Media Server: ' + ex(e), logger.ERROR)
return False hosts_failed.append(cur_host)
continue
sections = media_container.findall('.//Directory') sections = media_container.findall('.//Directory')
if not sections: if not sections:
logger.log(u"PLEX: Plex Media Server not running on: " + sickbeard.PLEX_SERVER_HOST, logger.MESSAGE) logger.log(u'PLEX: Plex Media Server not running on: ' + cur_host, logger.MESSAGE)
return False hosts_failed.append(cur_host)
continue
for section in sections: for section in sections:
if section.attrib['type'] == "show": if 'show' == section.attrib['type']:
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
return True 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 notifier = PLEXNotifier

View file

@ -1013,7 +1013,7 @@ class PostProcessor(object):
notifiers.xbmc_notifier.update_library(ep_obj.show.name) notifiers.xbmc_notifier.update_library(ep_obj.show.name)
# do the library update for Plex # do the library update for Plex
notifiers.plex_notifier.update_library() notifiers.plex_notifier.update_library(ep_obj)
# do the library update for NMJ # do the library update for NMJ
# nmj_notifier kicks off its library update when the notify_download is issued (inside notifiers) # 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_NOTIFY_ONSUBTITLEDOWNLOAD = config.checkbox_to_value(plex_notify_onsubtitledownload)
sickbeard.PLEX_UPDATE_LIBRARY = config.checkbox_to_value(plex_update_library) sickbeard.PLEX_UPDATE_LIBRARY = config.checkbox_to_value(plex_update_library)
sickbeard.PLEX_HOST = config.clean_hosts(plex_host) 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_USERNAME = plex_username
sickbeard.PLEX_PASSWORD = plex_password sickbeard.PLEX_PASSWORD = plex_password
@ -3412,21 +3412,37 @@ class Home(MainHandler):
return finalResult return finalResult
def testPMC(self, host=None, username=None, password=None):
def testPLEX(self, host=None, username=None, password=None):
self.set_header('Cache-Control', 'max-age=0,no-cache,no-store') self.set_header('Cache-Control', 'max-age=0,no-cache,no-store')
finalResult = '' finalResult = ''
for curHost in [x.strip() for x in host.split(",")]: for curHost in [x.strip() for x in host.split(',')]:
curResult = notifiers.plex_notifier.test_notify(urllib.unquote_plus(curHost), username, password) curResult = notifiers.plex_notifier.test_notify_pmc(urllib.unquote_plus(curHost), username, password)
if len(curResult.split(":")) > 2 and 'OK' in curResult.split(":")[2]: if len(curResult.split(':')) > 2 and 'OK' in curResult.split(':')[2]:
finalResult += "Test Plex notice sent successfully to " + urllib.unquote_plus(curHost) finalResult += 'Successful test notice sent to Plex client ... ' + urllib.unquote_plus(curHost)
else: else:
finalResult += "Test Plex notice failed to " + urllib.unquote_plus(curHost) finalResult += 'Test failed for Plex client ... ' + urllib.unquote_plus(curHost)
finalResult += "<br />\n" finalResult += '<br />' + "\n"
ui.notifications.message('Tested Plex client(s): ', urllib.unquote_plus(host.replace(',', ', ')))
return finalResult 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): def testLibnotify(self, *args, **kwargs):
self.set_header('Cache-Control', 'max-age=0,no-cache,no-store') 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) ui.notifications.error("Unable to contact one or more XBMC host(s): " + host)
redirect('/home/') redirect('/home/')
def updatePLEX(self, *args, **kwargs): def updatePLEX(self, *args, **kwargs):
if notifiers.plex_notifier.update_library(): result = notifiers.plex_notifier.update_library()
if None is result:
ui.notifications.message( 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: 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/') redirect('/home/')
def setStatus(self, show=None, eps=None, status=None, direct=False): def setStatus(self, show=None, eps=None, status=None, direct=False):
if show is None or eps is None or status is None: if show is None or eps is None or status is None: