updates to sql

fixes to multiple servers
This commit is contained in:
tyler breese 2023-10-16 00:54:03 -04:00
commit 9a03d30afb
12 changed files with 87 additions and 44 deletions

View file

@ -70,7 +70,6 @@ DOCUMENTATION :: END
<% <%
stat_id = top_stat['stat_id'] stat_id = top_stat['stat_id']
row0 = top_stat['rows'][0] row0 = top_stat['rows'][0]
row0['server_id']="test"
%> %>
<div class="dashboard-stats-instance" id="stats-instance-${stat_id}" data-stat_id="${stat_id}"> <div class="dashboard-stats-instance" id="stats-instance-${stat_id}" data-stat_id="${stat_id}">
<div class="dashboard-stats-container"> <div class="dashboard-stats-container">

View file

@ -738,6 +738,7 @@
var session_id = $(this).data('id'); var session_id = $(this).data('id');
var key = $(this).data('key'); var key = $(this).data('key');
var instance = $('#activity-instance-' + key); var instance = $('#activity-instance-' + key);
var server_id = $(this).data('server_id');
$('#terminate-user').text(instance.find('.dashboard-activity-metadata-user').text()); $('#terminate-user').text(instance.find('.dashboard-activity-metadata-user').text());
$('#terminate-title').text(instance.find('.dashboard-activity-metadata-title').text()); $('#terminate-title').text(instance.find('.dashboard-activity-metadata-title').text());
@ -755,7 +756,7 @@
session_key: key, session_key: key,
session_id: session_id, session_id: session_id,
message: message, message: message,
server_id: "test1" server_id: server_id
}, },
async: true, async: true,
success: function (data) { success: function (data) {

View file

@ -79,6 +79,19 @@ libraries_list_table_options = {
}, },
{ {
"targets": [3], "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", "data": "section_type",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== null && cellData !== '') { if (cellData !== null && cellData !== '') {
@ -89,7 +102,7 @@ libraries_list_table_options = {
"className": "no-wrap" "className": "no-wrap"
}, },
{ {
"targets": [4], "targets": [5],
"data": "count", "data": "count",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== null && cellData !== '') { if (cellData !== null && cellData !== '') {
@ -101,7 +114,7 @@ libraries_list_table_options = {
"className": "no-wrap" "className": "no-wrap"
}, },
{ {
"targets": [5], "targets": [6],
"data": "parent_count", "data": "parent_count",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== null && cellData !== '') { if (cellData !== null && cellData !== '') {
@ -113,7 +126,7 @@ libraries_list_table_options = {
"className": "no-wrap" "className": "no-wrap"
}, },
{ {
"targets": [6], "targets": [7],
"data": "child_count", "data": "child_count",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== null && cellData !== '') { if (cellData !== null && cellData !== '') {
@ -125,7 +138,7 @@ libraries_list_table_options = {
"className": "no-wrap" "className": "no-wrap"
}, },
{ {
"targets": [7], "targets": [8],
"data": "last_accessed", "data": "last_accessed",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== null && cellData !== '') { if (cellData !== null && cellData !== '') {
@ -139,7 +152,7 @@ libraries_list_table_options = {
"className": "no-wrap" "className": "no-wrap"
}, },
{ {
"targets": [8], "targets": [9],
"data":"last_played", "data":"last_played",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== null && cellData !== '') { if (cellData !== null && cellData !== '') {
@ -180,7 +193,7 @@ libraries_list_table_options = {
"className": "datatable-wrap" "className": "datatable-wrap"
}, },
{ {
"targets": [9], "targets": [10],
"data": "plays", "data": "plays",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== null && cellData !== '') { if (cellData !== null && cellData !== '') {
@ -192,7 +205,7 @@ libraries_list_table_options = {
"className": "no-wrap" "className": "no-wrap"
}, },
{ {
"targets": [10], "targets": [11],
"data": "duration", "data": "duration",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== null && cellData !== '') { if (cellData !== null && cellData !== '') {

View file

@ -33,6 +33,7 @@
<th align="left" id="edit_row">Edit</th> <th align="left" id="edit_row">Edit</th>
<th align="right" id="library_thumb"></th> <th align="right" id="library_thumb"></th>
<th align="left" id="section_name">Library Name</th> <th align="left" id="section_name">Library Name</th>
<th align="left" id="server_name">Server Name</th>
<th align="left" id="section_type">Library Type</th> <th align="left" id="section_type">Library Type</th>
<th align="left" id="count">Total Movies / TV Shows / Artists</th> <th align="left" id="count">Total Movies / TV Shows / Artists</th>
<th align="left" id="parent_count">Total Seasons / Albums</th> <th align="left" id="parent_count">Total Seasons / Albums</th>

View file

@ -19,6 +19,7 @@ thumb Returns the thumb of the library.
count Returns the number of top level items in the library. count Returns the number of top level items in the library.
parent_count Returns the number of parent 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. 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 DOCUMENTATION :: END
</%doc> </%doc>
@ -40,9 +41,9 @@ DOCUMENTATION :: END
%> %>
<div class="dashboard-stats-instance" id="library-stats-instance-${section_type}" data-section_type="${section_type}"> <div class="dashboard-stats-instance" id="library-stats-instance-${section_type}" data-section_type="${section_type}">
<div class="dashboard-stats-container"> <div class="dashboard-stats-container">
<div id="library-stats-background-${section_type}" class="dashboard-stats-background" style="background-image: url(${page('pms_image_proxy', row0['art'] or row0['library_art'], None, 500, 280, 40, '282828', 3, fallback=row0['library_art'])});" data-library_art="${row0['library_art']}"> <div id="library-stats-background-${section_type}" class="dashboard-stats-background" style="background-image: url(${page('pms_image_proxy', row0['art'] or row0['library_art'], None, 500, 280, 40, '282828', 3, fallback=row0['library_art'], server_id=row0['server_id'])});" data-library_art="${row0['library_art']}">
% if row0['thumb'].startswith('http'): % if row0['thumb'].startswith('http'):
<div id="library-stats-thumb-${section_type}" class="dashboard-stats-flat hidden-xs" style="background-image: url(${page('pms_image_proxy', row0['thumb'], None, 80, 80)});"></div> <div id="library-stats-thumb-${section_type}" class="dashboard-stats-flat hidden-xs" style="background-image: url(${page('pms_image_proxy', row0['thumb'], None, 80, 80, server_id=row0['server_id'])});"></div>
% else: % else:
<div id="library-stats-thumb-${section_type}" class="dashboard-stats-flat svg-icon library-${section_type} hidden-xs"></div> <div id="library-stats-thumb-${section_type}" class="dashboard-stats-flat svg-icon library-${section_type} hidden-xs"></div>
% endif % endif
@ -59,7 +60,7 @@ DOCUMENTATION :: END
data-art="${section.get('art')}" data-thumb="${section.get('thumb')}" data-library_art="${section.get('library_art')}"> data-art="${section.get('art')}" data-thumb="${section.get('thumb')}" data-library_art="${section.get('library_art')}">
<div class="sub-list">${loop.index + 1}</div> <div class="sub-list">${loop.index + 1}</div>
<div class="sub-value"> <div class="sub-value">
<a href="${page('library', section['section_id'])}" title="${section['section_name']}"> <a href="${page('library', section['section_id'], server_id=section['server_id'])}" title="${section['section_name']}">
${section['section_name']} ${section['section_name']}
</a> </a>
</div> </div>

View file

@ -2908,7 +2908,7 @@ $(document).ready(function() {
'<li class="card card-sortable">' + '<li class="card card-sortable">' +
'<div class="card-handle"><i class="fa fa-bars"></i></div>' + '<div class="card-handle"><i class="fa fa-bars"></i></div>' +
'<label>' + '<label>' +
'<input type="checkbox" id="hlcard-' + key + '" name="hlcard-' + key + '" value="' + key + '"> ' + title + '<input type="checkbox" id="hlcard-' + libraries_list[i].server_id + '_' + key + '" name="hlcard-' + libraries_list[i].server_id + '_' + key + '" value="' + libraries_list[i].server_id + '_' + key + '"> ' + title +
'</label>' + '</label>' +
'</li>' '</li>'
); );

View file

@ -662,8 +662,7 @@ def dbcheck():
"buffer_count INTEGER DEFAULT 0, buffer_last_triggered INTEGER, last_paused INTEGER, watched INTEGER DEFAULT 0, " "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, " "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, " "initial_stream INTEGER DEFAULT 1, write_attempts INTEGER DEFAULT 0, raw_stream_info TEXT, "
"rating_key_websocket TEXT, " "rating_key_websocket TEXT, server_id TEXT)"
"server_id TEXT)"
) )
# sessions_continued table :: This is a temp table that keeps track of continued streaming sessions # 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, " "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, " "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, " "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 # library_sections table :: This table keeps record of the servers library sections

View file

@ -701,9 +701,9 @@ def clear_recently_added_queue(rating_key, title):
del_keys(rating_key) del_keys(rating_key)
def on_created(rating_key, **kwargs): def on_created(rating_key, server_id, **kwargs):
for pms_connect in server_manager.ServerManger().get_server_list(): pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
metadata = pms_connect.get_metadata_details(rating_key) metadata = pms_connect.get_metadata_details(rating_key)
logger.debug("Tautulli TimelineHandler :: Library item '%s' (%s) added to Plex.", logger.debug("Tautulli TimelineHandler :: Library item '%s' (%s) added to Plex.",
metadata['full_title'], str(rating_key)) metadata['full_title'], str(rating_key))

View file

@ -152,11 +152,15 @@ class ActivityProcessor(object):
'channel_call_sign': session.get('channel_call_sign', ''), 'channel_call_sign': session.get('channel_call_sign', ''),
'channel_identifier': session.get('channel_identifier', ''), 'channel_identifier': session.get('channel_identifier', ''),
'channel_thumb': session.get('channel_thumb', ''), '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', ''), keys = {
'rating_key': session.get('rating_key', '')} '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) result = self.db.upsert('sessions', values, keys)
@ -412,7 +416,8 @@ class ActivityProcessor(object):
'synced_version_profile': session['synced_version_profile'], 'synced_version_profile': session['synced_version_profile'],
'optimized_version': session['optimized_version'], 'optimized_version': session['optimized_version'],
'optimized_version_profile': session['optimized_version_profile'], '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..." # logger.debug("Tautulli ActivityProcessor :: Writing sessionKey %s session_history_media_info transaction..."

View file

@ -1119,6 +1119,15 @@ class DataFactory(object):
library_stats = [] 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: try:
query = "SELECT ls.id, ls.section_id, ls.section_name, ls.section_type, ls.thumb AS library_thumb, " \ 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, " \ "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.rating_key, shm.grandparent_rating_key, shm.thumb, shm.grandparent_thumb, " \
"sh.user, sh.user_id, sh.player, " \ "sh.user, sh.user_id, sh.player, " \
"shm.art, sh.media_type, shm.content_rating, shm.labels, shm.live, shm.guid, " \ "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 " \ "FROM library_sections AS ls " \
"LEFT OUTER JOIN session_history AS sh ON ls.section_id = sh.section_id " \ "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 " \ "LEFT OUTER JOIN session_history_metadata AS shm ON sh.id = shm.id AND sh.server_id = shm.server_id " \
"WHERE ls.section_id IN (%s) AND ls.deleted_section = 0 " \ "WHERE "
"GROUP BY ls.id " \ query_parts = []
"ORDER BY ls.section_type, ls.count DESC, ls.parent_count DESC, ls.child_count DESC " % ",".join(library_cards) 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) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn("Tautulli DataFactory :: Unable to execute database query for get_library_stats: %s." % 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 (), 'labels': item['labels'].split(';') if item['labels'] else (),
'live': item['live'], 'live': item['live'],
'guid': item['guid'], 'guid': item['guid'],
'row_id': item['id'] 'row_id': item['id'],
'server_id': item['server_id']
} }
library_stats.append(library) library_stats.append(library)
@ -1191,7 +1207,7 @@ class DataFactory(object):
return library_stats 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: if rating_key is None:
return [] return []
@ -1233,11 +1249,12 @@ class DataFactory(object):
"COUNT(DISTINCT %s) AS total_plays, section_id " \ "COUNT(DISTINCT %s) AS total_plays, section_id " \
"FROM session_history " \ "FROM session_history " \
"JOIN session_history_metadata ON session_history_metadata.id = session_history.id " \ "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) " \ "AND (session_history.grandparent_rating_key IN (%s) " \
"OR session_history.parent_rating_key IN (%s) " \ "OR session_history.parent_rating_key IN (%s) " \
"OR session_history.rating_key IN (%s))" % ( "OR session_history.rating_key IN (%s)))" % (
group_by, rating_keys_arg, rating_keys_arg, rating_keys_arg group_by, server_id, rating_keys_arg, rating_keys_arg, rating_keys_arg
) )
result = monitor_db.select(query, args=[timestamp_query] + rating_keys * 3) 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 " \ "COUNT(DISTINCT %s) AS total_plays, section_id " \
"FROM session_history " \ "FROM session_history " \
"JOIN session_history_metadata ON session_history_metadata.id = session_history.id " \ "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.parent_rating_key IN (%s) " \
"OR session_history.rating_key IN (%s))" % ( "OR session_history.rating_key IN (%s)))" % (
group_by, rating_keys_arg, rating_keys_arg, rating_keys_arg group_by, server_id, rating_keys_arg, rating_keys_arg, rating_keys_arg
) )
result = monitor_db.select(query, args=rating_keys * 3) result = monitor_db.select(query, args=rating_keys * 3)

View file

@ -413,6 +413,9 @@ class Libraries(object):
else: else:
library_art = item['library_art'] 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'], row = {'row_id': item['row_id'],
'server_id': item['server_id'], 'server_id': item['server_id'],
'section_id': item['section_id'], 'section_id': item['section_id'],
@ -444,7 +447,8 @@ class Libraries(object):
'do_notify_created': item['do_notify_created'], 'do_notify_created': item['do_notify_created'],
'keep_history': item['keep_history'], 'keep_history': item['keep_history'],
'is_active': item['is_active'], 'is_active': item['is_active'],
'server_id': item['server_id'] 'server_id': item['server_id'],
'server_name': serverinfo['name']
} }
rows.append(row) rows.append(row)
@ -1040,7 +1044,7 @@ class Libraries(object):
"year, originally_available_at, added_at, live, started, user, content_rating, labels, section_id " \ "year, originally_available_at, added_at, live, started, user, content_rating, labels, section_id " \
"FROM session_history_metadata " \ "FROM session_history_metadata " \
"JOIN session_history ON session_history_metadata.id = session_history.id " \ "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 " \ "GROUP BY session_history.rating_key " \
"ORDER BY MAX(started) DESC LIMIT ?" "ORDER BY MAX(started) DESC LIMIT ?"
result = monitor_db.select(query, args=[section_id, limit]) result = monitor_db.select(query, args=[section_id, limit])
@ -1089,7 +1093,7 @@ class Libraries(object):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
try: 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" "FROM library_sections WHERE deleted_section = 0"
result = monitor_db.select(query=query) result = monitor_db.select(query=query)
except Exception as e: except Exception as e:
@ -1101,7 +1105,8 @@ class Libraries(object):
library = {'section_id': item['section_id'], library = {'section_id': item['section_id'],
'section_name': item['section_name'], 'section_name': item['section_name'],
'section_type': item['section_type'], 'section_type': item['section_type'],
'agent': item['agent'] 'agent': item['agent'],
'server_id': item['server_id']
} }
libraries.append(library) libraries.append(library)

View file

@ -143,7 +143,7 @@ def serve_template(template_name, **kwargs):
try: try:
template = TEMPLATE_LOOKUP.get_template(template_name) template = TEMPLATE_LOOKUP.get_template(template_name)
return template.render(http_root=http_root, server_name=server_name, cache_param=cache_param, 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: except Exception as e:
logger.exception("WebUI :: Mako template render error: %s" % e) logger.exception("WebUI :: Mako template render error: %s" % e)
return mako.exceptions.html_error_template().render() return mako.exceptions.html_error_template().render()
@ -575,6 +575,7 @@ class WebInterface(object):
# TODO: Find some one way to automatically get the columns # TODO: Find some one way to automatically get the columns
dt_columns = [("library_thumb", False, False), dt_columns = [("library_thumb", False, False),
("section_name", True, True), ("section_name", True, True),
("server_name", True, True),
("section_type", True, True), ("section_type", True, True),
("count", True, True), ("count", True, True),
("parent_count", True, True), ("parent_count", True, True),
@ -4484,10 +4485,10 @@ class WebInterface(object):
@cherrypy.expose @cherrypy.expose
@requireAuth() @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: if rating_key:
item_data = datafactory.DataFactory() 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: else:
result = None result = None