watch time & user stats for collections (#1982)

* user_stats for collection

* watch_time_stats for collection

* check for media_type to be compatible with API

* update API and datafactory optimizations

* beautify webserve class

* fix sql query build

* filter on suitable collections

* stats for collections of sub media type

* optimize array creation
This commit is contained in:
herby2212 2023-02-27 02:32:50 +01:00 committed by GitHub
parent 993909fa08
commit ae3d75bbe3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 29 deletions

View file

@ -12,6 +12,7 @@ data :: Usable parameters (if not applicable for media type, blank value will be
== 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'.
sub_media_type Returns the subtype of media. Either 'movie', 'show', 'season', 'episode', 'artist', 'album', or 'track'.
art Returns the location of the item's artwork
title Returns the name of the movie, show, episode, artist, album, or track.
edition_title Returns the edition title of a movie.
@ -553,7 +554,7 @@ DOCUMENTATION :: END
</div>
</div>
% endif
% if data['media_type'] in ('movie', 'show', 'season', 'episode', 'artist', 'album', 'track'):
% if data['media_type'] in ('movie', 'show', 'season', 'episode', 'artist', 'album', 'track', 'collection'):
<div class="col-md-12">
<div class="table-card-header">
<div class="header-bar">
@ -936,13 +937,16 @@ DOCUMENTATION :: END
});
</script>
% endif
% if data['media_type'] in ('movie', 'show', 'season', 'episode', 'artist', 'album', 'track'):
% if data['media_type'] in ('movie', 'show', 'season', 'episode', 'artist', 'album', 'track', 'collection'):
<script>
// Populate watch time stats
$.ajax({
url: 'item_watch_time_stats',
async: true,
data: { rating_key: "${data['rating_key']}" },
data: {
rating_key: "${data['rating_key']}",
media_type: "${data['media_type']}"
},
complete: function(xhr, status) {
$("#watch-time-stats").html(xhr.responseText);
}
@ -951,7 +955,10 @@ DOCUMENTATION :: END
$.ajax({
url: 'item_user_stats',
async: true,
data: { rating_key: "${data['rating_key']}" },
data: {
rating_key: "${data['rating_key']}",
media_type: "${data['media_type']}"
},
complete: function(xhr, status) {
$("#user-stats").html(xhr.responseText);
}

View file

@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
# This file is part of Tautulli.
#
@ -1188,7 +1188,7 @@ class DataFactory(object):
return library_stats
def get_watch_time_stats(self, rating_key=None, grouping=None, query_days=None):
def get_watch_time_stats(self, rating_key=None, media_type=None, grouping=None, query_days=None):
if rating_key is None:
return []
@ -1210,6 +1210,15 @@ class DataFactory(object):
group_by = 'session_history.reference_id' if grouping else 'session_history.id'
if media_type == 'collection':
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_item_children(rating_key=rating_key, media_type=media_type)
rating_keys = [child['rating_key'] for child in result['children_list']]
else:
rating_keys = [rating_key]
rating_keys_arg = ','.join(['?'] * len(rating_keys))
for days in query_days:
timestamp_query = timestamp - days * 24 * 60 * 60
@ -1221,11 +1230,14 @@ 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 >= %s ' \
'AND (session_history.grandparent_rating_key = ? ' \
'OR session_history.parent_rating_key = ? ' \
'OR session_history.rating_key = ?)' % (group_by, timestamp_query)
result = monitor_db.select(query, args=[rating_key, rating_key, rating_key])
'WHERE 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
)
result = monitor_db.select(query, args=[timestamp_query] + rating_keys * 3)
else:
result = []
else:
@ -1235,10 +1247,13 @@ 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 = ? ' \
'OR session_history.parent_rating_key = ? ' \
'OR session_history.rating_key = ?)' % group_by
result = monitor_db.select(query, args=[rating_key, rating_key, rating_key])
'WHERE (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
)
result = monitor_db.select(query, args=rating_keys * 3)
else:
result = []
except Exception as e:
@ -1267,7 +1282,7 @@ class DataFactory(object):
return item_watch_time_stats
def get_user_stats(self, rating_key=None, grouping=None):
def get_user_stats(self, rating_key=None, media_type=None, grouping=None):
if grouping is None:
grouping = plexpy.CONFIG.GROUP_HISTORY_TABLES
@ -1279,6 +1294,15 @@ class DataFactory(object):
group_by = 'session_history.reference_id' if grouping else 'session_history.id'
if media_type == 'collection':
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_item_children(rating_key=rating_key, media_type=media_type)
rating_keys = [child['rating_key'] for child in result['children_list']]
else:
rating_keys = [rating_key]
rating_keys_arg = ','.join(['?'] * len(rating_keys))
try:
if str(rating_key).isdigit():
query = 'SELECT (CASE WHEN users.friendly_name IS NULL OR TRIM(users.friendly_name) = "" ' \
@ -1290,12 +1314,15 @@ class DataFactory(object):
'FROM session_history ' \
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
'JOIN users ON users.user_id = session_history.user_id ' \
'WHERE (session_history.grandparent_rating_key = ? ' \
'OR session_history.parent_rating_key = ? ' \
'OR session_history.rating_key = ?) ' \
'WHERE (session_history.grandparent_rating_key IN (%s) ' \
'OR session_history.parent_rating_key IN (%s) ' \
'OR session_history.rating_key IN (%s)) ' \
'GROUP BY users.user_id ' \
'ORDER BY total_plays DESC, total_time DESC' % group_by
result = monitor_db.select(query, args=[rating_key, rating_key, rating_key])
'ORDER BY total_plays DESC, total_time DESC' % (
group_by, rating_keys_arg, rating_keys_arg, rating_keys_arg
)
result = monitor_db.select(query, args=rating_keys * 3)
else:
result = []
except Exception as e:

View file

@ -4431,10 +4431,10 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def item_watch_time_stats(self, rating_key=None, **kwargs):
def item_watch_time_stats(self, rating_key=None, media_type=None, **kwargs):
if rating_key:
item_data = datafactory.DataFactory()
result = item_data.get_watch_time_stats(rating_key=rating_key)
result = item_data.get_watch_time_stats(rating_key=rating_key, media_type=media_type)
else:
result = None
@ -4446,10 +4446,10 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def item_user_stats(self, rating_key=None, **kwargs):
def item_user_stats(self, rating_key=None, media_type=None, **kwargs):
if rating_key:
item_data = datafactory.DataFactory()
result = item_data.get_user_stats(rating_key=rating_key)
result = item_data.get_user_stats(rating_key=rating_key, media_type=media_type)
else:
result = None
@ -4463,7 +4463,7 @@ class WebInterface(object):
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))
@addtoapi()
def get_item_watch_time_stats(self, rating_key=None, grouping=None, query_days=None, **kwargs):
def get_item_watch_time_stats(self, rating_key=None, media_type=None, grouping=None, query_days=None, **kwargs):
""" Get the watch time stats for the media item.
```
@ -4471,6 +4471,7 @@ class WebInterface(object):
rating_key (str): Rating key of the item
Optional parameters:
media_type (str): Media type of the item (only required for a collection)
grouping (int): 0 or 1
query_days (str): Comma separated days, e.g. "1,7,30,0"
@ -4504,7 +4505,9 @@ class WebInterface(object):
if rating_key:
item_data = datafactory.DataFactory()
result = item_data.get_watch_time_stats(rating_key=rating_key, grouping=grouping,
result = item_data.get_watch_time_stats(rating_key=rating_key,
media_type=media_type,
grouping=grouping,
query_days=query_days)
if result:
return result
@ -4518,7 +4521,7 @@ class WebInterface(object):
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))
@addtoapi()
def get_item_user_stats(self, rating_key=None, grouping=None, **kwargs):
def get_item_user_stats(self, rating_key=None, media_type=None, grouping=None, **kwargs):
""" Get the user stats for the media item.
```
@ -4526,6 +4529,7 @@ class WebInterface(object):
rating_key (str): Rating key of the item
Optional parameters:
media_type (str): Media type of the item (only required for a collection)
grouping (int): 0 or 1
Returns:
@ -4554,7 +4558,9 @@ class WebInterface(object):
if rating_key:
item_data = datafactory.DataFactory()
result = item_data.get_user_stats(rating_key=rating_key, grouping=grouping)
result = item_data.get_user_stats(rating_key=rating_key,
media_type=media_type,
grouping=grouping)
if result:
return result
else: