mirror of
https://github.com/SickGear/SickGear.git
synced 2025-01-08 02:53:38 +00:00
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:
parent
b8a4afc923
commit
47f1c8eaaf
6 changed files with 289 additions and 194 deletions
|
@ -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
|
||||||
|
|
|
@ -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,103 +161,120 @@
|
||||||
<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="field-pair">
|
<div class="component-group" style="padding: 0; min-height: 130px">
|
||||||
<label for="plex_notify_onsnatch">
|
<div class="field-pair">
|
||||||
<span class="component-title">Notify on snatch</span>
|
<label for="plex_username">
|
||||||
<span class="component-desc">
|
<span class="component-title">Server/client username</span>
|
||||||
<input type="checkbox" name="plex_notify_onsnatch" id="plex_notify_onsnatch" #if $sickbeard.PLEX_NOTIFY_ONSNATCH then "checked=\"checked\"" else ""# />
|
<span class="component-desc">
|
||||||
<p>send a notification when a download starts ?</p>
|
<input type="text" name="plex_username" id="plex_username" value="$sickbeard.PLEX_USERNAME" class="form-control input-sm input250" />
|
||||||
</span>
|
<p>blank = no authentication</p>
|
||||||
</label>
|
</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>
|
||||||
<div class="field-pair">
|
|
||||||
<label for="plex_notify_ondownload">
|
<div class="component-group" style="padding: 0; min-height: 50px">
|
||||||
<span class="component-title">Notify on download</span>
|
<div class="field-pair">
|
||||||
<span class="component-desc">
|
<label for="plex_update_library">
|
||||||
<input type="checkbox" name="plex_notify_ondownload" id="plex_notify_ondownload" #if $sickbeard.PLEX_NOTIFY_ONDOWNLOAD then "checked=\"checked\"" else ""# />
|
<span class="component-title">Update server library</span>
|
||||||
<p>send a notification when a download finishes ?</p>
|
<span class="component-desc">
|
||||||
</span>
|
<input type="checkbox" class="enabler" name="plex_update_library" id="plex_update_library" #if $sickbeard.PLEX_UPDATE_LIBRARY then 'checked="checked" ' else ''#/>
|
||||||
</label>
|
<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"> </div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-pair">
|
|
||||||
<label for="plex_notify_onsubtitledownload">
|
<div>
|
||||||
<span class="component-title">Notify on subtitle download</span>
|
<div class="field-pair">
|
||||||
<span class="component-desc">
|
<label for="plex_notify_onsnatch">
|
||||||
<input type="checkbox" name="plex_notify_onsubtitledownload" id="plex_notify_onsubtitledownload" #if $sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD then "checked=\"checked\"" else ""# />
|
<span class="component-title">Notify on snatch</span>
|
||||||
<p>send a notification when subtitles are downloaded ?</p>
|
<span class="component-desc">
|
||||||
</span>
|
<input type="checkbox" name="plex_notify_onsnatch" id="plex_notify_onsnatch" #if $sickbeard.PLEX_NOTIFY_ONSNATCH then "checked=\"checked\"" else ""# />
|
||||||
</label>
|
<p>download start notification</p>
|
||||||
</div>
|
</span>
|
||||||
<div class="field-pair">
|
</label>
|
||||||
<label for="plex_update_library">
|
</div>
|
||||||
<span class="component-title">Update library</span>
|
<div class="field-pair">
|
||||||
<span class="component-desc">
|
<label for="plex_notify_ondownload">
|
||||||
<input type="checkbox" name="plex_update_library" id="plex_update_library" #if $sickbeard.PLEX_UPDATE_LIBRARY then "checked=\"checked\"" else ""# />
|
<span class="component-title">Notify on download</span>
|
||||||
<p>update Plex Media Server library when a download finishes ?</p>
|
<span class="component-desc">
|
||||||
</span>
|
<input type="checkbox" name="plex_notify_ondownload" id="plex_notify_ondownload" #if $sickbeard.PLEX_NOTIFY_ONDOWNLOAD then "checked=\"checked\"" else ""# />
|
||||||
</label>
|
<p>download finish notification</p>
|
||||||
</div>
|
</span>
|
||||||
<div class="field-pair">
|
</label>
|
||||||
<label for="plex_server_host">
|
</div>
|
||||||
<span class="component-title">Plex Media Server IP:Port</span>
|
<div class="field-pair">
|
||||||
<input type="text" name="plex_server_host" id="plex_server_host" value="$sickbeard.PLEX_SERVER_HOST" class="form-control input-sm input250" />
|
<label for="plex_notify_onsubtitledownload">
|
||||||
</label>
|
<span class="component-title">Notify on subtitle download</span>
|
||||||
<label>
|
<span class="component-desc">
|
||||||
<span class="component-title"> </span>
|
<input type="checkbox" name="plex_notify_onsubtitledownload" id="plex_notify_onsubtitledownload" #if $sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD then "checked=\"checked\"" else ""# />
|
||||||
<span class="component-desc">host running Plex Media Server (eg. 192.168.1.100:32400)</span>
|
<p>subtitle downloaded notification</p>
|
||||||
</label>
|
</span>
|
||||||
</div>
|
</label>
|
||||||
<div class="field-pair">
|
</div>
|
||||||
<label for="plex_host">
|
<div class="field-pair">
|
||||||
<span class="component-title">Plex client IP:Port</span>
|
<label for="plex_host">
|
||||||
<input type="text" name="plex_host" id="plex_host" value="$sickbeard.PLEX_HOST" class="form-control input-sm input350" />
|
<span class="component-title">Plex client IP:Port</span>
|
||||||
</label>
|
<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" />
|
||||||
<span class="component-title"> </span>
|
<div class="clear-left">
|
||||||
<span class="component-desc">host running Plex client (eg. 192.168.1.100:3000)</span>
|
<p>one or more hosts running Plex client<br />(eg. 192.168.1.100:3000, 192.168.1.101:3000)</p>
|
||||||
</label>
|
</div>
|
||||||
<label>
|
</span>
|
||||||
<span class="component-title"> </span>
|
</label>
|
||||||
<span class="component-desc">(multiple host strings must be separated by commas)</span>
|
</div>
|
||||||
</label>
|
|
||||||
</div>
|
<div class="field-pair">
|
||||||
<div class="field-pair">
|
<div class="testNotification" id="testPMC-result">Click below to test Plex client(s)</div>
|
||||||
<label for="plex_username">
|
<input class="btn" type="button" value="Test Plex Client" id="testPMC" />
|
||||||
<span class="component-title">Plex client username</span>
|
<input type="submit" class="config_submitter btn" value="Save Changes" />
|
||||||
<input type="text" name="plex_username" id="plex_username" value="$sickbeard.PLEX_USERNAME" class="form-control input-sm input250" />
|
<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>
|
||||||
</label>
|
</div>
|
||||||
<label>
|
</div><!-- /plex component-group -->
|
||||||
<span class="component-title"> </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"> </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><!-- /content_use_plex -->
|
</div><!-- /content_use_plex -->
|
||||||
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
|
@ -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')}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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,89 +146,124 @@ 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 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 sickbeard.USE_PLEX and sickbeard.PLEX_UPDATE_LIBRARY:
|
||||||
|
|
||||||
if not sickbeard.PLEX_SERVER_HOST:
|
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
|
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
|
# 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
|
||||||
try:
|
host_list = [x.strip() for x in host.split(',')]
|
||||||
xml_tree = etree.parse(urllib.urlopen(url))
|
hosts_all = {}
|
||||||
media_container = xml_tree.getroot()
|
hosts_match = {}
|
||||||
except IOError, e:
|
hosts_failed = []
|
||||||
logger.log(u"PLEX: Error while trying to contact Plex Media Server: " + ex(e), logger.ERROR)
|
for cur_host in host_list:
|
||||||
return False
|
|
||||||
|
|
||||||
sections = media_container.findall('.//Directory')
|
url = 'http://%s/library/sections%s' % (cur_host, token_arg)
|
||||||
if not sections:
|
try:
|
||||||
logger.log(u"PLEX: Plex Media Server not running on: " + sickbeard.PLEX_SERVER_HOST, logger.MESSAGE)
|
xml_tree = etree.parse(urllib.urlopen(url))
|
||||||
return False
|
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:
|
sections = media_container.findall('.//Directory')
|
||||||
if section.attrib['type'] == "show":
|
if not sections:
|
||||||
url = "http://%s/library/sections/%s/refresh%s" % (sickbeard.PLEX_SERVER_HOST, section.attrib['key'], token_arg)
|
logger.log(u'PLEX: Plex Media Server not running on: ' + cur_host, logger.MESSAGE)
|
||||||
try:
|
hosts_failed.append(cur_host)
|
||||||
urllib.urlopen(url)
|
continue
|
||||||
except Exception, e:
|
|
||||||
logger.log(u"PLEX: Error updating library section for Plex Media Server: " + ex(e), logger.ERROR)
|
|
||||||
return False
|
|
||||||
|
|
||||||
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
|
notifier = PLEXNotifier
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue