3 changed files with 230 additions and 170 deletions
@ -0,0 +1,85 @@ |
|||
import json |
|||
from couchpotato import CPLog |
|||
from couchpotato.core.event import addEvent |
|||
from couchpotato.core.helpers.encoding import tryUrlencode |
|||
import requests |
|||
|
|||
log = CPLog(__name__) |
|||
|
|||
|
|||
class PlexClientProtocol(object): |
|||
def __init__(self, plex): |
|||
self.plex = plex |
|||
|
|||
addEvent('notify.plex.notifyClient', self.notify) |
|||
|
|||
def notify(self, client, message): |
|||
raise NotImplementedError() |
|||
|
|||
|
|||
class PlexClientHTTP(PlexClientProtocol): |
|||
def request(self, command, client): |
|||
url = 'http://%s:%s/xbmcCmds/xbmcHttp/?%s' % ( |
|||
client['address'], |
|||
client['port'], |
|||
tryUrlencode(command) |
|||
) |
|||
|
|||
headers = {} |
|||
|
|||
try: |
|||
self.plex.urlopen(url, headers = headers, timeout = 3, show_error = False) |
|||
except Exception, err: |
|||
log.error("Couldn't sent command to Plex: %s", err) |
|||
return False |
|||
|
|||
return True |
|||
|
|||
def notify(self, client, message): |
|||
if client.get('protocol') != 'xbmchttp': |
|||
return None |
|||
|
|||
data = { |
|||
'command': 'ExecBuiltIn', |
|||
'parameter': 'Notification(CouchPotato, %s)' % message |
|||
} |
|||
|
|||
return self.request(data, client) |
|||
|
|||
|
|||
class PlexClientJSON(PlexClientProtocol): |
|||
def request(self, method, params, client): |
|||
log.debug('sendJSON("%s", %s, %s)', (method, params, client)) |
|||
url = 'http://%s:%s/jsonrpc' % ( |
|||
client['address'], |
|||
client['port'] |
|||
) |
|||
|
|||
headers = { |
|||
'Content-Type': 'application/json' |
|||
} |
|||
|
|||
request = { |
|||
'id': 1, |
|||
'jsonrpc': '2.0', |
|||
'method': method, |
|||
'params': params |
|||
} |
|||
|
|||
try: |
|||
requests.post(url, headers = headers, timeout = 3, data = json.dumps(request)) |
|||
except Exception, err: |
|||
log.error("Couldn't sent command to Plex: %s", err) |
|||
return False |
|||
|
|||
return True |
|||
|
|||
def notify(self, client, message): |
|||
if client.get('protocol') not in ['xbmcjson', 'plex']: |
|||
return None |
|||
|
|||
params = { |
|||
'title': 'CouchPotato', |
|||
'message': message |
|||
} |
|||
return self.request('GUI.ShowNotification', params, client) |
@ -0,0 +1,111 @@ |
|||
from datetime import timedelta, datetime |
|||
from couchpotato.core.helpers.variable import cleanHost |
|||
from couchpotato import CPLog |
|||
from urlparse import urlparse |
|||
import traceback |
|||
|
|||
|
|||
try: |
|||
import xml.etree.cElementTree as etree |
|||
except ImportError: |
|||
import xml.etree.ElementTree as etree |
|||
|
|||
log = CPLog(__name__) |
|||
|
|||
|
|||
class PlexServer(object): |
|||
def __init__(self, plex): |
|||
self.plex = plex |
|||
|
|||
self.clients = {} |
|||
self.last_clients_update = None |
|||
|
|||
def staleClients(self): |
|||
if not self.last_clients_update: |
|||
return True |
|||
|
|||
return self.last_clients_update + timedelta(minutes=15) < datetime.now() |
|||
|
|||
def request(self, path, data_type='xml'): |
|||
if not self.plex.conf('media_server'): |
|||
log.warning("Plex media server hostname is required") |
|||
return None |
|||
|
|||
if path.startswith('/'): |
|||
path = path[1:] |
|||
|
|||
data = self.plex.urlopen('%s/%s' % ( |
|||
self.createHost(self.plex.conf('media_server'), port = 32400), |
|||
path |
|||
)) |
|||
|
|||
if data_type == 'xml': |
|||
return etree.fromstring(data) |
|||
else: |
|||
return data |
|||
|
|||
def updateClients(self): |
|||
log.info('Searching for clients on Plex Media Server') |
|||
|
|||
self.clients = {} |
|||
|
|||
result = self.request('clients') |
|||
if not result: |
|||
return |
|||
|
|||
notify_clients = [ |
|||
x.strip().lower() |
|||
for x in self.plex.conf('clients').split(',') |
|||
] |
|||
|
|||
found_clients = [ |
|||
c for c in result.findall('Server') |
|||
if c.get('name') and c.get('name').lower() in notify_clients |
|||
] |
|||
|
|||
for client in found_clients: |
|||
name = client.get('name').lower() |
|||
|
|||
self.clients[name] = { |
|||
'name': client.get('name'), |
|||
'address': client.get('address'), |
|||
'port': client.get('port'), |
|||
'protocol': client.get('protocol', 'xbmchttp') |
|||
} |
|||
|
|||
notify_clients.remove(name) |
|||
|
|||
if len(notify_clients) > 0: |
|||
log.debug('Unable to find clients: %s', ', '.join(notify_clients)) |
|||
|
|||
self.last_clients_update = datetime.now() |
|||
|
|||
def refresh(self, section_types=None): |
|||
if not section_types: |
|||
section_types = ['movie'] |
|||
|
|||
sections = self.request('library/sections') |
|||
|
|||
try: |
|||
for section in sections.findall('Directory'): |
|||
if section.get('type') not in section_types: |
|||
continue |
|||
|
|||
self.request('library/sections/%s/refresh' % section.get('key'), 'text') |
|||
except: |
|||
log.error('Plex library update failed for %s, Media Server not running: %s', |
|||
(self.plex.conf('media_server'), traceback.format_exc(1))) |
|||
return False |
|||
|
|||
return True |
|||
|
|||
def createHost(self, host, port = None): |
|||
|
|||
h = cleanHost(host) |
|||
p = urlparse(h) |
|||
h = h.rstrip('/') |
|||
|
|||
if port and not p.port: |
|||
h += ':%s' % port |
|||
|
|||
return h |
Loading…
Reference in new issue