mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-08 06:00:51 -07:00
Add recently watched to user screen
This commit is contained in:
parent
fe6d5f17f0
commit
ba18c5b96e
6 changed files with 112 additions and 3 deletions
|
@ -218,3 +218,19 @@ function isPrivateIP(ip_address) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function humanTime(seconds) {
|
||||||
|
if (seconds >= 86400) {
|
||||||
|
text = '<h1> / </h1><h3>' + Math.floor(moment.duration(seconds, 'seconds').asDays()) +
|
||||||
|
'</h3><p> days </p><h3>' + Math.floor(moment.duration((seconds % 86400), 'seconds').asHours()) +
|
||||||
|
'</h3><p> hrs</p><h3>' + Math.floor(moment.duration(((seconds % 86400) % 3600), 'seconds').asMinutes()) + '</h3><p> mins</p>';
|
||||||
|
return text;
|
||||||
|
} else if (seconds >= 3600) {
|
||||||
|
text = '<h1> / </h1><h3>' + Math.floor(moment.duration((seconds % 86400), 'seconds').asHours()) +
|
||||||
|
'</h3><p>hrs</p><h3>' + Math.floor(moment.duration(((seconds % 86400) % 3600), 'seconds').asMinutes()) + '</h3><p> mins</p>';
|
||||||
|
return text;
|
||||||
|
} else if (seconds >= 60) {
|
||||||
|
text = '<h1> / </h1><h3>' + Math.floor(moment.duration(((seconds % 86400) % 3600), 'seconds').asMinutes()) + '</h3><p> mins</p>';
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
|
@ -190,6 +190,15 @@
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: 'get_user_watch_time_stats',
|
||||||
|
async: true,
|
||||||
|
data: { user: '${user}' },
|
||||||
|
complete: function(xhr, status) {
|
||||||
|
$("#user-time-stats").html(xhr.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'get_user_recently_watched',
|
url: 'get_user_recently_watched',
|
||||||
async: true,
|
async: true,
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
% if item['type'] == 'episode':
|
% if item['type'] == 'episode':
|
||||||
<h3>Season ${item['parentIndex']}, Episode ${item['index']}</h3>
|
<h3>Season ${item['parentIndex']}, Episode ${item['index']}</h3>
|
||||||
% elif item['type'] == 'movie':
|
% elif item['type'] == 'movie':
|
||||||
<h3>${item['title']} (${item['title']})</h3>
|
<h3>${item['title']} (${item['year']})</h3>
|
||||||
% endif
|
% endif
|
||||||
<div class="muted" id="time-${item['time']}">${item['time']}</div>
|
<div class="muted" id="time-${item['time']}">${item['time']}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
24
data/interfaces/default/user_watch_time_stats.html
Normal file
24
data/interfaces/default/user_watch_time_stats.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
% if watch_stats != None:
|
||||||
|
<ul>
|
||||||
|
% for a in watch_stats:
|
||||||
|
<div class='user-overview-stats-instance'>
|
||||||
|
<li>
|
||||||
|
<div class='user-overview-stats-instance-text'>
|
||||||
|
% if a['query_days'] == 0:
|
||||||
|
<h4>All Time</h4>
|
||||||
|
% elif a['query_days'] == 1:
|
||||||
|
<h4>Last 24 hours</h4>
|
||||||
|
% else:
|
||||||
|
<h4>Last ${a['query_days']} day(s)</h4>
|
||||||
|
% endif
|
||||||
|
<h3>${a['total_plays']}</h3><p>plays</p>
|
||||||
|
<span id="total-time-${a['query_days']}"></span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
$('#total-time-${a['query_days']}').html(humanTime(${a['total_time']}));
|
||||||
|
</script>
|
||||||
|
% endfor
|
||||||
|
</ul>
|
||||||
|
% endif
|
|
@ -414,9 +414,45 @@ class PlexWatch(object):
|
||||||
'thumb': thumb,
|
'thumb': thumb,
|
||||||
'index': self.get_xml_attr(a, 'index'),
|
'index': self.get_xml_attr(a, 'index'),
|
||||||
'parentIndex': self.get_xml_attr(a, 'parentIndex'),
|
'parentIndex': self.get_xml_attr(a, 'parentIndex'),
|
||||||
|
'year': self.get_xml_attr(a, 'year'),
|
||||||
'time': row[0],
|
'time': row[0],
|
||||||
'user': row[1]
|
'user': row[1]
|
||||||
}
|
}
|
||||||
recently_watched.append(recent_output)
|
recently_watched.append(recent_output)
|
||||||
|
|
||||||
return recently_watched
|
return recently_watched
|
||||||
|
|
||||||
|
def get_user_watch_time_stats(self, user=None):
|
||||||
|
myDB = db.DBConnection()
|
||||||
|
|
||||||
|
time_queries = [1, 7, 30, 0]
|
||||||
|
user_watch_time_stats = []
|
||||||
|
|
||||||
|
for days in time_queries:
|
||||||
|
if days > 0:
|
||||||
|
where = 'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||||
|
'AND user = "%s"' % (days, user)
|
||||||
|
else:
|
||||||
|
where = 'WHERE user = "%s"' % user
|
||||||
|
|
||||||
|
query = 'SELECT (SUM(stopped - time) - SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
||||||
|
'COUNT(id) AS total_plays ' \
|
||||||
|
'FROM %s %s' % (self.get_user_table_name(), where)
|
||||||
|
result = myDB.select(query)
|
||||||
|
|
||||||
|
for item in result:
|
||||||
|
if item[0]:
|
||||||
|
total_time = item[0]
|
||||||
|
total_plays = item[1]
|
||||||
|
else:
|
||||||
|
total_time = 0
|
||||||
|
total_plays = 0
|
||||||
|
|
||||||
|
row = {'query_days': days,
|
||||||
|
'total_time': total_time,
|
||||||
|
'total_plays': total_plays
|
||||||
|
}
|
||||||
|
|
||||||
|
user_watch_time_stats.append(row)
|
||||||
|
|
||||||
|
return user_watch_time_stats
|
|
@ -543,7 +543,19 @@ class WebInterface(object):
|
||||||
if result:
|
if result:
|
||||||
return serve_template(templatename="user_recently_watched.html", recently_watched=result, title="Recently Watched")
|
return serve_template(templatename="user_recently_watched.html", recently_watched=result, title="Recently Watched")
|
||||||
else:
|
else:
|
||||||
return serve_template(templatename="user_recently_watched.html", metadata='', title="Recently Watched")
|
return serve_template(templatename="user_recently_watched.html", recently_watched='', title="Recently Watched")
|
||||||
|
logger.warn('Unable to retrieve data.')
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
def get_user_watch_time_stats(self, user=None, **kwargs):
|
||||||
|
|
||||||
|
plex_watch = plexwatch.PlexWatch()
|
||||||
|
result = plex_watch.get_user_watch_time_stats(user)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
return serve_template(templatename="user_watch_time_stats.html", watch_stats=result, title="Watch Stats")
|
||||||
|
else:
|
||||||
|
return serve_template(templatename="user_watch_time_stats.html", watch_stats='', title="Watch Stats")
|
||||||
logger.warn('Unable to retrieve data.')
|
logger.warn('Unable to retrieve data.')
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
@ -618,3 +630,15 @@ class WebInterface(object):
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
else:
|
else:
|
||||||
logger.warn('Unable to retrieve data.')
|
logger.warn('Unable to retrieve data.')
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
def get_time_stats(self, user=None, **kwargs):
|
||||||
|
|
||||||
|
plex_watch = plexwatch.PlexWatch()
|
||||||
|
result = plex_watch.get_user_watch_time_stats(user)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||||
|
return json.dumps(result)
|
||||||
|
else:
|
||||||
|
logger.warn('Unable to retrieve data.')
|
Loading…
Add table
Add a link
Reference in a new issue