From ec0fd92b80a5ee33eefbd9d6519238b8ede4c5c5 Mon Sep 17 00:00:00 2001 From: Justin Tabish Date: Tue, 21 Jan 2014 04:28:56 -0800 Subject: [PATCH] Added Plex Media Server and Client Update Library and Notification functions. --- data/interfaces/default/config.html | 52 +++++++++++++++++ headphones/__init__.py | 28 ++++++++- headphones/notifiers.py | 88 +++++++++++++++++++++++++++++ headphones/postprocessor.py | 7 +++ headphones/webserve.py | 19 ++++++- 5 files changed, 191 insertions(+), 3 deletions(-) diff --git a/data/interfaces/default/config.html b/data/interfaces/default/config.html index 56b14ddf..8516b7c4 100644 --- a/data/interfaces/default/config.html +++ b/data/interfaces/default/config.html @@ -798,6 +798,38 @@ +
+

Plex Media Server

+
+ +
+
+
+ + + Host running Plex Media Server (eg. http://192.168.1.100:32400) +
+
+ + + Host running Plex Client (eg. http://192.168.1.100:3000) +
+
+ + Username of your Plex client API (blank for none) +
+
+ + Password of your Plex client API (blank for none) +
+
+ +
+
+ +
+
+

NotifyMyAndroid

@@ -1098,6 +1130,26 @@ } }); + if ($("#plex").is(":checked")) + { + $("#plexoptions").show(); + } + else + { + $("#plexoptions").hide(); + } + + $("#plex").click(function(){ + if ($("#plex").is(":checked")) + { + $("#plexoptions").slideDown(); + } + else + { + $("#plexoptions").slideUp(); + } + }); + if ($("#nma").is(":checked")) { $("#nmaoptions").show(); diff --git a/headphones/__init__.py b/headphones/__init__.py index 7f567afc..0ad8433e 100644 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -229,6 +229,13 @@ XBMC_USERNAME = None XBMC_PASSWORD = None XBMC_UPDATE = False XBMC_NOTIFY = False +PLEX_ENABLED = False +PLEX_SERVER_HOST = None +PLEX_CLIENT_HOST = None +PLEX_USERNAME = None +PLEX_PASSWORD = None +PLEX_UPDATE = False +PLEX_NOTIFY = False NMA_ENABLED = False NMA_APIKEY = None NMA_PRIORITY = None @@ -318,7 +325,8 @@ def initialize(): PROWL_ENABLED, PROWL_PRIORITY, PROWL_KEYS, PROWL_ONSNATCH, PUSHOVER_ENABLED, PUSHOVER_PRIORITY, PUSHOVER_KEYS, PUSHOVER_ONSNATCH, MIRRORLIST, \ MIRROR, CUSTOMHOST, CUSTOMPORT, CUSTOMSLEEP, HPUSER, HPPASS, XBMC_ENABLED, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, XBMC_UPDATE, \ XBMC_NOTIFY, NMA_ENABLED, NMA_APIKEY, NMA_PRIORITY, NMA_ONSNATCH, SYNOINDEX_ENABLED, ALBUM_COMPLETION_PCT, PREFERRED_BITRATE_HIGH_BUFFER, \ - PREFERRED_BITRATE_LOW_BUFFER, PREFERRED_BITRATE_ALLOW_LOSSLESS, CACHE_SIZEMB, JOURNAL_MODE, UMASK, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY + PREFERRED_BITRATE_LOW_BUFFER, PREFERRED_BITRATE_ALLOW_LOSSLESS, CACHE_SIZEMB, JOURNAL_MODE, UMASK, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \ + PLEX_ENABLED, PLEX_SERVER_HOST, PLEX_CLIENT_HOST, PLEX_USERNAME, PLEX_PASSWORD, PLEX_UPDATE, PLEX_NOTIFY if __INITIALIZED__: return False @@ -340,6 +348,7 @@ def initialize(): CheckSection('Prowl') CheckSection('Pushover') CheckSection('XBMC') + CheckSection('Plex') CheckSection('NMA') CheckSection('Synoindex') CheckSection('Advanced') @@ -515,6 +524,14 @@ def initialize(): XBMC_UPDATE = bool(check_setting_int(CFG, 'XBMC', 'xbmc_update', 0)) XBMC_NOTIFY = bool(check_setting_int(CFG, 'XBMC', 'xbmc_notify', 0)) + PLEX_ENABLED = bool(check_setting_int(CFG, 'Plex', 'plex_enabled', 0)) + PLEX_SERVER_HOST = check_setting_str(CFG, 'Plex', 'plex_server_host', '') + PLEX_CLIENT_HOST = check_setting_str(CFG, 'Plex', 'plex_client_host', '') + PLEX_USERNAME = check_setting_str(CFG, 'Plex', 'plex_username', '') + PLEX_PASSWORD = check_setting_str(CFG, 'Plex', 'plex_password', '') + PLEX_UPDATE = bool(check_setting_int(CFG, 'Plex', 'plex_update', 0)) + PLEX_NOTIFY = bool(check_setting_int(CFG, 'Plex', 'plex_notify', 0)) + NMA_ENABLED = bool(check_setting_int(CFG, 'NMA', 'nma_enabled', 0)) NMA_APIKEY = check_setting_str(CFG, 'NMA', 'nma_apikey', '') NMA_PRIORITY = check_setting_int(CFG, 'NMA', 'nma_priority', 0) @@ -881,6 +898,15 @@ def config_write(): new_config['XBMC']['xbmc_update'] = int(XBMC_UPDATE) new_config['XBMC']['xbmc_notify'] = int(XBMC_NOTIFY) + new_config['Plex'] = {} + new_config['Plex']['plex_enabled'] = int(PLEX_ENABLED) + new_config['Plex']['plex_server_host'] = PLEX_SERVER_HOST + new_config['Plex']['plex_client_host'] = PLEX_CLIENT_HOST + new_config['Plex']['plex_username'] = PLEX_USERNAME + new_config['Plex']['plex_password'] = PLEX_PASSWORD + new_config['Plex']['plex_update'] = int(PLEX_UPDATE) + new_config['Plex']['plex_notify'] = int(PLEX_NOTIFY) + new_config['NMA'] = {} new_config['NMA']['nma_enabled'] = int(NMA_ENABLED) new_config['NMA']['nma_apikey'] = NMA_APIKEY diff --git a/headphones/notifiers.py b/headphones/notifiers.py index 11a5e57c..5634105a 100644 --- a/headphones/notifiers.py +++ b/headphones/notifiers.py @@ -24,6 +24,7 @@ from urllib import urlencode import os.path import subprocess import lib.simplejson as simplejson +from xml.dom import minidom class PROWL: @@ -183,6 +184,93 @@ class XBMC: except: logger.warn('Error sending notification request to XBMC') +class Plex: + + def __init__(self): + + self.server_hosts = headphones.PLEX_SERVER_HOST + self.client_hosts = headphones.PLEX_CLIENT_HOST + self.username = headphones.PLEX_USERNAME + self.password = headphones.PLEX_PASSWORD + + def _sendhttp(self, host, command): + + username = self.username + password = self.password + + url_command = urllib.urlencode(command) + + url = host + '/xbmcCmds/xbmcHttp/?' + url_command + + req = urllib2.Request(url) + + if password: + base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '') + req.add_header("Authorization", "Basic %s" % base64string) + + logger.info('Plex url: %s' % url) + + try: + handle = urllib2.urlopen(req) + except Exception, e: + logger.warn('Error opening Plex url: %s' % e) + return + + response = handle.read().decode(headphones.SYS_ENCODING) + + return response + + def update(self): + + # From what I read you can't update the music library on a per directory or per path basis + # so need to update the whole thing + + hosts = [x.strip() for x in self.server_hosts.split(',')] + + for host in hosts: + logger.info('Sending library update command to Plex Media Server@ '+host) + url = "%s/library/sections" % host + try: + xml_sections = minidom.parse(urllib.urlopen(url)) + except IOError, e: + logger.warn("Error while trying to contact Plex Media Server: %s" % e) + return False + + sections = xml_sections.getElementsByTagName('Directory') + if not sections: + logger.info(u"Plex Media Server not running on: " + host) + return False + + for s in sections: + if s.getAttribute('type') == "artist": + url = "%s/library/sections/%s/refresh" % (host, s.getAttribute('key')) + try: + urllib.urlopen(url) + except Exception, e: + logger.warn("Error updating library section for Plex Media Server: %s" % e) + return False + + def notify(self, artist, album, albumartpath): + + hosts = [x.strip() for x in self.client_hosts.split(',')] + + header = "Headphones" + message = "%s - %s added to your library" % (artist, album) + time = "3000" # in ms + + for host in hosts: + logger.info('Sending notification command to Plex Media Server @ '+host) + try: + notification = header + "," + message + "," + time + "," + albumartpath + notifycommand = {'command': 'ExecBuiltIn', 'parameter': 'Notification('+notification+')'} + request = self._sendhttp(host, notifycommand) + + if not request: + raise Exception + + except: + logger.warn('Error sending notification request to Plex Media Server') + class NMA: def __init__(self): diff --git a/headphones/postprocessor.py b/headphones/postprocessor.py index 48e6c3ec..8234d25f 100644 --- a/headphones/postprocessor.py +++ b/headphones/postprocessor.py @@ -420,6 +420,13 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, if headphones.XBMC_NOTIFY: xbmc.notify(release['ArtistName'], release['AlbumTitle'], album_art_path) + if headphones.PLEX_ENABLED: + plex = notifiers.Plex() + if headphones.PLEX_UPDATE: + plex.update() + if headphones.PLEX_NOTIFY: + plex.notify(release['ArtistName'], release['AlbumTitle'], album_art_path) + if headphones.NMA_ENABLED: nma = notifiers.NMA() nma.notify(release['ArtistName'], release['AlbumTitle']) diff --git a/headphones/webserve.py b/headphones/webserve.py index 130a17b6..91eadcfd 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -933,6 +933,13 @@ class WebInterface(object): "xbmc_password": headphones.XBMC_PASSWORD, "xbmc_update": checked(headphones.XBMC_UPDATE), "xbmc_notify": checked(headphones.XBMC_NOTIFY), + "plex_enabled": checked(headphones.PLEX_ENABLED), + "plex_server_host": headphones.PLEX_SERVER_HOST, + "plex_client_host": headphones.PLEX_CLIENT_HOST, + "plex_username": headphones.PLEX_USERNAME, + "plex_password": headphones.PLEX_PASSWORD, + "plex_update": checked(headphones.PLEX_UPDATE), + "plex_notify": checked(headphones.PLEX_NOTIFY), "nma_enabled": checked(headphones.NMA_ENABLED), "nma_apikey": headphones.NMA_APIKEY, "nma_priority": int(headphones.NMA_PRIORITY), @@ -985,8 +992,9 @@ class WebInterface(object): delete_lossless_files=0, prowl_enabled=0, prowl_onsnatch=0, prowl_keys=None, prowl_priority=0, xbmc_enabled=0, xbmc_host=None, xbmc_username=None, xbmc_password=None, xbmc_update=0, xbmc_notify=0, nma_enabled=False, nma_apikey=None, nma_priority=0, nma_onsnatch=0, synoindex_enabled=False, pushover_enabled=0, pushover_onsnatch=0, pushover_keys=None, pushover_priority=0, mirror=None, customhost=None, customport=None, - customsleep=None, hpuser=None, hppass=None, preferred_bitrate_high_buffer=None, preferred_bitrate_low_buffer=None, preferred_bitrate_allow_lossless=0, cache_sizemb=None, - enable_https=0, https_cert=None, https_key=None, file_permissions=None, folder_permissions=None, **kwargs): + customsleep=None, hpuser=None, hppass=None, preferred_bitrate_high_buffer=None, preferred_bitrate_low_buffer=None, preferred_bitrate_allow_lossless=0, cache_sizemb=None, + enable_https=0, https_cert=None, https_key=None, file_permissions=None, folder_permissions=None, plex_enabled=0, plex_server_host=None, plex_client_host=None, + plex_username=None, plex_password=None, plex_update=0, plex_notify=0, **kwargs): headphones.HTTP_HOST = http_host headphones.HTTP_PORT = http_port @@ -1105,6 +1113,13 @@ class WebInterface(object): headphones.XBMC_PASSWORD = xbmc_password headphones.XBMC_UPDATE = xbmc_update headphones.XBMC_NOTIFY = xbmc_notify + headphones.PLEX_ENABLED = plex_enabled + headphones.PLEX_SERVER_HOST = plex_server_host + headphones.PLEX_CLIENT_HOST = plex_client_host + headphones.PLEX_USERNAME = plex_username + headphones.PLEX_PASSWORD = plex_password + headphones.PLEX_UPDATE = plex_update + headphones.PLEX_NOTIFY = plex_notify headphones.NMA_ENABLED = nma_enabled headphones.NMA_APIKEY = nma_apikey headphones.NMA_PRIORITY = nma_priority