You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
5.0 KiB
150 lines
5.0 KiB
from datetime import timedelta, datetime
|
|
from urlparse import urlparse
|
|
import traceback
|
|
|
|
from couchpotato.core.helpers.variable import cleanHost
|
|
from couchpotato import CPLog
|
|
|
|
|
|
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:]
|
|
|
|
#Maintain support for older Plex installations without myPlex
|
|
if not self.plex.conf('auth_token') and not self.plex.conf('username') and not self.plex.conf('password'):
|
|
data = self.plex.urlopen('%s/%s' % (
|
|
self.createHost(self.plex.conf('media_server'), port = 32400),
|
|
path
|
|
))
|
|
else:
|
|
#Fetch X-Plex-Token if it doesn't exist but a username/password do
|
|
if not self.plex.conf('auth_token') and (self.plex.conf('username') and self.plex.conf('password')):
|
|
import urllib2, base64
|
|
log.info("Fetching a new X-Plex-Token from plex.tv")
|
|
username = self.plex.conf('username')
|
|
password = self.plex.conf('password')
|
|
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-Product", "Couchpotato Notifier")
|
|
req.add_header("X-Plex-Client-Identifier", "b3a6b24dcab2224bdb101fc6aa08ea5e2f3147d6")
|
|
req.add_header("X-Plex-Version", "1.0")
|
|
|
|
try:
|
|
response = urllib2.urlopen(req)
|
|
except urllib2.URLError, e:
|
|
log.info("Error fetching token from plex.tv")
|
|
|
|
try:
|
|
auth_tree = etree.parse(response)
|
|
token = auth_tree.findall(".//authentication-token")[0].text
|
|
self.plex.conf('auth_token', token)
|
|
|
|
except (ValueError, IndexError) as e:
|
|
log.info("Error parsing plex.tv response: " + ex(e))
|
|
|
|
#Add X-Plex-Token header for myPlex support workaround
|
|
data = self.plex.urlopen('%s/%s?X-Plex-Token=%s' % (
|
|
self.createHost(self.plex.conf('media_server'), port = 32400),
|
|
path,
|
|
self.plex.conf('auth_token')
|
|
))
|
|
|
|
if data_type == 'xml':
|
|
return etree.fromstring(data)
|
|
else:
|
|
return data
|
|
|
|
def updateClients(self, client_names):
|
|
log.info('Searching for clients on Plex Media Server')
|
|
|
|
self.clients = {}
|
|
|
|
result = self.request('clients')
|
|
if not result:
|
|
return
|
|
|
|
found_clients = [
|
|
c for c in result.findall('Server')
|
|
if c.get('name') and c.get('name').lower() in client_names
|
|
]
|
|
|
|
# Store client details in cache
|
|
for client in found_clients:
|
|
name = client.get('name').lower()
|
|
|
|
self.clients[name] = {
|
|
'name': client.get('name'),
|
|
'found': True,
|
|
'address': client.get('address'),
|
|
'port': client.get('port'),
|
|
'protocol': client.get('protocol', 'xbmchttp')
|
|
}
|
|
|
|
client_names.remove(name)
|
|
|
|
# Store dummy info for missing clients
|
|
for client_name in client_names:
|
|
self.clients[client_name] = {
|
|
'found': False
|
|
}
|
|
|
|
if len(client_names) > 0:
|
|
log.debug('Unable to find clients: %s', ', '.join(client_names))
|
|
|
|
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
|
|
|