mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-16 02:02:58 -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
309
plexpy/plextv.py
309
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', '')
|
||||
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': plexpy.CONFIG.PMS_UUID,
|
||||
'Authorization': 'Basic %s' % base64string + ":"
|
||||
}
|
||||
|
||||
http_handler.request("POST",
|
||||
'/users/sign_in.xml',
|
||||
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',
|
||||
'Authorization': 'Basic %s' % base64string + ":"
|
||||
})
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='POST',
|
||||
headers=headers,
|
||||
output_format=output_format)
|
||||
|
||||
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)
|
||||
|
||||
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]
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue