Mask all info on the homepage

This commit is contained in:
JonnyWong16 2016-04-24 22:07:16 -07:00
parent af9786f149
commit 5d7ba8cf14
14 changed files with 251 additions and 73 deletions

View file

@ -884,6 +884,7 @@ a:hover .dashboard-activity-poster {
float: right; float: right;
} }
.dashboard-activity-metadata-user-thumb { .dashboard-activity-metadata-user-thumb {
background-color: #282828;
background-position: center; background-position: center;
background-size: cover; background-size: cover;
margin-top: 5px; margin-top: 5px;

View file

@ -68,20 +68,23 @@ DOCUMENTATION :: END
% if data['stream_count'] != '0': % if data['stream_count'] != '0':
% for a in data['sessions']: % for a in data['sessions']:
<div class="dashboard-instance" id="instance-${a['session_key']}"> <div class="dashboard-instance" id="instance-${a['session_key']}">
% if a['media_type'] == 'movie' or a['media_type'] == 'episode' or a['media_type'] == 'track': % if (a['media_type'] == 'movie' or a['media_type'] == 'episode' or a['media_type'] == 'track') and a['rating_key']:
<a href="info?rating_key=${a['rating_key']}"> <a href="info?rating_key=${a['rating_key']}">
% else:
<a href="#">
% endif % endif
<div class="dashboard-activity-poster"> <div class="dashboard-activity-poster">
% if not a['art'].startswith('interfaces') or not a['thumb'].startswith('interfaces'):
% if (a['media_type'] == 'movie' and not a['indexes']) or (a['indexes'] and not a['view_offset']): % if (a['media_type'] == 'movie' and not a['indexes']) or (a['indexes'] and not a['view_offset']):
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div> <div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280&fallback=poster&fallback=cover);"></div>
% elif (a['media_type'] == 'episode' and not a['indexes']) or (a['indexes'] and not a['view_offset']): % elif (a['media_type'] == 'episode' and not a['indexes']) or (a['indexes'] and not a['view_offset']):
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div> <div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280&fallback=poster&fallback=cover);"></div>
% elif a['indexes']: % elif a['indexes']:
<div class="dashboard-activity-poster-face bif" style="background-image: url(pms_image_proxy?img=${a['bif_thumb']}&width=500&height=280); display: none;"></div> <div class="dashboard-activity-poster-face bif" style="background-image: url(pms_image_proxy?img=${a['bif_thumb']}&width=500&height=280&fallback=cover); display: none;"></div>
% else: % else:
% if a['media_type'] == 'track': % if a['media_type'] == 'track':
<div class="dashboard-activity-cover-face-bg" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300);"></div> <div class="dashboard-activity-cover-face-bg" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300&fallback=cover);"></div>
<div class="dashboard-activity-cover-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300);"></div> <div class="dashboard-activity-cover-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300&fallback=cover);"></div>
% elif a['media_type'] == 'clip': % elif a['media_type'] == 'clip':
% if a['art'][:4] == 'http': % if a['art'][:4] == 'http':
<div class="dashboard-activity-poster-face" style="background-image: url(${a['art']});"></div> <div class="dashboard-activity-poster-face" style="background-image: url(${a['art']});"></div>
@ -89,17 +92,20 @@ DOCUMENTATION :: END
<div class="dashboard-activity-poster-face" style="background-image: url(${a['thumb']});"></div> <div class="dashboard-activity-poster-face" style="background-image: url(${a['thumb']});"></div>
% else: % else:
% if a['art']: % if a['art']:
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div> <div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280&fallback=cover);"></div>
% else: % else:
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=280);"></div> <div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=280&fallback=cover);"></div>
% endif % endif
% endif % endif
% elif a['media_type'] == 'photo': % elif a['media_type'] == 'photo':
<div class="dashboard-activity-poster-face bif" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=500);"></div> <div class="dashboard-activity-poster-face bif" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=500&fallback=cover);"></div>
% else: % else:
<div class="dashboard-activity-cover-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300&fallback=cover);"></div> <div class="dashboard-activity-cover-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300&fallback=cover);"></div>
% endif % endif
% endif % endif
% else:
<div class="dashboard-activity-poster-face" style="background-image: url(${a['art']});"></div>
% endif
<div class="dashboard-activity-button-info"> <div class="dashboard-activity-button-info">
<button type="button" class="btn btn-activity-info btn-lg" data-target="#stream-${a['session_key']}"> <button type="button" class="btn btn-activity-info btn-lg" data-target="#stream-${a['session_key']}">
<i class="fa fa-info-circle"></i> <i class="fa fa-info-circle"></i>
@ -212,7 +218,9 @@ DOCUMENTATION :: END
</div> </div>
% endif % endif
</div> </div>
% if a['media_type'] == 'movie' or a['media_type'] == 'episode' or a['media_type'] == 'track': % if (a['media_type'] == 'movie' or a['media_type'] == 'episode' or a['media_type'] == 'track') and a['rating_key']:
</a>
% else:
</a> </a>
% endif % endif
<div class="dashboard-activity-progress"> <div class="dashboard-activity-progress">
@ -222,9 +230,13 @@ DOCUMENTATION :: END
</div> </div>
</div> </div>
<div class="dashboard-activity-metadata-wrapper"> <div class="dashboard-activity-metadata-wrapper">
% if a['user_id']:
<a href="user?user_id=${a['user_id']}"> <a href="user?user_id=${a['user_id']}">
<div class="dashboard-activity-metadata-user-thumb" style="background-image: url(${a['user_thumb']});"></div> <div class="dashboard-activity-metadata-user-thumb" style="background-image: url(${a['user_thumb']});"></div>
</a> </a>
% else:
<div class="dashboard-activity-metadata-user-thumb" style="background-image: url(${a['user_thumb']});"></div>
% endif
<div class="dashboard-activity-metadata-title"> <div class="dashboard-activity-metadata-title">
% if a['state'] == 'playing': % if a['state'] == 'playing':
<i class="fa fa-play"></i>&nbsp; <i class="fa fa-play"></i>&nbsp;
@ -233,6 +245,7 @@ DOCUMENTATION :: END
% elif a['state'] == 'buffering': % elif a['state'] == 'buffering':
<i class="fa fa-spinner"></i>&nbsp; <i class="fa fa-spinner"></i>&nbsp;
% endif % endif
% if a['title']:
% if a['media_type'] == 'episode': % if a['media_type'] == 'episode':
<a href="info?rating_key=${a['rating_key']}" title="${a['grandparent_title']} - ${a['title']}">${a['grandparent_title']} - ${a['title']}</a> <a href="info?rating_key=${a['rating_key']}" title="${a['grandparent_title']} - ${a['title']}">${a['grandparent_title']} - ${a['title']}</a>
% elif a['media_type'] == 'movie': % elif a['media_type'] == 'movie':
@ -246,8 +259,12 @@ DOCUMENTATION :: END
% else: % else:
<span title="${a['title']}">${a['title']}</span> <span title="${a['title']}">${a['title']}</span>
% endif % endif
% else:
Title
% endif
</div> </div>
<div class="dashboard-activity-metadata-subtitle"> <div class="dashboard-activity-metadata-subtitle">
% if a['media_index'] or a['parent_media_index'] or a['parent_title'] or a['title'] or a['year']:
% if a['media_type'] == 'episode': % if a['media_type'] == 'episode':
<span title="S${a['parent_media_index']} &middot; E${a['media_index']}">S${a['parent_media_index']} &middot; E${a['media_index']}</span> <span title="S${a['parent_media_index']} &middot; E${a['media_index']}">S${a['parent_media_index']} &middot; E${a['media_index']}</span>
% elif a['media_type'] == 'movie': % elif a['media_type'] == 'movie':
@ -259,9 +276,14 @@ DOCUMENTATION :: END
% else: % else:
<span title="${a['year']}">${a['year']}</span> <span title="${a['year']}">${a['year']}</span>
% endif % endif
% endif
</div> </div>
<div class="dashboard-activity-metadata-user"> <div class="dashboard-activity-metadata-user">
% if a['user_id']:
<a href="user?user_id=${a['user_id']}" title="${a['friendly_name']}">${a['friendly_name']}</a> <a href="user?user_id=${a['user_id']}" title="${a['friendly_name']}">${a['friendly_name']}</a>
% else:
${a['friendly_name']}
% endif
</div> </div>
</div> </div>
</div> </div>

View file

@ -540,11 +540,13 @@ DOCUMENTATION :: END
<h4> <h4>
% if top_stat['rows'][0]['user_id']: % if top_stat['rows'][0]['user_id']:
<a href="user?user_id=${top_stat['rows'][0]['user_id']}" title="${top_stat['rows'][0]['friendly_name']}"> <a href="user?user_id=${top_stat['rows'][0]['user_id']}" title="${top_stat['rows'][0]['friendly_name']}">
% else: % elif top_stat['rows'][0]['user']:
<a href="user?user=${top_stat['rows'][0]['user']}" title="${top_stat['rows'][0]['friendly_name']}"> <a href="user?user=${top_stat['rows'][0]['user']}" title="${top_stat['rows'][0]['friendly_name']}">
% endif % endif
${top_stat['rows'][0]['friendly_name']} ${top_stat['rows'][0]['friendly_name']}
% if top_stat['rows'][0]['user_id'] or top_stat['rows'][0]['user']:
</a> </a>
% endif
</h4> </h4>
% if top_stat['stat_type'] == 'total_plays': % if top_stat['stat_type'] == 'total_plays':
<h3>${top_stat['rows'][0]['total_plays']}</h3> <h3>${top_stat['rows'][0]['total_plays']}</h3>
@ -556,7 +558,7 @@ DOCUMENTATION :: END
</div> </div>
% if top_stat['rows'][0]['user_id']: % if top_stat['rows'][0]['user_id']:
<a href="user?user_id=${top_stat['rows'][0]['user_id']}" title="${top_stat['rows'][0]['friendly_name']}"> <a href="user?user_id=${top_stat['rows'][0]['user_id']}" title="${top_stat['rows'][0]['friendly_name']}">
% else: % elif top_stat['rows'][0]['user']:
<a href="user?user=${top_stat['rows'][0]['user']}" title="${top_stat['rows'][0]['friendly_name']}"> <a href="user?user=${top_stat['rows'][0]['user']}" title="${top_stat['rows'][0]['friendly_name']}">
% endif % endif
% if top_stat['rows'][0]['user_thumb'] != '': % if top_stat['rows'][0]['user_thumb'] != '':
@ -568,7 +570,9 @@ DOCUMENTATION :: END
<div class="home-platforms-instance-oval" style="background-image: url(${http_root}images/gravatar-default.png);"></div> <div class="home-platforms-instance-oval" style="background-image: url(${http_root}images/gravatar-default.png);"></div>
</div> </div>
% endif % endif
% if top_stat['rows'][0]['user_id'] or top_stat['rows'][0]['user']:
</a> </a>
% endif
% if len(top_stat['rows']) > 1: % if len(top_stat['rows']) > 1:
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div> <div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
<ul class="list-unstyled"> <ul class="list-unstyled">
@ -582,11 +586,13 @@ DOCUMENTATION :: END
<h5> <h5>
% if top_stat['rows'][loop.index]['user_id']: % if top_stat['rows'][loop.index]['user_id']:
<a href="user?user_id=${top_stat['rows'][loop.index]['user_id']}" title="${top_stat['rows'][loop.index]['friendly_name']}"> <a href="user?user_id=${top_stat['rows'][loop.index]['user_id']}" title="${top_stat['rows'][loop.index]['friendly_name']}">
% else: % elif top_stat['rows'][loop.index]['user']:
<a href="user?user=${top_stat['rows'][loop.index]['user']}" title="${top_stat['rows'][loop.index]['friendly_name']}"> <a href="user?user=${top_stat['rows'][loop.index]['user']}" title="${top_stat['rows'][loop.index]['friendly_name']}">
% endif % endif
${top_stat['rows'][loop.index]['friendly_name']} ${top_stat['rows'][loop.index]['friendly_name']}
% if top_stat['rows'][loop.index]['user_id'] or top_stat['rows'][loop.index]['user']:
</a> </a>
% endif
</h5> </h5>
</div> </div>
<div class="home-platforms-instance-list-playcount"> <div class="home-platforms-instance-list-playcount">
@ -600,7 +606,7 @@ DOCUMENTATION :: END
</div> </div>
% if top_stat['rows'][loop.index]['user_id']: % if top_stat['rows'][loop.index]['user_id']:
<a href="user?user_id=${top_stat['rows'][loop.index]['user_id']}" title="${top_stat['rows'][loop.index]['friendly_name']}"> <a href="user?user_id=${top_stat['rows'][loop.index]['user_id']}" title="${top_stat['rows'][loop.index]['friendly_name']}">
% else: % elif top_stat['rows'][loop.index]['user']:
<a href="user?user=${top_stat['rows'][loop.index]['user']}" title="${top_stat['rows'][loop.index]['friendly_name']}"> <a href="user?user=${top_stat['rows'][loop.index]['user']}" title="${top_stat['rows'][loop.index]['friendly_name']}">
% endif % endif
% if top_stat['rows'][loop.index]['user_thumb'] != '': % if top_stat['rows'][loop.index]['user_thumb'] != '':
@ -612,7 +618,9 @@ DOCUMENTATION :: END
<div class="home-platforms-instance-list-oval" style="background-image: url(${http_root}images/gravatar-default.png);"></div> <div class="home-platforms-instance-list-oval" style="background-image: url(${http_root}images/gravatar-default.png);"></div>
</div> </div>
% endif % endif
% if top_stat['rows'][loop.index]['user_id'] or top_stat['rows'][loop.index]['user']:
</a> </a>
% endif
<div class="home-platforms-instance-list-number"> <div class="home-platforms-instance-list-number">
<h4>${loop.index + 1}</h4> <h4>${loop.index + 1}</h4>
</div> </div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -46,7 +46,7 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="padded-header"> <div class="padded-header">
<ul class="nav nav-header nav-dashboard pull-right"> <ul class="nav nav-header nav-dashboard pull-right" style="margin-top: -12px;">
<li> <li>
<a href="#" id="recently-added-page-left" class="paginate btn-gray disabled" data-id="+1"><i class="fa fa-lg fa-chevron-left"></i></a> <a href="#" id="recently-added-page-left" class="paginate btn-gray disabled" data-id="+1"><i class="fa fa-lg fa-chevron-left"></i></a>
</li> </li>
@ -55,9 +55,9 @@
</li> </li>
</ul> </ul>
<h3>Recently Added &nbsp;&nbsp;<small> <h3>Recently Added &nbsp;&nbsp;<small>
<a href="#" class="toggle-recently-added-type" data-type="movie">Movies</a> &nbsp; <a href="#" class="toggle-recently-added-type btn-gray disabled" id="toggle-recently-added-movie" data-type="movie">Movies</a> &nbsp;
<a href="#" class="toggle-recently-added-type" data-type="season">TV Shows</a> &nbsp; <a href="#" class="toggle-recently-added-type btn-gray disabled" id="toggle-recently-added-season" data-type="season">TV Shows</a> &nbsp;
<a href="#" class="toggle-recently-added-type" data-type="album">Music</a></small></h3> <a href="#" class="toggle-recently-added-type btn-gray disabled" id="toggle-recently-added-album" data-type="album">Music</a></small></h3>
</div> </div>
<div id="recentlyAdded" style="margin-right: -15px;"> <div id="recentlyAdded" style="margin-right: -15px;">
<div class="text-muted"><i class="fa fa-refresh fa-spin"></i> Looking for new items...</div> <div class="text-muted"><i class="fa fa-refresh fa-spin"></i> Looking for new items...</div>
@ -138,6 +138,51 @@
complete: function(xhr, status) { complete: function(xhr, status) {
$("#recentlyAdded").html(xhr.responseText); $("#recentlyAdded").html(xhr.responseText);
highlightAddedScrollerButton(); highlightAddedScrollerButton();
if ($('.dashboard-recent-media-instance li[data-type=movie]').length) { $('#toggle-recently-added-movie').removeClass('disabled'); }
if ($('.dashboard-recent-media-instance li[data-type=season]').length) { $('#toggle-recently-added-season').removeClass('disabled'); }
if ($('.dashboard-recent-media-instance li[data-type=album]').length) { $('#toggle-recently-added-album').removeClass('disabled'); }
$('.toggle-recently-added-type').not('.disabled').click(function () {
var scroller = $("#recently-added-row-scroller");
var media_type = $(this).data('type');
var margin_right = $(this).hasClass('text-muted') ? '25px' : 0;
var toggle_items = $('.dashboard-recent-media-instance li[data-type=' + media_type + ']');
var containerWidth = $("body").find(".container-fluid").width();
if (margin_right == 0) {
toggle_items.animate({ width: 'toggle', marginRight: margin_right }, 1000, function () {
toggle_items.hide();
var scroller_width = $('.dashboard-recent-media-instance li:visible').length * 175;
scroller.width(scroller_width);
if (scroller_width < containerWidth) {
$("#recently-added-page-right").addClass("disabled").blur();
} else {
$("#recently-added-page-right").removeClass("disabled");
}
})
} else {
scroller.width(50 * 175);
toggle_items.animate({ width: 'toggle', marginRight: margin_right }, 1000, function () {
toggle_items.show();
var scroller_width = $('.dashboard-recent-media-instance li:visible').length * 175;
scroller.width(scroller_width);
if (scroller_width < containerWidth) {
$("#recently-added-page-right").addClass("disabled").blur();
} else {
$("#recently-added-page-right").removeClass("disabled");
}
})
}
leftTotal = 0;
scroller.animate({ left: leftTotal }, 1000);
$("#recently-added-page-left").addClass("disabled").blur();
$(this).toggleClass('text-muted').blur();
});
} }
}); });
} }
@ -156,7 +201,7 @@
function highlightAddedScrollerButton() { function highlightAddedScrollerButton() {
var scroller = $("#recently-added-row-scroller"); var scroller = $("#recently-added-row-scroller");
var numElems = scroller.find("li").length; var numElems = scroller.find("li:visible").length;
scroller.width(numElems * 175); scroller.width(numElems * 175);
if (scroller.width() > $("body").find(".container-fluid").width()) { if (scroller.width() > $("body").find(".container-fluid").width()) {
$("#recently-added-page-right").removeClass("disabled"); $("#recently-added-page-right").removeClass("disabled");
@ -192,13 +237,6 @@
$("#recently-added-page-right").removeClass("disabled"); $("#recently-added-page-right").removeClass("disabled");
} }
}); });
$('.toggle-recently-added-type').click(function () {
var media_type = $(this).data('type');
var margin_right = $(this).hasClass('text-muted') ? '25px' : 0;
$('.dashboard-recent-media-instance li[data-type=' + media_type + ']').animate({ width: 'toggle', marginRight: margin_right }, 1000);
$(this).toggleClass('text-muted').blur();
});
</script> </script>
</%def> </%def>

View file

@ -42,6 +42,7 @@ notify_strings[NOTIFY_STOPPED] = "Playback stopped"
DEFAULT_USER_THUMB = "interfaces/default/images/gravatar-default-80x80.png" DEFAULT_USER_THUMB = "interfaces/default/images/gravatar-default-80x80.png"
DEFAULT_POSTER_THUMB = "interfaces/default/images/poster.png" DEFAULT_POSTER_THUMB = "interfaces/default/images/poster.png"
DEFAULT_COVER_THUMB = "interfaces/default/images/cover.png" DEFAULT_COVER_THUMB = "interfaces/default/images/cover.png"
DEFAULT_ART = "interfaces/default/images/art.png"
PLATFORM_NAME_OVERRIDES = {'Konvergo': 'Plex Media Player', PLATFORM_NAME_OVERRIDES = {'Konvergo': 'Plex Media Player',
'Mystery 3': 'Playstation 3', 'Mystery 3': 'Playstation 3',

View file

@ -148,7 +148,7 @@ class DataFactory(object):
dict = {'recordsFiltered': query['filteredCount'], dict = {'recordsFiltered': query['filteredCount'],
'recordsTotal': query['totalCount'], 'recordsTotal': query['totalCount'],
'data': helpers.filter_datatable_session(rows), 'data': helpers.filter_session_info(rows, 'user_id'),
'draw': query['draw'], 'draw': query['draw'],
'filter_duration': helpers.human_duration(filter_duration, sig='dhm'), 'filter_duration': helpers.human_duration(filter_duration, sig='dhm'),
'total_duration': helpers.human_duration(total_duration, sig='dhm') 'total_duration': helpers.human_duration(total_duration, sig='dhm')
@ -168,7 +168,7 @@ class DataFactory(object):
if stat == 'top_tv': if stat == 'top_tv':
top_tv = [] top_tv = []
try: try:
query = 'SELECT t.id, t.grandparent_title, t.grandparent_rating_key, t.grandparent_thumb, ' \ query = 'SELECT t.id, t.grandparent_title, t.grandparent_rating_key, t.grandparent_thumb, t.section_id, ' \
'MAX(t.started) AS last_watch, COUNT(t.id) AS total_plays, SUM(t.d) AS total_duration ' \ 'MAX(t.started) AS last_watch, COUNT(t.id) AS total_plays, SUM(t.d) AS total_duration ' \
'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \ 'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \
' (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) ' \ ' (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) ' \
@ -196,6 +196,7 @@ class DataFactory(object):
'last_play': item['last_watch'], 'last_play': item['last_watch'],
'grandparent_thumb': item['grandparent_thumb'], 'grandparent_thumb': item['grandparent_thumb'],
'thumb': '', 'thumb': '',
'section_id': item['section_id'],
'user': '', 'user': '',
'friendly_name': '', 'friendly_name': '',
'platform_type': '', 'platform_type': '',
@ -206,12 +207,12 @@ class DataFactory(object):
home_stats.append({'stat_id': stat, home_stats.append({'stat_id': stat,
'stat_type': sort_type, 'stat_type': sort_type,
'rows': top_tv}) 'rows': helpers.filter_session_info(top_tv, 'section_id')})
elif stat == 'popular_tv': elif stat == 'popular_tv':
popular_tv = [] popular_tv = []
try: try:
query = 'SELECT t.id, t.grandparent_title, t.grandparent_rating_key, t.grandparent_thumb, ' \ query = 'SELECT t.id, t.grandparent_title, t.grandparent_rating_key, t.grandparent_thumb, t.section_id, ' \
'COUNT(DISTINCT t.user_id) AS users_watched, ' \ 'COUNT(DISTINCT t.user_id) AS users_watched, ' \
'MAX(t.started) AS last_watch, COUNT(t.id) as total_plays, SUM(t.d) AS total_duration ' \ 'MAX(t.started) AS last_watch, COUNT(t.id) as total_plays, SUM(t.d) AS total_duration ' \
'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \ 'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \
@ -239,6 +240,7 @@ class DataFactory(object):
'total_plays': item['total_plays'], 'total_plays': item['total_plays'],
'grandparent_thumb': item['grandparent_thumb'], 'grandparent_thumb': item['grandparent_thumb'],
'thumb': '', 'thumb': '',
'section_id': item['section_id'],
'user': '', 'user': '',
'friendly_name': '', 'friendly_name': '',
'platform_type': '', 'platform_type': '',
@ -248,12 +250,12 @@ class DataFactory(object):
popular_tv.append(row) popular_tv.append(row)
home_stats.append({'stat_id': stat, home_stats.append({'stat_id': stat,
'rows': popular_tv}) 'rows': helpers.filter_session_info(popular_tv, 'section_id')})
elif stat == 'top_movies': elif stat == 'top_movies':
top_movies = [] top_movies = []
try: try:
query = 'SELECT t.id, t.full_title, t.rating_key, t.thumb, ' \ query = 'SELECT t.id, t.full_title, t.rating_key, t.thumb, t.section_id, ' \
'MAX(t.started) AS last_watch, COUNT(t.id) AS total_plays, SUM(t.d) AS total_duration ' \ 'MAX(t.started) AS last_watch, COUNT(t.id) AS total_plays, SUM(t.d) AS total_duration ' \
'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \ 'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \
' (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) ' \ ' (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) ' \
@ -281,6 +283,7 @@ class DataFactory(object):
'last_play': item['last_watch'], 'last_play': item['last_watch'],
'grandparent_thumb': '', 'grandparent_thumb': '',
'thumb': item['thumb'], 'thumb': item['thumb'],
'section_id': item['section_id'],
'user': '', 'user': '',
'friendly_name': '', 'friendly_name': '',
'platform_type': '', 'platform_type': '',
@ -290,12 +293,12 @@ class DataFactory(object):
top_movies.append(row) top_movies.append(row)
home_stats.append({'stat_id': stat, home_stats.append({'stat_id': stat,
'stat_type': sort_type, 'stat_type': sort_type,
'rows': top_movies}) 'rows': helpers.filter_session_info(top_movies, 'section_id')})
elif stat == 'popular_movies': elif stat == 'popular_movies':
popular_movies = [] popular_movies = []
try: try:
query = 'SELECT t.id, t.full_title, t.rating_key, t.thumb, ' \ query = 'SELECT t.id, t.full_title, t.rating_key, t.thumb, t.section_id, ' \
'COUNT(DISTINCT t.user_id) AS users_watched, ' \ 'COUNT(DISTINCT t.user_id) AS users_watched, ' \
'MAX(t.started) AS last_watch, COUNT(t.id) as total_plays, SUM(t.d) AS total_duration ' \ 'MAX(t.started) AS last_watch, COUNT(t.id) as total_plays, SUM(t.d) AS total_duration ' \
'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \ 'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \
@ -323,6 +326,7 @@ class DataFactory(object):
'total_plays': item['total_plays'], 'total_plays': item['total_plays'],
'grandparent_thumb': '', 'grandparent_thumb': '',
'thumb': item['thumb'], 'thumb': item['thumb'],
'section_id': item['section_id'],
'user': '', 'user': '',
'friendly_name': '', 'friendly_name': '',
'platform_type': '', 'platform_type': '',
@ -332,12 +336,12 @@ class DataFactory(object):
popular_movies.append(row) popular_movies.append(row)
home_stats.append({'stat_id': stat, home_stats.append({'stat_id': stat,
'rows': popular_movies}) 'rows': helpers.filter_session_info(popular_movies, 'section_id')})
elif stat == 'top_music': elif stat == 'top_music':
top_music = [] top_music = []
try: try:
query = 'SELECT t.id, t.grandparent_title, t.grandparent_rating_key, t.grandparent_thumb, ' \ query = 'SELECT t.id, t.grandparent_title, t.grandparent_rating_key, t.grandparent_thumb, t.section_id, ' \
'MAX(t.started) AS last_watch, COUNT(t.id) AS total_plays, SUM(t.d) AS total_duration ' \ 'MAX(t.started) AS last_watch, COUNT(t.id) AS total_plays, SUM(t.d) AS total_duration ' \
'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \ 'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \
' (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) ' \ ' (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) ' \
@ -365,6 +369,7 @@ class DataFactory(object):
'last_play': item['last_watch'], 'last_play': item['last_watch'],
'grandparent_thumb': item['grandparent_thumb'], 'grandparent_thumb': item['grandparent_thumb'],
'thumb': '', 'thumb': '',
'section_id': item['section_id'],
'user': '', 'user': '',
'friendly_name': '', 'friendly_name': '',
'platform_type': '', 'platform_type': '',
@ -375,12 +380,12 @@ class DataFactory(object):
home_stats.append({'stat_id': stat, home_stats.append({'stat_id': stat,
'stat_type': sort_type, 'stat_type': sort_type,
'rows': top_music}) 'rows': helpers.filter_session_info(top_music, 'section_id')})
elif stat == 'popular_music': elif stat == 'popular_music':
popular_music = [] popular_music = []
try: try:
query = 'SELECT t.id, t.grandparent_title, t.grandparent_rating_key, t.grandparent_thumb, ' \ query = 'SELECT t.id, t.grandparent_title, t.grandparent_rating_key, t.grandparent_thumb, t.section_id, ' \
'COUNT(DISTINCT t.user_id) AS users_watched, ' \ 'COUNT(DISTINCT t.user_id) AS users_watched, ' \
'MAX(t.started) AS last_watch, COUNT(t.id) as total_plays, SUM(t.d) AS total_duration ' \ 'MAX(t.started) AS last_watch, COUNT(t.id) as total_plays, SUM(t.d) AS total_duration ' \
'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \ 'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \
@ -408,6 +413,7 @@ class DataFactory(object):
'total_plays': item['total_plays'], 'total_plays': item['total_plays'],
'grandparent_thumb': item['grandparent_thumb'], 'grandparent_thumb': item['grandparent_thumb'],
'thumb': '', 'thumb': '',
'section_id': item['section_id'],
'user': '', 'user': '',
'friendly_name': '', 'friendly_name': '',
'platform_type': '', 'platform_type': '',
@ -417,7 +423,7 @@ class DataFactory(object):
popular_music.append(row) popular_music.append(row)
home_stats.append({'stat_id': stat, home_stats.append({'stat_id': stat,
'rows': popular_music}) 'rows': helpers.filter_session_info(popular_music, 'section_id')})
elif stat == 'top_users': elif stat == 'top_users':
top_users = [] top_users = []
@ -470,7 +476,7 @@ class DataFactory(object):
home_stats.append({'stat_id': stat, home_stats.append({'stat_id': stat,
'stat_type': sort_type, 'stat_type': sort_type,
'rows': helpers.filter_datatable_session(top_users)}) 'rows': helpers.mask_session_info(top_users)})
elif stat == 'top_platforms': elif stat == 'top_platforms':
top_platform = [] top_platform = []
@ -567,7 +573,7 @@ class DataFactory(object):
last_watched.append(row) last_watched.append(row)
home_stats.append({'stat_id': stat, home_stats.append({'stat_id': stat,
'rows': helpers.filter_datatable_session(last_watched)}) 'rows': helpers.filter_session_info(last_watched, 'user_id')})
elif stat == 'most_concurrent': elif stat == 'most_concurrent':
@ -686,7 +692,7 @@ class DataFactory(object):
} }
library_stats.append(library) library_stats.append(library)
return library_stats return helpers.filter_session_info(library_stats, 'section_id')
def get_stream_details(self, row_id=None): def get_stream_details(self, row_id=None):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()

View file

@ -33,7 +33,8 @@ from xml.dom import minidom
import xmltodict import xmltodict
import plexpy import plexpy
from api2 import API2 from plexpy import common
from plexpy.api2 import API2
def addtoapi(*dargs, **dkwargs): def addtoapi(*dargs, **dkwargs):
@ -564,18 +565,102 @@ def uploadToImgur(imgPath, imgTitle=''):
return img_url return img_url
def filter_datatable_session(list_of_dicts):
def allow_session_user(user_id):
"""
Returns True or False if the user_id is allowed for the user session
"""
import cherrypy import cherrypy
from plexpy.webauth import SESSION_KEY from plexpy.webauth import SESSION_KEY
if cherrypy.config.get('tools.auth.on'): if cherrypy.config.get('tools.auth.on'):
_session = {} _session = cherrypy.session.get(SESSION_KEY)
_cp_session = cherrypy.session.get(SESSION_KEY) if str(user_id) != _session['user_id']:
_session['username'], _session['user_id'], _session['user_group'], _session['expiry'] = \ return False
_cp_session if _cp_session else (None, None, None, None)
return True
def allow_session_library(section_id):
"""
Returns True or False if the section_id is allowed for the user session
"""
import cherrypy
from plexpy.webauth import SESSION_KEY
if cherrypy.config.get('tools.auth.on'):
_session = cherrypy.session.get(SESSION_KEY)
if str(section_id) not in _session['user_libraries']:
return False
return True
def filter_session_info(list_of_dicts, filter_key=None):
"""
Filters a list of dictionary items to only return the info for the current logged in user
"""
import cherrypy
from plexpy.webauth import SESSION_KEY
if cherrypy.config.get('tools.auth.on'):
_session = cherrypy.session.get(SESSION_KEY)
if filter_key == 'user_id' and _session['user_id']:
session_user_id = str(_session['user_id'])
return [d for d in list_of_dicts if str(d.get('user_id','')) == session_user_id]
elif filter_key == 'section_id' and _session['user_libraries']:
session_library_ids = _session['user_libraries']
return [d for d in list_of_dicts if str(d.get('section_id','')) in session_library_ids]
return list_of_dicts
def mask_session_info(list_of_dicts, mask_metadata=False):
"""
Masks user info in a list of dictionary items to only display info for the current logged in user
"""
import cherrypy
from plexpy.webauth import SESSION_KEY
if cherrypy.config.get('tools.auth.on'):
_session = cherrypy.session.get(SESSION_KEY)
keys_to_mask = {'user_id': '',
'user': '',
'friendly_name': 'Plex User',
'user_thumb': common.DEFAULT_USER_THUMB,
'ip_address': 'N/A',
'machine_id': ''
}
metadata_to_mask = {'media_index': '',
'parent_media_index': '',
'art': common.DEFAULT_ART,
'parent_thumb': common.DEFAULT_POSTER_THUMB,
'grandparent_thumb': common.DEFAULT_POSTER_THUMB,
'thumb': common.DEFAULT_POSTER_THUMB,
'bif_thumb': '',
'grandparent_title': '',
'parent_title': '',
'title': '',
'rating_key': '',
'parent_rating_key': '',
'grandparent_rating_key': '',
'year': ''
}
if _session['user_id']: if _session['user_id']:
session_user_id = str(_session['user_id']) session_user_id = str(_session['user_id'])
return [d for d in list_of_dicts if str(d.get('user_id')) == session_user_id] session_library_ids = _session['user_libraries']
for d in list_of_dicts:
if not (str(d.get('user_id')) == session_user_id or d.get('user') == _session['user']):
for k, v in keys_to_mask.iteritems():
if k in d: d[k] = keys_to_mask[k]
if mask_metadata and str(d.get('section_id','')) not in session_library_ids:
for k, v in metadata_to_mask.iteritems():
if k in d: d[k] = metadata_to_mask[k]
return list_of_dicts
return list_of_dicts return list_of_dicts

View file

@ -222,7 +222,7 @@ class Libraries(object):
dict = {'recordsFiltered': query['filteredCount'], dict = {'recordsFiltered': query['filteredCount'],
'recordsTotal': query['totalCount'], 'recordsTotal': query['totalCount'],
'data': rows, 'data': helpers.filter_session_info(rows, 'section_id'),
'draw': query['draw'] 'draw': query['draw']
} }
@ -700,7 +700,7 @@ class Libraries(object):
} }
user_stats.append(row) user_stats.append(row)
return helpers.filter_datatable_session(user_stats) return helpers.filter_session_info(user_stats, 'user_id')
def get_recently_watched(self, section_id=None, limit='10'): def get_recently_watched(self, section_id=None, limit='10'):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()

View file

@ -401,7 +401,7 @@ class PlexTV(object):
synced_items.append(sync_details) synced_items.append(sync_details)
return helpers.filter_datatable_session(synced_items) return helpers.filter_session_info(synced_items, 'user_id')
def get_server_urls(self, include_https=True): def get_server_urls(self, include_https=True):

View file

@ -94,7 +94,7 @@ class PmsConnect(object):
Retrieve data from Plex Server Retrieve data from Plex Server
""" """
def __init__(self): def __init__(self, token=None):
if plexpy.CONFIG.PMS_URL: if plexpy.CONFIG.PMS_URL:
url_parsed = urlparse(plexpy.CONFIG.PMS_URL) url_parsed = urlparse(plexpy.CONFIG.PMS_URL)
hostname = url_parsed.hostname hostname = url_parsed.hostname
@ -105,9 +105,11 @@ class PmsConnect(object):
port = plexpy.CONFIG.PMS_PORT port = plexpy.CONFIG.PMS_PORT
self.protocol = 'http' self.protocol = 'http'
token = token if token else plexpy.CONFIG.PMS_TOKEN
self.request_handler = http_handler.HTTPHandler(host=hostname, self.request_handler = http_handler.HTTPHandler(host=hostname,
port=port, port=port,
token=plexpy.CONFIG.PMS_TOKEN) token=token)
def get_sessions(self, output_format=''): def get_sessions(self, output_format=''):
""" """
@ -492,7 +494,8 @@ class PmsConnect(object):
} }
recents_list.append(recent_items) recents_list.append(recent_items)
output = {'recently_added': sorted(recents_list, key=lambda k: k['added_at'], reverse=True)} output = {'recently_added': helpers.filter_session_info(
sorted(recents_list, key=lambda k: k['added_at'], reverse=True), 'section_id')}
return output return output
def get_metadata_details(self, rating_key='', get_media_info=False): def get_metadata_details(self, rating_key='', get_media_info=False):
@ -972,7 +975,7 @@ class PmsConnect(object):
session_list.append(session_output) session_list.append(session_output)
output = {'stream_count': helpers.get_xml_attr(xml_head[0], 'size'), output = {'stream_count': helpers.get_xml_attr(xml_head[0], 'size'),
'sessions': session_list 'sessions': helpers.mask_session_info(session_list, True)
} }
return output return output

View file

@ -190,7 +190,7 @@ class Users(object):
dict = {'recordsFiltered': query['filteredCount'], dict = {'recordsFiltered': query['filteredCount'],
'recordsTotal': query['totalCount'], 'recordsTotal': query['totalCount'],
'data': helpers.filter_datatable_session(rows), 'data': helpers.filter_session_info(rows, 'user_id'),
'draw': query['draw'] 'draw': query['draw']
} }
@ -284,7 +284,7 @@ class Users(object):
dict = {'recordsFiltered': query['filteredCount'], dict = {'recordsFiltered': query['filteredCount'],
'recordsTotal': query['totalCount'], 'recordsTotal': query['totalCount'],
'data': helpers.filter_datatable_session(rows), 'data': helpers.filter_session_info(rows, 'user_id'),
'draw': query['draw'] 'draw': query['draw']
} }

View file

@ -26,6 +26,7 @@ from datetime import datetime, timedelta
import plexpy import plexpy
from plexpy import logger from plexpy import logger
from plexpy.users import Users, user_login from plexpy.users import Users, user_login
from plexpy.pmsconnect import PmsConnect
SESSION_KEY = '_cp_username' SESSION_KEY = '_cp_username'
@ -50,11 +51,10 @@ def check_auth(*args, **kwargs):
conditions that the user must fulfill""" conditions that the user must fulfill"""
conditions = cherrypy.request.config.get('auth.require', None) conditions = cherrypy.request.config.get('auth.require', None)
if conditions is not None: if conditions is not None:
cp_sesssion = cherrypy.session.get(SESSION_KEY) _session = cherrypy.session.get(SESSION_KEY)
username, user_id, user_group, expiry = cp_sesssion if cp_sesssion else (None, None, None, None)
if (username and expiry) and expiry > datetime.now(): if _session and (_session['user'] and _session['expiry']) and _session['expiry'] > datetime.now():
cherrypy.request.login = username cherrypy.request.login = _session['user']
for condition in conditions: for condition in conditions:
# A condition is just a callable that returns true or false # A condition is just a callable that returns true or false
if not condition(): if not condition():
@ -148,14 +148,25 @@ class AuthController(object):
if user_group == 'guest': if user_group == 'guest':
user_details = Users().get_details(user=username) user_details = Users().get_details(user=username)
user_id = user_details['user_id'] user_id = user_details['user_id']
user_tokens = Users().get_tokens(user_id=user_details['user_id'])
server_token = user_tokens['server_token']
library_details = PmsConnect(token=server_token).get_server_children()
user_libraries = tuple(d['section_id'] for d in library_details['libraries_list'])
else: else:
user_id = None user_id = None
user_libraries = None
expiry = datetime.now() + (timedelta(days=30) if remember_me == '1' else timedelta(minutes=60)) expiry = datetime.now() + (timedelta(days=30) if remember_me == '1' else timedelta(minutes=60))
cherrypy.session.regenerate() cherrypy.session.regenerate()
cherrypy.request.login = username cherrypy.request.login = username
cherrypy.session[SESSION_KEY] = (username, user_id, user_group, expiry) cherrypy.session[SESSION_KEY] = {'user_id': user_id,
'user': username,
'user_group': user_group,
'user_libraries': user_libraries,
'expiry': expiry}
self.on_login(username) self.on_login(username)
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT) raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT)
@ -169,11 +180,10 @@ class AuthController(object):
if not plexpy.CONFIG.HTTP_PASSWORD: if not plexpy.CONFIG.HTTP_PASSWORD:
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT) raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT)
cp_sesssion = cherrypy.session.get(SESSION_KEY) _session = cherrypy.session.get(SESSION_KEY)
username, user_id, user_group, expiry = cp_sesssion if cp_sesssion else (None, None, None, None)
cherrypy.session[SESSION_KEY] = None cherrypy.session[SESSION_KEY] = None
if username: if _session['user']:
cherrypy.request.login = None cherrypy.request.login = None
self.on_logout(username) self.on_logout(_session['user'])
raise cherrypy.HTTPRedirect("login") raise cherrypy.HTTPRedirect("login")

View file

@ -49,15 +49,13 @@ def serve_template(templatename, **kwargs):
server_name = plexpy.CONFIG.PMS_NAME server_name = plexpy.CONFIG.PMS_NAME
_session = {'username': None, _session = {'user_id': None,
'user_id': None, 'user': None,
'user_group': 'admin', 'user_group': 'admin',
'expiry': None} 'expiry': None}
if cherrypy.config.get('tools.auth.on'): if cherrypy.config.get('tools.auth.on'):
_cp_session = cherrypy.session.get(SESSION_KEY) _session = cherrypy.session.get(SESSION_KEY)
_session['username'], _session['user_id'], _session['user_group'], _session['expiry'] = \
_cp_session if _cp_session else (None, None, 'admin', None)
try: try:
template = _hplookup.get_template(templatename) template = _hplookup.get_template(templatename)
@ -173,6 +171,7 @@ class WebInterface(object):
return serve_template(templatename="index.html", title="Home", config=config) return serve_template(templatename="index.html", title="Home", config=config)
@cherrypy.expose @cherrypy.expose
@requireAuth()
@addtoapi() @addtoapi()
def get_date_formats(self): def get_date_formats(self):
""" Get the date and time formats used by plexpy """ """ Get the date and time formats used by plexpy """
@ -193,6 +192,7 @@ class WebInterface(object):
return json.dumps(formats) return json.dumps(formats)
@cherrypy.expose @cherrypy.expose
@requireAuth()
def get_current_activity(self, **kwargs): def get_current_activity(self, **kwargs):
try: try:
@ -215,6 +215,7 @@ class WebInterface(object):
return serve_template(templatename="current_activity.html", data=None) return serve_template(templatename="current_activity.html", data=None)
@cherrypy.expose @cherrypy.expose
@requireAuth()
def get_current_activity_header(self, **kwargs): def get_current_activity_header(self, **kwargs):
try: try:
@ -230,6 +231,7 @@ class WebInterface(object):
return serve_template(templatename="current_activity_header.html", data=None) return serve_template(templatename="current_activity_header.html", data=None)
@cherrypy.expose @cherrypy.expose
@requireAuth()
def home_stats(self, **kwargs): def home_stats(self, **kwargs):
data_factory = datafactory.DataFactory() data_factory = datafactory.DataFactory()
@ -250,6 +252,7 @@ class WebInterface(object):
return serve_template(templatename="home_stats.html", title="Stats", data=stats_data) return serve_template(templatename="home_stats.html", title="Stats", data=stats_data)
@cherrypy.expose @cherrypy.expose
@requireAuth()
def library_stats(self, **kwargs): def library_stats(self, **kwargs):
data_factory = datafactory.DataFactory() data_factory = datafactory.DataFactory()
@ -260,6 +263,7 @@ class WebInterface(object):
return serve_template(templatename="library_stats.html", title="Library Stats", data=stats_data) return serve_template(templatename="library_stats.html", title="Library Stats", data=stats_data)
@cherrypy.expose @cherrypy.expose
@requireAuth()
def get_recently_added(self, count='0', **kwargs): def get_recently_added(self, count='0', **kwargs):
try: try: