Create new class to handle HTTP requests

Some more clean-up
This commit is contained in:
Tim 2015-07-05 15:59:57 +02:00
parent e1e3659eb3
commit 9b7f529d02
6 changed files with 456 additions and 545 deletions

View file

@ -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]