Merge pull request #207 from JonnyWong16/update-metadata

Update rating key for missing items
This commit is contained in:
drzoidberg33 2015-09-27 21:03:14 +02:00
commit f15e3a47ea
8 changed files with 1097 additions and 24 deletions

View file

@ -781,3 +781,202 @@ class DataFactory(object):
else:
return 'Unable to delete items. Input user_id not valid.'
def get_search_query(self, rating_key=''):
monitor_db = database.MonitorDatabase()
if rating_key:
query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \
'media_index, parent_media_index, year, media_type ' \
'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])
else:
result = []
query = {}
query_string = None
media_type = None
for item in result:
title = item['title']
parent_title = item['parent_title']
grandparent_title = item['grandparent_title']
media_index = item['media_index']
parent_media_index = item['parent_media_index']
year = item['year']
if str(item['rating_key']) == rating_key:
query_string = item['title']
media_type = item['media_type']
elif str(item['parent_rating_key']) == rating_key:
if item['media_type'] == 'episode':
query_string = item['grandparent_title']
media_type = 'season'
elif item['media_type'] == 'track':
query_string = item['parent_title']
media_type = 'album'
elif str(item['grandparent_rating_key']) == rating_key:
if item['media_type'] == 'episode':
query_string = item['grandparent_title']
media_type = 'show'
elif item['media_type'] == 'track':
query_string = item['grandparent_title']
media_type = 'artist'
if query_string and media_type:
query = {'query_string': query_string.replace('"', ''),
'title': title,
'parent_title': parent_title,
'grandparent_title': grandparent_title,
'media_index': media_index,
'parent_media_index': parent_media_index,
'year': year,
'media_type': media_type,
'rating_key': rating_key
}
else:
return None
return query
def get_rating_keys_list(self, rating_key='', media_type=''):
monitor_db = database.MonitorDatabase()
if media_type == 'movie':
key_list = {0: {'rating_key': int(rating_key)}}
return key_list
if media_type == 'artist' or media_type == 'album' or media_type == 'track':
match_type = 'title'
else:
match_type = 'index'
# 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])
grandparent_rating_key = result[0]['grandparent_rating_key']
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']
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,
[old_key, new_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,
[old_key, new_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,
[old_key, new_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,
[old_key, new_key])
return 'Updated rating key in database.'
else:
return 'No updated rating key needed in database. No changes were made.'
# for debugging
#return mapping

View file

@ -17,6 +17,7 @@ from plexpy import logger, helpers, users, http_handler
from urlparse import urlparse
import plexpy
import urllib2
class PmsConnect(object):
@ -72,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.
@ -219,6 +237,22 @@ class PmsConnect(object):
return request
"""
Return search results.
Optional parameters: output_format { dict, json }
Output: array
"""
def get_search(self, query='', track='', output_format=''):
uri = '/search?query=' + urllib2.quote(query.encode('utf8')) + track
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
request_type='GET',
output_format=output_format)
return request
"""
Return processed and validated list of recently added items.
@ -1340,3 +1374,202 @@ class PmsConnect(object):
else:
logger.error("Image proxy queries but no input received.")
return None
"""
Return processed list of search results.
Output: array
"""
def get_search_results(self, query=''):
search_results = self.get_search(query=query, output_format='xml')
search_results_tracks = self.get_search(query=query, track='&type=10', output_format='xml')
xml_head = []
try:
try:
xml_head += search_results.getElementsByTagName('MediaContainer')
except:
pass
try:
xml_head += search_results_tracks.getElementsByTagName('MediaContainer')
except:
pass
except:
logger.warn("Unable to parse XML for get_search_result_details.")
return []
search_results_count = 0
search_results_list = {'movie': [],
'show': [],
'season': [],
'episode': [],
'artist': [],
'album': [],
'track': []
}
totalSize = 0
for a in xml_head:
if a.getAttribute('size'):
totalSize += int(a.getAttribute('size'))
if totalSize == 0:
logger.debug(u"No search results.")
search_results_list = {'results_count': search_results_count,
'results_list': []
}
return search_results_list
for a in xml_head:
if a.getElementsByTagName('Video'):
result_data = a.getElementsByTagName('Video')
for result in result_data:
rating_key = helpers.get_xml_attr(result, 'ratingKey')
metadata = self.get_metadata_details(rating_key=rating_key)
if metadata['metadata']['type'] == 'movie':
search_results_list['movie'].append(metadata['metadata'])
elif metadata['metadata']['type'] == 'episode':
search_results_list['episode'].append(metadata['metadata'])
search_results_count += 1
if a.getElementsByTagName('Directory'):
result_data = a.getElementsByTagName('Directory')
for result in result_data:
rating_key = helpers.get_xml_attr(result, 'ratingKey')
metadata = self.get_metadata_details(rating_key=rating_key)
if metadata['metadata']['type'] == 'show':
search_results_list['show'].append(metadata['metadata'])
show_seasons = self.get_item_children(rating_key=metadata['metadata']['rating_key'])
if show_seasons['children_count'] != '0':
for season in show_seasons['children_list']:
if season['rating_key']:
rating_key = season['rating_key']
metadata = self.get_metadata_details(rating_key=rating_key)
search_results_list['season'].append(metadata['metadata'])
search_results_count += 1
elif metadata['metadata']['type'] == 'artist':
search_results_list['artist'].append(metadata['metadata'])
elif metadata['metadata']['type'] == 'album':
search_results_list['album'].append(metadata['metadata'])
search_results_count += 1
if a.getElementsByTagName('Track'):
result_data = a.getElementsByTagName('Track')
for result in result_data:
rating_key = helpers.get_xml_attr(result, 'ratingKey')
metadata = self.get_metadata_details(rating_key=rating_key)
search_results_list['track'].append(metadata['metadata'])
search_results_count += 1
output = {'results_count': search_results_count,
'results_list': search_results_list
}
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 == 'artist' or media_type == 'album' or media_type == 'track':
match_type = 'title'
else:
match_type = 'index'
# 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)
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

View file

@ -749,6 +749,7 @@ class WebInterface(object):
@cherrypy.expose
def info(self, item_id=None, source=None, **kwargs):
metadata = None
query = None
config = {
"pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER
@ -762,12 +763,15 @@ class WebInterface(object):
result = pms_connect.get_metadata_details(rating_key=item_id)
if result:
metadata = result['metadata']
else:
data_factory = datafactory.DataFactory()
query = data_factory.get_search_query(rating_key=item_id)
if metadata:
return serve_template(templatename="info.html", data=metadata, title="Info", config=config)
else:
logger.warn('Unable to retrieve data.')
return serve_template(templatename="info.html", data=None, title="Info")
return serve_template(templatename="info.html", data=None, query=query, title="Info")
@cherrypy.expose
def get_user_recently_watched(self, user=None, user_id=None, limit='10', **kwargs):
@ -1323,3 +1327,105 @@ class WebInterface(object):
cherrypy.response.headers['Content-type'] = 'application/json'
return json.dumps({'message': 'no data received'})
@cherrypy.expose
def search(self, search_query=''):
query = search_query.replace('"', '')
return serve_template(templatename="search.html", title="Search", query=query)
@cherrypy.expose
def search_results(self, query, **kwargs):
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_search_results(query)
if result:
cherrypy.response.headers['Content-type'] = 'application/json'
return json.dumps(result)
else:
logger.warn('Unable to retrieve data.')
@cherrypy.expose
def get_search_results_children(self, query, media_type=None, season_index=None, **kwargs):
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_search_results(query)
if media_type:
result['results_list'] = {media_type: result['results_list'][media_type]}
if media_type == 'season' and season_index:
for season in result['results_list']['season']:
if season['index'] == season_index:
result['results_list']['season'] = [season]
break
if result:
return serve_template(templatename="info_search_results_list.html", data=result, title="Search Result List")
else:
logger.warn('Unable to retrieve data.')
return serve_template(templatename="info_search_results_list.html", data=None, title="Search Result List")
@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()
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)
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.')