Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fd3daae491 | ||
![]() |
697d107952 | ||
![]() |
65e42be278 | ||
![]() |
ad79d860db | ||
![]() |
5826a823a8 | ||
![]() |
cbec1e7768 | ||
![]() |
40f72bbe5f |
@@ -22,4 +22,11 @@
|
||||
* Fix bug on home stats which wouldn't update unless a TV show was first logged.
|
||||
* Fix alignment of bands on daily graphs which highlight weekends.
|
||||
* Fix behaviour of close button on update popup, will now stay closed for an hour after clicking close.
|
||||
* Fix some styling niggles.
|
||||
* Fix some styling niggles.
|
||||
|
||||
## v1.1.1 (2015-08-15)
|
||||
|
||||
* Added Most watched movie for home stats. Thanks @jroyal.
|
||||
* Added TV show title to recently added text. Thanks @jroyal.
|
||||
* Fix bug with buffer warnings where notification would trigger continuously after first trigger.
|
||||
* Fix bug where custom avatar URL would get reset on every user refresh.
|
@@ -31,7 +31,7 @@ DOCUMENTATION :: END
|
||||
<div class="form-group">
|
||||
<label for="friendly_name">Friendly Name</label>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" id="friendly_name" name="friendly_name" value="${data['friendly_name']}" size="30">
|
||||
</div>
|
||||
</div>
|
||||
@@ -40,11 +40,11 @@ DOCUMENTATION :: END
|
||||
<div class="form-group">
|
||||
<label for="profile_url">Profile Picture URL</label>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" id="profile_url" name="profile_url" value="${data['thumb']}">
|
||||
</div>
|
||||
</div>
|
||||
<p class="help-block">Change the users profile picture in plexpy. You should save the URL if you would like to go back as this replaces the existing one.</p>
|
||||
<p class="help-block">Change the users profile picture in PlexPy.</p>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
|
@@ -93,6 +93,31 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
% elif a['stat_id'] == 'top_movies' and a['rows']:
|
||||
<div class="home-platforms-instance">
|
||||
<li>
|
||||
<span>
|
||||
<a href="info?item_id=${a['rows'][0]['rating_key']}">
|
||||
% if a['rows'][0]['thumb']:
|
||||
<img class="home-platforms-instance-poster"
|
||||
src="pms_image_proxy?img=${a['rows'][0]['thumb']}&width=162&height=240&fallback=poster">
|
||||
% else:
|
||||
<img class="home-platforms-instance-poster" src="interfaces/default/images/poster.png">
|
||||
% endif
|
||||
</a>
|
||||
</span>
|
||||
<div class="home-platforms-instance-name">
|
||||
<h4>Most Watched Movie</h4>
|
||||
<h5><a href="info?item_id=${a['rows'][0]['rating_key']}">
|
||||
${a['rows'][0]['title']}
|
||||
</a></h5>
|
||||
</div>
|
||||
<div class="user-platforms-instance-playcount">
|
||||
<h3>${a['rows'][0]['total_plays']}</h3>
|
||||
<p> plays</p>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
% elif a['stat_id'] == 'top_users' and a['rows']:
|
||||
<div class="home-platforms-instance">
|
||||
<li>
|
||||
|
@@ -15,6 +15,7 @@ type Returns the type of media. Either 'movie' or 'season'.
|
||||
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
|
||||
added_at Returns the time when the media was added to the library.
|
||||
title Returns the name of the movie or season.
|
||||
parent_title Returns the name of the TV Show a season belongs too.
|
||||
|
||||
== Only if 'type' is 'movie' ==
|
||||
year Returns the movie release year.
|
||||
@@ -42,7 +43,9 @@ DOCUMENTATION :: END
|
||||
% endif
|
||||
</div>
|
||||
<div class="dashboard-recent-media-metacontainer">
|
||||
% if item['type'] == 'season' or item['type'] == 'album':
|
||||
% if item['type'] == 'season':
|
||||
<h3>${item['parent_title']} - ${item['title']}</h3>
|
||||
% elif item['type'] == 'album':
|
||||
<h3>${item['title']}</h3>
|
||||
% elif item['type'] == 'movie':
|
||||
<h3>${item['title']} (${item['year']})</h3>
|
||||
|
@@ -369,10 +369,10 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||
<label for="buffer_threshold">Buffer Threshold</label>
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<input type="text" class="form-control" data-parsley-type="integer" id="buffer_threshold" name="buffer_threshold" value="${config['buffer_threshold']}" data-parsley-range="[1,50]" data-parsley-trigger="change" required>
|
||||
<input type="text" class="form-control" data-parsley-type="integer" id="buffer_threshold" name="buffer_threshold" value="${config['buffer_threshold']}" data-parsley-range="[0,50]" data-parsley-trigger="change" required>
|
||||
</div>
|
||||
</div>
|
||||
<p class="help-block">How many buffer events should we wait before triggering the first warning. Buffer events increment on each monitor ping if play state is buffering.</p>
|
||||
<p class="help-block">How many buffer events should we wait before triggering the first warning. Buffer events increment on each monitor ping if play state is buffering. 0 to disable buffer warnings.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="buffer_wait">Buffer Wait</label>
|
||||
|
@@ -388,7 +388,7 @@ def dbcheck():
|
||||
'user_id INTEGER DEFAULT NULL UNIQUE, username TEXT NOT NULL UNIQUE, '
|
||||
'friendly_name TEXT, thumb TEXT, email TEXT, is_home_user INTEGER DEFAULT NULL, '
|
||||
'is_allow_sync INTEGER DEFAULT NULL, is_restricted INTEGER DEFAULT NULL, do_notify INTEGER DEFAULT 1, '
|
||||
'keep_history INTEGER DEFAULT 1)'
|
||||
'keep_history INTEGER DEFAULT 1, custom_avatar_url TEXT)'
|
||||
)
|
||||
|
||||
# Upgrade sessions table from earlier versions
|
||||
@@ -534,29 +534,29 @@ def dbcheck():
|
||||
'on_pause INTEGER, on_resume INTEGER, on_buffer INTEGER)'
|
||||
)
|
||||
|
||||
# Upgrade sessions table from earlier versions
|
||||
# Upgrade users table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT do_notify from users')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table sessions.")
|
||||
logger.debug(u"Altering database. Updating database table users.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE users ADD COLUMN do_notify INTEGER DEFAULT 1'
|
||||
)
|
||||
|
||||
# Upgrade sessions table from earlier versions
|
||||
# Upgrade users table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT keep_history from users')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table sessions.")
|
||||
logger.debug(u"Altering database. Updating database table users.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE users ADD COLUMN keep_history INTEGER DEFAULT 1'
|
||||
)
|
||||
|
||||
# Upgrade sessions table from earlier versions
|
||||
# Upgrade notify_log table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT on_pause from notify_log')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table sessions.")
|
||||
logger.debug(u"Altering database. Updating database table notify_log.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE notify_log ADD COLUMN on_pause INTEGER'
|
||||
)
|
||||
@@ -579,6 +579,15 @@ def dbcheck():
|
||||
'ALTER TABLE sessions ADD COLUMN buffer_last_triggered INTEGER'
|
||||
)
|
||||
|
||||
# Upgrade users table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT custom_avatar_url from users')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table users.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE users ADD COLUMN custom_avatar_url TEXT'
|
||||
)
|
||||
|
||||
conn_db.commit()
|
||||
c_db.close()
|
||||
|
||||
|
@@ -30,7 +30,7 @@ class DataFactory(object):
|
||||
data_tables = datatables.DataTables()
|
||||
|
||||
columns = ['users.user_id as user_id',
|
||||
'users.thumb as thumb',
|
||||
'users.custom_avatar_url as thumb',
|
||||
'(case when users.friendly_name is null then users.username else \
|
||||
users.friendly_name end) as friendly_name',
|
||||
'MAX(session_history.started) as last_seen',
|
||||
@@ -256,7 +256,7 @@ class DataFactory(object):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
control_value_dict = {"user_id": user_id}
|
||||
new_value_dict = {"thumb": profile_url}
|
||||
new_value_dict = {"custom_avatar_url": profile_url}
|
||||
try:
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
except Exception, e:
|
||||
@@ -268,7 +268,7 @@ class DataFactory(object):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
control_value_dict = {"username": user}
|
||||
new_value_dict = {"thumb": profile_url}
|
||||
new_value_dict = {"custom_avatar_url": profile_url}
|
||||
try:
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
except Exception, e:
|
||||
@@ -279,7 +279,7 @@ class DataFactory(object):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
query = 'select username, ' \
|
||||
'(CASE WHEN friendly_name IS NULL THEN username ELSE friendly_name END),' \
|
||||
'do_notify, keep_history, thumb ' \
|
||||
'do_notify, keep_history, custom_avatar_url as thumb ' \
|
||||
'FROM users WHERE user_id = ?'
|
||||
result = monitor_db.select(query, args=[user_id])
|
||||
if result:
|
||||
@@ -303,7 +303,7 @@ class DataFactory(object):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
query = 'select user_id, ' \
|
||||
'(CASE WHEN friendly_name IS NULL THEN username ELSE friendly_name END),' \
|
||||
'do_notify, keep_history, thumb ' \
|
||||
'do_notify, keep_history, custom_avatar_url as thumb ' \
|
||||
'FROM users WHERE username = ?'
|
||||
result = monitor_db.select(query, args=[user])
|
||||
if result:
|
||||
@@ -347,7 +347,7 @@ class DataFactory(object):
|
||||
|
||||
if user:
|
||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
||||
'thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'FROM users ' \
|
||||
'WHERE username = ? ' \
|
||||
'UNION ALL ' \
|
||||
@@ -359,7 +359,7 @@ class DataFactory(object):
|
||||
result = monitor_db.select(query, args=[user, user])
|
||||
elif user_id:
|
||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
||||
'thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'FROM users ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'UNION ALL ' \
|
||||
@@ -402,7 +402,7 @@ class DataFactory(object):
|
||||
# Refresh users
|
||||
plextv.refresh_users()
|
||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
||||
'thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'FROM users ' \
|
||||
'WHERE username = ? ' \
|
||||
'UNION ALL ' \
|
||||
@@ -416,7 +416,7 @@ class DataFactory(object):
|
||||
# Refresh users
|
||||
plextv.refresh_users()
|
||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
||||
'thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'FROM users ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'UNION ALL ' \
|
||||
@@ -472,7 +472,8 @@ class DataFactory(object):
|
||||
if not time_range.isdigit():
|
||||
time_range = '30'
|
||||
|
||||
stats_queries = ["top_tv", "popular_tv", "top_users", "top_platforms"]
|
||||
# This actually determines the output order in the home page
|
||||
stats_queries = ["top_tv", "popular_tv", "top_movies", "top_users", "top_platforms"]
|
||||
home_stats = []
|
||||
|
||||
for stat in stats_queries:
|
||||
@@ -516,6 +517,46 @@ class DataFactory(object):
|
||||
home_stats.append({'stat_id': stat,
|
||||
'rows': top_tv})
|
||||
|
||||
elif 'top_movies' in stat:
|
||||
top_movies = []
|
||||
try:
|
||||
query = 'SELECT session_history_metadata.id, ' \
|
||||
'session_history_metadata.full_title, ' \
|
||||
'COUNT(session_history_metadata.full_title) as total_plays, ' \
|
||||
'session_history_metadata.rating_key, ' \
|
||||
'MAX(session_history.started) as last_watch,' \
|
||||
'session_history_metadata.thumb ' \
|
||||
'FROM session_history_metadata ' \
|
||||
'JOIN session_history on session_history_metadata.id = session_history.id ' \
|
||||
'WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
|
||||
'>= datetime("now", "-%s days", "localtime") ' \
|
||||
'AND session_history_metadata.media_type = "movie" ' \
|
||||
'GROUP BY session_history_metadata.full_title ' \
|
||||
'ORDER BY total_plays DESC LIMIT 10' % time_range
|
||||
result = monitor_db.select(query)
|
||||
except:
|
||||
logger.warn("Unable to execute database query.")
|
||||
return None
|
||||
|
||||
for item in result:
|
||||
row = {'title': item[1],
|
||||
'total_plays': item[2],
|
||||
'users_watched': '',
|
||||
'rating_key': item[3],
|
||||
'last_play': item[4],
|
||||
'grandparent_thumb': '',
|
||||
'thumb': item[5],
|
||||
'user': '',
|
||||
'friendly_name': '',
|
||||
'platform_type': '',
|
||||
'platform': '',
|
||||
'row_id': item[0]
|
||||
}
|
||||
top_movies.append(row)
|
||||
|
||||
home_stats.append({'stat_id': stat,
|
||||
'rows': top_movies})
|
||||
|
||||
elif 'popular_tv' in stat:
|
||||
popular_tv = []
|
||||
try:
|
||||
@@ -566,7 +607,7 @@ class DataFactory(object):
|
||||
'users.friendly_name end) as friendly_name,' \
|
||||
'COUNT(session_history.id) as total_plays, ' \
|
||||
'MAX(session_history.started) as last_watch, ' \
|
||||
'users.thumb, ' \
|
||||
'users.custom_avatar_url as thumb, ' \
|
||||
'users.user_id ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_metadata ON session_history.id = session_history_metadata.id ' \
|
||||
|
@@ -72,7 +72,7 @@ def check_active_sessions():
|
||||
monitor_db.action('UPDATE sessions SET paused_counter = ? '
|
||||
'WHERE session_key = ? AND rating_key = ?',
|
||||
[paused_counter, stream['session_key'], stream['rating_key']])
|
||||
if session['state'] == 'buffering':
|
||||
if session['state'] == 'buffering' and plexpy.CONFIG.BUFFER_THRESHOLD > 0:
|
||||
# The stream is buffering so we need to increment the buffer_count
|
||||
# We're going just increment on every monitor ping,
|
||||
# would be difficult to keep track otherwise
|
||||
@@ -107,6 +107,12 @@ def check_active_sessions():
|
||||
plexpy.CONFIG.BUFFER_WAIT:
|
||||
logger.info(u"PlexPy Monitor :: User '%s' has triggered multiple buffer warnings."
|
||||
% stream['user'])
|
||||
# Set the buffer trigger time
|
||||
monitor_db.action('UPDATE sessions '
|
||||
'SET buffer_last_triggered = strftime("%s","now") '
|
||||
'WHERE session_key = ? AND rating_key = ?',
|
||||
[stream['session_key'], stream['rating_key']])
|
||||
|
||||
threading.Thread(target=notification_handler.notify,
|
||||
kwargs=dict(stream_data=stream, notify_action='buffer')).start()
|
||||
|
||||
|
@@ -37,6 +37,15 @@ def refresh_users():
|
||||
"is_restricted": item['is_restricted']
|
||||
}
|
||||
|
||||
# Check if we've set a custom avatar if so don't overwrite it.
|
||||
avatar_urls = monitor_db.select('SELECT thumb, custom_avatar_url '
|
||||
'FROM users WHERE user_id = ?',
|
||||
[item['user_id']])
|
||||
|
||||
if not avatar_urls[0]['custom_avatar_url'] or \
|
||||
avatar_urls[0]['custom_avatar_url'] == avatar_urls[0]['thumb']:
|
||||
new_value_dict['custom_avatar_url'] = item['thumb']
|
||||
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
|
||||
logger.info("Users list refreshed.")
|
||||
|
@@ -218,6 +218,7 @@ class PmsConnect(object):
|
||||
recent_items = {'type': recent_type,
|
||||
'rating_key': helpers.get_xml_attr(item, 'ratingKey'),
|
||||
'title': helpers.get_xml_attr(item, 'title'),
|
||||
'parent_title': helpers.get_xml_attr(item, 'parentTitle'),
|
||||
'thumb': helpers.get_xml_attr(item, 'thumb'),
|
||||
'added_at': helpers.get_xml_attr(item, 'addedAt')
|
||||
}
|
||||
@@ -232,6 +233,7 @@ class PmsConnect(object):
|
||||
recent_items = {'type': recent_type,
|
||||
'rating_key': helpers.get_xml_attr(item, 'ratingKey'),
|
||||
'title': helpers.get_xml_attr(item, 'title'),
|
||||
'parent_title': helpers.get_xml_attr(item, 'parentTitle'),
|
||||
'year': helpers.get_xml_attr(item, 'year'),
|
||||
'thumb': helpers.get_xml_attr(item, 'thumb'),
|
||||
'added_at': helpers.get_xml_attr(item, 'addedAt')
|
||||
|
@@ -186,6 +186,11 @@ class WebInterface(object):
|
||||
keep_history = kwargs.get('keep_history')
|
||||
else:
|
||||
keep_history = 0
|
||||
if 'thumb' in kwargs:
|
||||
custom_avatar = kwargs['thumb']
|
||||
else:
|
||||
custom_avatar = ''
|
||||
|
||||
if user_id:
|
||||
try:
|
||||
data_factory = datafactory.DataFactory()
|
||||
@@ -194,7 +199,7 @@ class WebInterface(object):
|
||||
do_notify=do_notify,
|
||||
keep_history=keep_history)
|
||||
data_factory.set_user_profile_url(user_id=user_id,
|
||||
profile_url=kwargs['thumb'])
|
||||
profile_url=custom_avatar)
|
||||
|
||||
status_message = "Successfully updated user."
|
||||
return status_message
|
||||
@@ -209,7 +214,7 @@ class WebInterface(object):
|
||||
do_notify=do_notify,
|
||||
keep_history=keep_history)
|
||||
data_factory.set_user_profile_url(user=user,
|
||||
profile_url=kwargs['thumb'])
|
||||
profile_url=custom_avatar)
|
||||
|
||||
status_message = "Successfully updated user."
|
||||
return status_message
|
||||
|
Reference in New Issue
Block a user