mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-08 14:10:52 -07:00
Create new class to handle HTTP requests
Some more clean-up
This commit is contained in:
parent
e1e3659eb3
commit
9b7f529d02
6 changed files with 456 additions and 545 deletions
|
@ -27,6 +27,7 @@ _CONFIG_DEFINITIONS = {
|
|||
'PMS_PORT': (int, 'PMS', 32400),
|
||||
'PMS_PASSWORD': (str, 'PMS', ''),
|
||||
'PMS_TOKEN': (str, 'PMS', ''),
|
||||
'PMS_SSL': (int, 'General', 0),
|
||||
'PMS_USERNAME': (str, 'PMS', ''),
|
||||
'PMS_USE_BIF': (int, 'PMS', 0),
|
||||
'PMS_UUID': (str, 'PMS', ''),
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from operator import itemgetter
|
||||
from xml.dom import minidom
|
||||
|
||||
import unicodedata
|
||||
import plexpy
|
||||
|
@ -360,3 +361,35 @@ def get_percent(value1, value2):
|
|||
percent = 0
|
||||
|
||||
return math.trunc(percent)
|
||||
|
||||
def parse_xml(unparsed=None):
|
||||
from plexpy import logger
|
||||
|
||||
if unparsed:
|
||||
try:
|
||||
xml_parse = minidom.parseString(unparsed)
|
||||
return xml_parse
|
||||
except Exception, e:
|
||||
logger.warn("Error parsing XML. %s" % e)
|
||||
return []
|
||||
except:
|
||||
logger.warn("Error parsing XML.")
|
||||
return []
|
||||
else:
|
||||
logger.warn("XML parse request made but no data received.")
|
||||
return []
|
||||
|
||||
"""
|
||||
Validate xml keys to make sure they exist and return their attribute value, return blank value is none found
|
||||
"""
|
||||
def get_xml_attr(xml_key, attribute, return_bool=False, default_return=''):
|
||||
if xml_key.getAttribute(attribute):
|
||||
if return_bool:
|
||||
return True
|
||||
else:
|
||||
return xml_key.getAttribute(attribute)
|
||||
else:
|
||||
if return_bool:
|
||||
return False
|
||||
else:
|
||||
return default_return
|
||||
|
|
93
plexpy/http_handler.py
Normal file
93
plexpy/http_handler.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
# This file is part of PlexPy.
|
||||
#
|
||||
# PlexPy is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# PlexPy is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from plexpy import logger, helpers
|
||||
|
||||
from httplib import HTTPSConnection
|
||||
from httplib import HTTPConnection
|
||||
|
||||
|
||||
class HTTPHandler(object):
|
||||
"""
|
||||
Retrieve data from Plex Server
|
||||
"""
|
||||
|
||||
def __init__(self, host, port, token):
|
||||
self.host = host
|
||||
self.port = str(port)
|
||||
self.token = token
|
||||
|
||||
"""
|
||||
Handle the HTTP requests.
|
||||
|
||||
Output: object
|
||||
"""
|
||||
def make_request(self,
|
||||
uri=None, proto='HTTP',
|
||||
request_type='GET',
|
||||
headers=None,
|
||||
output_format='raw',
|
||||
return_type=False):
|
||||
|
||||
valid_request_types = ['GET', 'POST', 'PUT', 'DELETE']
|
||||
|
||||
if request_type.upper() not in valid_request_types:
|
||||
logger.debug(u"HTTP request made but unsupported request type given.")
|
||||
return None
|
||||
|
||||
if uri:
|
||||
if proto.upper() == 'HTTPS':
|
||||
handler = HTTPSConnection(self.host, self.port, timeout=10)
|
||||
else:
|
||||
handler = HTTPConnection(self.host, self.port, timeout=10)
|
||||
|
||||
if uri.find('?') > 0:
|
||||
token_string = '&X-Plex-Token=' + self.token
|
||||
else:
|
||||
token_string = '?X-Plex-Token=' + self.token
|
||||
|
||||
try:
|
||||
if headers:
|
||||
handler.request(request_type, uri + token_string, headers=headers)
|
||||
else:
|
||||
handler.request(request_type, uri + token_string)
|
||||
response = handler.getresponse()
|
||||
request_status = response.status
|
||||
request_content = response.read()
|
||||
content_type = response.getheader('content-type')
|
||||
except IOError, e:
|
||||
logger.warn(u"Failed to access uri endpoint %s with error %s" % (uri, e))
|
||||
return None
|
||||
|
||||
if request_status == 200:
|
||||
if output_format == 'dict':
|
||||
output = helpers.convert_xml_to_dict(request_content)
|
||||
elif output_format == 'json':
|
||||
output = helpers.convert_xml_to_json(request_content)
|
||||
elif output_format == 'xml':
|
||||
output = helpers.parse_xml(request_content)
|
||||
else:
|
||||
output = request_content
|
||||
|
||||
if return_type:
|
||||
return output, content_type
|
||||
|
||||
return output
|
||||
else:
|
||||
logger.warn(u"Failed to access uri endpoint %s. Status code %r" % (uri, request_status))
|
||||
return []
|
||||
else:
|
||||
logger.debug(u"HTTP request made but no enpoint given.")
|
||||
return None
|
299
plexpy/plextv.py
299
plexpy/plextv.py
|
@ -13,10 +13,9 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from plexpy import logger, helpers, plexwatch, db
|
||||
from plexpy import logger, helpers, plexwatch, db, http_handler
|
||||
|
||||
from xml.dom import minidom
|
||||
from httplib import HTTPSConnection
|
||||
|
||||
import base64
|
||||
import plexpy
|
||||
|
@ -50,201 +49,93 @@ class PlexTV(object):
|
|||
Plex.tv authentication
|
||||
"""
|
||||
|
||||
def __init__(self, username='', password=''):
|
||||
def __init__(self, username=None, password=None):
|
||||
self.protocol = 'HTTPS'
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.url = 'plex.tv'
|
||||
|
||||
def get_plex_auth(self):
|
||||
self.request_handler = http_handler.HTTPHandler(host='plex.tv',
|
||||
port=443,
|
||||
token=plexpy.CONFIG.PMS_TOKEN)
|
||||
|
||||
http_handler = HTTPSConnection(self.url)
|
||||
def get_plex_auth(self, output_format='raw'):
|
||||
uri = '/users/sign_in.xml'
|
||||
base64string = base64.encodestring('%s:%s' % (self.username, self.password)).replace('\n', '')
|
||||
|
||||
http_handler.request("POST",
|
||||
'/users/sign_in.xml',
|
||||
headers={'Content-Type': 'application/xml; charset=utf-8',
|
||||
headers = {'Content-Type': 'application/xml; charset=utf-8',
|
||||
'Content-Length': '0',
|
||||
'X-Plex-Device-Name': 'PlexPy',
|
||||
'X-Plex-Product': 'PlexPy',
|
||||
'X-Plex-Version': 'v0.1 dev',
|
||||
'X-Plex-Client-Identifier': 'f0864d3531d75b19fa9204eaea456515e2502017',
|
||||
'X-Plex-Client-Identifier': plexpy.CONFIG.PMS_UUID,
|
||||
'Authorization': 'Basic %s' % base64string + ":"
|
||||
})
|
||||
}
|
||||
|
||||
response = http_handler.getresponse()
|
||||
request_status = response.status
|
||||
request_body = response.read()
|
||||
logger.debug(u"Plex.tv response status: %r" % request_status)
|
||||
logger.debug(u"Plex.tv response headers: %r" % response.getheaders())
|
||||
logger.debug(u"Plex.tv content type: %r" % response.getheader('content-type'))
|
||||
logger.debug(u"Plex.tv response body: %r" % request_body)
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='POST',
|
||||
headers=headers,
|
||||
output_format=output_format)
|
||||
|
||||
if request_status == 201:
|
||||
logger.info(u"Plex.tv connection successful.")
|
||||
return request_body
|
||||
elif request_status >= 400 and request_status < 500:
|
||||
logger.info(u"Plex.tv request failed: %s" % response.reason)
|
||||
return False
|
||||
else:
|
||||
logger.info(u"Plex.tv notification failed serverside.")
|
||||
return False
|
||||
return request
|
||||
|
||||
def get_token(self):
|
||||
|
||||
plextv_response = self.get_plex_auth()
|
||||
plextv_response = self.get_plex_auth(output_format='xml')
|
||||
|
||||
if plextv_response:
|
||||
try:
|
||||
xml_parse = minidom.parseString(helpers.latinToAscii(plextv_response))
|
||||
except IOError, e:
|
||||
logger.warn("Error parsing XML for Plex.tv token: %s" % e)
|
||||
return False
|
||||
|
||||
xml_head = xml_parse.getElementsByTagName('user')
|
||||
xml_head = plextv_response.getElementsByTagName('user')
|
||||
if not xml_head:
|
||||
logger.warn("Error parsing XML for Plex.tv token: %s" % e)
|
||||
return False
|
||||
return []
|
||||
|
||||
auth_token = xml_head[0].getAttribute('authenticationToken')
|
||||
|
||||
return auth_token
|
||||
else:
|
||||
return False
|
||||
return []
|
||||
|
||||
def get_plextv_user_data(self):
|
||||
|
||||
plextv_response = self.get_plex_auth()
|
||||
plextv_response = self.get_plex_auth(output_format='dict')
|
||||
|
||||
if plextv_response:
|
||||
try:
|
||||
user_data = helpers.convert_xml_to_dict(plextv_response)
|
||||
except IOError, e:
|
||||
logger.warn("Error parsing XML for Plex.tv user data: %s" % e)
|
||||
return False
|
||||
|
||||
return user_data
|
||||
return plextv_response
|
||||
else:
|
||||
return False
|
||||
return []
|
||||
|
||||
def get_plextv_friends(self, output_format=''):
|
||||
url_command = '/api/users'
|
||||
http_handler = HTTPSConnection(self.url, timeout=10)
|
||||
uri = '/api/users'
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
||||
try:
|
||||
http_handler.request("GET", url_command + '?X-Plex-Token=' + plexpy.CONFIG.PMS_TOKEN)
|
||||
response = http_handler.getresponse()
|
||||
request_status = response.status
|
||||
request_content = response.read()
|
||||
except IOError, e:
|
||||
logger.warn(u"Failed to access friends list. %s" % e)
|
||||
return None
|
||||
|
||||
if request_status == 200:
|
||||
if output_format == 'dict':
|
||||
output = helpers.convert_xml_to_dict(request_content)
|
||||
elif output_format == 'json':
|
||||
output = helpers.convert_xml_to_json(request_content)
|
||||
else:
|
||||
output = request_content
|
||||
else:
|
||||
logger.warn(u"Failed to access friends list. Status code %r" % request_status)
|
||||
return None
|
||||
|
||||
return output
|
||||
return request
|
||||
|
||||
def get_plextv_user_details(self, output_format=''):
|
||||
url_command = '/users/account'
|
||||
http_handler = HTTPSConnection(self.url, timeout=10)
|
||||
uri = '/users/account'
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
||||
try:
|
||||
http_handler.request("GET", url_command + '?X-Plex-Token=' + plexpy.CONFIG.PMS_TOKEN)
|
||||
response = http_handler.getresponse()
|
||||
request_status = response.status
|
||||
request_content = response.read()
|
||||
except IOError, e:
|
||||
logger.warn(u"Failed to access user details. %s" % e)
|
||||
return None
|
||||
|
||||
if request_status == 200:
|
||||
if output_format == 'dict':
|
||||
output = helpers.convert_xml_to_dict(request_content)
|
||||
elif output_format == 'json':
|
||||
output = helpers.convert_xml_to_json(request_content)
|
||||
else:
|
||||
output = request_content
|
||||
else:
|
||||
logger.warn(u"Failed to access user details. Status code %r" % request_status)
|
||||
return None
|
||||
|
||||
return output
|
||||
return request
|
||||
|
||||
def get_plextv_server_list(self, output_format=''):
|
||||
url_command = '/pms/servers.xml'
|
||||
http_handler = HTTPSConnection(self.url, timeout=10)
|
||||
uri = '/pms/servers.xml'
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
||||
try:
|
||||
http_handler.request("GET", url_command + '?includeLite=1&X-Plex-Token=' + plexpy.CONFIG.PMS_TOKEN)
|
||||
response = http_handler.getresponse()
|
||||
request_status = response.status
|
||||
request_content = response.read()
|
||||
except IOError, e:
|
||||
logger.warn(u"Failed to access server list. %s" % e)
|
||||
return None
|
||||
|
||||
if request_status == 200:
|
||||
if output_format == 'dict':
|
||||
output = helpers.convert_xml_to_dict(request_content)
|
||||
elif output_format == 'json':
|
||||
output = helpers.convert_xml_to_json(request_content)
|
||||
else:
|
||||
output = request_content
|
||||
else:
|
||||
logger.warn(u"Failed to access server list. Status code %r" % request_status)
|
||||
return None
|
||||
|
||||
return output
|
||||
return request
|
||||
|
||||
def get_plextv_sync_lists(self, machine_id='', output_format=''):
|
||||
url_command = '/servers/' + machine_id + '/sync_lists'
|
||||
http_handler = HTTPSConnection(self.url, timeout=10)
|
||||
uri = '/servers/' + machine_id + '/sync_lists'
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
||||
try:
|
||||
http_handler.request("GET", url_command + '?X-Plex-Token=' + plexpy.CONFIG.PMS_TOKEN)
|
||||
response = http_handler.getresponse()
|
||||
request_status = response.status
|
||||
request_content = response.read()
|
||||
except IOError, e:
|
||||
logger.warn(u"Failed to access server list. %s" % e)
|
||||
return None
|
||||
|
||||
if request_status == 200:
|
||||
if output_format == 'dict':
|
||||
output = helpers.convert_xml_to_dict(request_content)
|
||||
elif output_format == 'json':
|
||||
output = helpers.convert_xml_to_json(request_content)
|
||||
else:
|
||||
output = request_content
|
||||
else:
|
||||
logger.warn(u"Failed to access server list. Status code %r" % request_status)
|
||||
return None
|
||||
|
||||
return output
|
||||
|
||||
"""
|
||||
Validate xml keys to make sure they exist and return their attribute value, return blank value is none found
|
||||
"""
|
||||
@staticmethod
|
||||
def get_xml_attr(xml_key, attribute, return_bool=False, default_return=''):
|
||||
if xml_key.getAttribute(attribute):
|
||||
if return_bool:
|
||||
return True
|
||||
else:
|
||||
return xml_key.getAttribute(attribute)
|
||||
else:
|
||||
if return_bool:
|
||||
return False
|
||||
else:
|
||||
return default_return
|
||||
return request
|
||||
|
||||
def get_full_users_list(self):
|
||||
friends_list = self.get_plextv_friends()
|
||||
|
@ -265,13 +156,13 @@ class PlexTV(object):
|
|||
logger.warn("Error parsing XML for Plex account details.")
|
||||
else:
|
||||
for a in xml_head:
|
||||
own_details = {"user_id": self.get_xml_attr(a, 'id'),
|
||||
"username": self.get_xml_attr(a, 'username'),
|
||||
"thumb": self.get_xml_attr(a, 'thumb'),
|
||||
"email": self.get_xml_attr(a, 'email'),
|
||||
"is_home_user": self.get_xml_attr(a, 'home'),
|
||||
own_details = {"user_id": helpers.get_xml_attr(a, 'id'),
|
||||
"username": helpers.get_xml_attr(a, 'username'),
|
||||
"thumb": helpers.get_xml_attr(a, 'thumb'),
|
||||
"email": helpers.get_xml_attr(a, 'email'),
|
||||
"is_home_user": helpers.get_xml_attr(a, 'home'),
|
||||
"is_allow_sync": None,
|
||||
"is_restricted": self.get_xml_attr(a, 'restricted')
|
||||
"is_restricted": helpers.get_xml_attr(a, 'restricted')
|
||||
}
|
||||
|
||||
users_list.append(own_details)
|
||||
|
@ -288,13 +179,13 @@ class PlexTV(object):
|
|||
logger.warn("Error parsing XML for Plex friends list.")
|
||||
else:
|
||||
for a in xml_head:
|
||||
friend = {"user_id": self.get_xml_attr(a, 'id'),
|
||||
"username": self.get_xml_attr(a, 'title'),
|
||||
"thumb": self.get_xml_attr(a, 'thumb'),
|
||||
"email": self.get_xml_attr(a, 'email'),
|
||||
"is_home_user": self.get_xml_attr(a, 'home'),
|
||||
"is_allow_sync": self.get_xml_attr(a, 'allowSync'),
|
||||
"is_restricted": self.get_xml_attr(a, 'restricted')
|
||||
friend = {"user_id": helpers.get_xml_attr(a, 'id'),
|
||||
"username": helpers.get_xml_attr(a, 'title'),
|
||||
"thumb": helpers.get_xml_attr(a, 'thumb'),
|
||||
"email": helpers.get_xml_attr(a, 'email'),
|
||||
"is_home_user": helpers.get_xml_attr(a, 'home'),
|
||||
"is_allow_sync": helpers.get_xml_attr(a, 'allowSync'),
|
||||
"is_restricted": helpers.get_xml_attr(a, 'restricted')
|
||||
}
|
||||
|
||||
users_list.append(friend)
|
||||
|
@ -322,24 +213,24 @@ class PlexTV(object):
|
|||
logger.warn("Error parsing XML for Plex sync lists.")
|
||||
else:
|
||||
for a in xml_head:
|
||||
client_id = self.get_xml_attr(a, 'id')
|
||||
client_id = helpers.get_xml_attr(a, 'id')
|
||||
sync_device = a.getElementsByTagName('Device')
|
||||
for device in sync_device:
|
||||
device_user_id = self.get_xml_attr(device, 'userID')
|
||||
device_user_id = helpers.get_xml_attr(device, 'userID')
|
||||
try:
|
||||
device_username = plex_watch.get_user_details(user_id=device_user_id)['username']
|
||||
device_friendly_name = plex_watch.get_user_details(user_id=device_user_id)['friendly_name']
|
||||
except:
|
||||
device_username = ''
|
||||
device_friendly_name = ''
|
||||
device_name = self.get_xml_attr(device, 'name')
|
||||
device_product = self.get_xml_attr(device, 'product')
|
||||
device_product_version = self.get_xml_attr(device, 'productVersion')
|
||||
device_platform = self.get_xml_attr(device, 'platform')
|
||||
device_platform_version = self.get_xml_attr(device, 'platformVersion')
|
||||
device_type = self.get_xml_attr(device, 'device')
|
||||
device_model = self.get_xml_attr(device, 'model')
|
||||
device_last_seen = self.get_xml_attr(device, 'lastSeenAt')
|
||||
device_name = helpers.get_xml_attr(device, 'name')
|
||||
device_product = helpers.get_xml_attr(device, 'product')
|
||||
device_product_version = helpers.get_xml_attr(device, 'productVersion')
|
||||
device_platform = helpers.get_xml_attr(device, 'platform')
|
||||
device_platform_version = helpers.get_xml_attr(device, 'platformVersion')
|
||||
device_type = helpers.get_xml_attr(device, 'device')
|
||||
device_model = helpers.get_xml_attr(device, 'model')
|
||||
device_last_seen = helpers.get_xml_attr(device, 'lastSeenAt')
|
||||
|
||||
# Filter by user_id
|
||||
if user_id and user_id != device_user_id:
|
||||
|
@ -348,38 +239,38 @@ class PlexTV(object):
|
|||
for synced in a.getElementsByTagName('SyncItems'):
|
||||
sync_item = synced.getElementsByTagName('SyncItem')
|
||||
for item in sync_item:
|
||||
sync_id = self.get_xml_attr(item, 'id')
|
||||
sync_version = self.get_xml_attr(item, 'version')
|
||||
sync_root_title = self.get_xml_attr(item, 'rootTitle')
|
||||
sync_title = self.get_xml_attr(item, 'title')
|
||||
sync_metadata_type = self.get_xml_attr(item, 'metadataType')
|
||||
sync_content_type = self.get_xml_attr(item, 'contentType')
|
||||
sync_id = helpers.get_xml_attr(item, 'id')
|
||||
sync_version = helpers.get_xml_attr(item, 'version')
|
||||
sync_root_title = helpers.get_xml_attr(item, 'rootTitle')
|
||||
sync_title = helpers.get_xml_attr(item, 'title')
|
||||
sync_metadata_type = helpers.get_xml_attr(item, 'metadataType')
|
||||
sync_content_type = helpers.get_xml_attr(item, 'contentType')
|
||||
|
||||
for status in item.getElementsByTagName('Status'):
|
||||
status_failure_code = self.get_xml_attr(status, 'failureCode')
|
||||
status_failure = self.get_xml_attr(status, 'failure')
|
||||
status_state = self.get_xml_attr(status, 'state')
|
||||
status_item_count = self.get_xml_attr(status, 'itemsCount')
|
||||
status_item_complete_count = self.get_xml_attr(status, 'itemsCompleteCount')
|
||||
status_item_downloaded_count = self.get_xml_attr(status, 'itemsDownloadedCount')
|
||||
status_item_ready_count = self.get_xml_attr(status, 'itemsReadyCount')
|
||||
status_item_successful_count = self.get_xml_attr(status, 'itemsSuccessfulCount')
|
||||
status_total_size = self.get_xml_attr(status, 'totalSize')
|
||||
status_failure_code = helpers.get_xml_attr(status, 'failureCode')
|
||||
status_failure = helpers.get_xml_attr(status, 'failure')
|
||||
status_state = helpers.get_xml_attr(status, 'state')
|
||||
status_item_count = helpers.get_xml_attr(status, 'itemsCount')
|
||||
status_item_complete_count = helpers.get_xml_attr(status, 'itemsCompleteCount')
|
||||
status_item_downloaded_count = helpers.get_xml_attr(status, 'itemsDownloadedCount')
|
||||
status_item_ready_count = helpers.get_xml_attr(status, 'itemsReadyCount')
|
||||
status_item_successful_count = helpers.get_xml_attr(status, 'itemsSuccessfulCount')
|
||||
status_total_size = helpers.get_xml_attr(status, 'totalSize')
|
||||
status_item_download_percent_complete = helpers.get_percent(
|
||||
status_item_downloaded_count, status_item_count)
|
||||
|
||||
for settings in item.getElementsByTagName('MediaSettings'):
|
||||
settings_audio_boost = self.get_xml_attr(settings, 'audioBoost')
|
||||
settings_music_bitrate = self.get_xml_attr(settings, 'musicBitrate')
|
||||
settings_photo_quality = self.get_xml_attr(settings, 'photoQuality')
|
||||
settings_photo_resolution = self.get_xml_attr(settings, 'photoResolution')
|
||||
settings_video_quality = self.get_xml_attr(settings, 'videoQuality')
|
||||
settings_video_resolution = self.get_xml_attr(settings, 'videoResolution')
|
||||
settings_audio_boost = helpers.get_xml_attr(settings, 'audioBoost')
|
||||
settings_music_bitrate = helpers.get_xml_attr(settings, 'musicBitrate')
|
||||
settings_photo_quality = helpers.get_xml_attr(settings, 'photoQuality')
|
||||
settings_photo_resolution = helpers.get_xml_attr(settings, 'photoResolution')
|
||||
settings_video_quality = helpers.get_xml_attr(settings, 'videoQuality')
|
||||
settings_video_resolution = helpers.get_xml_attr(settings, 'videoResolution')
|
||||
|
||||
if self.get_xml_attr(item.getElementsByTagName('Location')[0], 'uri').endswith('%2Fchildren'):
|
||||
clean_uri = self.get_xml_attr(item.getElementsByTagName('Location')[0], 'uri')[:-11]
|
||||
if helpers.get_xml_attr(item.getElementsByTagName('Location')[0], 'uri').endswith('%2Fchildren'):
|
||||
clean_uri = helpers.get_xml_attr(item.getElementsByTagName('Location')[0], 'uri')[:-11]
|
||||
else:
|
||||
clean_uri = self.get_xml_attr(item.getElementsByTagName('Location')[0], 'uri')
|
||||
clean_uri = helpers.get_xml_attr(item.getElementsByTagName('Location')[0], 'uri')
|
||||
|
||||
rating_key = clean_uri.rpartition('%2F')[-1]
|
||||
|
||||
|
|
|
@ -13,11 +13,7 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from plexpy import logger, helpers, plexwatch
|
||||
|
||||
from xml.dom import minidom
|
||||
from httplib import HTTPSConnection
|
||||
from httplib import HTTPConnection
|
||||
from plexpy import logger, helpers, plexwatch, http_handler
|
||||
|
||||
import plexpy
|
||||
|
||||
|
@ -28,88 +24,10 @@ class PmsConnect(object):
|
|||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.host = plexpy.CONFIG.PMS_IP
|
||||
self.port = str(plexpy.CONFIG.PMS_PORT)
|
||||
self.token = plexpy.CONFIG.PMS_TOKEN
|
||||
self.protocol = 'HTTP'
|
||||
|
||||
"""
|
||||
Return base url of Plex Server.
|
||||
|
||||
Output: string
|
||||
"""
|
||||
def get_base_url(self):
|
||||
if self.host != '' and self.port != '':
|
||||
base_url = self.protocol + self.host + ':' + self.port
|
||||
return base_url
|
||||
else:
|
||||
return False
|
||||
|
||||
"""
|
||||
Handle the HTTP requests.
|
||||
|
||||
Output: object
|
||||
"""
|
||||
def make_request(self, uri=None, proto='HTTP', request_type='GET', output_format='xml'):
|
||||
|
||||
valid_request_types = ['GET', 'POST', 'PUT', 'DELETE']
|
||||
|
||||
if request_type.upper() not in valid_request_types:
|
||||
logger.debug(u"HTTP request made but unsupported request type given.")
|
||||
return None
|
||||
|
||||
if uri:
|
||||
if proto.upper() == 'HTTPS':
|
||||
handler = HTTPSConnection(self.host, self.port, timeout=10)
|
||||
else:
|
||||
handler = HTTPConnection(self.host, self.port, timeout=10)
|
||||
|
||||
if uri.find('?') > 0:
|
||||
token_string = '&X-Plex-Token=' + self.token
|
||||
else:
|
||||
token_string = '?X-Plex-Token=' + self.token
|
||||
|
||||
try:
|
||||
handler.request(request_type, uri + token_string)
|
||||
response = handler.getresponse()
|
||||
request_status = response.status
|
||||
request_content = response.read()
|
||||
except IOError, e:
|
||||
logger.warn(u"Failed to access uri endpoint %s with error %s" % (uri, e))
|
||||
return None
|
||||
|
||||
if request_status == 200:
|
||||
if output_format == 'dict':
|
||||
output = helpers.convert_xml_to_dict(request_content)
|
||||
elif output_format == 'json':
|
||||
output = helpers.convert_xml_to_json(request_content)
|
||||
elif output_format == 'xml':
|
||||
output = self.parse_xml(request_content)
|
||||
else:
|
||||
output = request_content
|
||||
|
||||
return output
|
||||
else:
|
||||
logger.warn(u"Failed to access uri endpoint %s. Status code %r" % (uri, request_status))
|
||||
return []
|
||||
else:
|
||||
logger.debug(u"HTTP request made but no enpoint given.")
|
||||
return None
|
||||
|
||||
def parse_xml(self, unparsed=None):
|
||||
if unparsed:
|
||||
try:
|
||||
xml_parse = minidom.parseString(unparsed)
|
||||
return xml_parse
|
||||
except Exception, e:
|
||||
logger.warn("Error parsing XML for Plex recently added: %s" % e)
|
||||
return []
|
||||
except:
|
||||
logger.warn("Error parsing XML for Plex recently added.")
|
||||
return []
|
||||
else:
|
||||
logger.warn("XML parse request made but no data received.")
|
||||
return []
|
||||
self.protocol = 'HTTPS'
|
||||
self.request_handler = http_handler.HTTPHandler(host=plexpy.CONFIG.PMS_IP,
|
||||
port=plexpy.CONFIG.PMS_PORT,
|
||||
token=plexpy.CONFIG.PMS_TOKEN)
|
||||
|
||||
"""
|
||||
Return current sessions.
|
||||
|
@ -120,7 +38,7 @@ class PmsConnect(object):
|
|||
"""
|
||||
def get_sessions(self, output_format=''):
|
||||
uri = '/status/sessions'
|
||||
request = self.make_request(uri=uri,
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
@ -137,7 +55,7 @@ class PmsConnect(object):
|
|||
"""
|
||||
def get_metadata(self, rating_key='', output_format=''):
|
||||
uri = '/library/metadata/' + rating_key
|
||||
request = self.make_request(uri=uri,
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
@ -154,7 +72,7 @@ class PmsConnect(object):
|
|||
"""
|
||||
def get_recently_added(self, count='0', output_format=''):
|
||||
uri = '/library/recentlyAdded?X-Plex-Container-Start=0&X-Plex-Container-Size=' + count
|
||||
request = self.make_request(uri=uri,
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
@ -171,7 +89,7 @@ class PmsConnect(object):
|
|||
"""
|
||||
def get_episode_list(self, rating_key='', output_format=''):
|
||||
uri = '/library/metadata/' + rating_key + '/children'
|
||||
request = self.make_request(uri=uri,
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
@ -187,7 +105,7 @@ class PmsConnect(object):
|
|||
"""
|
||||
def get_server_list(self, output_format=''):
|
||||
uri = '/servers'
|
||||
request = self.make_request(uri=uri,
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
@ -203,7 +121,7 @@ class PmsConnect(object):
|
|||
"""
|
||||
def get_server_prefs(self, output_format=''):
|
||||
uri = '/:/prefs'
|
||||
request = self.make_request(uri=uri,
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
@ -219,7 +137,7 @@ class PmsConnect(object):
|
|||
"""
|
||||
def get_local_server_identity(self, output_format=''):
|
||||
uri = '/identity'
|
||||
request = self.make_request(uri=uri,
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
@ -236,7 +154,7 @@ class PmsConnect(object):
|
|||
"""
|
||||
def get_sync_item(self, sync_id=None, output_format=''):
|
||||
uri = '/sync/items/' + sync_id
|
||||
request = self.make_request(uri=uri,
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
@ -252,7 +170,7 @@ class PmsConnect(object):
|
|||
"""
|
||||
def get_sync_transcode_queue(self, output_format=''):
|
||||
uri = '/sync/transcodeQueue'
|
||||
request = self.make_request(uri=uri,
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
@ -284,14 +202,14 @@ class PmsConnect(object):
|
|||
if a.getElementsByTagName('Directory'):
|
||||
recents_main = a.getElementsByTagName('Directory')
|
||||
for item in recents_main:
|
||||
recent_type = self.get_xml_attr(item, 'type')
|
||||
recent_type = helpers.get_xml_attr(item, 'type')
|
||||
|
||||
if recent_type == 'season':
|
||||
recent_items = {'type': recent_type,
|
||||
'ratingKey': self.get_xml_attr(item, 'ratingKey'),
|
||||
'title': self.get_xml_attr(item, 'title'),
|
||||
'thumb': self.get_xml_attr(item, 'thumb'),
|
||||
'addedAt': self.get_xml_attr(item, 'addedAt')
|
||||
'ratingKey': helpers.get_xml_attr(item, 'ratingKey'),
|
||||
'title': helpers.get_xml_attr(item, 'title'),
|
||||
'thumb': helpers.get_xml_attr(item, 'thumb'),
|
||||
'addedAt': helpers.get_xml_attr(item, 'addedAt')
|
||||
}
|
||||
recents_list.append(recent_items)
|
||||
else:
|
||||
|
@ -300,15 +218,15 @@ class PmsConnect(object):
|
|||
if a.getElementsByTagName('Video'):
|
||||
recents_main = a.getElementsByTagName('Video')
|
||||
for item in recents_main:
|
||||
recent_type = self.get_xml_attr(item, 'type')
|
||||
recent_type = helpers.get_xml_attr(item, 'type')
|
||||
|
||||
if recent_type == 'movie':
|
||||
recent_items = {'type': recent_type,
|
||||
'ratingKey': self.get_xml_attr(item, 'ratingKey'),
|
||||
'title': self.get_xml_attr(item, 'title'),
|
||||
'year': self.get_xml_attr(item, 'year'),
|
||||
'thumb': self.get_xml_attr(item, 'thumb'),
|
||||
'addedAt': self.get_xml_attr(item, 'addedAt')
|
||||
'ratingKey': helpers.get_xml_attr(item, 'ratingKey'),
|
||||
'title': helpers.get_xml_attr(item, 'title'),
|
||||
'year': helpers.get_xml_attr(item, 'year'),
|
||||
'thumb': helpers.get_xml_attr(item, 'thumb'),
|
||||
'addedAt': helpers.get_xml_attr(item, 'addedAt')
|
||||
}
|
||||
recents_list.append(recent_items)
|
||||
else:
|
||||
|
@ -342,10 +260,10 @@ class PmsConnect(object):
|
|||
|
||||
if a.getElementsByTagName('Directory'):
|
||||
metadata_main = a.getElementsByTagName('Directory')[0]
|
||||
metadata_type = self.get_xml_attr(metadata_main, 'type')
|
||||
metadata_type = helpers.get_xml_attr(metadata_main, 'type')
|
||||
elif a.getElementsByTagName('Video'):
|
||||
metadata_main = a.getElementsByTagName('Video')[0]
|
||||
metadata_type = self.get_xml_attr(metadata_main, 'type')
|
||||
metadata_type = helpers.get_xml_attr(metadata_main, 'type')
|
||||
else:
|
||||
logger.debug(u"Metadata failed")
|
||||
|
||||
|
@ -356,38 +274,38 @@ class PmsConnect(object):
|
|||
|
||||
if metadata_main.getElementsByTagName('Genre'):
|
||||
for genre in metadata_main.getElementsByTagName('Genre'):
|
||||
genres.append(self.get_xml_attr(genre, 'tag'))
|
||||
genres.append(helpers.get_xml_attr(genre, 'tag'))
|
||||
|
||||
if metadata_main.getElementsByTagName('Role'):
|
||||
for actor in metadata_main.getElementsByTagName('Role'):
|
||||
actors.append(self.get_xml_attr(actor, 'tag'))
|
||||
actors.append(helpers.get_xml_attr(actor, 'tag'))
|
||||
|
||||
if metadata_main.getElementsByTagName('Writer'):
|
||||
for writer in metadata_main.getElementsByTagName('Writer'):
|
||||
writers.append(self.get_xml_attr(writer, 'tag'))
|
||||
writers.append(helpers.get_xml_attr(writer, 'tag'))
|
||||
|
||||
if metadata_main.getElementsByTagName('Director'):
|
||||
for director in metadata_main.getElementsByTagName('Director'):
|
||||
directors.append(self.get_xml_attr(director, 'tag'))
|
||||
directors.append(helpers.get_xml_attr(director, 'tag'))
|
||||
|
||||
if metadata_type == 'show':
|
||||
metadata = {'type': metadata_type,
|
||||
'rating_key': self.get_xml_attr(metadata_main, 'ratingKey'),
|
||||
'grandparent_title': self.get_xml_attr(metadata_main, 'grandparentTitle'),
|
||||
'parent_index': self.get_xml_attr(metadata_main, 'parentIndex'),
|
||||
'parent_title': self.get_xml_attr(metadata_main, 'parentTitle'),
|
||||
'index': self.get_xml_attr(metadata_main, 'index'),
|
||||
'studio': self.get_xml_attr(metadata_main, 'studio'),
|
||||
'title': self.get_xml_attr(metadata_main, 'title'),
|
||||
'content_rating': self.get_xml_attr(metadata_main, 'contentRating'),
|
||||
'summary': self.get_xml_attr(metadata_main, 'summary'),
|
||||
'rating': self.get_xml_attr(metadata_main, 'rating'),
|
||||
'duration': helpers.convert_milliseconds_to_minutes(self.get_xml_attr(metadata_main, 'duration')),
|
||||
'year': self.get_xml_attr(metadata_main, 'year'),
|
||||
'thumb': self.get_xml_attr(metadata_main, 'thumb'),
|
||||
'parent_thumb': self.get_xml_attr(metadata_main, 'parentThumb'),
|
||||
'art': self.get_xml_attr(metadata_main, 'art'),
|
||||
'originally_available_at': self.get_xml_attr(metadata_main, 'originallyAvailableAt'),
|
||||
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||
'grandparent_title': helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
|
||||
'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
|
||||
'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'),
|
||||
'index': helpers.get_xml_attr(metadata_main, 'index'),
|
||||
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
|
||||
'title': helpers.get_xml_attr(metadata_main, 'title'),
|
||||
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
|
||||
'summary': helpers.get_xml_attr(metadata_main, 'summary'),
|
||||
'rating': helpers.get_xml_attr(metadata_main, 'rating'),
|
||||
'duration': helpers.convert_milliseconds_to_minutes(helpers.get_xml_attr(metadata_main, 'duration')),
|
||||
'year': helpers.get_xml_attr(metadata_main, 'year'),
|
||||
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
|
||||
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
|
||||
'art': helpers.get_xml_attr(metadata_main, 'art'),
|
||||
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
|
||||
'writers': writers,
|
||||
'directors': directors,
|
||||
'genres': genres,
|
||||
|
@ -396,22 +314,22 @@ class PmsConnect(object):
|
|||
metadata_list = {'metadata': metadata}
|
||||
elif metadata_type == 'episode':
|
||||
metadata = {'type': metadata_type,
|
||||
'rating_key': self.get_xml_attr(metadata_main, 'ratingKey'),
|
||||
'grandparent_title': self.get_xml_attr(metadata_main, 'grandparentTitle'),
|
||||
'parent_index': self.get_xml_attr(metadata_main, 'parentIndex'),
|
||||
'parent_title': self.get_xml_attr(metadata_main, 'parentTitle'),
|
||||
'index': self.get_xml_attr(metadata_main, 'index'),
|
||||
'studio': self.get_xml_attr(metadata_main, 'studio'),
|
||||
'title': self.get_xml_attr(metadata_main, 'title'),
|
||||
'content_rating': self.get_xml_attr(metadata_main, 'contentRating'),
|
||||
'summary': self.get_xml_attr(metadata_main, 'summary'),
|
||||
'rating': self.get_xml_attr(metadata_main, 'rating'),
|
||||
'duration': helpers.convert_milliseconds_to_minutes(self.get_xml_attr(metadata_main, 'duration')),
|
||||
'year': self.get_xml_attr(metadata_main, 'year'),
|
||||
'thumb': self.get_xml_attr(metadata_main, 'thumb'),
|
||||
'parent_thumb': self.get_xml_attr(metadata_main, 'parentThumb'),
|
||||
'art': self.get_xml_attr(metadata_main, 'art'),
|
||||
'originally_available_at': self.get_xml_attr(metadata_main, 'originallyAvailableAt'),
|
||||
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||
'grandparent_title': helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
|
||||
'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
|
||||
'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'),
|
||||
'index': helpers.get_xml_attr(metadata_main, 'index'),
|
||||
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
|
||||
'title': helpers.get_xml_attr(metadata_main, 'title'),
|
||||
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
|
||||
'summary': helpers.get_xml_attr(metadata_main, 'summary'),
|
||||
'rating': helpers.get_xml_attr(metadata_main, 'rating'),
|
||||
'duration': helpers.convert_milliseconds_to_minutes(helpers.get_xml_attr(metadata_main, 'duration')),
|
||||
'year': helpers.get_xml_attr(metadata_main, 'year'),
|
||||
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
|
||||
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
|
||||
'art': helpers.get_xml_attr(metadata_main, 'art'),
|
||||
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
|
||||
'writers': writers,
|
||||
'directors': directors,
|
||||
'genres': genres,
|
||||
|
@ -420,22 +338,22 @@ class PmsConnect(object):
|
|||
metadata_list = {'metadata': metadata}
|
||||
elif metadata_type == 'movie':
|
||||
metadata = {'type': metadata_type,
|
||||
'rating_key': self.get_xml_attr(metadata_main, 'ratingKey'),
|
||||
'grandparent_title': self.get_xml_attr(metadata_main, 'grandparentTitle'),
|
||||
'parent_index': self.get_xml_attr(metadata_main, 'parentIndex'),
|
||||
'parent_title': self.get_xml_attr(metadata_main, 'parentTitle'),
|
||||
'index': self.get_xml_attr(metadata_main, 'index'),
|
||||
'studio': self.get_xml_attr(metadata_main, 'studio'),
|
||||
'title': self.get_xml_attr(metadata_main, 'title'),
|
||||
'content_rating': self.get_xml_attr(metadata_main, 'contentRating'),
|
||||
'summary': self.get_xml_attr(metadata_main, 'summary'),
|
||||
'rating': self.get_xml_attr(metadata_main, 'rating'),
|
||||
'duration': helpers.convert_milliseconds_to_minutes(self.get_xml_attr(metadata_main, 'duration')),
|
||||
'year': self.get_xml_attr(metadata_main, 'year'),
|
||||
'thumb': self.get_xml_attr(metadata_main, 'thumb'),
|
||||
'parent_thumb': self.get_xml_attr(metadata_main, 'parentThumb'),
|
||||
'art': self.get_xml_attr(metadata_main, 'art'),
|
||||
'originally_available_at': self.get_xml_attr(metadata_main, 'originallyAvailableAt'),
|
||||
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||
'grandparent_title': helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
|
||||
'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
|
||||
'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'),
|
||||
'index': helpers.get_xml_attr(metadata_main, 'index'),
|
||||
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
|
||||
'title': helpers.get_xml_attr(metadata_main, 'title'),
|
||||
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
|
||||
'summary': helpers.get_xml_attr(metadata_main, 'summary'),
|
||||
'rating': helpers.get_xml_attr(metadata_main, 'rating'),
|
||||
'duration': helpers.convert_milliseconds_to_minutes(helpers.get_xml_attr(metadata_main, 'duration')),
|
||||
'year': helpers.get_xml_attr(metadata_main, 'year'),
|
||||
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
|
||||
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
|
||||
'art': helpers.get_xml_attr(metadata_main, 'art'),
|
||||
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
|
||||
'genres': genres,
|
||||
'actors': actors,
|
||||
'writers': writers,
|
||||
|
@ -443,25 +361,25 @@ class PmsConnect(object):
|
|||
}
|
||||
metadata_list = {'metadata': metadata}
|
||||
elif metadata_type == 'season':
|
||||
parent_rating_key = self.get_xml_attr(metadata_main, 'parentRatingKey')
|
||||
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
|
||||
show_details = self.get_metadata_details(parent_rating_key)
|
||||
metadata = {'type': metadata_type,
|
||||
'rating_key': self.get_xml_attr(metadata_main, 'ratingKey'),
|
||||
'grandparent_title': self.get_xml_attr(metadata_main, 'grandparentTitle'),
|
||||
'parent_index': self.get_xml_attr(metadata_main, 'parentIndex'),
|
||||
'parent_title': self.get_xml_attr(metadata_main, 'parentTitle'),
|
||||
'index': self.get_xml_attr(metadata_main, 'index'),
|
||||
'studio': self.get_xml_attr(metadata_main, 'studio'),
|
||||
'title': self.get_xml_attr(metadata_main, 'title'),
|
||||
'content_rating': self.get_xml_attr(metadata_main, 'contentRating'),
|
||||
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||
'grandparent_title': helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
|
||||
'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
|
||||
'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'),
|
||||
'index': helpers.get_xml_attr(metadata_main, 'index'),
|
||||
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
|
||||
'title': helpers.get_xml_attr(metadata_main, 'title'),
|
||||
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
|
||||
'summary': show_details['metadata']['summary'],
|
||||
'rating': self.get_xml_attr(metadata_main, 'rating'),
|
||||
'rating': helpers.get_xml_attr(metadata_main, 'rating'),
|
||||
'duration': show_details['metadata']['duration'],
|
||||
'year': self.get_xml_attr(metadata_main, 'year'),
|
||||
'thumb': self.get_xml_attr(metadata_main, 'thumb'),
|
||||
'parent_thumb': self.get_xml_attr(metadata_main, 'parentThumb'),
|
||||
'art': self.get_xml_attr(metadata_main, 'art'),
|
||||
'originally_available_at': self.get_xml_attr(metadata_main, 'originallyAvailableAt'),
|
||||
'year': helpers.get_xml_attr(metadata_main, 'year'),
|
||||
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
|
||||
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
|
||||
'art': helpers.get_xml_attr(metadata_main, 'art'),
|
||||
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
|
||||
'genres': genres,
|
||||
'actors': actors,
|
||||
'writers': writers,
|
||||
|
@ -473,22 +391,6 @@ class PmsConnect(object):
|
|||
|
||||
return metadata_list
|
||||
|
||||
"""
|
||||
Validate xml keys to make sure they exist and return their attribute value, return blank value is none found
|
||||
"""
|
||||
@staticmethod
|
||||
def get_xml_attr(xml_key, attribute, return_bool=False, default_return=''):
|
||||
if xml_key.getAttribute(attribute):
|
||||
if return_bool:
|
||||
return True
|
||||
else:
|
||||
return xml_key.getAttribute(attribute)
|
||||
else:
|
||||
if return_bool:
|
||||
return False
|
||||
else:
|
||||
return default_return
|
||||
|
||||
"""
|
||||
Return processed and validated session list.
|
||||
|
||||
|
@ -524,7 +426,7 @@ class PmsConnect(object):
|
|||
session_output = self.get_session_each(session_type, session)
|
||||
session_list.append(session_output)
|
||||
|
||||
output = {'stream_count': self.get_xml_attr(xml_head[0], 'size'),
|
||||
output = {'stream_count': helpers.get_xml_attr(xml_head[0], 'size'),
|
||||
'sessions': session_list
|
||||
}
|
||||
|
||||
|
@ -544,32 +446,32 @@ class PmsConnect(object):
|
|||
if stream_type == 'track':
|
||||
if session.getElementsByTagName('TranscodeSession'):
|
||||
transcode_session = session.getElementsByTagName('TranscodeSession')[0]
|
||||
audio_decision = self.get_xml_attr(transcode_session, 'audioDecision')
|
||||
audio_channels = self.get_xml_attr(transcode_session, 'audioChannels')
|
||||
audio_codec = self.get_xml_attr(transcode_session, 'audioCodec')
|
||||
duration = self.get_xml_attr(transcode_session, 'duration')
|
||||
progress = self.get_xml_attr(session, 'viewOffset')
|
||||
audio_decision = helpers.get_xml_attr(transcode_session, 'audioDecision')
|
||||
audio_channels = helpers.get_xml_attr(transcode_session, 'audioChannels')
|
||||
audio_codec = helpers.get_xml_attr(transcode_session, 'audioCodec')
|
||||
duration = helpers.get_xml_attr(transcode_session, 'duration')
|
||||
progress = helpers.get_xml_attr(session, 'viewOffset')
|
||||
else:
|
||||
media_info = session.getElementsByTagName('Media')[0]
|
||||
audio_decision = 'direct play'
|
||||
audio_channels = self.get_xml_attr(media_info, 'audioChannels')
|
||||
audio_codec = self.get_xml_attr(media_info, 'audioCodec')
|
||||
duration = self.get_xml_attr(media_info, 'duration')
|
||||
progress = self.get_xml_attr(session, 'viewOffset')
|
||||
audio_channels = helpers.get_xml_attr(media_info, 'audioChannels')
|
||||
audio_codec = helpers.get_xml_attr(media_info, 'audioCodec')
|
||||
duration = helpers.get_xml_attr(media_info, 'duration')
|
||||
progress = helpers.get_xml_attr(session, 'viewOffset')
|
||||
|
||||
session_output = {'session_key': self.get_xml_attr(session, 'sessionKey'),
|
||||
'art': self.get_xml_attr(session, 'art'),
|
||||
'parent_thumb': self.get_xml_attr(session, 'parentThumb'),
|
||||
'thumb': self.get_xml_attr(session, 'thumb'),
|
||||
'user': self.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
|
||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||
'art': helpers.get_xml_attr(session, 'art'),
|
||||
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
|
||||
'thumb': helpers.get_xml_attr(session, 'thumb'),
|
||||
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
|
||||
'friendly_name': plex_watch.get_user_friendly_name(
|
||||
self.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
|
||||
'player': self.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||
'state': self.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
|
||||
'grandparent_title': self.get_xml_attr(session, 'grandparentTitle'),
|
||||
'parent_title': self.get_xml_attr(session, 'parentTitle'),
|
||||
'title': self.get_xml_attr(session, 'title'),
|
||||
'rating_key': self.get_xml_attr(session, 'ratingKey'),
|
||||
helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
|
||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||
'state': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
|
||||
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
|
||||
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
|
||||
'title': helpers.get_xml_attr(session, 'title'),
|
||||
'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
|
||||
'audio_decision': audio_decision,
|
||||
'audio_channels': audio_channels,
|
||||
'audio_codec': audio_codec,
|
||||
|
@ -586,31 +488,31 @@ class PmsConnect(object):
|
|||
elif stream_type == 'video':
|
||||
if session.getElementsByTagName('TranscodeSession'):
|
||||
transcode_session = session.getElementsByTagName('TranscodeSession')[0]
|
||||
audio_decision = self.get_xml_attr(transcode_session, 'audioDecision')
|
||||
audio_channels = self.get_xml_attr(transcode_session, 'audioChannels')
|
||||
audio_codec = self.get_xml_attr(transcode_session, 'audioCodec')
|
||||
video_decision = self.get_xml_attr(transcode_session, 'videoDecision')
|
||||
video_codec = self.get_xml_attr(transcode_session, 'videoCodec')
|
||||
width = self.get_xml_attr(transcode_session, 'width')
|
||||
height = self.get_xml_attr(transcode_session, 'height')
|
||||
duration = self.get_xml_attr(session, 'duration')
|
||||
progress = self.get_xml_attr(session, 'viewOffset')
|
||||
audio_decision = helpers.get_xml_attr(transcode_session, 'audioDecision')
|
||||
audio_channels = helpers.get_xml_attr(transcode_session, 'audioChannels')
|
||||
audio_codec = helpers.get_xml_attr(transcode_session, 'audioCodec')
|
||||
video_decision = helpers.get_xml_attr(transcode_session, 'videoDecision')
|
||||
video_codec = helpers.get_xml_attr(transcode_session, 'videoCodec')
|
||||
width = helpers.get_xml_attr(transcode_session, 'width')
|
||||
height = helpers.get_xml_attr(transcode_session, 'height')
|
||||
duration = helpers.get_xml_attr(session, 'duration')
|
||||
progress = helpers.get_xml_attr(session, 'viewOffset')
|
||||
else:
|
||||
media_info = session.getElementsByTagName('Media')[0]
|
||||
audio_decision = 'direct play'
|
||||
audio_channels = self.get_xml_attr(media_info, 'audioChannels')
|
||||
audio_codec = self.get_xml_attr(media_info, 'audioCodec')
|
||||
audio_channels = helpers.get_xml_attr(media_info, 'audioChannels')
|
||||
audio_codec = helpers.get_xml_attr(media_info, 'audioCodec')
|
||||
video_decision = 'direct play'
|
||||
video_codec = self.get_xml_attr(media_info, 'videoCodec')
|
||||
width = self.get_xml_attr(media_info, 'width')
|
||||
height = self.get_xml_attr(media_info, 'height')
|
||||
duration = self.get_xml_attr(media_info, 'duration')
|
||||
progress = self.get_xml_attr(session, 'viewOffset')
|
||||
video_codec = helpers.get_xml_attr(media_info, 'videoCodec')
|
||||
width = helpers.get_xml_attr(media_info, 'width')
|
||||
height = helpers.get_xml_attr(media_info, 'height')
|
||||
duration = helpers.get_xml_attr(media_info, 'duration')
|
||||
progress = helpers.get_xml_attr(session, 'viewOffset')
|
||||
|
||||
media_info = session.getElementsByTagName('Media')[0]
|
||||
if media_info.getElementsByTagName('Part'):
|
||||
indexes = self.get_xml_attr(media_info.getElementsByTagName('Part')[0], 'indexes')
|
||||
part_id = self.get_xml_attr(media_info.getElementsByTagName('Part')[0], 'id')
|
||||
indexes = helpers.get_xml_attr(media_info.getElementsByTagName('Part')[0], 'indexes')
|
||||
part_id = helpers.get_xml_attr(media_info.getElementsByTagName('Part')[0], 'id')
|
||||
if indexes == 'sd':
|
||||
bif_thumb = '/library/parts/' + part_id + '/indexes/sd/' + progress
|
||||
else:
|
||||
|
@ -623,23 +525,23 @@ class PmsConnect(object):
|
|||
thumb = bif_thumb
|
||||
use_indexes = 1
|
||||
else:
|
||||
thumb = self.get_xml_attr(session, 'thumb')
|
||||
thumb = helpers.get_xml_attr(session, 'thumb')
|
||||
use_indexes = 0
|
||||
|
||||
if self.get_xml_attr(session, 'type') == 'episode':
|
||||
session_output = {'session_key': self.get_xml_attr(session, 'sessionKey'),
|
||||
'art': self.get_xml_attr(session, 'art'),
|
||||
'parent_thumb': self.get_xml_attr(session, 'parentThumb'),
|
||||
if helpers.get_xml_attr(session, 'type') == 'episode':
|
||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||
'art': helpers.get_xml_attr(session, 'art'),
|
||||
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
|
||||
'thumb': thumb,
|
||||
'user': self.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
|
||||
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
|
||||
'friendly_name': plex_watch.get_user_friendly_name(
|
||||
self.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
|
||||
'player': self.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||
'state': self.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
|
||||
'grandparent_title': self.get_xml_attr(session, 'grandparentTitle'),
|
||||
'parent_title': self.get_xml_attr(session, 'parentTitle'),
|
||||
'title': self.get_xml_attr(session, 'title'),
|
||||
'rating_key': self.get_xml_attr(session, 'ratingKey'),
|
||||
helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
|
||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||
'state': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
|
||||
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
|
||||
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
|
||||
'title': helpers.get_xml_attr(session, 'title'),
|
||||
'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
|
||||
'audio_decision': audio_decision,
|
||||
'audio_channels': audio_channels,
|
||||
'audio_codec': audio_codec,
|
||||
|
@ -650,23 +552,23 @@ class PmsConnect(object):
|
|||
'duration': duration,
|
||||
'progress': progress,
|
||||
'progress_percent': str(helpers.get_percent(progress, duration)),
|
||||
'type': self.get_xml_attr(session, 'type'),
|
||||
'type': helpers.get_xml_attr(session, 'type'),
|
||||
'indexes': use_indexes
|
||||
}
|
||||
elif self.get_xml_attr(session, 'type') == 'movie':
|
||||
session_output = {'session_key': self.get_xml_attr(session, 'sessionKey'),
|
||||
'art': self.get_xml_attr(session, 'art'),
|
||||
elif helpers.get_xml_attr(session, 'type') == 'movie':
|
||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||
'art': helpers.get_xml_attr(session, 'art'),
|
||||
'thumb': thumb,
|
||||
'parent_thumb': self.get_xml_attr(session, 'parentThumb'),
|
||||
'user': self.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
|
||||
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
|
||||
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
|
||||
'friendly_name': plex_watch.get_user_friendly_name(
|
||||
self.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
|
||||
'player': self.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||
'state': self.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
|
||||
'grandparent_title': self.get_xml_attr(session, 'grandparentTitle'),
|
||||
'parent_title': self.get_xml_attr(session, 'parentTitle'),
|
||||
'title': self.get_xml_attr(session, 'title'),
|
||||
'rating_key': self.get_xml_attr(session, 'ratingKey'),
|
||||
helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
|
||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||
'state': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
|
||||
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
|
||||
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
|
||||
'title': helpers.get_xml_attr(session, 'title'),
|
||||
'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
|
||||
'audio_decision': audio_decision,
|
||||
'audio_channels': audio_channels,
|
||||
'audio_codec': audio_codec,
|
||||
|
@ -677,23 +579,23 @@ class PmsConnect(object):
|
|||
'duration': duration,
|
||||
'progress': progress,
|
||||
'progress_percent': str(helpers.get_percent(progress, duration)),
|
||||
'type': self.get_xml_attr(session, 'type'),
|
||||
'type': helpers.get_xml_attr(session, 'type'),
|
||||
'indexes': use_indexes
|
||||
}
|
||||
elif self.get_xml_attr(session, 'type') == 'clip':
|
||||
session_output = {'session_key': self.get_xml_attr(session, 'sessionKey'),
|
||||
'art': self.get_xml_attr(session, 'art'),
|
||||
elif helpers.get_xml_attr(session, 'type') == 'clip':
|
||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||
'art': helpers.get_xml_attr(session, 'art'),
|
||||
'thumb': thumb,
|
||||
'parent_thumb': self.get_xml_attr(session, 'parentThumb'),
|
||||
'user': self.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
|
||||
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
|
||||
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
|
||||
'friendly_name': plex_watch.get_user_friendly_name(
|
||||
self.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
|
||||
'player': self.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||
'state': self.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
|
||||
'grandparent_title': self.get_xml_attr(session, 'grandparentTitle'),
|
||||
'parent_title': self.get_xml_attr(session, 'parentTitle'),
|
||||
'title': self.get_xml_attr(session, 'title'),
|
||||
'rating_key': self.get_xml_attr(session, 'ratingKey'),
|
||||
helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title')),
|
||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||
'state': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
|
||||
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
|
||||
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
|
||||
'title': helpers.get_xml_attr(session, 'title'),
|
||||
'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
|
||||
'audio_decision': audio_decision,
|
||||
'audio_channels': audio_channels,
|
||||
'audio_codec': audio_codec,
|
||||
|
@ -704,7 +606,7 @@ class PmsConnect(object):
|
|||
'duration': duration,
|
||||
'progress': progress,
|
||||
'progress_percent': str(helpers.get_percent(progress, duration)),
|
||||
'type': self.get_xml_attr(session, 'type'),
|
||||
'type': helpers.get_xml_attr(session, 'type'),
|
||||
'indexes': 0
|
||||
}
|
||||
else:
|
||||
|
@ -738,15 +640,15 @@ class PmsConnect(object):
|
|||
if a.getElementsByTagName('Video'):
|
||||
result_data = a.getElementsByTagName('Video')
|
||||
for result in result_data:
|
||||
episode_output = {'rating_key': self.get_xml_attr(result, 'ratingKey'),
|
||||
'index': self.get_xml_attr(result, 'index'),
|
||||
'title': self.get_xml_attr(result, 'title'),
|
||||
'thumb': self.get_xml_attr(result, 'thumb')
|
||||
episode_output = {'rating_key': helpers.get_xml_attr(result, 'ratingKey'),
|
||||
'index': helpers.get_xml_attr(result, 'index'),
|
||||
'title': helpers.get_xml_attr(result, 'title'),
|
||||
'thumb': helpers.get_xml_attr(result, 'thumb')
|
||||
}
|
||||
episode_list.append(episode_output)
|
||||
|
||||
output = {'episode_count': self.get_xml_attr(xml_head[0], 'size'),
|
||||
'title': self.get_xml_attr(xml_head[0], 'title2'),
|
||||
output = {'episode_count': helpers.get_xml_attr(xml_head[0], 'size'),
|
||||
'title': helpers.get_xml_attr(xml_head[0], 'title2'),
|
||||
'episode_list': episode_list
|
||||
}
|
||||
|
||||
|
@ -767,11 +669,11 @@ class PmsConnect(object):
|
|||
|
||||
server_info = []
|
||||
for a in xml_head:
|
||||
output = {"name": self.get_xml_attr(a, 'name'),
|
||||
"machine_identifier": self.get_xml_attr(a, 'machineIdentifier'),
|
||||
"host": self.get_xml_attr(a, 'host'),
|
||||
"port": self.get_xml_attr(a, 'port'),
|
||||
"version": self.get_xml_attr(a, 'version')
|
||||
output = {"name": helpers.get_xml_attr(a, 'name'),
|
||||
"machine_identifier": helpers.get_xml_attr(a, 'machineIdentifier'),
|
||||
"host": helpers.get_xml_attr(a, 'host'),
|
||||
"port": helpers.get_xml_attr(a, 'port'),
|
||||
"version": helpers.get_xml_attr(a, 'version')
|
||||
}
|
||||
|
||||
server_info.append(output)
|
||||
|
@ -793,8 +695,8 @@ class PmsConnect(object):
|
|||
|
||||
server_identity = {}
|
||||
for a in xml_head:
|
||||
server_identity = {"machine_identifier": self.get_xml_attr(a, 'machineIdentifier'),
|
||||
"version": self.get_xml_attr(a, 'version')
|
||||
server_identity = {"machine_identifier": helpers.get_xml_attr(a, 'machineIdentifier'),
|
||||
"version": helpers.get_xml_attr(a, 'version')
|
||||
}
|
||||
|
||||
return server_identity
|
||||
|
@ -808,28 +710,19 @@ class PmsConnect(object):
|
|||
height { the image height }
|
||||
Output: array
|
||||
"""
|
||||
def get_image(self, img, width='0', height='0'):
|
||||
if img != '':
|
||||
try:
|
||||
http_handler = HTTPConnection(self.host, self.port, timeout=10)
|
||||
if width != '0' and height != '0':
|
||||
image_path = '/photo/:/transcode?url=http://127.0.0.1:32400' + img + '&width=' + width + '&height=' + height
|
||||
def get_image(self, img=None, width=None, height=None):
|
||||
if img:
|
||||
if width.isdigit() and height.isdigit():
|
||||
uri = '/photo/:/transcode?url=http://127.0.0.1:32400' + img + '&width=' + width + '&height=' + height
|
||||
else:
|
||||
image_path = '/photo/:/transcode?url=http://127.0.0.1:32400' + img
|
||||
uri = '/photo/:/transcode?url=http://127.0.0.1:32400' + img
|
||||
|
||||
http_handler.request("GET", image_path + '&X-Plex-Token=' + self.token)
|
||||
response = http_handler.getresponse()
|
||||
request_status = response.status
|
||||
request_content = response.read()
|
||||
request_content_type = response.getheader('content-type')
|
||||
except IOError, e:
|
||||
logger.warn(u"Failed to retrieve image. %s" % e)
|
||||
return None
|
||||
request, content_type = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
return_type=True)
|
||||
|
||||
if request_status == 200:
|
||||
return [request_content_type, request_content]
|
||||
return [request, content_type]
|
||||
else:
|
||||
logger.warn(u"Failed to retrieve image. Status code %r" % request_status)
|
||||
return None
|
||||
|
||||
logger.error("Image proxy queries but no input received.")
|
||||
return None
|
||||
|
|
|
@ -547,8 +547,8 @@ class WebInterface(object):
|
|||
try:
|
||||
pms_connect = pmsconnect.PmsConnect()
|
||||
result = pms_connect.get_image(img, width, height)
|
||||
cherrypy.response.headers['Content-type'] = result[0]
|
||||
return result[1]
|
||||
cherrypy.response.headers['Content-type'] = result[1]
|
||||
return result[0]
|
||||
except:
|
||||
logger.warn('Image proxy queried but errors occured.')
|
||||
if fallback == 'poster':
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue