Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
cea4992331 | ||
![]() |
c98a8865d6 | ||
![]() |
fd3daae491 | ||
![]() |
697d107952 | ||
![]() |
65e42be278 | ||
![]() |
ad79d860db | ||
![]() |
5826a823a8 | ||
![]() |
cbec1e7768 | ||
![]() |
40f72bbe5f |
13
CHANGELOG.md
13
CHANGELOG.md
@@ -22,4 +22,15 @@
|
||||
* 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.
|
||||
|
||||
## v1.1.2 (2015-08-16)
|
||||
|
||||
* Fix bug where user refresh would fail under certain circumstances.
|
@@ -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. To reset to default, leave this field empty and save then perform a user refresh.</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()
|
||||
|
||||
|
@@ -26,63 +26,6 @@ class DataFactory(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def get_user_list(self, kwargs=None):
|
||||
data_tables = datatables.DataTables()
|
||||
|
||||
columns = ['users.user_id as user_id',
|
||||
'users.thumb 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',
|
||||
'session_history.ip_address as ip_address',
|
||||
'COUNT(session_history.id) as plays',
|
||||
'users.username as user'
|
||||
]
|
||||
try:
|
||||
query = data_tables.ssp_query(table_name='users',
|
||||
columns=columns,
|
||||
custom_where=[],
|
||||
group_by=['users.user_id'],
|
||||
join_types=['LEFT OUTER JOIN'],
|
||||
join_tables=['session_history'],
|
||||
join_evals=[['session_history.user_id', 'users.user_id']],
|
||||
kwargs=kwargs)
|
||||
except:
|
||||
logger.warn("Unable to execute database query.")
|
||||
return {'recordsFiltered': 0,
|
||||
'recordsTotal': 0,
|
||||
'draw': 0,
|
||||
'data': 'null',
|
||||
'error': 'Unable to execute database query.'}
|
||||
|
||||
users = query['result']
|
||||
|
||||
rows = []
|
||||
for item in users:
|
||||
if not item['thumb'] or item['thumb'] == '':
|
||||
user_thumb = common.DEFAULT_USER_THUMB
|
||||
else:
|
||||
user_thumb = item['thumb']
|
||||
|
||||
row = {"plays": item['plays'],
|
||||
"last_seen": item['last_seen'],
|
||||
"friendly_name": item["friendly_name"],
|
||||
"ip_address": item["ip_address"],
|
||||
"thumb": user_thumb,
|
||||
"user": item["user"],
|
||||
"user_id": item['user_id']
|
||||
}
|
||||
|
||||
rows.append(row)
|
||||
|
||||
dict = {'recordsFiltered': query['filteredCount'],
|
||||
'recordsTotal': query['totalCount'],
|
||||
'data': rows,
|
||||
'draw': query['draw']
|
||||
}
|
||||
|
||||
return dict
|
||||
|
||||
def get_history(self, kwargs=None, custom_where=None):
|
||||
data_tables = datatables.DataTables()
|
||||
|
||||
@@ -167,312 +110,14 @@ class DataFactory(object):
|
||||
|
||||
return dict
|
||||
|
||||
def get_user_unique_ips(self, kwargs=None, custom_where=None):
|
||||
data_tables = datatables.DataTables()
|
||||
|
||||
columns = ['session_history.started as last_seen',
|
||||
'session_history.ip_address as ip_address',
|
||||
'COUNT(session_history.id) as play_count',
|
||||
'session_history.player as platform',
|
||||
'session_history_metadata.full_title as last_watched',
|
||||
'session_history.user as user',
|
||||
'session_history.user_id as user_id'
|
||||
]
|
||||
|
||||
try:
|
||||
query = data_tables.ssp_query(table_name='session_history',
|
||||
columns=columns,
|
||||
custom_where=custom_where,
|
||||
group_by=['ip_address'],
|
||||
join_types=['JOIN'],
|
||||
join_tables=['session_history_metadata'],
|
||||
join_evals=[['session_history.id', 'session_history_metadata.id']],
|
||||
kwargs=kwargs)
|
||||
except:
|
||||
logger.warn("Unable to execute database query.")
|
||||
return {'recordsFiltered': 0,
|
||||
'recordsTotal': 0,
|
||||
'draw': 0,
|
||||
'data': 'null',
|
||||
'error': 'Unable to execute database query.'}
|
||||
|
||||
results = query['result']
|
||||
|
||||
rows = []
|
||||
for item in results:
|
||||
row = {"last_seen": item['last_seen'],
|
||||
"ip_address": item['ip_address'],
|
||||
"play_count": item['play_count'],
|
||||
"platform": item['platform'],
|
||||
"last_watched": item['last_watched']
|
||||
}
|
||||
|
||||
rows.append(row)
|
||||
|
||||
dict = {'recordsFiltered': query['filteredCount'],
|
||||
'recordsTotal': query['totalCount'],
|
||||
'data': rows,
|
||||
'draw': query['draw']
|
||||
}
|
||||
|
||||
return dict
|
||||
|
||||
# TODO: The getter and setter for this needs to become a config getter/setter for more than just friendlyname
|
||||
def set_user_friendly_name(self, user=None, user_id=None, friendly_name=None, do_notify=0, keep_history=1):
|
||||
if user_id:
|
||||
if friendly_name.strip() == '':
|
||||
friendly_name = None
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
control_value_dict = {"user_id": user_id}
|
||||
new_value_dict = {"friendly_name": friendly_name,
|
||||
"do_notify": do_notify,
|
||||
"keep_history": keep_history}
|
||||
try:
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
except Exception, e:
|
||||
logger.debug(u"Uncaught exception %s" % e)
|
||||
if user:
|
||||
if friendly_name.strip() == '':
|
||||
friendly_name = None
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
control_value_dict = {"username": user}
|
||||
new_value_dict = {"friendly_name": friendly_name,
|
||||
"do_notify": do_notify,
|
||||
"keep_history": keep_history}
|
||||
try:
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
except Exception, e:
|
||||
logger.debug(u"Uncaught exception %s" % e)
|
||||
|
||||
def set_user_profile_url(self, user=None, user_id=None, profile_url=None):
|
||||
if user_id:
|
||||
if profile_url.strip() == '':
|
||||
profile_url = None
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
control_value_dict = {"user_id": user_id}
|
||||
new_value_dict = {"thumb": profile_url}
|
||||
try:
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
except Exception, e:
|
||||
logger.debug(u"Uncaught exception %s" % e)
|
||||
if user:
|
||||
if profile_url.strip() == '':
|
||||
profile_url = None
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
control_value_dict = {"username": user}
|
||||
new_value_dict = {"thumb": profile_url}
|
||||
try:
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
except Exception, e:
|
||||
logger.debug(u"Uncaught exception %s" % e)
|
||||
|
||||
def get_user_friendly_name(self, user=None, user_id=None):
|
||||
if user_id:
|
||||
monitor_db = database.MonitorDatabase()
|
||||
query = 'select username, ' \
|
||||
'(CASE WHEN friendly_name IS NULL THEN username ELSE friendly_name END),' \
|
||||
'do_notify, keep_history, thumb ' \
|
||||
'FROM users WHERE user_id = ?'
|
||||
result = monitor_db.select(query, args=[user_id])
|
||||
if result:
|
||||
user_detail = {'user_id': user_id,
|
||||
'user': result[0][0],
|
||||
'friendly_name': result[0][1],
|
||||
'thumb': result[0][4],
|
||||
'do_notify': helpers.checked(result[0][2]),
|
||||
'keep_history': helpers.checked(result[0][3])
|
||||
}
|
||||
return user_detail
|
||||
else:
|
||||
user_detail = {'user_id': user_id,
|
||||
'user': '',
|
||||
'friendly_name': '',
|
||||
'do_notify': '',
|
||||
'thumb': '',
|
||||
'keep_history': ''}
|
||||
return user_detail
|
||||
elif user:
|
||||
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 ' \
|
||||
'FROM users WHERE username = ?'
|
||||
result = monitor_db.select(query, args=[user])
|
||||
if result:
|
||||
user_detail = {'user_id': result[0][0],
|
||||
'user': user,
|
||||
'friendly_name': result[0][1],
|
||||
'thumb': result[0][4],
|
||||
'do_notify': helpers.checked(result[0][2]),
|
||||
'keep_history': helpers.checked(result[0][3])}
|
||||
return user_detail
|
||||
else:
|
||||
user_detail = {'user_id': None,
|
||||
'user': user,
|
||||
'friendly_name': '',
|
||||
'do_notify': '',
|
||||
'thumb': '',
|
||||
'keep_history': ''}
|
||||
return user_detail
|
||||
|
||||
return None
|
||||
|
||||
def get_user_id(self, user=None):
|
||||
if user:
|
||||
try:
|
||||
monitor_db = database.MonitorDatabase()
|
||||
query = 'select user_id FROM users WHERE username = ?'
|
||||
result = monitor_db.select_single(query, args=[user])
|
||||
if result:
|
||||
return result
|
||||
else:
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
def get_user_details(self, user=None, user_id=None):
|
||||
from plexpy import plextv
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
if user:
|
||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
||||
'thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'FROM users ' \
|
||||
'WHERE username = ? ' \
|
||||
'UNION ALL ' \
|
||||
'SELECT null, user, null, null, null, null, null, null, null ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user = ? ' \
|
||||
'GROUP BY user ' \
|
||||
'LIMIT 1'
|
||||
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 ' \
|
||||
'FROM users ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'UNION ALL ' \
|
||||
'SELECT user_id, user, null, null, null, null, null, null, null ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'GROUP BY user ' \
|
||||
'LIMIT 1'
|
||||
result = monitor_db.select(query, args=[user_id, user_id])
|
||||
else:
|
||||
result = None
|
||||
|
||||
if result:
|
||||
user_details = {}
|
||||
for item in result:
|
||||
if not item['friendly_name']:
|
||||
friendly_name = item['username']
|
||||
else:
|
||||
friendly_name = item['friendly_name']
|
||||
if not item['thumb'] or item['thumb'] == '':
|
||||
user_thumb = common.DEFAULT_USER_THUMB
|
||||
else:
|
||||
user_thumb = item['thumb']
|
||||
|
||||
user_details = {"user_id": item['user_id'],
|
||||
"username": item['username'],
|
||||
"friendly_name": friendly_name,
|
||||
"email": item['email'],
|
||||
"thumb": user_thumb,
|
||||
"is_home_user": item['is_home_user'],
|
||||
"is_allow_sync": item['is_allow_sync'],
|
||||
"is_restricted": item['is_restricted'],
|
||||
"do_notify": item['do_notify']
|
||||
}
|
||||
return user_details
|
||||
else:
|
||||
logger.warn(u"PlexPy :: Unable to retrieve user from local database. Requesting user list refresh.")
|
||||
# Let's first refresh the user list to make sure the user isn't newly added and not in the db yet
|
||||
if user:
|
||||
# Refresh users
|
||||
plextv.refresh_users()
|
||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
||||
'thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'FROM users ' \
|
||||
'WHERE username = ? ' \
|
||||
'UNION ALL ' \
|
||||
'SELECT null, user, null, null, null, null, null, null, null ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user = ? ' \
|
||||
'GROUP BY user ' \
|
||||
'LIMIT 1'
|
||||
result = monitor_db.select(query, args=[user, user])
|
||||
elif user_id:
|
||||
# Refresh users
|
||||
plextv.refresh_users()
|
||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
||||
'thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'FROM users ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'UNION ALL ' \
|
||||
'SELECT user_id, user, null, null, null, null, null, null, null ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'GROUP BY user ' \
|
||||
'LIMIT 1'
|
||||
result = monitor_db.select(query, args=[user_id, user_id])
|
||||
else:
|
||||
result = None
|
||||
|
||||
if result:
|
||||
user_details = {}
|
||||
for item in result:
|
||||
if not item['friendly_name']:
|
||||
friendly_name = item['username']
|
||||
else:
|
||||
friendly_name = item['friendly_name']
|
||||
if not item['thumb'] or item['thumb'] == '':
|
||||
user_thumb = common.DEFAULT_USER_THUMB
|
||||
else:
|
||||
user_thumb = item['thumb']
|
||||
|
||||
user_details = {"user_id": item['user_id'],
|
||||
"username": item['username'],
|
||||
"friendly_name": friendly_name,
|
||||
"email": item['email'],
|
||||
"thumb": user_thumb,
|
||||
"is_home_user": item['is_home_user'],
|
||||
"is_allow_sync": item['is_allow_sync'],
|
||||
"is_restricted": item['is_restricted'],
|
||||
"do_notify": item['do_notify']
|
||||
}
|
||||
return user_details
|
||||
else:
|
||||
# If there is no user data we must return something
|
||||
# Use "Local" user to retain compatibility with PlexWatch database value
|
||||
return {"user_id": None,
|
||||
"username": 'Local',
|
||||
"friendly_name": 'Local',
|
||||
"email": '',
|
||||
"thumb": '',
|
||||
"is_home_user": 0,
|
||||
"is_allow_sync": 0,
|
||||
"is_restricted": 0,
|
||||
"do_notify": 0
|
||||
}
|
||||
|
||||
def get_home_stats(self, time_range='30'):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
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 +161,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 +251,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 ' \
|
||||
@@ -740,91 +425,6 @@ class DataFactory(object):
|
||||
|
||||
return recently_watched
|
||||
|
||||
def get_user_watch_time_stats(self, user=None, user_id=None):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
time_queries = [1, 7, 30, 0]
|
||||
user_watch_time_stats = []
|
||||
|
||||
for days in time_queries:
|
||||
if days > 0:
|
||||
if user_id:
|
||||
query = 'SELECT (SUM(stopped - started) - ' \
|
||||
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
||||
'COUNT(id) AS total_plays ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||
'AND user_id = ?' % days
|
||||
result = monitor_db.select(query, args=[user_id])
|
||||
elif user:
|
||||
query = 'SELECT (SUM(stopped - started) - ' \
|
||||
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
||||
'COUNT(id) AS total_plays ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||
'AND user = ?' % days
|
||||
result = monitor_db.select(query, args=[user])
|
||||
else:
|
||||
query = 'SELECT (SUM(stopped - started) - ' \
|
||||
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
||||
'COUNT(id) AS total_plays ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user = ?'
|
||||
result = monitor_db.select(query, args=[user])
|
||||
|
||||
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
|
||||
|
||||
def get_user_platform_stats(self, user=None, user_id=None):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
platform_stats = []
|
||||
result_id = 0
|
||||
|
||||
try:
|
||||
if user_id:
|
||||
query = 'SELECT player, COUNT(player) as player_count, platform ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'GROUP BY player ' \
|
||||
'ORDER BY player_count DESC'
|
||||
result = monitor_db.select(query, args=[user_id])
|
||||
else:
|
||||
query = 'SELECT player, COUNT(player) as player_count, platform ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user = ? ' \
|
||||
'GROUP BY player ' \
|
||||
'ORDER BY player_count DESC'
|
||||
result = monitor_db.select(query, args=[user])
|
||||
except:
|
||||
logger.warn("Unable to execute database query.")
|
||||
return None
|
||||
|
||||
for item in result:
|
||||
row = {'platform_name': item[0],
|
||||
'platform_type': item[2],
|
||||
'total_plays': item[1],
|
||||
'result_id': result_id
|
||||
}
|
||||
platform_stats.append(row)
|
||||
result_id += 1
|
||||
|
||||
return platform_stats
|
||||
|
||||
def get_metadata_details(self, row_id):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
|
@@ -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()
|
||||
|
||||
@@ -225,10 +231,10 @@ class MonitorProcessing(object):
|
||||
self.db.upsert('sessions', timestamp, keys)
|
||||
|
||||
def write_session_history(self, session=None, import_metadata=None, is_import=False, import_ignore_interval=0):
|
||||
from plexpy import datafactory
|
||||
from plexpy import users
|
||||
|
||||
data_factory = datafactory.DataFactory()
|
||||
user_details = data_factory.get_user_friendly_name(user=session['user'])
|
||||
user_data = users.Users()
|
||||
user_details = user_data.get_user_friendly_name(user=session['user'])
|
||||
|
||||
if session:
|
||||
logging_enabled = False
|
||||
|
@@ -20,12 +20,12 @@ import time
|
||||
|
||||
|
||||
def notify(stream_data=None, notify_action=None):
|
||||
from plexpy import datafactory
|
||||
from plexpy import users
|
||||
|
||||
if stream_data and notify_action:
|
||||
# Check if notifications enabled for user
|
||||
data_factory = datafactory.DataFactory()
|
||||
user_details = data_factory.get_user_friendly_name(user=stream_data['user'])
|
||||
user_data = users.Users()
|
||||
user_details = user_data.get_user_friendly_name(user=stream_data['user'])
|
||||
|
||||
if not user_details['do_notify']:
|
||||
return
|
||||
|
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from plexpy import logger, helpers, datafactory, http_handler, database
|
||||
from plexpy import logger, helpers, users, http_handler, database
|
||||
|
||||
from xml.dom import minidom
|
||||
|
||||
@@ -37,6 +37,18 @@ def refresh_users():
|
||||
"is_restricted": item['is_restricted']
|
||||
}
|
||||
|
||||
# Check if we've set a custom avatar if so don't overwrite it.
|
||||
if item['user_id']:
|
||||
avatar_urls = monitor_db.select('SELECT thumb, custom_avatar_url '
|
||||
'FROM users WHERE user_id = ?',
|
||||
[item['user_id']])
|
||||
if avatar_urls:
|
||||
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']
|
||||
else:
|
||||
new_value_dict['custom_avatar_url'] = item['thumb']
|
||||
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
|
||||
logger.info("Users list refreshed.")
|
||||
@@ -244,7 +256,7 @@ class PlexTV(object):
|
||||
|
||||
def get_synced_items(self, machine_id=None, user_id=None):
|
||||
sync_list = self.get_plextv_sync_lists(machine_id)
|
||||
data_factory = datafactory.DataFactory()
|
||||
user_data = users.Users()
|
||||
|
||||
synced_items = []
|
||||
|
||||
@@ -268,8 +280,8 @@ class PlexTV(object):
|
||||
for device in sync_device:
|
||||
device_user_id = helpers.get_xml_attr(device, 'userID')
|
||||
try:
|
||||
device_username = data_factory.get_user_details(user_id=device_user_id)['username']
|
||||
device_friendly_name = data_factory.get_user_details(user_id=device_user_id)['friendly_name']
|
||||
device_username = user_data.get_user_details(user_id=device_user_id)['username']
|
||||
device_friendly_name = user_data.get_user_details(user_id=device_user_id)['friendly_name']
|
||||
except:
|
||||
device_username = ''
|
||||
device_friendly_name = ''
|
||||
|
@@ -15,7 +15,7 @@
|
||||
|
||||
import sqlite3
|
||||
|
||||
from plexpy import logger, helpers, monitor, datafactory, plextv
|
||||
from plexpy import logger, helpers, monitor, users, plextv
|
||||
from xml.dom import minidom
|
||||
|
||||
import plexpy
|
||||
@@ -246,7 +246,7 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
|
||||
plexpy.schedule_job(monitor.check_active_sessions, 'Check for active sessions', hours=0, minutes=0, seconds=0)
|
||||
|
||||
monitor_processing = monitor.MonitorProcessing()
|
||||
data_factory = datafactory.DataFactory()
|
||||
user_data = users.Users()
|
||||
|
||||
# Get the latest friends list so we can pull user id's
|
||||
try:
|
||||
@@ -292,8 +292,8 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
|
||||
continue
|
||||
|
||||
# If the user_id no longer exists in the friends list, pull it from the xml.
|
||||
if data_factory.get_user_id(user=row['user']):
|
||||
user_id = data_factory.get_user_id(user=row['user'])
|
||||
if user_data.get_user_id(user=row['user']):
|
||||
user_id = user_data.get_user_id(user=row['user'])
|
||||
else:
|
||||
user_id = extracted_xml['user_id']
|
||||
|
||||
|
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from plexpy import logger, helpers, datafactory, http_handler
|
||||
from plexpy import logger, helpers, users, http_handler
|
||||
from urlparse import urlparse
|
||||
|
||||
import plexpy
|
||||
@@ -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')
|
||||
@@ -505,7 +507,7 @@ class PmsConnect(object):
|
||||
"""
|
||||
def get_session_each(self, stream_type='', session=None):
|
||||
session_output = None
|
||||
data_factory = datafactory.DataFactory()
|
||||
user_data = users.Users()
|
||||
if stream_type == 'track':
|
||||
|
||||
media_info = session.getElementsByTagName('Media')[0]
|
||||
@@ -531,7 +533,7 @@ class PmsConnect(object):
|
||||
transcode_container = ''
|
||||
transcode_protocol = ''
|
||||
|
||||
user_details = data_factory.get_user_details(
|
||||
user_details = user_data.get_user_details(
|
||||
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
|
||||
|
||||
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Track'):
|
||||
@@ -639,7 +641,7 @@ class PmsConnect(object):
|
||||
else:
|
||||
use_indexes = 0
|
||||
|
||||
user_details = data_factory.get_user_details(
|
||||
user_details = user_data.get_user_details(
|
||||
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
|
||||
|
||||
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Video'):
|
||||
|
463
plexpy/users.py
Normal file
463
plexpy/users.py
Normal file
@@ -0,0 +1,463 @@
|
||||
# This file is part of PlexPy.
|
||||
#
|
||||
# PlexPy is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# PlexPy is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from plexpy import logger, datatables, common, database, helpers
|
||||
|
||||
|
||||
class Users(object):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def get_user_list(self, kwargs=None):
|
||||
data_tables = datatables.DataTables()
|
||||
|
||||
columns = ['users.user_id as user_id',
|
||||
'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',
|
||||
'session_history.ip_address as ip_address',
|
||||
'COUNT(session_history.id) as plays',
|
||||
'users.username as user'
|
||||
]
|
||||
try:
|
||||
query = data_tables.ssp_query(table_name='users',
|
||||
columns=columns,
|
||||
custom_where=[],
|
||||
group_by=['users.user_id'],
|
||||
join_types=['LEFT OUTER JOIN'],
|
||||
join_tables=['session_history'],
|
||||
join_evals=[['session_history.user_id', 'users.user_id']],
|
||||
kwargs=kwargs)
|
||||
except:
|
||||
logger.warn("Unable to execute database query.")
|
||||
return {'recordsFiltered': 0,
|
||||
'recordsTotal': 0,
|
||||
'draw': 0,
|
||||
'data': 'null',
|
||||
'error': 'Unable to execute database query.'}
|
||||
|
||||
users = query['result']
|
||||
|
||||
rows = []
|
||||
for item in users:
|
||||
if not item['thumb'] or item['thumb'] == '':
|
||||
user_thumb = common.DEFAULT_USER_THUMB
|
||||
else:
|
||||
user_thumb = item['thumb']
|
||||
|
||||
row = {"plays": item['plays'],
|
||||
"last_seen": item['last_seen'],
|
||||
"friendly_name": item["friendly_name"],
|
||||
"ip_address": item["ip_address"],
|
||||
"thumb": user_thumb,
|
||||
"user": item["user"],
|
||||
"user_id": item['user_id']
|
||||
}
|
||||
|
||||
rows.append(row)
|
||||
|
||||
dict = {'recordsFiltered': query['filteredCount'],
|
||||
'recordsTotal': query['totalCount'],
|
||||
'data': rows,
|
||||
'draw': query['draw']
|
||||
}
|
||||
|
||||
return dict
|
||||
|
||||
def get_user_unique_ips(self, kwargs=None, custom_where=None):
|
||||
data_tables = datatables.DataTables()
|
||||
|
||||
columns = ['session_history.started as last_seen',
|
||||
'session_history.ip_address as ip_address',
|
||||
'COUNT(session_history.id) as play_count',
|
||||
'session_history.player as platform',
|
||||
'session_history_metadata.full_title as last_watched',
|
||||
'session_history.user as user',
|
||||
'session_history.user_id as user_id'
|
||||
]
|
||||
|
||||
try:
|
||||
query = data_tables.ssp_query(table_name='session_history',
|
||||
columns=columns,
|
||||
custom_where=custom_where,
|
||||
group_by=['ip_address'],
|
||||
join_types=['JOIN'],
|
||||
join_tables=['session_history_metadata'],
|
||||
join_evals=[['session_history.id', 'session_history_metadata.id']],
|
||||
kwargs=kwargs)
|
||||
except:
|
||||
logger.warn("Unable to execute database query.")
|
||||
return {'recordsFiltered': 0,
|
||||
'recordsTotal': 0,
|
||||
'draw': 0,
|
||||
'data': 'null',
|
||||
'error': 'Unable to execute database query.'}
|
||||
|
||||
results = query['result']
|
||||
|
||||
rows = []
|
||||
for item in results:
|
||||
row = {"last_seen": item['last_seen'],
|
||||
"ip_address": item['ip_address'],
|
||||
"play_count": item['play_count'],
|
||||
"platform": item['platform'],
|
||||
"last_watched": item['last_watched']
|
||||
}
|
||||
|
||||
rows.append(row)
|
||||
|
||||
dict = {'recordsFiltered': query['filteredCount'],
|
||||
'recordsTotal': query['totalCount'],
|
||||
'data': rows,
|
||||
'draw': query['draw']
|
||||
}
|
||||
|
||||
return dict
|
||||
|
||||
# TODO: The getter and setter for this needs to become a config getter/setter for more than just friendlyname
|
||||
def set_user_friendly_name(self, user=None, user_id=None, friendly_name=None, do_notify=0, keep_history=1):
|
||||
if user_id:
|
||||
if friendly_name.strip() == '':
|
||||
friendly_name = None
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
control_value_dict = {"user_id": user_id}
|
||||
new_value_dict = {"friendly_name": friendly_name,
|
||||
"do_notify": do_notify,
|
||||
"keep_history": keep_history}
|
||||
try:
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
except Exception, e:
|
||||
logger.debug(u"Uncaught exception %s" % e)
|
||||
if user:
|
||||
if friendly_name.strip() == '':
|
||||
friendly_name = None
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
control_value_dict = {"username": user}
|
||||
new_value_dict = {"friendly_name": friendly_name,
|
||||
"do_notify": do_notify,
|
||||
"keep_history": keep_history}
|
||||
try:
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
except Exception, e:
|
||||
logger.debug(u"Uncaught exception %s" % e)
|
||||
|
||||
def set_user_profile_url(self, user=None, user_id=None, profile_url=None):
|
||||
if user_id:
|
||||
if profile_url.strip() == '':
|
||||
profile_url = None
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
control_value_dict = {"user_id": user_id}
|
||||
new_value_dict = {"custom_avatar_url": profile_url}
|
||||
try:
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
except Exception, e:
|
||||
logger.debug(u"Uncaught exception %s" % e)
|
||||
if user:
|
||||
if profile_url.strip() == '':
|
||||
profile_url = None
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
control_value_dict = {"username": user}
|
||||
new_value_dict = {"custom_avatar_url": profile_url}
|
||||
try:
|
||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||
except Exception, e:
|
||||
logger.debug(u"Uncaught exception %s" % e)
|
||||
|
||||
def get_user_friendly_name(self, user=None, user_id=None):
|
||||
if user_id:
|
||||
monitor_db = database.MonitorDatabase()
|
||||
query = 'select username, ' \
|
||||
'(CASE WHEN friendly_name IS NULL THEN username ELSE friendly_name END),' \
|
||||
'do_notify, keep_history, custom_avatar_url as thumb ' \
|
||||
'FROM users WHERE user_id = ?'
|
||||
result = monitor_db.select(query, args=[user_id])
|
||||
if result:
|
||||
user_detail = {'user_id': user_id,
|
||||
'user': result[0][0],
|
||||
'friendly_name': result[0][1],
|
||||
'thumb': result[0][4],
|
||||
'do_notify': helpers.checked(result[0][2]),
|
||||
'keep_history': helpers.checked(result[0][3])
|
||||
}
|
||||
return user_detail
|
||||
else:
|
||||
user_detail = {'user_id': user_id,
|
||||
'user': '',
|
||||
'friendly_name': '',
|
||||
'do_notify': '',
|
||||
'thumb': '',
|
||||
'keep_history': ''}
|
||||
return user_detail
|
||||
elif user:
|
||||
monitor_db = database.MonitorDatabase()
|
||||
query = 'select user_id, ' \
|
||||
'(CASE WHEN friendly_name IS NULL THEN username ELSE friendly_name END),' \
|
||||
'do_notify, keep_history, custom_avatar_url as thumb ' \
|
||||
'FROM users WHERE username = ?'
|
||||
result = monitor_db.select(query, args=[user])
|
||||
if result:
|
||||
user_detail = {'user_id': result[0][0],
|
||||
'user': user,
|
||||
'friendly_name': result[0][1],
|
||||
'thumb': result[0][4],
|
||||
'do_notify': helpers.checked(result[0][2]),
|
||||
'keep_history': helpers.checked(result[0][3])}
|
||||
return user_detail
|
||||
else:
|
||||
user_detail = {'user_id': None,
|
||||
'user': user,
|
||||
'friendly_name': '',
|
||||
'do_notify': '',
|
||||
'thumb': '',
|
||||
'keep_history': ''}
|
||||
return user_detail
|
||||
|
||||
return None
|
||||
|
||||
def get_user_id(self, user=None):
|
||||
if user:
|
||||
try:
|
||||
monitor_db = database.MonitorDatabase()
|
||||
query = 'select user_id FROM users WHERE username = ?'
|
||||
result = monitor_db.select_single(query, args=[user])
|
||||
if result:
|
||||
return result
|
||||
else:
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
def get_user_details(self, user=None, user_id=None):
|
||||
from plexpy import plextv
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
if user:
|
||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
||||
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'FROM users ' \
|
||||
'WHERE username = ? ' \
|
||||
'UNION ALL ' \
|
||||
'SELECT null, user, null, null, null, null, null, null, null ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user = ? ' \
|
||||
'GROUP BY user ' \
|
||||
'LIMIT 1'
|
||||
result = monitor_db.select(query, args=[user, user])
|
||||
elif user_id:
|
||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
||||
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'FROM users ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'UNION ALL ' \
|
||||
'SELECT user_id, user, null, null, null, null, null, null, null ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'GROUP BY user ' \
|
||||
'LIMIT 1'
|
||||
result = monitor_db.select(query, args=[user_id, user_id])
|
||||
else:
|
||||
result = None
|
||||
|
||||
if result:
|
||||
user_details = {}
|
||||
for item in result:
|
||||
if not item['friendly_name']:
|
||||
friendly_name = item['username']
|
||||
else:
|
||||
friendly_name = item['friendly_name']
|
||||
if not item['thumb'] or item['thumb'] == '':
|
||||
user_thumb = common.DEFAULT_USER_THUMB
|
||||
else:
|
||||
user_thumb = item['thumb']
|
||||
|
||||
user_details = {"user_id": item['user_id'],
|
||||
"username": item['username'],
|
||||
"friendly_name": friendly_name,
|
||||
"email": item['email'],
|
||||
"thumb": user_thumb,
|
||||
"is_home_user": item['is_home_user'],
|
||||
"is_allow_sync": item['is_allow_sync'],
|
||||
"is_restricted": item['is_restricted'],
|
||||
"do_notify": item['do_notify']
|
||||
}
|
||||
return user_details
|
||||
else:
|
||||
logger.warn(u"PlexPy :: Unable to retrieve user from local database. Requesting user list refresh.")
|
||||
# Let's first refresh the user list to make sure the user isn't newly added and not in the db yet
|
||||
if user:
|
||||
# Refresh users
|
||||
plextv.refresh_users()
|
||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
||||
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'FROM users ' \
|
||||
'WHERE username = ? ' \
|
||||
'UNION ALL ' \
|
||||
'SELECT null, user, null, null, null, null, null, null, null ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user = ? ' \
|
||||
'GROUP BY user ' \
|
||||
'LIMIT 1'
|
||||
result = monitor_db.select(query, args=[user, user])
|
||||
elif user_id:
|
||||
# Refresh users
|
||||
plextv.refresh_users()
|
||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
||||
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
||||
'FROM users ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'UNION ALL ' \
|
||||
'SELECT user_id, user, null, null, null, null, null, null, null ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'GROUP BY user ' \
|
||||
'LIMIT 1'
|
||||
result = monitor_db.select(query, args=[user_id, user_id])
|
||||
else:
|
||||
result = None
|
||||
|
||||
if result:
|
||||
user_details = {}
|
||||
for item in result:
|
||||
if not item['friendly_name']:
|
||||
friendly_name = item['username']
|
||||
else:
|
||||
friendly_name = item['friendly_name']
|
||||
if not item['thumb'] or item['thumb'] == '':
|
||||
user_thumb = common.DEFAULT_USER_THUMB
|
||||
else:
|
||||
user_thumb = item['thumb']
|
||||
|
||||
user_details = {"user_id": item['user_id'],
|
||||
"username": item['username'],
|
||||
"friendly_name": friendly_name,
|
||||
"email": item['email'],
|
||||
"thumb": user_thumb,
|
||||
"is_home_user": item['is_home_user'],
|
||||
"is_allow_sync": item['is_allow_sync'],
|
||||
"is_restricted": item['is_restricted'],
|
||||
"do_notify": item['do_notify']
|
||||
}
|
||||
return user_details
|
||||
else:
|
||||
# If there is no user data we must return something
|
||||
# Use "Local" user to retain compatibility with PlexWatch database value
|
||||
return {"user_id": None,
|
||||
"username": 'Local',
|
||||
"friendly_name": 'Local',
|
||||
"email": '',
|
||||
"thumb": '',
|
||||
"is_home_user": 0,
|
||||
"is_allow_sync": 0,
|
||||
"is_restricted": 0,
|
||||
"do_notify": 0
|
||||
}
|
||||
|
||||
def get_user_watch_time_stats(self, user=None, user_id=None):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
time_queries = [1, 7, 30, 0]
|
||||
user_watch_time_stats = []
|
||||
|
||||
for days in time_queries:
|
||||
if days > 0:
|
||||
if user_id:
|
||||
query = 'SELECT (SUM(stopped - started) - ' \
|
||||
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
||||
'COUNT(id) AS total_plays ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||
'AND user_id = ?' % days
|
||||
result = monitor_db.select(query, args=[user_id])
|
||||
elif user:
|
||||
query = 'SELECT (SUM(stopped - started) - ' \
|
||||
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
||||
'COUNT(id) AS total_plays ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||
'AND user = ?' % days
|
||||
result = monitor_db.select(query, args=[user])
|
||||
else:
|
||||
query = 'SELECT (SUM(stopped - started) - ' \
|
||||
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
||||
'COUNT(id) AS total_plays ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user = ?'
|
||||
result = monitor_db.select(query, args=[user])
|
||||
|
||||
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
|
||||
|
||||
def get_user_platform_stats(self, user=None, user_id=None):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
platform_stats = []
|
||||
result_id = 0
|
||||
|
||||
try:
|
||||
if user_id:
|
||||
query = 'SELECT player, COUNT(player) as player_count, platform ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user_id = ? ' \
|
||||
'GROUP BY player ' \
|
||||
'ORDER BY player_count DESC'
|
||||
result = monitor_db.select(query, args=[user_id])
|
||||
else:
|
||||
query = 'SELECT player, COUNT(player) as player_count, platform ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE user = ? ' \
|
||||
'GROUP BY player ' \
|
||||
'ORDER BY player_count DESC'
|
||||
result = monitor_db.select(query, args=[user])
|
||||
except:
|
||||
logger.warn("Unable to execute database query.")
|
||||
return None
|
||||
|
||||
for item in result:
|
||||
row = {'platform_name': item[0],
|
||||
'platform_type': item[2],
|
||||
'total_plays': item[1],
|
||||
'result_id': result_id
|
||||
}
|
||||
platform_stats.append(row)
|
||||
result_id += 1
|
||||
|
||||
return platform_stats
|
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from plexpy import logger, notifiers, plextv, pmsconnect, common, log_reader, datafactory, graphs
|
||||
from plexpy import logger, notifiers, plextv, pmsconnect, common, log_reader, datafactory, graphs, users
|
||||
from plexpy.helpers import checked, radio
|
||||
|
||||
from mako.lookup import TemplateLookup
|
||||
@@ -142,16 +142,15 @@ class WebInterface(object):
|
||||
|
||||
@cherrypy.expose
|
||||
def user(self, user=None, user_id=None):
|
||||
user_data = users.Users()
|
||||
if user_id:
|
||||
try:
|
||||
data_factory = datafactory.DataFactory()
|
||||
user_details = data_factory.get_user_details(user_id=user_id)
|
||||
user_details = user_data.get_user_details(user_id=user_id)
|
||||
except:
|
||||
logger.warn("Unable to retrieve friendly name for user_id %s " % user_id)
|
||||
elif user:
|
||||
try:
|
||||
data_factory = datafactory.DataFactory()
|
||||
user_details = data_factory.get_user_details(user=user)
|
||||
user_details = user_data.get_user_details(user=user)
|
||||
except:
|
||||
logger.warn("Unable to retrieve friendly name for user %s " % user)
|
||||
else:
|
||||
@@ -162,13 +161,12 @@ class WebInterface(object):
|
||||
|
||||
@cherrypy.expose
|
||||
def edit_user_dialog(self, user=None, user_id=None, **kwargs):
|
||||
user_data = users.Users()
|
||||
if user_id:
|
||||
data_factory = datafactory.DataFactory()
|
||||
result = data_factory.get_user_friendly_name(user_id=user_id)
|
||||
result = user_data.get_user_friendly_name(user_id=user_id)
|
||||
status_message = ''
|
||||
elif user:
|
||||
data_factory = datafactory.DataFactory()
|
||||
result = data_factory.get_user_friendly_name(user=user)
|
||||
result = user_data.get_user_friendly_name(user=user)
|
||||
status_message = ''
|
||||
else:
|
||||
result = None
|
||||
@@ -186,15 +184,20 @@ class WebInterface(object):
|
||||
keep_history = kwargs.get('keep_history')
|
||||
else:
|
||||
keep_history = 0
|
||||
if 'thumb' in kwargs:
|
||||
custom_avatar = kwargs['thumb']
|
||||
else:
|
||||
custom_avatar = ''
|
||||
|
||||
user_data = users.Users()
|
||||
if user_id:
|
||||
try:
|
||||
data_factory = datafactory.DataFactory()
|
||||
data_factory.set_user_friendly_name(user_id=user_id,
|
||||
friendly_name=friendly_name,
|
||||
do_notify=do_notify,
|
||||
keep_history=keep_history)
|
||||
data_factory.set_user_profile_url(user_id=user_id,
|
||||
profile_url=kwargs['thumb'])
|
||||
user_data.set_user_friendly_name(user_id=user_id,
|
||||
friendly_name=friendly_name,
|
||||
do_notify=do_notify,
|
||||
keep_history=keep_history)
|
||||
user_data.set_user_profile_url(user_id=user_id,
|
||||
profile_url=custom_avatar)
|
||||
|
||||
status_message = "Successfully updated user."
|
||||
return status_message
|
||||
@@ -203,13 +206,12 @@ class WebInterface(object):
|
||||
return status_message
|
||||
if user:
|
||||
try:
|
||||
data_factory = datafactory.DataFactory()
|
||||
data_factory.set_user_friendly_name(user=user,
|
||||
friendly_name=friendly_name,
|
||||
do_notify=do_notify,
|
||||
keep_history=keep_history)
|
||||
data_factory.set_user_profile_url(user=user,
|
||||
profile_url=kwargs['thumb'])
|
||||
user_data.set_user_friendly_name(user=user,
|
||||
friendly_name=friendly_name,
|
||||
do_notify=do_notify,
|
||||
keep_history=keep_history)
|
||||
user_data.set_user_profile_url(user=user,
|
||||
profile_url=custom_avatar)
|
||||
|
||||
status_message = "Successfully updated user."
|
||||
return status_message
|
||||
@@ -239,11 +241,11 @@ class WebInterface(object):
|
||||
@cherrypy.expose
|
||||
def get_user_list(self, **kwargs):
|
||||
|
||||
data_factory = datafactory.DataFactory()
|
||||
users = data_factory.get_user_list(kwargs=kwargs)
|
||||
user_data = users.Users()
|
||||
user_list = user_data.get_user_list(kwargs=kwargs)
|
||||
|
||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||
return json.dumps(users)
|
||||
return json.dumps(user_list)
|
||||
|
||||
@cherrypy.expose
|
||||
def checkGithub(self):
|
||||
@@ -758,8 +760,8 @@ class WebInterface(object):
|
||||
@cherrypy.expose
|
||||
def get_user_watch_time_stats(self, user=None, user_id=None, **kwargs):
|
||||
|
||||
data_factory = datafactory.DataFactory()
|
||||
result = data_factory.get_user_watch_time_stats(user_id=user_id, user=user)
|
||||
user_data = users.Users()
|
||||
result = user_data.get_user_watch_time_stats(user_id=user_id, user=user)
|
||||
|
||||
if result:
|
||||
return serve_template(templatename="user_watch_time_stats.html", data=result, title="Watch Stats")
|
||||
@@ -770,8 +772,8 @@ class WebInterface(object):
|
||||
@cherrypy.expose
|
||||
def get_user_platform_stats(self, user=None, user_id=None, **kwargs):
|
||||
|
||||
data_factory = datafactory.DataFactory()
|
||||
result = data_factory.get_user_platform_stats(user_id=user_id, user=user)
|
||||
user_data = users.Users()
|
||||
result = user_data.get_user_platform_stats(user_id=user_id, user=user)
|
||||
|
||||
if result:
|
||||
return serve_template(templatename="user_platform_stats.html", data=result,
|
||||
@@ -849,9 +851,9 @@ class WebInterface(object):
|
||||
elif user:
|
||||
custom_where = [['user', user]]
|
||||
|
||||
data_factory = datafactory.DataFactory()
|
||||
history = data_factory.get_user_unique_ips(kwargs=kwargs,
|
||||
custom_where=custom_where)
|
||||
user_data = users.Users()
|
||||
history = user_data.get_user_unique_ips(kwargs=kwargs,
|
||||
custom_where=custom_where)
|
||||
|
||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||
return json.dumps(history)
|
||||
|
Reference in New Issue
Block a user