def get_connections(device): conn = [] connections = device.getElementsByTagName('Connection') for c in connections: server_details = {"protocol": helpers.get_xml_attr(c, 'protocol'), "address": helpers.get_xml_attr(c, 'address'), "port": helpers.get_xml_attr(c, 'port'), "uri": helpers.get_xml_attr(c, 'uri'), "local": helpers.get_xml_attr(c, 'local') } conn.append(server_details) return conn
def get_server_token(self): servers = self.get_plextv_server_list(output_format='xml') server_token = '' try: xml_head = servers.getElementsByTagName('Server') except Exception as e: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_token: %s." % e) return None for a in xml_head: if helpers.get_xml_attr(a, 'machineIdentifier') == plexpy.CONFIG.PMS_IDENTIFIER: server_token = helpers.get_xml_attr(a, 'accessToken') break return server_token
def get_server_token(self): servers = self.get_plextv_resources(output_format='xml') server_token = '' try: xml_head = servers.getElementsByTagName('Device') except Exception as e: logger.warn("Tautulli PlexTV :: Unable to parse XML for get_server_token: %s." % e) return None for a in xml_head: if helpers.get_xml_attr(a, 'clientIdentifier') == plexpy.CONFIG.PMS_IDENTIFIER \ and 'server' in helpers.get_xml_attr(a, 'provides'): server_token = helpers.get_xml_attr(a, 'accessToken') break return server_token
def get_cloud_server_status(self): cloud_status = self.cloud_server_status(output_format='xml') try: status_info = cloud_status.getElementsByTagName('info') except Exception as e: logger.warn("Tautulli PlexTV :: Unable to parse XML for get_cloud_server_status: %s." % e) return False for info in status_info: servers = info.getElementsByTagName('server') for s in servers: if helpers.get_xml_attr(s, 'address') == plexpy.CONFIG.PMS_IP: if helpers.get_xml_attr(info, 'running') == '1': return True else: return False
def get_geoip_lookup(self, ip_address=''): if not ip_address or not helpers.is_valid_ip(ip_address): return geoip_data = self.get_plextv_geoip(ip_address=ip_address, output_format='xml') try: xml_head = geoip_data.getElementsByTagName('location') except Exception as e: logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_geoip_lookup: %s." % e) return None for a in xml_head: coordinates = helpers.get_xml_attr(a, 'coordinates').split(',') latitude = longitude = None if len(coordinates) == 2: latitude, longitude = [helpers.cast_to_float(c) for c in coordinates] geo_info = {"code": helpers.get_xml_attr(a, 'code') or None, "country": helpers.get_xml_attr(a, 'country') or None, "region": helpers.get_xml_attr(a, 'subdivisions') or None, "city": helpers.get_xml_attr(a, 'city') or None, "postal_code": helpers.get_xml_attr(a, 'postal_code') or None, "timezone": helpers.get_xml_attr(a, 'time_zone') or None, "latitude": latitude, "longitude": longitude, "continent": None, # keep for backwards compatibility with GeoLite2 "accuracy": None # keep for backwards compatibility with GeoLite2 } return geo_info
def get_server_times(self): servers = self.get_plextv_server_list(output_format='xml') server_times = {} try: xml_head = servers.getElementsByTagName('Server') except Exception as e: logger.warn("Tautulli PlexTV :: Unable to parse XML for get_server_times: %s." % e) return {} for a in xml_head: if helpers.get_xml_attr(a, 'machineIdentifier') == plexpy.CONFIG.PMS_IDENTIFIER: server_times = {"created_at": helpers.get_xml_attr(a, 'createdAt'), "updated_at": helpers.get_xml_attr(a, 'updatedAt'), "version": helpers.get_xml_attr(a, 'version') } break return server_times
def get_server_times(self): servers = self.get_plextv_server_list(output_format='xml') server_times = {} try: xml_head = servers.getElementsByTagName('Server') except Exception as e: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_times: %s." % e) return {} for a in xml_head: if helpers.get_xml_attr(a, 'machineIdentifier') == plexpy.CONFIG.PMS_IDENTIFIER: server_times = {"created_at": helpers.get_xml_attr(a, 'createdAt'), "updated_at": helpers.get_xml_attr(a, 'updatedAt'), "version": helpers.get_xml_attr(a, 'version') } break return server_times
def get_plexpass_status(self): account_data = self.get_plextv_user_details(output_format='xml') try: subscription = account_data.getElementsByTagName('subscription') except Exception as e: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_plexpass_status: %s." % e) return False if subscription and helpers.get_xml_attr(subscription[0], 'active') == '1': return True else: logger.debug(u"PlexPy PlexTV :: Plex Pass subscription not found.") plexpy.CONFIG.__setattr__('PMS_PLEXPASS', 0) plexpy.CONFIG.write() return False
def get_connections(device): conn = [] connections = device.getElementsByTagName('Connection') server = {"platform": helpers.get_xml_attr(device, 'platform'), "version": helpers.get_xml_attr(device, 'productVersion') } for c in connections: server_details = {"protocol": helpers.get_xml_attr(c, 'protocol'), "address": helpers.get_xml_attr(c, 'address'), "port": helpers.get_xml_attr(c, 'port'), "uri": helpers.get_xml_attr(c, 'uri'), "local": helpers.get_xml_attr(c, 'local') } conn.append(server_details) server['connections'] = conn return server
def get_server_urls(self, include_https=True): if plexpy.CONFIG.PMS_IDENTIFIER: server_id = plexpy.CONFIG.PMS_IDENTIFIER else: logger.error(u"PlexPy PlexTV :: Unable to retrieve server identity.") return {} plextv_resources = self.get_plextv_resources(include_https=include_https) try: xml_parse = minidom.parseString(plextv_resources) except Exception as e: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls: %s" % e) return {} except: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls.") return {} try: xml_head = xml_parse.getElementsByTagName('Device') except Exception as e: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls: %s." % e) return {} # Function to get all connections for a device def get_connections(device): conn = [] connections = device.getElementsByTagName('Connection') server = {"platform": helpers.get_xml_attr(device, 'platform'), "version": helpers.get_xml_attr(device, 'productVersion') } for c in connections: server_details = {"protocol": helpers.get_xml_attr(c, 'protocol'), "address": helpers.get_xml_attr(c, 'address'), "port": helpers.get_xml_attr(c, 'port'), "uri": helpers.get_xml_attr(c, 'uri'), "local": helpers.get_xml_attr(c, 'local') } conn.append(server_details) server['connections'] = conn return server server = {} # Try to match the device for a in xml_head: if helpers.get_xml_attr(a, 'clientIdentifier') == server_id: server = get_connections(a) break # Else no device match found if not server: # Try to match the PMS_IP and PMS_PORT for a in xml_head: if helpers.get_xml_attr(a, 'provides') == 'server': connections = a.getElementsByTagName('Connection') for connection in connections: if helpers.get_xml_attr(connection, 'address') == plexpy.CONFIG.PMS_IP and \ int(helpers.get_xml_attr(connection, 'port')) == plexpy.CONFIG.PMS_PORT: plexpy.CONFIG.PMS_IDENTIFIER = helpers.get_xml_attr(a, 'clientIdentifier') plexpy.CONFIG.write() logger.info(u"PlexPy PlexTV :: PMS identifier changed from %s to %s." % (server_id, plexpy.CONFIG.PMS_IDENTIFIER)) server = get_connections(a) break if server.get('connections'): break return server
def get_synced_items(self, machine_id=None, user_id=None): sync_list = self.get_plextv_sync_lists(machine_id) user_data = users.Users() synced_items = [] try: xml_parse = minidom.parseString(sync_list) except Exception as e: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_synced_items: %s" % e) return [] except: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_synced_items.") return [] xml_head = xml_parse.getElementsByTagName('SyncList') if not xml_head: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_synced_items.") else: for a in xml_head: client_id = helpers.get_xml_attr(a, 'id') sync_device = a.getElementsByTagName('Device') for device in sync_device: device_user_id = helpers.get_xml_attr(device, 'userID') try: device_username = user_data.get_details(user_id=device_user_id)['username'] device_friendly_name = user_data.get_details(user_id=device_user_id)['friendly_name'] except: device_username = '' device_friendly_name = '' 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: continue for synced in a.getElementsByTagName('SyncItems'): sync_item = synced.getElementsByTagName('SyncItem') for item in sync_item: 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 = 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 = 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') for location in item.getElementsByTagName('Location'): clean_uri = helpers.get_xml_attr(location, 'uri').split('%2F') rating_key = next((clean_uri[(idx + 1) % len(clean_uri)] for idx, item in enumerate(clean_uri) if item == 'metadata'), None) sync_details = {"device_name": helpers.sanitize(device_name), "platform": helpers.sanitize(device_platform), "username": helpers.sanitize(device_username), "friendly_name": helpers.sanitize(device_friendly_name), "user_id": device_user_id, "root_title": helpers.sanitize(sync_root_title), "title": helpers.sanitize(sync_title), "metadata_type": sync_metadata_type, "content_type": sync_content_type, "rating_key": rating_key, "state": status_state, "item_count": status_item_count, "item_complete_count": status_item_complete_count, "item_downloaded_count": status_item_downloaded_count, "item_downloaded_percent_complete": status_item_download_percent_complete, "music_bitrate": settings_music_bitrate, "photo_quality": settings_photo_quality, "video_quality": settings_video_quality, "total_size": status_total_size, "failure": status_failure, "sync_id": sync_id } synced_items.append(sync_details) return session.filter_session_info(synced_items, filter_key='user_id')
def get_full_users_list(self): friends_list = self.get_plextv_friends() own_account = self.get_plextv_user_details() users_list = [] try: xml_parse = minidom.parseString(own_account) except Exception as e: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list own account: %s" % e) return [] except: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list own account.") return [] xml_head = xml_parse.getElementsByTagName('user') if not xml_head: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list.") else: for a in xml_head: 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": helpers.get_xml_attr(a, 'restricted'), "filter_all": helpers.get_xml_attr(a, 'filterAll'), "filter_movies": helpers.get_xml_attr(a, 'filterMovies'), "filter_tv": helpers.get_xml_attr(a, 'filterTelevision'), "filter_music": helpers.get_xml_attr(a, 'filterMusic'), "filter_photos": helpers.get_xml_attr(a, 'filterPhotos') } users_list.append(own_details) try: xml_parse = minidom.parseString(friends_list) except Exception as e: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list friends list: %s" % e) return [] except: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list friends list.") return [] xml_head = xml_parse.getElementsByTagName('User') if not xml_head: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list.") else: for a in xml_head: 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'), "filter_all": helpers.get_xml_attr(a, 'filterAll'), "filter_movies": helpers.get_xml_attr(a, 'filterMovies'), "filter_tv": helpers.get_xml_attr(a, 'filterTelevision'), "filter_music": helpers.get_xml_attr(a, 'filterMusic'), "filter_photos": helpers.get_xml_attr(a, 'filterPhotos') } users_list.append(friend) return users_list
def discover(self, include_cloud=True, all_servers=False): """ Query plex for all servers online. Returns the ones you own in a selectize format """ servers = self.get_plextv_resources(include_https=True, output_format='xml') clean_servers = [] try: xml_head = servers.getElementsByTagName('MediaContainer') except Exception as e: logger.warn( u"Tautulli PlexTV :: Failed to get servers from plex: %s." % e) return [] for a in xml_head: if a.getAttribute('size'): if a.getAttribute('size') == '0': return [] if a.getElementsByTagName('Device'): devices = a.getElementsByTagName('Device') for d in devices: if helpers.get_xml_attr(d, 'presence') == '1' and \ helpers.get_xml_attr(d, 'owned') == '1' and \ helpers.get_xml_attr(d, 'provides') == 'server': is_cloud = (helpers.get_xml_attr( d, 'platform').lower() == 'cloud') if not include_cloud and is_cloud: continue connections = d.getElementsByTagName('Connection') for c in connections: if not all_servers: # If this is a remote server don't show any local IPs. if helpers.get_xml_attr(d, 'publicAddressMatches') == '0' and \ helpers.get_xml_attr(c, 'local') == '1': continue # If this is a local server don't show any remote IPs. if helpers.get_xml_attr(d, 'publicAddressMatches') == '1' and \ helpers.get_xml_attr(c, 'local') == '0': continue server = { 'httpsRequired': '1' if is_cloud else helpers.get_xml_attr( d, 'httpsRequired'), 'clientIdentifier': helpers.get_xml_attr(d, 'clientIdentifier'), 'label': helpers.get_xml_attr(d, 'name'), 'ip': helpers.get_xml_attr(c, 'address'), 'port': helpers.get_xml_attr(c, 'port'), 'uri': helpers.get_xml_attr(c, 'uri'), 'local': helpers.get_xml_attr(c, 'local'), 'value': helpers.get_xml_attr(c, 'address'), 'is_cloud': is_cloud } clean_servers.append(server) return clean_servers
def get_server_connections(self, pms_identifier='', pms_ip='', pms_port=32400, include_https=True): if not pms_identifier: logger.error( u"Tautulli PlexTV :: Unable to retrieve server connections: no pms_identifier provided." ) return {} plextv_resources = self.get_plextv_resources( include_https=include_https, output_format='xml') try: xml_head = plextv_resources.getElementsByTagName('Device') except Exception as e: logger.warn( u"Tautulli PlexTV :: Unable to parse XML for get_server_urls: %s." % e) return {} # Function to get all connections for a device def get_connections(device): conn = [] connections = device.getElementsByTagName('Connection') server = { 'pms_identifier': helpers.get_xml_attr(device, 'clientIdentifier'), 'pms_name': helpers.get_xml_attr(device, 'name'), 'pms_version': helpers.get_xml_attr(device, 'productVersion'), 'pms_platform': helpers.get_xml_attr(device, 'platform'), 'pms_presence': helpers.get_xml_attr(device, 'presence'), 'pms_is_cloud': 1 if helpers.get_xml_attr(device, 'platform') == 'Cloud' else 0 } for c in connections: server_details = { 'protocol': helpers.get_xml_attr(c, 'protocol'), 'address': helpers.get_xml_attr(c, 'address'), 'port': helpers.get_xml_attr(c, 'port'), 'uri': helpers.get_xml_attr(c, 'uri'), 'local': helpers.get_xml_attr(c, 'local') } conn.append(server_details) server['connections'] = conn return server server = {} # Try to match the device for a in xml_head: if helpers.get_xml_attr(a, 'clientIdentifier') == pms_identifier: server = get_connections(a) break # Else no device match found if not server: # Try to match the PMS_IP and PMS_PORT for a in xml_head: if helpers.get_xml_attr(a, 'provides') == 'server': connections = a.getElementsByTagName('Connection') for connection in connections: if helpers.get_xml_attr(connection, 'address') == pms_ip and \ helpers.get_xml_attr(connection, 'port') == str(pms_port): server = get_connections(a) break if server.get('connections'): break return server
def get_full_users_list(self): own_account = self.get_plextv_user_details(output_format='xml') friends_list = self.get_plextv_friends(output_format='xml') shared_servers = self.get_plextv_shared_servers( machine_id=plexpy.CONFIG.PMS_IDENTIFIER, output_format='xml') users_list = [] try: xml_head = own_account.getElementsByTagName('user') except Exception as e: logger.warn( u"Tautulli PlexTV :: Unable to parse own account XML for get_full_users_list: %s." % e) return [] for a in xml_head: 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_admin": 1, "is_allow_sync": 1, "is_restricted": helpers.get_xml_attr(a, 'restricted'), "filter_all": helpers.get_xml_attr(a, 'filterAll'), "filter_movies": helpers.get_xml_attr(a, 'filterMovies'), "filter_tv": helpers.get_xml_attr(a, 'filterTelevision'), "filter_music": helpers.get_xml_attr(a, 'filterMusic'), "filter_photos": helpers.get_xml_attr(a, 'filterPhotos'), "user_token": helpers.get_xml_attr(a, 'authToken'), "server_token": helpers.get_xml_attr(a, 'authToken'), "shared_libraries": None, } users_list.append(own_details) try: xml_head = friends_list.getElementsByTagName('User') except Exception as e: logger.warn( u"Tautulli PlexTV :: Unable to parse friends list XML for get_full_users_list: %s." % e) return [] for a in xml_head: 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_admin": 0, "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'), "filter_all": helpers.get_xml_attr(a, 'filterAll'), "filter_movies": helpers.get_xml_attr(a, 'filterMovies'), "filter_tv": helpers.get_xml_attr(a, 'filterTelevision'), "filter_music": helpers.get_xml_attr(a, 'filterMusic'), "filter_photos": helpers.get_xml_attr(a, 'filterPhotos') } users_list.append(friend) try: xml_head = shared_servers.getElementsByTagName('SharedServer') except Exception as e: logger.warn( u"Tautulli PlexTV :: Unable to parse shared server list XML for get_full_users_list: %s." % e) return [] user_map = {} for a in xml_head: user_id = helpers.get_xml_attr(a, 'userID') server_token = helpers.get_xml_attr(a, 'accessToken') sections = a.getElementsByTagName('Section') shared_libraries = [ helpers.get_xml_attr(s, 'key') for s in sections if helpers.get_xml_attr(s, 'shared') == '1' ] user_map[user_id] = { 'server_token': server_token, 'shared_libraries': shared_libraries } for u in users_list: d = user_map.get(u['user_id'], {}) u.update(d) return users_list
def extract_plexwatch_xml(xml=None): output = {} clean_xml = helpers.latinToAscii(xml) try: xml_parse = minidom.parseString(clean_xml) except: logger.warn(u"PlexPy Importer :: Error parsing XML for PlexWatch database.") return None xml_head = xml_parse.getElementsByTagName('opt') if not xml_head: logger.warn(u"PlexPy Importer :: Error parsing XML for PlexWatch database.") return None for a in xml_head: added_at = helpers.get_xml_attr(a, 'addedAt') art = helpers.get_xml_attr(a, 'art') duration = helpers.get_xml_attr(a, 'duration') grandparent_thumb = helpers.get_xml_attr(a, 'grandparentThumb') grandparent_title = helpers.get_xml_attr(a, 'grandparentTitle') guid = helpers.get_xml_attr(a, 'guid') section_id = helpers.get_xml_attr(a, 'librarySectionID') media_index = helpers.get_xml_attr(a, 'index') originally_available_at = helpers.get_xml_attr(a, 'originallyAvailableAt') last_viewed_at = helpers.get_xml_attr(a, 'lastViewedAt') parent_media_index = helpers.get_xml_attr(a, 'parentIndex') parent_thumb = helpers.get_xml_attr(a, 'parentThumb') rating = helpers.get_xml_attr(a, 'rating') thumb = helpers.get_xml_attr(a, 'thumb') media_type = helpers.get_xml_attr(a, 'type') updated_at = helpers.get_xml_attr(a, 'updatedAt') view_offset = helpers.get_xml_attr(a, 'viewOffset') year = helpers.get_xml_attr(a, 'year') parent_title = helpers.get_xml_attr(a, 'parentTitle') studio = helpers.get_xml_attr(a, 'studio') title = helpers.get_xml_attr(a, 'title') tagline = helpers.get_xml_attr(a, 'tagline') directors = [] if a.getElementsByTagName('Director'): director_elem = a.getElementsByTagName('Director') for b in director_elem: directors.append(helpers.get_xml_attr(b, 'tag')) aspect_ratio = '' audio_channels = None audio_codec = '' bitrate = None container = '' height = None video_codec = '' video_framerate = '' video_resolution = '' width = None if a.getElementsByTagName('Media'): media_elem = a.getElementsByTagName('Media') for c in media_elem: aspect_ratio = helpers.get_xml_attr(c, 'aspectRatio') audio_channels = helpers.get_xml_attr(c, 'audioChannels') audio_codec = helpers.get_xml_attr(c, 'audioCodec') bitrate = helpers.get_xml_attr(c, 'bitrate') container = helpers.get_xml_attr(c, 'container') height = helpers.get_xml_attr(c, 'height') video_codec = helpers.get_xml_attr(c, 'videoCodec') video_framerate = helpers.get_xml_attr(c, 'videoFrameRate') video_resolution = helpers.get_xml_attr(c, 'videoResolution') width = helpers.get_xml_attr(c, 'width') machine_id = '' platform = '' player = '' if a.getElementsByTagName('Player'): player_elem = a.getElementsByTagName('Player') for d in player_elem: ip_address = helpers.get_xml_attr(d, 'address') machine_id = helpers.get_xml_attr(d, 'machineIdentifier') platform = helpers.get_xml_attr(d, 'platform') player = helpers.get_xml_attr(d, 'title') transcode_audio_channels = None transcode_audio_codec = '' audio_decision = 'direct play' transcode_container = '' transcode_height = None transcode_protocol = '' transcode_video_codec = '' video_decision = 'direct play' transcode_width = None if a.getElementsByTagName('TranscodeSession'): transcode_elem = a.getElementsByTagName('TranscodeSession') for e in transcode_elem: transcode_audio_channels = helpers.get_xml_attr(e, 'audioChannels') transcode_audio_codec = helpers.get_xml_attr(e, 'audioCodec') audio_decision = helpers.get_xml_attr(e, 'audioDecision') transcode_container = helpers.get_xml_attr(e, 'container') transcode_height = helpers.get_xml_attr(e, 'height') transcode_protocol = helpers.get_xml_attr(e, 'protocol') transcode_video_codec = helpers.get_xml_attr(e, 'videoCodec') video_decision = helpers.get_xml_attr(e, 'videoDecision') transcode_width = helpers.get_xml_attr(e, 'width') # Generate a combined transcode decision value if video_decision == 'transcode' or audio_decision == 'transcode': transcode_decision = 'transcode' elif video_decision == 'copy' or audio_decision == 'copy': transcode_decision = 'copy' else: transcode_decision = 'direct play' user_id = None if a.getElementsByTagName('User'): user_elem = a.getElementsByTagName('User') for f in user_elem: user_id = helpers.get_xml_attr(f, 'id') writers = [] if a.getElementsByTagName('Writer'): writer_elem = a.getElementsByTagName('Writer') for g in writer_elem: writers.append(helpers.get_xml_attr(g, 'tag')) actors = [] if a.getElementsByTagName('Role'): actor_elem = a.getElementsByTagName('Role') for h in actor_elem: actors.append(helpers.get_xml_attr(h, 'tag')) genres = [] if a.getElementsByTagName('Genre'): genre_elem = a.getElementsByTagName('Genre') for i in genre_elem: genres.append(helpers.get_xml_attr(i, 'tag')) labels = [] if a.getElementsByTagName('Lables'): label_elem = a.getElementsByTagName('Lables') for i in label_elem: labels.append(helpers.get_xml_attr(i, 'tag')) output = {'added_at': added_at, 'art': art, 'duration': duration, 'grandparent_thumb': grandparent_thumb, 'grandparent_title': grandparent_title, 'parent_title': parent_title, 'title': title, 'tagline': tagline, 'guid': guid, 'section_id': section_id, 'media_index': media_index, 'originally_available_at': originally_available_at, 'last_viewed_at': last_viewed_at, 'parent_media_index': parent_media_index, 'parent_thumb': parent_thumb, 'rating': rating, 'thumb': thumb, 'media_type': media_type, 'updated_at': updated_at, 'view_offset': view_offset, 'year': year, 'directors': directors, 'aspect_ratio': aspect_ratio, 'audio_channels': audio_channels, 'audio_codec': audio_codec, 'bitrate': bitrate, 'container': container, 'height': height, 'video_codec': video_codec, 'video_framerate': video_framerate, 'video_resolution': video_resolution, 'width': width, 'ip_address': ip_address, 'machine_id': machine_id, 'platform': platform, 'player': player, 'transcode_audio_channels': transcode_audio_channels, 'transcode_audio_codec': transcode_audio_codec, 'audio_decision': audio_decision, 'transcode_container': transcode_container, 'transcode_height': transcode_height, 'transcode_protocol': transcode_protocol, 'transcode_video_codec': transcode_video_codec, 'video_decision': video_decision, 'transcode_width': transcode_width, 'transcode_decision': transcode_decision, 'user_id': user_id, 'writers': writers, 'actors': actors, 'genres': genres, 'studio': studio, 'labels': labels } return output
def get_synced_items(self, machine_id=None, client_id_filter=None, user_id_filter=None, rating_key_filter=None, sync_id_filter=None): if not machine_id: machine_id = plexpy.CONFIG.PMS_IDENTIFIER if isinstance(rating_key_filter, list): rating_key_filter = [str(k) for k in rating_key_filter] elif rating_key_filter: rating_key_filter = [str(rating_key_filter)] if isinstance(user_id_filter, list): user_id_filter = [str(k) for k in user_id_filter] elif user_id_filter: user_id_filter = [str(user_id_filter)] sync_list = self.get_plextv_sync_lists(machine_id, output_format='xml') user_data = users.Users() synced_items = [] try: xml_head = sync_list.getElementsByTagName('SyncList') except Exception as e: logger.warn("Tautulli PlexTV :: Unable to parse XML for get_synced_items: %s." % e) return {} for a in xml_head: client_id = helpers.get_xml_attr(a, 'clientIdentifier') # Filter by client_id if client_id_filter and str(client_id_filter) != client_id: continue sync_list_id = helpers.get_xml_attr(a, 'id') sync_device = a.getElementsByTagName('Device') for device in sync_device: device_user_id = helpers.get_xml_attr(device, 'userID') try: device_username = user_data.get_details(user_id=device_user_id)['username'] device_friendly_name = user_data.get_details(user_id=device_user_id)['friendly_name'] except: device_username = '' device_friendly_name = '' 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_filter and device_user_id not in user_id_filter: continue for synced in a.getElementsByTagName('SyncItems'): sync_item = synced.getElementsByTagName('SyncItem') for item in sync_item: sync_media_type = None rating_key = None for location in item.getElementsByTagName('Location'): location_uri = unquote(helpers.get_xml_attr(location, 'uri')) if location_uri.startswith('library://'): if 'collection' in location_uri: sync_media_type = 'collection' clean_uri = location_uri.split('/') rating_key = next((j for i, j in zip(clean_uri[:-1], clean_uri[1:]) if i in ('metadata', 'collections')), None) elif location_uri.startswith('playlist://'): sync_media_type = 'playlist' tokens = users.Users().get_tokens(user_id=device_user_id) if tokens['server_token']: plex = Plex(token=tokens['server_token']) for playlist in plex.PlexServer.playlists(): if location_uri.endswith(playlist.guid): rating_key = str(playlist.ratingKey) # String for backwards consistency # Filter by rating_key if rating_key_filter and rating_key not in rating_key_filter: continue sync_id = helpers.get_xml_attr(item, 'id') # Filter by sync_id if sync_id_filter and str(sync_id_filter) != sync_id: continue 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 = 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_video_bitrate = helpers.get_xml_attr(settings, 'maxVideoBitrate') settings_video_quality = helpers.get_xml_attr(settings, 'videoQuality') settings_video_resolution = helpers.get_xml_attr(settings, 'videoResolution') settings_audio_boost = helpers.get_xml_attr(settings, 'audioBoost') settings_audio_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') sync_details = {"device_name": device_name, "platform": device_platform, "user_id": device_user_id, "user": device_friendly_name, "username": device_username, "root_title": sync_root_title, "sync_title": sync_title, "metadata_type": sync_metadata_type, "content_type": sync_content_type, "rating_key": rating_key, "state": status_state, "item_count": status_item_count, "item_complete_count": status_item_complete_count, "item_downloaded_count": status_item_downloaded_count, "item_downloaded_percent_complete": status_item_download_percent_complete, "video_bitrate": settings_video_bitrate, "audio_bitrate": settings_audio_bitrate, "photo_quality": settings_photo_quality, "video_quality": settings_video_quality, "total_size": status_total_size, "failure": status_failure, "client_id": client_id, "sync_id": sync_id, "sync_media_type": sync_media_type } synced_items.append(sync_details) return session.filter_session_info(synced_items, filter_key='user_id')
def discover(self): """ Query plex for all servers online. Returns the ones you own in a selectize format """ servers = self.get_plextv_resources(include_https=True, output_format='xml') clean_servers = [] try: xml_head = servers.getElementsByTagName('MediaContainer') except Exception as e: logger.warn(u"PlexPy PlexTV :: Failed to get servers from plex: %s." % e) return [] for a in xml_head: if a.getAttribute('size'): if a.getAttribute('size') == '0': return [] if a.getElementsByTagName('Device'): devices = a.getElementsByTagName('Device') for d in devices: if helpers.get_xml_attr(d, 'presence') == '1' and \ helpers.get_xml_attr(d, 'owned') == '1' and \ helpers.get_xml_attr(d, 'provides') == 'server': connections = d.getElementsByTagName('Connection') for c in connections: # If this is a remote server don't show any local IPs. if helpers.get_xml_attr(d, 'publicAddressMatches') == '0' and \ helpers.get_xml_attr(c, 'local') == '1': continue # If this is a local server don't show any remote IPs. if helpers.get_xml_attr(d, 'publicAddressMatches') == '1' and \ helpers.get_xml_attr(c, 'local') == '0': continue server = {'httpsRequired': helpers.get_xml_attr(d, 'httpsRequired'), 'clientIdentifier': helpers.get_xml_attr(d, 'clientIdentifier'), 'label': helpers.get_xml_attr(d, 'name'), 'ip': helpers.get_xml_attr(c, 'address'), 'port': helpers.get_xml_attr(c, 'port'), 'local': helpers.get_xml_attr(c, 'local'), 'value': helpers.get_xml_attr(c, 'address') } clean_servers.append(server) return clean_servers
def extract_plexivity_xml(xml=None): output = {} clean_xml = helpers.latinToAscii(xml) try: xml_parse = minidom.parseString(clean_xml) except: logger.warn("Tautulli Importer :: Error parsing XML for Plexivity database.") return None # I think Plexivity only tracked videos and not music? xml_head = xml_parse.getElementsByTagName('Video') if not xml_head: logger.warn("Tautulli Importer :: Error parsing XML for Plexivity database.") return None for a in xml_head: rating_key = helpers.get_xml_attr(a, 'ratingKey') added_at = helpers.get_xml_attr(a, 'addedAt') art = helpers.get_xml_attr(a, 'art') duration = helpers.get_xml_attr(a, 'duration') grandparent_rating_key = helpers.get_xml_attr(a, 'grandparentRatingKey') grandparent_thumb = helpers.get_xml_attr(a, 'grandparentThumb') grandparent_title = helpers.get_xml_attr(a, 'grandparentTitle') original_title = helpers.get_xml_attr(a, 'originalTitle') guid = helpers.get_xml_attr(a, 'guid') section_id = helpers.get_xml_attr(a, 'librarySectionID') media_index = helpers.get_xml_attr(a, 'index') originally_available_at = helpers.get_xml_attr(a, 'originallyAvailableAt') last_viewed_at = helpers.get_xml_attr(a, 'lastViewedAt') parent_rating_key = helpers.get_xml_attr(a, 'parentRatingKey') parent_media_index = helpers.get_xml_attr(a, 'parentIndex') parent_thumb = helpers.get_xml_attr(a, 'parentThumb') parent_title = helpers.get_xml_attr(a, 'parentTitle') rating = helpers.get_xml_attr(a, 'rating') thumb = helpers.get_xml_attr(a, 'thumb') media_type = helpers.get_xml_attr(a, 'type') updated_at = helpers.get_xml_attr(a, 'updatedAt') view_offset = helpers.get_xml_attr(a, 'viewOffset') year = helpers.get_xml_attr(a, 'year') studio = helpers.get_xml_attr(a, 'studio') title = helpers.get_xml_attr(a, 'title') tagline = helpers.get_xml_attr(a, 'tagline') directors = [] if a.getElementsByTagName('Director'): director_elem = a.getElementsByTagName('Director') for b in director_elem: directors.append(helpers.get_xml_attr(b, 'tag')) aspect_ratio = '' audio_channels = None audio_codec = '' bitrate = None container = '' height = None video_codec = '' video_framerate = '' video_resolution = '' width = None if a.getElementsByTagName('Media'): media_elem = a.getElementsByTagName('Media') for c in media_elem: aspect_ratio = helpers.get_xml_attr(c, 'aspectRatio') audio_channels = helpers.get_xml_attr(c, 'audioChannels') audio_codec = helpers.get_xml_attr(c, 'audioCodec') bitrate = helpers.get_xml_attr(c, 'bitrate') container = helpers.get_xml_attr(c, 'container') height = helpers.get_xml_attr(c, 'height') video_codec = helpers.get_xml_attr(c, 'videoCodec') video_framerate = helpers.get_xml_attr(c, 'videoFrameRate') video_resolution = helpers.get_xml_attr(c, 'videoResolution') width = helpers.get_xml_attr(c, 'width') ip_address = '' machine_id = '' platform = '' player = '' if a.getElementsByTagName('Player'): player_elem = a.getElementsByTagName('Player') for d in player_elem: ip_address = helpers.get_xml_attr(d, 'address').split('::ffff:')[-1] machine_id = helpers.get_xml_attr(d, 'machineIdentifier') platform = helpers.get_xml_attr(d, 'platform') player = helpers.get_xml_attr(d, 'title') transcode_audio_channels = None transcode_audio_codec = '' audio_decision = 'direct play' transcode_container = '' transcode_height = None transcode_protocol = '' transcode_video_codec = '' video_decision = 'direct play' transcode_width = None if a.getElementsByTagName('TranscodeSession'): transcode_elem = a.getElementsByTagName('TranscodeSession') for e in transcode_elem: transcode_audio_channels = helpers.get_xml_attr(e, 'audioChannels') transcode_audio_codec = helpers.get_xml_attr(e, 'audioCodec') audio_decision = helpers.get_xml_attr(e, 'audioDecision') transcode_container = helpers.get_xml_attr(e, 'container') transcode_height = helpers.get_xml_attr(e, 'height') transcode_protocol = helpers.get_xml_attr(e, 'protocol') transcode_video_codec = helpers.get_xml_attr(e, 'videoCodec') video_decision = helpers.get_xml_attr(e, 'videoDecision') transcode_width = helpers.get_xml_attr(e, 'width') # Generate a combined transcode decision value if video_decision == 'transcode' or audio_decision == 'transcode': transcode_decision = 'transcode' elif video_decision == 'copy' or audio_decision == 'copy': transcode_decision = 'copy' else: transcode_decision = 'direct play' user_id = None if a.getElementsByTagName('User'): user_elem = a.getElementsByTagName('User') for f in user_elem: user_id = helpers.get_xml_attr(f, 'id') writers = [] if a.getElementsByTagName('Writer'): writer_elem = a.getElementsByTagName('Writer') for g in writer_elem: writers.append(helpers.get_xml_attr(g, 'tag')) actors = [] if a.getElementsByTagName('Role'): actor_elem = a.getElementsByTagName('Role') for h in actor_elem: actors.append(helpers.get_xml_attr(h, 'tag')) genres = [] if a.getElementsByTagName('Genre'): genre_elem = a.getElementsByTagName('Genre') for i in genre_elem: genres.append(helpers.get_xml_attr(i, 'tag')) labels = [] if a.getElementsByTagName('Lables'): label_elem = a.getElementsByTagName('Lables') for i in label_elem: labels.append(helpers.get_xml_attr(i, 'tag')) output = {'rating_key': rating_key, 'added_at': added_at, 'art': art, 'duration': duration, 'grandparent_rating_key': grandparent_rating_key, 'grandparent_thumb': grandparent_thumb, 'title': title, 'parent_title': parent_title, 'grandparent_title': grandparent_title, 'original_title': original_title, 'tagline': tagline, 'guid': guid, 'section_id': section_id, 'media_index': media_index, 'originally_available_at': originally_available_at, 'last_viewed_at': last_viewed_at, 'parent_rating_key': parent_rating_key, 'parent_media_index': parent_media_index, 'parent_thumb': parent_thumb, 'rating': rating, 'thumb': thumb, 'media_type': media_type, 'updated_at': updated_at, 'view_offset': view_offset, 'year': year, 'directors': directors, 'aspect_ratio': aspect_ratio, 'audio_channels': audio_channels, 'audio_codec': audio_codec, 'bitrate': bitrate, 'container': container, 'height': height, 'video_codec': video_codec, 'video_framerate': video_framerate, 'video_resolution': video_resolution, 'width': width, 'ip_address': ip_address, 'machine_id': machine_id, 'platform': platform, 'player': player, 'transcode_audio_channels': transcode_audio_channels, 'transcode_audio_codec': transcode_audio_codec, 'audio_decision': audio_decision, 'transcode_container': transcode_container, 'transcode_height': transcode_height, 'transcode_protocol': transcode_protocol, 'transcode_video_codec': transcode_video_codec, 'video_decision': video_decision, 'transcode_width': transcode_width, 'transcode_decision': transcode_decision, 'user_id': user_id, 'writers': writers, 'actors': actors, 'genres': genres, 'studio': studio, 'labels': labels } return output
def get_devices_list(self): devices = self.get_plextv_devices_list(output_format='xml') try: xml_head = devices.getElementsByTagName('Device') except Exception as e: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_devices_list: %s." % e) return [] devices_list = [] for a in xml_head: device = {"device_name": helpers.get_xml_attr(a, 'name'), "product": helpers.get_xml_attr(a, 'product'), "product_version": helpers.get_xml_attr(a, 'productVersion'), "platform": helpers.get_xml_attr(a, 'platform'), "platform_version": helpers.get_xml_attr(a, 'platformVersion'), "device": helpers.get_xml_attr(a, 'device'), "model": helpers.get_xml_attr(a, 'model'), "vendor": helpers.get_xml_attr(a, 'vendor'), "provides": helpers.get_xml_attr(a, 'provides'), "device_identifier": helpers.get_xml_attr(a, 'clientIdentifier'), "device_id": helpers.get_xml_attr(a, 'id'), "token": helpers.get_xml_attr(a, 'token') } devices_list.append(device) return devices_list
def get_server_urls(self, include_https=True): if plexpy.CONFIG.PMS_IDENTIFIER: server_id = plexpy.CONFIG.PMS_IDENTIFIER else: logger.error(u"PlexPy PlexTV :: Unable to retrieve server identity.") return [] plextv_resources = self.get_plextv_resources(include_https=include_https) try: xml_parse = minidom.parseString(plextv_resources) except Exception as e: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls: %s" % e) return [] except: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls.") return [] try: xml_head = xml_parse.getElementsByTagName('Device') except Exception as e: logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls: %s." % e) return [] # Function to get all connections for a device def get_connections(device): conn = [] connections = device.getElementsByTagName('Connection') for c in connections: server_details = {"protocol": helpers.get_xml_attr(c, 'protocol'), "address": helpers.get_xml_attr(c, 'address'), "port": helpers.get_xml_attr(c, 'port'), "uri": helpers.get_xml_attr(c, 'uri'), "local": helpers.get_xml_attr(c, 'local') } conn.append(server_details) return conn server_urls = [] # Try to match the device for a in xml_head: if helpers.get_xml_attr(a, 'clientIdentifier') == server_id: server_urls = get_connections(a) break # Else no device match found if not server_urls: # Try to match the PMS_IP and PMS_PORT for a in xml_head: if helpers.get_xml_attr(a, 'provides') == 'server': connections = a.getElementsByTagName('Connection') for connection in connections: if helpers.get_xml_attr(connection, 'address') == plexpy.CONFIG.PMS_IP and \ int(helpers.get_xml_attr(connection, 'port')) == plexpy.CONFIG.PMS_PORT: plexpy.CONFIG.PMS_IDENTIFIER = helpers.get_xml_attr(a, 'clientIdentifier') plexpy.CONFIG.write() logger.info(u"PlexPy PlexTV :: PMS identifier changed from %s to %s." % \ (server_id, plexpy.CONFIG.PMS_IDENTIFIER)) server_urls = get_connections(a) break if server_urls: break return server_urls
def get_synced_items(self, machine_id=None, client_id_filter=None, user_id_filter=None, rating_key_filter=None, sync_id_filter=None): if not machine_id: machine_id = plexpy.CONFIG.PMS_IDENTIFIER if isinstance(rating_key_filter, list): rating_key_filter = [str(k) for k in rating_key_filter] elif rating_key_filter: rating_key_filter = [str(rating_key_filter)] if isinstance(user_id_filter, list): user_id_filter = [str(k) for k in user_id_filter] elif user_id_filter: user_id_filter = [str(user_id_filter)] sync_list = self.get_plextv_sync_lists(machine_id, output_format='xml') user_data = users.Users() synced_items = [] try: xml_head = sync_list.getElementsByTagName('SyncList') except Exception as e: logger.warn( u"Tautulli PlexTV :: Unable to parse XML for get_synced_items: %s." % e) return {} for a in xml_head: client_id = helpers.get_xml_attr(a, 'clientIdentifier') # Filter by client_id if client_id_filter and str(client_id_filter) != client_id: continue sync_list_id = helpers.get_xml_attr(a, 'id') sync_device = a.getElementsByTagName('Device') for device in sync_device: device_user_id = helpers.get_xml_attr(device, 'userID') try: device_username = user_data.get_details( user_id=device_user_id)['username'] device_friendly_name = user_data.get_details( user_id=device_user_id)['friendly_name'] except: device_username = '' device_friendly_name = '' 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_filter and device_user_id not in user_id_filter: continue for synced in a.getElementsByTagName('SyncItems'): sync_item = synced.getElementsByTagName('SyncItem') for item in sync_item: for location in item.getElementsByTagName('Location'): clean_uri = helpers.get_xml_attr(location, 'uri').split('%2F') rating_key = next((clean_uri[(idx + 1) % len(clean_uri)] for idx, item in enumerate(clean_uri) if item == 'metadata'), None) # Filter by rating_key if rating_key_filter and rating_key not in rating_key_filter: continue sync_id = helpers.get_xml_attr(item, 'id') # Filter by sync_id if sync_id_filter and str(sync_id_filter) != sync_id: continue 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 = 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_video_bitrate = helpers.get_xml_attr( settings, 'maxVideoBitrate') settings_video_quality = helpers.get_xml_attr( settings, 'videoQuality') settings_video_resolution = helpers.get_xml_attr( settings, 'videoResolution') settings_audio_boost = helpers.get_xml_attr( settings, 'audioBoost') settings_audio_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') sync_details = { "device_name": helpers.sanitize(device_name), "platform": helpers.sanitize(device_platform), "user_id": device_user_id, "user": helpers.sanitize(device_friendly_name), "username": helpers.sanitize(device_username), "root_title": helpers.sanitize(sync_root_title), "sync_title": helpers.sanitize(sync_title), "metadata_type": sync_metadata_type, "content_type": sync_content_type, "rating_key": rating_key, "state": status_state, "item_count": status_item_count, "item_complete_count": status_item_complete_count, "item_downloaded_count": status_item_downloaded_count, "item_downloaded_percent_complete": status_item_download_percent_complete, "video_bitrate": settings_video_bitrate, "audio_bitrate": settings_audio_bitrate, "photo_quality": settings_photo_quality, "video_quality": settings_video_quality, "total_size": status_total_size, "failure": status_failure, "client_id": client_id, "sync_id": sync_id } synced_items.append(sync_details) return session.filter_session_info(synced_items, filter_key='user_id')
def get_plex_account_details(self): account_data = self.get_plextv_user_details(output_format='xml') try: xml_head = account_data.getElementsByTagName('user') except Exception as e: logger.warn( "Tautulli PlexTV :: Unable to parse XML for get_plex_account_details: %s." % e) return None for a in xml_head: account_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_restricted": helpers.get_xml_attr(a, 'restricted'), "filter_all": helpers.get_xml_attr(a, 'filterAll'), "filter_movies": helpers.get_xml_attr(a, 'filterMovies'), "filter_tv": helpers.get_xml_attr(a, 'filterTelevision'), "filter_music": helpers.get_xml_attr(a, 'filterMusic'), "filter_photos": helpers.get_xml_attr(a, 'filterPhotos'), "user_token": helpers.get_xml_attr(a, 'authToken') } return account_details
def get_connections(device): conn = [] connections = device.getElementsByTagName('Connection') server = { 'pms_identifier': helpers.get_xml_attr(device, 'clientIdentifier'), 'pms_name': helpers.get_xml_attr(device, 'name'), 'pms_version': helpers.get_xml_attr(device, 'productVersion'), 'pms_platform': helpers.get_xml_attr(device, 'platform'), 'pms_presence': helpers.get_xml_attr(device, 'presence'), 'pms_is_cloud': 1 if helpers.get_xml_attr(device, 'platform') == 'Cloud' else 0 } for c in connections: server_details = { 'protocol': helpers.get_xml_attr(c, 'protocol'), 'address': helpers.get_xml_attr(c, 'address'), 'port': helpers.get_xml_attr(c, 'port'), 'uri': helpers.get_xml_attr(c, 'uri'), 'local': helpers.get_xml_attr(c, 'local') } conn.append(server_details) server['connections'] = conn return server
def discover(self, include_cloud=True, all_servers=False): """ Query plex for all servers online. Returns the ones you own in a selectize format """ # Try to discover localhost server local_machine_identifier = None request_handler = http_handler.HTTPHandler( urls='http://127.0.0.1:32400', timeout=1, ssl_verify=False, silent=True) request = request_handler.make_request(uri='/identity', request_type='GET', output_format='xml') if request: xml_head = request.getElementsByTagName('MediaContainer')[0] local_machine_identifier = xml_head.getAttribute( 'machineIdentifier') local_server = { 'httpsRequired': '0', 'clientIdentifier': local_machine_identifier, 'label': 'Local', 'ip': '127.0.0.1', 'port': '32400', 'uri': 'http://127.0.0.1:32400', 'local': '1', 'value': '127.0.0.1:32400', 'is_cloud': False } servers = self.get_plextv_resources(include_https=True, output_format='xml') clean_servers = [] try: xml_head = servers.getElementsByTagName('MediaContainer') except Exception as e: logger.warn( "Tautulli PlexTV :: Failed to get servers from plex: %s." % e) return [] for a in xml_head: if a.getAttribute('size'): if a.getAttribute('size') == '0': return [] if a.getElementsByTagName('Device'): devices = a.getElementsByTagName('Device') for d in devices: if helpers.get_xml_attr(d, 'presence') == '1' and \ helpers.get_xml_attr(d, 'owned') == '1' and \ helpers.get_xml_attr(d, 'provides') == 'server': is_cloud = (helpers.get_xml_attr( d, 'platform').lower() == 'cloud') if not include_cloud and is_cloud: continue connections = d.getElementsByTagName('Connection') for c in connections: if not all_servers: # If this is a remote server don't show any local IPs. if helpers.get_xml_attr(d, 'publicAddressMatches') == '0' and \ helpers.get_xml_attr(c, 'local') == '1': continue # If this is a local server don't show any remote IPs. if helpers.get_xml_attr(d, 'publicAddressMatches') == '1' and \ helpers.get_xml_attr(c, 'local') == '0': continue if helpers.get_xml_attr( d, 'clientIdentifier' ) == local_machine_identifier: local_server[ 'httpsRequired'] = helpers.get_xml_attr( d, 'httpsRequired') local_server['label'] = helpers.get_xml_attr( d, 'name') clean_servers.append(local_server) local_machine_identifier = None server = { 'httpsRequired': '1' if is_cloud else helpers.get_xml_attr( d, 'httpsRequired'), 'clientIdentifier': helpers.get_xml_attr(d, 'clientIdentifier'), 'label': helpers.get_xml_attr(d, 'name'), 'ip': helpers.get_xml_attr(c, 'address'), 'port': helpers.get_xml_attr(c, 'port'), 'uri': helpers.get_xml_attr(c, 'uri'), 'local': helpers.get_xml_attr(c, 'local'), 'value': helpers.get_xml_attr(c, 'address') + ':' + helpers.get_xml_attr(c, 'port'), 'is_cloud': is_cloud } clean_servers.append(server) if local_machine_identifier: clean_servers.append(local_server) clean_servers.sort( key=lambda s: (s['label'], -int(s['local']), s['ip'])) return clean_servers
def get_devices_list(self): devices = self.get_plextv_devices_list(output_format='xml') try: xml_head = devices.getElementsByTagName('Device') except Exception as e: logger.warn( u"Tautulli PlexTV :: Unable to parse XML for get_devices_list: %s." % e) return [] devices_list = [] for a in xml_head: device = { "device_name": helpers.get_xml_attr(a, 'name'), "product": helpers.get_xml_attr(a, 'product'), "product_version": helpers.get_xml_attr(a, 'productVersion'), "platform": helpers.get_xml_attr(a, 'platform'), "platform_version": helpers.get_xml_attr(a, 'platformVersion'), "device": helpers.get_xml_attr(a, 'device'), "model": helpers.get_xml_attr(a, 'model'), "vendor": helpers.get_xml_attr(a, 'vendor'), "provides": helpers.get_xml_attr(a, 'provides'), "device_identifier": helpers.get_xml_attr(a, 'clientIdentifier'), "device_id": helpers.get_xml_attr(a, 'id'), "token": helpers.get_xml_attr(a, 'token') } devices_list.append(device) return devices_list
def get_full_users_list(self): friends_list = self.get_plextv_friends(output_format='xml') own_account = self.get_plextv_user_details(output_format='xml') users_list = [] try: xml_head = own_account.getElementsByTagName('user') except Exception as e: logger.warn( u"Tautulli PlexTV :: Unable to parse own account XML for get_full_users_list: %s." % e) return {} for a in xml_head: 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_admin": 1, "is_allow_sync": None, "is_restricted": helpers.get_xml_attr(a, 'restricted'), "filter_all": helpers.get_xml_attr(a, 'filterAll'), "filter_movies": helpers.get_xml_attr(a, 'filterMovies'), "filter_tv": helpers.get_xml_attr(a, 'filterTelevision'), "filter_music": helpers.get_xml_attr(a, 'filterMusic'), "filter_photos": helpers.get_xml_attr(a, 'filterPhotos') } users_list.append(own_details) try: xml_head = friends_list.getElementsByTagName('User') except Exception as e: logger.warn( u"Tautulli PlexTV :: Unable to parse friends list XML for get_full_users_list: %s." % e) return {} for a in xml_head: 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_admin": 0, "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'), "filter_all": helpers.get_xml_attr(a, 'filterAll'), "filter_movies": helpers.get_xml_attr(a, 'filterMovies'), "filter_tv": helpers.get_xml_attr(a, 'filterTelevision'), "filter_music": helpers.get_xml_attr(a, 'filterMusic'), "filter_photos": helpers.get_xml_attr(a, 'filterPhotos') } users_list.append(friend) return users_list