diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py index 119662e3..939587aa 100644 --- a/plexpy/datafactory.py +++ b/plexpy/datafactory.py @@ -842,35 +842,127 @@ class DataFactory(object): return query - def update_rating_key(self, old_rating_key='', new_rating_key='', media_type=''): + def get_rating_keys_list(self, rating_key='', media_type=''): monitor_db = database.MonitorDatabase() - if new_rating_key.isdigit(): - logger.info(u"PlexPy DataFactory :: Updating rating key %s to %s in the session history database." % (old_rating_key, new_rating_key)) - if media_type == 'movie' or media_type == 'episode' or media_type == 'track': - monitor_db.action('UPDATE session_history SET rating_key = ? WHERE rating_key = ?', [new_rating_key, old_rating_key]) - monitor_db.action('UPDATE session_history_media_info SET rating_key = ? WHERE rating_key = ?', [new_rating_key, old_rating_key]) - monitor_db.action('UPDATE session_history_metadata SET rating_key = ? WHERE rating_key = ?', [new_rating_key, old_rating_key]) - monitor_db.action('UPDATE session_history_metadata SET thumb = replace(thumb, ?, ?) WHERE thumb LIKE "/library/metadata/%s/thumb/%%"' % old_rating_key, - [old_rating_key, new_rating_key]) + if media_type == 'movie': + key_list = {0: {'rating_key': int(rating_key)}} + return key_list - if media_type == 'season' or media_type == 'album': - monitor_db.action('UPDATE session_history SET parent_rating_key = ? WHERE parent_rating_key = ?', [new_rating_key, old_rating_key]) - monitor_db.action('UPDATE session_history_metadata SET parent_rating_key = ? WHERE parent_rating_key = ?', [new_rating_key, old_rating_key]) - monitor_db.action('UPDATE session_history_metadata SET parent_thumb = replace(parent_thumb, ?, ?) WHERE parent_thumb LIKE "/library/metadata/%s/thumb/%%"' % old_rating_key, - [old_rating_key, new_rating_key]) + if media_type == 'show' or media_type == 'season' or media_type == 'episode': + match_type = 'index' + elif media_type == 'artist' or media_type == 'album' or media_type == 'track': + match_type = 'title' - if media_type == 'show' or media_type == 'artist': - monitor_db.action('UPDATE session_history SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?', [new_rating_key, old_rating_key]) - monitor_db.action('UPDATE session_history_metadata SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?', [new_rating_key, old_rating_key]) - monitor_db.action('UPDATE session_history_metadata SET grandparent_thumb = replace(grandparent_thumb, ?, ?) WHERE grandparent_thumb LIKE "/library/metadata/%s/thumb/%%"' % old_rating_key, - [old_rating_key, new_rating_key]) + # Get the grandparent rating key + try: + query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key ' \ + 'FROM session_history_metadata ' \ + 'WHERE rating_key = ? ' \ + 'OR parent_rating_key = ? ' \ + 'OR grandparent_rating_key = ? ' \ + 'LIMIT 1' + result = monitor_db.select(query=query, args=[rating_key, rating_key, rating_key]) - if media_type == 'movie' or media_type == 'show': - monitor_db.action('UPDATE session_history_metadata SET art = replace(art, ?, ?) WHERE art LIKE "/library/metadata/%s/art/%%"' % old_rating_key, - [old_rating_key, new_rating_key]) + grandparent_rating_key = result[0]['grandparent_rating_key'] - return 'Updated rating key %s to %s.' % (old_rating_key, new_rating_key) - else: - return 'Unable to update rating key. Input new_rating_key not valid.' + except: + logger.warn("Unable to execute database query.") + return {} + query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \ + 'media_index, parent_media_index ' \ + 'FROM session_history_metadata ' \ + 'WHERE {0} = ? ' \ + 'GROUP BY {1} ' + + # get grandparent_rating_keys + grandparents = {} + result = monitor_db.select(query=query.format('grandparent_rating_key', 'grandparent_rating_key'), + args=[grandparent_rating_key]) + for item in result: + # get parent_rating_keys + parents = {} + result = monitor_db.select(query=query.format('grandparent_rating_key', 'parent_rating_key'), + args=[item['grandparent_rating_key']]) + for item in result: + # get rating_keys + children = {} + result = monitor_db.select(query=query.format('parent_rating_key', 'rating_key'), + args=[item['parent_rating_key']]) + for item in result: + key = item['media_index'] if match_type == 'index' else item['title'] + children.update({key: {'rating_key': item['rating_key']}}) + + key = item['parent_media_index'] if match_type == 'index' else item['parent_title'] + parents.update({key: + {'rating_key': item['parent_rating_key'], + 'children': children} + }) + + key = 0 if match_type == 'index' else item['grandparent_title'] + grandparents.update({key: + {'rating_key': item['grandparent_rating_key'], + 'children': parents} + }) + + key_list = grandparents + + return key_list + + def update_rating_key(self, old_key_list='', new_key_list='', media_type=''): + monitor_db = database.MonitorDatabase() + + # function to map rating keys pairs + def get_pairs(old, new): + pairs = {} + for k, v in old.iteritems(): + if k in new: + if v['rating_key'] != new[k]['rating_key']: + pairs.update({v['rating_key']: new[k]['rating_key']}) + if 'children' in old[k]: + pairs.update(get_pairs(old[k]['children'], new[k]['children'])) + + return pairs + + # map rating keys pairs + mapping = {} + if old_key_list and new_key_list: + mapping = get_pairs(old_key_list, new_key_list) + + if mapping: + logger.info(u"PlexPy DataFactory :: Updating rating keys in the database.") + for old_key, new_key in mapping.iteritems(): + # check rating_key (3 tables) + monitor_db.action('UPDATE session_history SET rating_key = ? WHERE rating_key = ?', [new_key, old_key]) + monitor_db.action('UPDATE session_history_media_info SET rating_key = ? WHERE rating_key = ?', [new_key, old_key]) + monitor_db.action('UPDATE session_history_metadata SET rating_key = ? WHERE rating_key = ?', [new_key, old_key]) + + # check parent_rating_key (2 tables) + monitor_db.action('UPDATE session_history SET parent_rating_key = ? WHERE parent_rating_key = ?', [new_key, old_key]) + monitor_db.action('UPDATE session_history_metadata SET parent_rating_key = ? WHERE parent_rating_key = ?', [new_key, old_key]) + + # check grandparent_rating_key (2 tables) + monitor_db.action('UPDATE session_history SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?', [new_key, old_key]) + monitor_db.action('UPDATE session_history_metadata SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?', [new_key, old_key]) + + # check thumb (1 table) + monitor_db.action('UPDATE session_history_metadata SET thumb = replace(thumb, ?, ?) WHERE thumb LIKE "/library/metadata/%s/thumb/%%"' % old_key, + [new_key, old_key]) + + # check parent_thumb (1 table) + monitor_db.action('UPDATE session_history_metadata SET parent_thumb = replace(parent_thumb, ?, ?) WHERE parent_thumb LIKE "/library/metadata/%s/thumb/%%"' % old_key, + [new_key, old_key]) + + # check grandparent_thumb (1 table) + monitor_db.action('UPDATE session_history_metadata SET grandparent_thumb = replace(grandparent_thumb, ?, ?) WHERE grandparent_thumb LIKE "/library/metadata/%s/thumb/%%"' % old_key, + [new_key, old_key]) + + # check art (1 table) + monitor_db.action('UPDATE session_history_metadata SET art = replace(art, ?, ?) WHERE art LIKE "/library/metadata/%s/art/%%"' % old_key, + [new_key, old_key]) + + #return 'Updated rating key in database.' + #else: + #return 'No updated rating key needed in database. No changes were made.' + return mapping \ No newline at end of file diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py index 902840df..69622a7b 100644 --- a/plexpy/pmsconnect.py +++ b/plexpy/pmsconnect.py @@ -73,6 +73,23 @@ class PmsConnect(object): return request + """ + Return metadata for children of the request item. + + Parameters required: rating_key { Plex ratingKey } + Optional parameters: output_format { dict, json } + + Output: array + """ + def get_metadata_children(self, rating_key='', output_format=''): + uri = '/library/metadata/' + rating_key + '/children' + request = self.request_handler.make_request(uri=uri, + proto=self.protocol, + request_type='GET', + output_format=output_format) + + return request + """ Return list of recently added items. @@ -1449,4 +1466,110 @@ class PmsConnect(object): 'results_list': search_results_list } - return output \ No newline at end of file + return output + + """ + Return processed list of grandparent/parent/child rating keys. + + Output: array + """ + def get_rating_keys_list(self, rating_key='', media_type=''): + + if media_type == 'movie': + key_list = {0: {'rating_key': int(rating_key)}} + return key_list + + if media_type == 'show' or media_type == 'season' or media_type == 'episode': + match_type = 'index' + elif media_type == 'artist' or media_type == 'album' or media_type == 'track': + match_type = 'title' + + # get grandparent rating key + if media_type == 'season' or media_type == 'album': + try: + metadata = self.get_metadata_details(rating_key=rating_key) + rating_key = metadata['metadata']['parent_rating_key'] + except: + logger.warn("Unable to get parent_rating_key for get_rating_keys_list.") + return {} + + elif media_type == 'episode' or media_type == 'track': + try: + metadata = self.get_metadata_details(rating_key=rating_key) + rating_key = metadata['metadata']['grandparent_rating_key'] + except: + logger.warn("Unable to get grandparent_rating_key for get_rating_keys_list.") + return {} + + # get parent_rating_keys + metadata = self.get_metadata_children(str(rating_key), output_format='xml') + + try: + xml_head = metadata.getElementsByTagName('MediaContainer') + except: + logger.warn("Unable to parse XML for get_rating_keys_list.") + return {} + + for a in xml_head: + if a.getAttribute('size'): + if a.getAttribute('size') == '0': + return {} + + title = helpers.get_xml_attr(a, 'title2') + + if a.getElementsByTagName('Directory'): + parents_metadata = a.getElementsByTagName('Directory') + else: + parents_metadata = [] + + parents = {} + for item in parents_metadata: + parent_rating_key = helpers.get_xml_attr(item, 'ratingKey') + parent_index = helpers.get_xml_attr(item, 'index') + parent_title = helpers.get_xml_attr(item, 'title') + + if parent_rating_key: + # get rating_keys + metadata = self.get_metadata_children(str(parent_rating_key), output_format='xml') + + try: + xml_head = metadata.getElementsByTagName('MediaContainer') + except: + logger.warn("Unable to parse XML for get_rating_keys_list.") + return {} + + for a in xml_head: + if a.getAttribute('size'): + if a.getAttribute('size') == '0': + return {} + + if a.getElementsByTagName('Video'): + children_metadata = a.getElementsByTagName('Video') + elif a.getElementsByTagName('Track'): + children_metadata = a.getElementsByTagName('Track') + else: + children_metadata = [] + + children = {} + for item in children_metadata: + child_rating_key = helpers.get_xml_attr(item, 'ratingKey') + child_index = helpers.get_xml_attr(item, 'index') + child_title = helpers.get_xml_attr(item, 'title') + + if child_rating_key: + key = int(child_index) if match_type == 'index' else child_title + children.update({key: {'rating_key': int(child_rating_key)}}) + + key = int(parent_index) if match_type == 'index' else parent_title + parents.update({key: + {'rating_key': int(parent_rating_key), + 'children': children} + }) + + key = 0 if match_type == 'index' else title + key_list = {key: + {'rating_key': int(rating_key), + 'children': parents} + } + + return key_list \ No newline at end of file diff --git a/plexpy/webserve.py b/plexpy/webserve.py index 66aa9e79..30272681 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -1368,15 +1368,64 @@ class WebInterface(object): @cherrypy.expose def update_history_rating_key(self, old_rating_key, new_rating_key, media_type, **kwargs): data_factory = datafactory.DataFactory() + pms_connect = pmsconnect.PmsConnect() - if new_rating_key: - update_row = data_factory.update_rating_key(old_rating_key=old_rating_key, - new_rating_key=new_rating_key, - media_type=media_type) + old_key_list = data_factory.get_rating_keys_list(rating_key=old_rating_key, media_type=media_type) + new_key_list = pms_connect.get_rating_keys_list(rating_key=new_rating_key, media_type=media_type) - if update_row: - cherrypy.response.headers['Content-type'] = 'application/json' - return json.dumps({'message': update_row}) + update_db = data_factory.update_rating_key(old_key_list=old_key_list, + new_key_list=new_key_list, + media_type=media_type) + + if update_db: + cherrypy.response.headers['Content-type'] = 'application/json' + return json.dumps({'message': update_db}) else: cherrypy.response.headers['Content-type'] = 'application/json' return json.dumps({'message': 'no data received'}) + + + # test code + @cherrypy.expose + def get_new_rating_keys(self, rating_key='', media_type='', **kwargs): + + pms_connect = pmsconnect.PmsConnect() + result = pms_connect.get_rating_keys_list(rating_key=rating_key, media_type=media_type) + + if result: + cherrypy.response.headers['Content-type'] = 'application/json' + return json.dumps(result) + else: + logger.warn('Unable to retrieve data.') + + @cherrypy.expose + def get_old_rating_keys(self, rating_key='', media_type='', **kwargs): + + data_factory = datafactory.DataFactory() + result = data_factory.get_rating_keys_list(rating_key=rating_key, media_type=media_type) + + if result: + cherrypy.response.headers['Content-type'] = 'application/json' + return json.dumps(result) + else: + logger.warn('Unable to retrieve data.') + + @cherrypy.expose + def get_map_rating_keys(self, old_rating_key, new_rating_key, media_type, **kwargs): + + data_factory = datafactory.DataFactory() + pms_connect = pmsconnect.PmsConnect() + + if new_rating_key: + old_key_list = data_factory.get_rating_keys_list(rating_key=old_rating_key, media_type=media_type) + new_key_list = pms_connect.get_rating_keys_list(rating_key=new_rating_key, media_type=media_type) + + result = data_factory.update_rating_key(old_key_list=old_key_list, + new_key_list=new_key_list, + media_type=media_type) + + if result: + cherrypy.response.headers['Content-type'] = 'application/json' + return json.dumps(result) + else: + logger.warn('Unable to retrieve data.') \ No newline at end of file