From d36de5a5358d64baa5fcfa5462affa68e9de9f9c Mon Sep 17 00:00:00 2001 From: Jonathan Wong Date: Thu, 24 Sep 2015 18:42:56 -0700 Subject: [PATCH 01/18] Add search functions --- plexpy/pmsconnect.py | 102 +++++++++++++++++++++++++++++++++++++++++++ plexpy/webserve.py | 26 +++++++++++ 2 files changed, 128 insertions(+) diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py index 3b58adb5..e7701788 100644 --- a/plexpy/pmsconnect.py +++ b/plexpy/pmsconnect.py @@ -17,6 +17,7 @@ from plexpy import logger, helpers, users, http_handler from urlparse import urlparse import plexpy +import urllib class PmsConnect(object): @@ -219,6 +220,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=' + urllib.quote_plus(query) + 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 +1357,88 @@ 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 = {'movies': [], + 'shows': [], + 'seasons': [], + 'episodes': [], + 'artists': [], + 'albums': [], + 'tracks': [] + } + + 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['movies'].append(metadata['metadata']) + elif metadata['metadata']['type'] == 'episode': + search_results_list['episodes'].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['shows'].append(metadata['metadata']) + elif metadata['metadata']['type'] == 'season': + search_results_list['seasons'].append(metadata['metadata']) + elif metadata['metadata']['type'] == 'artist': + search_results_list['artists'].append(metadata['metadata']) + elif metadata['metadata']['type'] == 'album': + search_results_list['albums'].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['tracks'].append(metadata['metadata']) + search_results_count += 1 + + output = {'results_count': search_results_count, + 'results_list': search_results_list + } + + return output \ No newline at end of file diff --git a/plexpy/webserve.py b/plexpy/webserve.py index 519577c7..d082e85f 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -1323,3 +1323,29 @@ class WebInterface(object): cherrypy.response.headers['Content-type'] = 'application/json' return json.dumps({'message': 'no data received'}) + @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, **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 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") From 25249e7538f05124d103aba841a7ab6e10d6b34d Mon Sep 17 00:00:00 2001 From: Jonathan Wong Date: Thu, 24 Sep 2015 19:33:44 -0700 Subject: [PATCH 02/18] Display search results if metadata not found --- data/interfaces/default/css/plexpy.css | 24 ++ data/interfaces/default/info.html | 68 +++++- .../default/info_search_results_list.html | 222 ++++++++++++++++++ plexpy/datafactory.py | 45 ++++ plexpy/pmsconnect.py | 28 +-- plexpy/webserve.py | 6 +- 6 files changed, 366 insertions(+), 27 deletions(-) create mode 100644 data/interfaces/default/info_search_results_list.html diff --git a/data/interfaces/default/css/plexpy.css b/data/interfaces/default/css/plexpy.css index 649f36ac..60d76b35 100644 --- a/data/interfaces/default/css/plexpy.css +++ b/data/interfaces/default/css/plexpy.css @@ -1248,9 +1248,33 @@ a:hover .summary-poster-face-track .summary-poster-face-overlay span { } .item-children-wrapper { } +.item-children-section-title { + position: relative; + padding: 10px; + background-color: #2c2c2c; + border-bottom: 1px solid #3d3d3d; + border-top: 1px solid #282828; + height: 50px; + line-height: 22px; + padding: 13px 20px; + margin: 20px 0; +} +.item-children-section-title h4 { + position: relative; + margin: 0; + line-height: 22px; + color: #fff; + font-size: 16px; + text-align: center; + text-transform: uppercase; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} .item-children-instance { list-style: none; margin: 0; + overflow: hidden; } .item-children-instance li { float: left; diff --git a/data/interfaces/default/info.html b/data/interfaces/default/info.html index 02b97a10..1c1e8f4b 100644 --- a/data/interfaces/default/info.html +++ b/data/interfaces/default/info.html @@ -32,6 +32,14 @@ directors Returns an array of directors. studio Returns the name of the studio. originally_available_at Returns the air date of the item. +query :: Usable parameters + +== Global keys == +rating_key Returns the unique identifier for the media item. +media_type Returns the type of media. Either 'movie', 'show', 'season', 'episode', 'artist', 'album', or 'track'. +title Returns the title for the search query. + + DOCUMENTATION :: END @@ -361,11 +369,34 @@ DOCUMENTATION :: END % else:
-
-

- Error retrieving item data. This media may not be available in the Plex Media Server database - anymore. -

+
+
+
+
+

+ Error retrieving item metadata. This media item is not available in the Plex Media Server library. +

+ % if query: +

+ If the item has been moved, please select the correct match below to update the PlexPy database. +

+ % endif +
+
+
+
+ % if query: +
+
+ Search Results for ${query['title']} +
+
+
+
+
+ % endif +
+
@@ -381,13 +412,6 @@ DOCUMENTATION :: END % if data: -% if data['type'] == 'movie' or data['type'] == 'show' or data['type'] == 'episode': - -% endif % if data['type'] == 'show' or data['type'] == 'artist': % endif +% if data['rating']: + +% endif +% elif query: + % endif diff --git a/data/interfaces/default/info_search_results_list.html b/data/interfaces/default/info_search_results_list.html new file mode 100644 index 00000000..cdc05b83 --- /dev/null +++ b/data/interfaces/default/info_search_results_list.html @@ -0,0 +1,222 @@ +<%doc> +USAGE DOCUMENTATION :: PLEASE LEAVE THIS AT THE TOP OF THIS FILE + +For Mako templating syntax documentation please visit: http://docs.makotemplates.org/en/latest/ + +Filename: info_children_list.html +Version: 0.1 +Variable names: data [list] + +data :: Usable parameters + +== Global keys == +results_count Returns the number of search results. +results_list Returns a dictionary of search result types. + +data['results_list'] :: Usable paramaters + +== media_type keys == +movie Returns an array of movie results +show Returns an array of show results +season Returns an array of season results +episode Returns an array of episode results +artist Returns an array of artist results +album Returns an array of album results +track Returns an array of track results + +data['results_list'][media_type] :: Usable paramaters + +== Global keys == +rating_key Returns the unique identifier for the media item. +type Returns the type of media. Either 'movie', 'episode' or 'show' or 'season'. +art Returns the location of the item's artwork +title Returns the name of the episode, show, season or movie. +duration Returns the standard runtime of the media. +content_rating Returns the age rating for the media. +summary Returns a brief description of the media plot. +grandparent_title Returns the name of the TV show. +parent_index Returns the season number of the TV show. +index Returns the episode number. +parent_thumb Returns the location of the item's thumbnail. Use with pms_image_proxy. +writers Returns an array of writers. +thumb Returns the location of the item's thumbnail. Use with pms_image_proxy. +parent_title Returns the name of the TV show. +rating Returns the 5 star rating value for the movie. Between 1 and 5. +year Returns the release year of the movie. +genres Returns an array of genres. +actors Returns an array of actors. +directors Returns an array of directors. +studio Returns the name of the studio. +originally_available_at Returns the air date of the item. + +DOCUMENTATION :: END + + +% if data != None: +% if data['results_count'] > 0: +% if 'movie' in data['results_list'] and data['results_list']['movie']: +
+
+

Movies

+
+ +
+% endif +% if 'show' in data['results_list'] and data['results_list']['show']: +
+
+

TV Shows

+
+ +
+% endif +% if 'season' in data['results_list'] and data['results_list']['season']: +
+
+

Seasons

+
+ +
+% endif +% if 'episode' in data['results_list'] and data['results_list']['episode']: +
+
+

Episodes

+
+ +
+% endif +% if 'artist' in data['results_list'] and data['results_list']['artist']: +
+
+

Artists

+
+ +
+% endif +% if 'album' in data['results_list'] and data['results_list']['album']: +
+
+

Albums

+
+ +
+% endif +% if 'track' in data['results_list'] and data['results_list']['track']: +
+
+

Tracks

+
+ +
+% endif +% else: +
+ No search results found. +
+% endif +% endif + diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py index 2343ce42..991201cc 100644 --- a/plexpy/datafactory.py +++ b/plexpy/datafactory.py @@ -779,3 +779,48 @@ 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_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 = {} + title = None + media_type = None + + for item in result: + if str(item['rating_key']) == rating_key: + title = item['title'] + media_type = item['media_type'] + + elif str(item['parent_rating_key']) == rating_key: + title = item['parent_title'] + if item['media_type'] == episode: + media_type = 'season' + elif item['media_type'] == track: + media_type = 'album' + + elif str(item['grandparent_rating_key']) == rating_key: + title = item['grandparent_title'] + if item['media_type'] == episode: + media_type = 'show' + elif item['media_type'] == track: + media_type = 'artist' + + if title and media_type: + query = {'title': title, + 'media_type': media_type, + 'rating_key': rating_key} + else: + return None + + return query diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py index e7701788..95b41f24 100644 --- a/plexpy/pmsconnect.py +++ b/plexpy/pmsconnect.py @@ -1382,13 +1382,13 @@ class PmsConnect(object): return [] search_results_count = 0 - search_results_list = {'movies': [], - 'shows': [], - 'seasons': [], - 'episodes': [], - 'artists': [], - 'albums': [], - 'tracks': [] + search_results_list = {'movie': [], + 'show': [], + 'season': [], + 'episode': [], + 'artist': [], + 'album': [], + 'track': [] } totalSize = 0 @@ -1409,9 +1409,9 @@ class PmsConnect(object): 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['movies'].append(metadata['metadata']) + search_results_list['movie'].append(metadata['metadata']) elif metadata['metadata']['type'] == 'episode': - search_results_list['episodes'].append(metadata['metadata']) + search_results_list['episode'].append(metadata['metadata']) search_results_count += 1 if a.getElementsByTagName('Directory'): @@ -1420,13 +1420,13 @@ class PmsConnect(object): 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['shows'].append(metadata['metadata']) + search_results_list['show'].append(metadata['metadata']) elif metadata['metadata']['type'] == 'season': - search_results_list['seasons'].append(metadata['metadata']) + search_results_list['season'].append(metadata['metadata']) elif metadata['metadata']['type'] == 'artist': - search_results_list['artists'].append(metadata['metadata']) + search_results_list['artist'].append(metadata['metadata']) elif metadata['metadata']['type'] == 'album': - search_results_list['albums'].append(metadata['metadata']) + search_results_list['album'].append(metadata['metadata']) search_results_count += 1 if a.getElementsByTagName('Track'): @@ -1434,7 +1434,7 @@ class PmsConnect(object): 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['tracks'].append(metadata['metadata']) + search_results_list['track'].append(metadata['metadata']) search_results_count += 1 output = {'results_count': search_results_count, diff --git a/plexpy/webserve.py b/plexpy/webserve.py index d082e85f..28983de1 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -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): From 28d05ba9fe8913e25eb251631f427aca62d31856 Mon Sep 17 00:00:00 2001 From: Jonathan Wong Date: Thu, 24 Sep 2015 22:09:14 -0700 Subject: [PATCH 03/18] Add seasons to search query --- plexpy/datafactory.py | 16 +++++++++------- plexpy/pmsconnect.py | 11 +++++++++-- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py index 991201cc..9a8cdeba 100644 --- a/plexpy/datafactory.py +++ b/plexpy/datafactory.py @@ -803,21 +803,23 @@ class DataFactory(object): media_type = item['media_type'] elif str(item['parent_rating_key']) == rating_key: - title = item['parent_title'] - if item['media_type'] == episode: + if item['media_type'] == 'episode': + title = item['grandparent_title'] media_type = 'season' - elif item['media_type'] == track: + elif item['media_type'] == 'track': + title = item['parent_title'] media_type = 'album' elif str(item['grandparent_rating_key']) == rating_key: - title = item['grandparent_title'] - if item['media_type'] == episode: + if item['media_type'] == 'episode': + title = item['grandparent_title'] media_type = 'show' - elif item['media_type'] == track: + elif item['media_type'] == 'track': + title = item['grandparent_title'] media_type = 'artist' if title and media_type: - query = {'title': title, + query = {'title': title.replace('"', ''), 'media_type': media_type, 'rating_key': rating_key} else: diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py index 95b41f24..003e7aa1 100644 --- a/plexpy/pmsconnect.py +++ b/plexpy/pmsconnect.py @@ -1421,8 +1421,15 @@ class PmsConnect(object): metadata = self.get_metadata_details(rating_key=rating_key) if metadata['metadata']['type'] == 'show': search_results_list['show'].append(metadata['metadata']) - elif metadata['metadata']['type'] == 'season': - search_results_list['season'].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']) + elif metadata['metadata']['type'] == 'artist': search_results_list['artist'].append(metadata['metadata']) elif metadata['metadata']['type'] == 'album': From e6556eaf2723d8306f3b6f18d8b6bddb46ca247c Mon Sep 17 00:00:00 2001 From: Jonathan Wong Date: Thu, 24 Sep 2015 22:11:56 -0700 Subject: [PATCH 04/18] Add function to update rating keys --- plexpy/datafactory.py | 33 +++++++++++++++++++++++++++++++++ plexpy/webserve.py | 16 ++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py index 9a8cdeba..d29813e1 100644 --- a/plexpy/datafactory.py +++ b/plexpy/datafactory.py @@ -826,3 +826,36 @@ class DataFactory(object): return None return query + + def update_rating_key(self, old_rating_key='', new_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 == '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 == '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]) + + 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]) + + 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.' + diff --git a/plexpy/webserve.py b/plexpy/webserve.py index 28983de1..b951554a 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -1353,3 +1353,19 @@ class WebInterface(object): 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() + + 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) + + if update_row: + cherrypy.response.headers['Content-type'] = 'application/json' + return json.dumps({'message': update_row}) + else: + cherrypy.response.headers['Content-type'] = 'application/json' + return json.dumps({'message': 'no data received'}) From c45a903f9f4d3fdde4a19187ddac0a46d18de276 Mon Sep 17 00:00:00 2001 From: Jonathan Wong Date: Thu, 24 Sep 2015 22:12:44 -0700 Subject: [PATCH 05/18] Add user selection to update rating key --- data/interfaces/default/info.html | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/data/interfaces/default/info.html b/data/interfaces/default/info.html index 1c1e8f4b..f710532a 100644 --- a/data/interfaces/default/info.html +++ b/data/interfaces/default/info.html @@ -394,6 +394,25 @@ DOCUMENTATION :: END
+ % endif
@@ -536,6 +555,31 @@ DOCUMENTATION :: END complete: function(xhr, status) { $("#search-results-list").html(xhr.responseText); } }); + $(document).on('click', '#search-results-list a', function (e) { + e.preventDefault(); + var new_rating_key = $(this).attr("id"); + var new_href = $(this).attr("href"); + + $('#new_title').text($(this).find('.item-children-instance-text-wrapper').text()); + + $('#confirm-modal').modal(); + $('#confirm-modal').one('click', '#confirm-update', function () { + var msg = " Updating database..." + showMsg(msg, false, false, 0) + + $.ajax({ + url: 'update_history_rating_key', + data: { old_rating_key: "${query['rating_key']}", + new_rating_key: new_rating_key, + media_type: "${query['media_type']}" + }, + async: false, + success: function (data) { + window.location.href = new_href; + } + }); + }); + }); % endif From 91446d01a718b1d081bbfb44876dd4926ba7473a Mon Sep 17 00:00:00 2001 From: Jonathan Wong Date: Thu, 24 Sep 2015 23:41:15 -0700 Subject: [PATCH 06/18] Filter season search by season index --- data/interfaces/default/info.html | 7 ++++--- plexpy/datafactory.py | 33 +++++++++++++++++++++---------- plexpy/webserve.py | 7 ++++++- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/data/interfaces/default/info.html b/data/interfaces/default/info.html index f710532a..60df76ae 100644 --- a/data/interfaces/default/info.html +++ b/data/interfaces/default/info.html @@ -388,7 +388,7 @@ DOCUMENTATION :: END % if query:
- Search Results for ${query['title']} + Search Results for ${query['query_string']}
@@ -549,8 +549,9 @@ DOCUMENTATION :: END url: 'get_search_results_children', type: "GET", async: true, - data: { query: "${query['title']}", - media_type: "${query['media_type']}" + data: {'query': "${query['query_string']}", + 'media_type': "${query['media_type']}", + 'season_index': "${query['parent_media_index']}" }, complete: function(xhr, status) { $("#search-results-list").html(xhr.responseText); } diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py index d29813e1..2dfda9cb 100644 --- a/plexpy/datafactory.py +++ b/plexpy/datafactory.py @@ -783,7 +783,8 @@ class DataFactory(object): monitor_db = database.MonitorDatabase() if rating_key: - query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, media_type ' \ + query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \ + 'media_index, parent_media_index, media_type ' \ 'FROM session_history_metadata ' \ 'WHERE rating_key = ? ' \ 'OR parent_rating_key = ? ' \ @@ -794,34 +795,46 @@ class DataFactory(object): result = [] query = {} - title = None + 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'] + if str(item['rating_key']) == rating_key: - title = item['title'] + query_string = item['title'] media_type = item['media_type'] elif str(item['parent_rating_key']) == rating_key: if item['media_type'] == 'episode': - title = item['grandparent_title'] + query_string = item['grandparent_title'] media_type = 'season' elif item['media_type'] == 'track': - title = item['parent_title'] + query_string = item['parent_title'] media_type = 'album' elif str(item['grandparent_rating_key']) == rating_key: if item['media_type'] == 'episode': - title = item['grandparent_title'] + query_string = item['grandparent_title'] media_type = 'show' elif item['media_type'] == 'track': - title = item['grandparent_title'] + query_string = item['grandparent_title'] media_type = 'artist' - if title and media_type: - query = {'title': title.replace('"', ''), + 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, 'media_type': media_type, - 'rating_key': rating_key} + 'rating_key': rating_key + } else: return None diff --git a/plexpy/webserve.py b/plexpy/webserve.py index b951554a..252dd078 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -1340,13 +1340,18 @@ class WebInterface(object): logger.warn('Unable to retrieve data.') @cherrypy.expose - def get_search_results_children(self, query, media_type=None, **kwargs): + 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") From 1f2efedf7f5adf4777466225f814e4b0b5ed0a47 Mon Sep 17 00:00:00 2001 From: Jonathan Wong Date: Thu, 24 Sep 2015 23:41:48 -0700 Subject: [PATCH 07/18] Fix search URL encoding --- plexpy/pmsconnect.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py index 003e7aa1..12dc7a20 100644 --- a/plexpy/pmsconnect.py +++ b/plexpy/pmsconnect.py @@ -17,7 +17,7 @@ from plexpy import logger, helpers, users, http_handler from urlparse import urlparse import plexpy -import urllib +import urllib2 class PmsConnect(object): @@ -228,7 +228,7 @@ class PmsConnect(object): Output: array """ def get_search(self, query='', track='', output_format=''): - uri = '/search?query=' + urllib.quote_plus(query) + track + uri = '/search?query=' + urllib2.quote(query.encode('utf8')) + track request = self.request_handler.make_request(uri=uri, proto=self.protocol, request_type='GET', From e0873ff5ad261c066bf703eb99ab933a619d9c65 Mon Sep 17 00:00:00 2001 From: Jonathan Wong Date: Thu, 24 Sep 2015 23:44:02 -0700 Subject: [PATCH 08/18] Style fixes for search/info pages --- data/interfaces/default/css/plexpy.css | 3 + data/interfaces/default/info.html | 60 +++++++++++++++++-- .../default/info_search_results_list.html | 19 +++++- 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/data/interfaces/default/css/plexpy.css b/data/interfaces/default/css/plexpy.css index 60d76b35..2edde3f0 100644 --- a/data/interfaces/default/css/plexpy.css +++ b/data/interfaces/default/css/plexpy.css @@ -1372,6 +1372,9 @@ a:hover .item-children-poster { text-align: left; clear: both; } +.item-children-instance-text-wrapper h3.text-muted { + color: #777; +} .item-children-list-item-odd { border-top: 0px solid #343434; border-bottom: 0px solid #343434; diff --git a/data/interfaces/default/info.html b/data/interfaces/default/info.html index 60df76ae..d20ebe3d 100644 --- a/data/interfaces/default/info.html +++ b/data/interfaces/default/info.html @@ -269,7 +269,7 @@ DOCUMENTATION :: END
-
+
  Loading season list...
% elif data['type'] == 'season': @@ -280,7 +280,7 @@ DOCUMENTATION :: END
-
+
  Loading episode list...
% elif data['type'] == 'artist': @@ -291,7 +291,7 @@ DOCUMENTATION :: END
-
+
  Loading album list...
% elif data['type'] == 'album': @@ -302,7 +302,7 @@ DOCUMENTATION :: END
-
+
  Loading track list...
% endif @@ -370,7 +370,55 @@ DOCUMENTATION :: END
-
+
+
+
+ % if query: + % if query['media_type'] == 'movie': + Movies + + ${query['title']} + % elif query['media_type'] == 'show': + TV Shows + + ${query['grandparent_title']} + % elif query['media_type'] == 'season': + + + + + Season ${query['parent_media_index']} + % elif query['media_type'] == 'episode': + + + + + Season ${query['parent_media_index']} + + Episode ${query['media_index']} - ${query['title']} + % elif query['media_type'] == 'artist': + Music + + ${query['grandparent_title']} + % elif query['media_type'] == 'album': + + + ${query['grandparent_title']} + + ${query['parent_title']} + % elif query['media_type'] == 'track': + + + + + ${query['parent_title']} + + Track ${query['media_index']} - ${query['title']} + % endif + % endif +
+
+

@@ -392,7 +440,7 @@ DOCUMENTATION :: END

-
+
  Loading search results...