From 9a03d30afb0e33d7713b522b93156578dfce48d6 Mon Sep 17 00:00:00 2001 From: tyler breese Date: Mon, 16 Oct 2023 00:54:03 -0400 Subject: [PATCH] updates to sql fixes to multiple servers --- data/interfaces/default/home_stats.html | 1 - data/interfaces/default/index.html | 3 +- .../interfaces/default/js/tables/libraries.js | 27 ++++++++--- data/interfaces/default/libraries.html | 1 + data/interfaces/default/library_stats.html | 7 +-- data/interfaces/default/settings.html | 2 +- plexpy/__init__.py | 5 +- plexpy/activity_handler.py | 6 +-- plexpy/activity_processor.py | 13 ++++-- plexpy/datafactory.py | 46 +++++++++++++------ plexpy/libraries.py | 13 ++++-- plexpy/webserve.py | 7 +-- 12 files changed, 87 insertions(+), 44 deletions(-) diff --git a/data/interfaces/default/home_stats.html b/data/interfaces/default/home_stats.html index 08fb2a47..4098cf3b 100644 --- a/data/interfaces/default/home_stats.html +++ b/data/interfaces/default/home_stats.html @@ -70,7 +70,6 @@ DOCUMENTATION :: END <% stat_id = top_stat['stat_id'] row0 = top_stat['rows'][0] - row0['server_id']="test" %>
diff --git a/data/interfaces/default/index.html b/data/interfaces/default/index.html index 0f62f569..4ec4560b 100644 --- a/data/interfaces/default/index.html +++ b/data/interfaces/default/index.html @@ -738,6 +738,7 @@ var session_id = $(this).data('id'); var key = $(this).data('key'); var instance = $('#activity-instance-' + key); + var server_id = $(this).data('server_id'); $('#terminate-user').text(instance.find('.dashboard-activity-metadata-user').text()); $('#terminate-title').text(instance.find('.dashboard-activity-metadata-title').text()); @@ -755,7 +756,7 @@ session_key: key, session_id: session_id, message: message, - server_id: "test1" + server_id: server_id }, async: true, success: function (data) { diff --git a/data/interfaces/default/js/tables/libraries.js b/data/interfaces/default/js/tables/libraries.js index eb0f0f58..ddd027df 100644 --- a/data/interfaces/default/js/tables/libraries.js +++ b/data/interfaces/default/js/tables/libraries.js @@ -79,6 +79,19 @@ libraries_list_table_options = { }, { "targets": [3], + "data": "server_name", + "createdCell": function (td, cellData, rowData, row, col) { + if (cellData !== null && cellData !== '') { + $(td).html(cellData); + } + }, + "width": "10%", + "className": "no-wrap", + "orderable": false, + "searchable": false + }, + { + "targets": [4], "data": "section_type", "createdCell": function (td, cellData, rowData, row, col) { if (cellData !== null && cellData !== '') { @@ -89,7 +102,7 @@ libraries_list_table_options = { "className": "no-wrap" }, { - "targets": [4], + "targets": [5], "data": "count", "createdCell": function (td, cellData, rowData, row, col) { if (cellData !== null && cellData !== '') { @@ -101,7 +114,7 @@ libraries_list_table_options = { "className": "no-wrap" }, { - "targets": [5], + "targets": [6], "data": "parent_count", "createdCell": function (td, cellData, rowData, row, col) { if (cellData !== null && cellData !== '') { @@ -113,7 +126,7 @@ libraries_list_table_options = { "className": "no-wrap" }, { - "targets": [6], + "targets": [7], "data": "child_count", "createdCell": function (td, cellData, rowData, row, col) { if (cellData !== null && cellData !== '') { @@ -125,7 +138,7 @@ libraries_list_table_options = { "className": "no-wrap" }, { - "targets": [7], + "targets": [8], "data": "last_accessed", "createdCell": function (td, cellData, rowData, row, col) { if (cellData !== null && cellData !== '') { @@ -139,7 +152,7 @@ libraries_list_table_options = { "className": "no-wrap" }, { - "targets": [8], + "targets": [9], "data":"last_played", "createdCell": function (td, cellData, rowData, row, col) { if (cellData !== null && cellData !== '') { @@ -180,7 +193,7 @@ libraries_list_table_options = { "className": "datatable-wrap" }, { - "targets": [9], + "targets": [10], "data": "plays", "createdCell": function (td, cellData, rowData, row, col) { if (cellData !== null && cellData !== '') { @@ -192,7 +205,7 @@ libraries_list_table_options = { "className": "no-wrap" }, { - "targets": [10], + "targets": [11], "data": "duration", "createdCell": function (td, cellData, rowData, row, col) { if (cellData !== null && cellData !== '') { diff --git a/data/interfaces/default/libraries.html b/data/interfaces/default/libraries.html index 70468ff3..2c795232 100644 --- a/data/interfaces/default/libraries.html +++ b/data/interfaces/default/libraries.html @@ -33,6 +33,7 @@ Edit Library Name + Server Name Library Type Total Movies / TV Shows / Artists Total Seasons / Albums diff --git a/data/interfaces/default/library_stats.html b/data/interfaces/default/library_stats.html index 0690fd4e..92849bef 100644 --- a/data/interfaces/default/library_stats.html +++ b/data/interfaces/default/library_stats.html @@ -19,6 +19,7 @@ thumb Returns the thumb of the library. count Returns the number of top level items in the library. parent_count Returns the number of parent items in the library. child_count Returns the number of child items in the library. +server_id Returns the hardware_id of the server the library is in. DOCUMENTATION :: END @@ -40,9 +41,9 @@ DOCUMENTATION :: END %>
-
+
% if row0['thumb'].startswith('http'): - + % else: % endif @@ -59,7 +60,7 @@ DOCUMENTATION :: END data-art="${section.get('art')}" data-thumb="${section.get('thumb')}" data-library_art="${section.get('library_art')}">
${loop.index + 1}
diff --git a/data/interfaces/default/settings.html b/data/interfaces/default/settings.html index c5d8fe37..e351aa2a 100644 --- a/data/interfaces/default/settings.html +++ b/data/interfaces/default/settings.html @@ -2908,7 +2908,7 @@ $(document).ready(function() { '
  • ' + '
    ' + '' + '
  • ' ); diff --git a/plexpy/__init__.py b/plexpy/__init__.py index ac541a18..7d745678 100644 --- a/plexpy/__init__.py +++ b/plexpy/__init__.py @@ -662,8 +662,7 @@ def dbcheck(): "buffer_count INTEGER DEFAULT 0, buffer_last_triggered INTEGER, last_paused INTEGER, watched INTEGER DEFAULT 0, " "intro INTEGER DEFAULT 0, credits INTEGER DEFAULT 0, commercial INTEGER DEFAULT 0, marker INTEGER DEFAULT 0, " "initial_stream INTEGER DEFAULT 1, write_attempts INTEGER DEFAULT 0, raw_stream_info TEXT, " - "rating_key_websocket TEXT, " - "server_id TEXT)" + "rating_key_websocket TEXT, server_id TEXT)" ) # sessions_continued table :: This is a temp table that keeps track of continued streaming sessions @@ -733,7 +732,7 @@ def dbcheck(): "do_notify INTEGER DEFAULT 1, keep_history INTEGER DEFAULT 1, deleted_user INTEGER DEFAULT 0, " "allow_guest INTEGER DEFAULT 0, user_token TEXT, server_token TEXT, shared_libraries TEXT, " "filter_all TEXT, filter_movies TEXT, filter_tv TEXT, filter_music TEXT, filter_photos TEXT, " - "server_id TEXT )" + "server_id TEXT)" ) # library_sections table :: This table keeps record of the servers library sections diff --git a/plexpy/activity_handler.py b/plexpy/activity_handler.py index ffeb7298..532d3c50 100644 --- a/plexpy/activity_handler.py +++ b/plexpy/activity_handler.py @@ -701,9 +701,9 @@ def clear_recently_added_queue(rating_key, title): del_keys(rating_key) -def on_created(rating_key, **kwargs): - for pms_connect in server_manager.ServerManger().get_server_list(): - metadata = pms_connect.get_metadata_details(rating_key) +def on_created(rating_key, server_id, **kwargs): + pms_connect = server_manager.ServerManger().get_server(server_id=server_id) + metadata = pms_connect.get_metadata_details(rating_key) logger.debug("Tautulli TimelineHandler :: Library item '%s' (%s) added to Plex.", metadata['full_title'], str(rating_key)) diff --git a/plexpy/activity_processor.py b/plexpy/activity_processor.py index 7bbcfc51..a4f50485 100644 --- a/plexpy/activity_processor.py +++ b/plexpy/activity_processor.py @@ -152,11 +152,15 @@ class ActivityProcessor(object): 'channel_call_sign': session.get('channel_call_sign', ''), 'channel_identifier': session.get('channel_identifier', ''), 'channel_thumb': session.get('channel_thumb', ''), - 'stopped': helpers.timestamp() + 'stopped': helpers.timestamp(), + 'server_id': session.get('server_id') } - keys = {'session_key': session.get('session_key', ''), - 'rating_key': session.get('rating_key', '')} + keys = { + 'session_key': session.get('session_key', ''), + 'rating_key': session.get('rating_key', ''), + 'server_id': session.get('server_id') + } result = self.db.upsert('sessions', values, keys) @@ -412,7 +416,8 @@ class ActivityProcessor(object): 'synced_version_profile': session['synced_version_profile'], 'optimized_version': session['optimized_version'], 'optimized_version_profile': session['optimized_version_profile'], - 'optimized_version_title': session['optimized_version_title'] + 'optimized_version_title': session['optimized_version_title'], + 'server_id': "test3" } # logger.debug("Tautulli ActivityProcessor :: Writing sessionKey %s session_history_media_info transaction..." diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py index 2cfc80b6..82803631 100644 --- a/plexpy/datafactory.py +++ b/plexpy/datafactory.py @@ -1119,6 +1119,15 @@ class DataFactory(object): library_stats = [] + libraries = {} + + for library in library_cards: + parts = library.split('_') + if len(parts) > 1: + if (parts[0] not in libraries): + libraries[parts[0]] = [] + libraries[parts[0]].append(parts[1]) + try: query = "SELECT ls.id, ls.section_id, ls.section_name, ls.section_type, ls.thumb AS library_thumb, " \ "ls.custom_thumb_url AS custom_thumb, ls.art AS library_art, ls.custom_art_url AS custom_art, " \ @@ -1128,13 +1137,19 @@ class DataFactory(object): "sh.rating_key, shm.grandparent_rating_key, shm.thumb, shm.grandparent_thumb, " \ "sh.user, sh.user_id, sh.player, " \ "shm.art, sh.media_type, shm.content_rating, shm.labels, shm.live, shm.guid, " \ - "MAX(sh.started) AS last_watch " \ + "MAX(sh.started) AS last_watch, ls.server_id as server_id " \ "FROM library_sections AS ls " \ - "LEFT OUTER JOIN session_history AS sh ON ls.section_id = sh.section_id " \ - "LEFT OUTER JOIN session_history_metadata AS shm ON sh.id = shm.id " \ - "WHERE ls.section_id IN (%s) AND ls.deleted_section = 0 " \ - "GROUP BY ls.id " \ - "ORDER BY ls.section_type, ls.count DESC, ls.parent_count DESC, ls.child_count DESC " % ",".join(library_cards) + "LEFT OUTER JOIN session_history AS sh ON ls.section_id = sh.section_id AND ls.server_id = sh.server_id " \ + "LEFT OUTER JOIN session_history_metadata AS shm ON sh.id = shm.id AND sh.server_id = shm.server_id " \ + "WHERE " + query_parts = [] + for library in libraries: + query_parts.append("(ls.section_id IN (" + ",".join(libraries[library]) + ") AND ls.deleted_section = 0 AND ls.server_id = '" + library +"' )") + + query +=(" or ").join(query_parts) + + query += "GROUP BY ls.id " \ + "ORDER BY ls.section_type, ls.count DESC, ls.parent_count DESC, ls.child_count DESC " result = monitor_db.select(query) except Exception as e: logger.warn("Tautulli DataFactory :: Unable to execute database query for get_library_stats: %s." % e) @@ -1182,7 +1197,8 @@ class DataFactory(object): 'labels': item['labels'].split(';') if item['labels'] else (), 'live': item['live'], 'guid': item['guid'], - 'row_id': item['id'] + 'row_id': item['id'], + 'server_id': item['server_id'] } library_stats.append(library) @@ -1191,7 +1207,7 @@ class DataFactory(object): return library_stats - def get_watch_time_stats(self, rating_key=None, media_type=None, grouping=None, query_days=None): + def get_watch_time_stats(self, rating_key=None, media_type=None, grouping=None, query_days=None, server_id=None): if rating_key is None: return [] @@ -1233,11 +1249,12 @@ class DataFactory(object): "COUNT(DISTINCT %s) AS total_plays, section_id " \ "FROM session_history " \ "JOIN session_history_metadata ON session_history_metadata.id = session_history.id " \ - "WHERE stopped >= ? " \ + "WHERE session_history.server_id is '%s'" \ + "AND (stopped >= ? " \ "AND (session_history.grandparent_rating_key IN (%s) " \ "OR session_history.parent_rating_key IN (%s) " \ - "OR session_history.rating_key IN (%s))" % ( - group_by, rating_keys_arg, rating_keys_arg, rating_keys_arg + "OR session_history.rating_key IN (%s)))" % ( + group_by, server_id, rating_keys_arg, rating_keys_arg, rating_keys_arg ) result = monitor_db.select(query, args=[timestamp_query] + rating_keys * 3) @@ -1250,10 +1267,11 @@ class DataFactory(object): "COUNT(DISTINCT %s) AS total_plays, section_id " \ "FROM session_history " \ "JOIN session_history_metadata ON session_history_metadata.id = session_history.id " \ - "WHERE (session_history.grandparent_rating_key IN (%s) " \ + "WHERE session_history.server_id is '%s'" \ + "AND ((session_history.grandparent_rating_key IN (%s) " \ "OR session_history.parent_rating_key IN (%s) " \ - "OR session_history.rating_key IN (%s))" % ( - group_by, rating_keys_arg, rating_keys_arg, rating_keys_arg + "OR session_history.rating_key IN (%s)))" % ( + group_by, server_id, rating_keys_arg, rating_keys_arg, rating_keys_arg ) result = monitor_db.select(query, args=rating_keys * 3) diff --git a/plexpy/libraries.py b/plexpy/libraries.py index 682d4111..4172089f 100644 --- a/plexpy/libraries.py +++ b/plexpy/libraries.py @@ -413,6 +413,9 @@ class Libraries(object): else: library_art = item['library_art'] + pmsconnect = server_manager.ServerManger().get_server(server_id=item['server_id']) + serverinfo = pmsconnect.get_server_info() + row = {'row_id': item['row_id'], 'server_id': item['server_id'], 'section_id': item['section_id'], @@ -444,7 +447,8 @@ class Libraries(object): 'do_notify_created': item['do_notify_created'], 'keep_history': item['keep_history'], 'is_active': item['is_active'], - 'server_id': item['server_id'] + 'server_id': item['server_id'], + 'server_name': serverinfo['name'] } rows.append(row) @@ -1040,7 +1044,7 @@ class Libraries(object): "year, originally_available_at, added_at, live, started, user, content_rating, labels, section_id " \ "FROM session_history_metadata " \ "JOIN session_history ON session_history_metadata.id = session_history.id " \ - "WHERE section_id = ? and server_id = '" + server_id + "' " \ + "WHERE section_id = ? and session_history.server_id = '" + server_id + "' " \ "GROUP BY session_history.rating_key " \ "ORDER BY MAX(started) DESC LIMIT ?" result = monitor_db.select(query, args=[section_id, limit]) @@ -1089,7 +1093,7 @@ class Libraries(object): monitor_db = database.MonitorDatabase() try: - query = "SELECT section_id, section_name, section_type, agent " \ + query = "SELECT section_id, section_name, section_type, agent, server_id " \ "FROM library_sections WHERE deleted_section = 0" result = monitor_db.select(query=query) except Exception as e: @@ -1101,7 +1105,8 @@ class Libraries(object): library = {'section_id': item['section_id'], 'section_name': item['section_name'], 'section_type': item['section_type'], - 'agent': item['agent'] + 'agent': item['agent'], + 'server_id': item['server_id'] } libraries.append(library) diff --git a/plexpy/webserve.py b/plexpy/webserve.py index 182b9da3..82afcec5 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -143,7 +143,7 @@ def serve_template(template_name, **kwargs): try: template = TEMPLATE_LOOKUP.get_template(template_name) return template.render(http_root=http_root, server_name=server_name, cache_param=cache_param, - _session=_session, server_id="test2", **kwargs) + _session=_session, server_id=NotImplemented, **kwargs) except Exception as e: logger.exception("WebUI :: Mako template render error: %s" % e) return mako.exceptions.html_error_template().render() @@ -575,6 +575,7 @@ class WebInterface(object): # TODO: Find some one way to automatically get the columns dt_columns = [("library_thumb", False, False), ("section_name", True, True), + ("server_name", True, True), ("section_type", True, True), ("count", True, True), ("parent_count", True, True), @@ -4484,10 +4485,10 @@ class WebInterface(object): @cherrypy.expose @requireAuth() - def item_watch_time_stats(self, rating_key=None, media_type=None, **kwargs): + def item_watch_time_stats(self, rating_key=None, media_type=None, server_id=None, **kwargs): if rating_key: item_data = datafactory.DataFactory() - result = item_data.get_watch_time_stats(rating_key=rating_key, media_type=media_type) + result = item_data.get_watch_time_stats(rating_key=rating_key, media_type=media_type, server_id=server_id) else: result = None