Compare commits

..

11 Commits

Author SHA1 Message Date
JonnyWong16
08714436c3 v2.1.34 2019-09-03 21:46:48 -07:00
JonnyWong16
f65f5d07c0 Add product to get_history API command 2019-09-03 19:52:54 -07:00
JonnyWong16
a9b10c4560 Add Product column to history tables 2019-09-03 19:52:33 -07:00
JonnyWong16
589fbd3158 Add TVMaze and TMDB IDs to notification parameters after lookup 2019-08-27 19:54:54 -07:00
JonnyWong16
0ffc8c5d19 Update JWT secret instead of UUID 2019-08-24 22:00:31 -07:00
JonnyWong16
7498617b74 Flag update JWT UUID after restarting 2019-08-24 21:13:39 -07:00
JonnyWong16
f21d505ab8 Force logout all clients when changing the admin password 2019-08-24 20:49:56 -07:00
JonnyWong16
7b16af0585 Fix verifying PMS with unpublished hostnames (Fixes Tautulli/Tautulli-Issues#190) 2019-08-16 21:27:34 -07:00
JonnyWong16
a83108282a Fix add title to searchable media info fields 2019-08-14 22:50:23 -07:00
JonnyWong16
1c4d01d6ec Fix libraries/users table respect grouping setting 2019-08-09 19:15:53 -07:00
JonnyWong16
22e6d4067d Missing space for episode titles on tables 2019-08-09 19:01:27 -07:00
20 changed files with 112 additions and 46 deletions

7
API.md
View File

@@ -700,8 +700,9 @@ Returns:
"parent_title": "", "parent_title": "",
"paused_counter": 0, "paused_counter": 0,
"percent_complete": 84, "percent_complete": 84,
"platform": "Chrome", "platform": "Windows",
"player": "Plex Web (Chrome)", "product": "Plex for Windows",
"player": "Castle-PC",
"rating_key": 4348, "rating_key": 4348,
"reference_id": 1123, "reference_id": 1123,
"session_key": null, "session_key": null,
@@ -833,6 +834,7 @@ Required parameters:
None None
Optional parameters: Optional parameters:
grouping (int): 0 or 1
order_column (str): "library_thumb", "section_name", "section_type", "count", "parent_count", order_column (str): "library_thumb", "section_name", "section_type", "count", "parent_count",
"child_count", "last_accessed", "last_played", "plays", "duration" "child_count", "last_accessed", "last_played", "plays", "duration"
order_dir (str): "desc" or "asc" order_dir (str): "desc" or "asc"
@@ -2341,6 +2343,7 @@ Required parameters:
None None
Optional parameters: Optional parameters:
grouping (int): 0 or 1
order_column (str): "user_thumb", "friendly_name", "last_seen", "ip_address", "platform", order_column (str): "user_thumb", "friendly_name", "last_seen", "ip_address", "platform",
"player", "last_played", "plays", "duration" "player", "last_played", "plays", "duration"
order_dir (str): "desc" or "asc" order_dir (str): "desc" or "asc"

View File

@@ -1,5 +1,22 @@
# Changelog # Changelog
## v2.1.34 (2019-09-03)
* History:
* New: Added Product column to history tables.
* Notifications:
* Fix: IMDB/TMDb/TVDB/TVmaze ID notification parameters showing blank values after lookup.
* UI:
* Fix: Libraries and Users tables did not respect the group history setting.
* API:
* Fix: Title field was not searchable in get_library_media_info command.
* New: Added grouping option to get_libraries_table and get_users_table commands.
* New: Added product value to get_history command.
* Other:
* Fix: Could not verify Plex Media Server with unpublished hostnames.
* Change: Automatically logout all Tautulli instances when changing the admin password.
## v2.1.33 (2019-07-27) ## v2.1.33 (2019-07-27)
* Notifications: * Notifications:

View File

@@ -60,7 +60,8 @@
<th align="left" id="friendly_name">User</th> <th align="left" id="friendly_name">User</th>
<th align="left" id="ip_address">IP Address</th> <th align="left" id="ip_address">IP Address</th>
<th align="left" id="platform">Platform</th> <th align="left" id="platform">Platform</th>
<th align="left" id="device">Player</th> <th align="left" id="product">Product</th>
<th align="left" id="player">Player</th>
<th align="left" id="title">Title</th> <th align="left" id="title">Title</th>
<th align="left" id="started">Started</th> <th align="left" id="started">Started</th>
<th align="left" id="paused_counter">Paused</th> <th align="left" id="paused_counter">Paused</th>
@@ -143,7 +144,7 @@
var colvis = new $.fn.dataTable.ColVis(history_table, { var colvis = new $.fn.dataTable.ColVis(history_table, {
buttonText: '<i class="fa fa-columns"></i> Select columns', buttonText: '<i class="fa fa-columns"></i> Select columns',
buttonClass: 'btn btn-dark', buttonClass: 'btn btn-dark',
exclude: [0, 11] exclude: [0, 12]
}); });
$(colvis.button()).appendTo('div.colvis-button-bar'); $(colvis.button()).appendTo('div.colvis-button-bar');

View File

@@ -26,6 +26,7 @@
<th align="left" id="friendly_name">User</th> <th align="left" id="friendly_name">User</th>
<th align="left" id="ip_address">IP Address</th> <th align="left" id="ip_address">IP Address</th>
<th align="left" id="platform">Platform</th> <th align="left" id="platform">Platform</th>
<th align="left" id="product">Product</th>
<th align="left" id="device">Player</th> <th align="left" id="device">Player</th>
<th align="left" id="title">Title</th> <th align="left" id="title">Title</th>
<th align="left" id="started">Started</th> <th align="left" id="started">Started</th>
@@ -61,7 +62,7 @@
}; };
history_table = $('#history_table_modal').DataTable(history_table_options); history_table = $('#history_table_modal').DataTable(history_table_options);
history_table.columns([0, 3, 4, 8, 10, 11]).visible(false); history_table.columns([0, 3, 4, 5, 9, 11, 12]).visible(false);
clearSearchButton('history_table_modal', history_table); clearSearchButton('history_table_modal', history_table);

View File

@@ -451,6 +451,7 @@ DOCUMENTATION :: END
<th align="left" id="friendly_name">User</th> <th align="left" id="friendly_name">User</th>
<th align="left" id="ip_address">IP Address</th> <th align="left" id="ip_address">IP Address</th>
<th align="left" id="platform">Platform</th> <th align="left" id="platform">Platform</th>
<th align="left" id="product">Product</th>
<th align="left" id="player">Player</th> <th align="left" id="player">Player</th>
<th align="left" id="title">Title</th> <th align="left" id="title">Title</th>
<th align="left" id="started">Started</th> <th align="left" id="started">Started</th>
@@ -613,7 +614,7 @@ DOCUMENTATION :: END
$(document).ready(function () { $(document).ready(function () {
get_history(); get_history();
history_table = $('#history_table-RK-${data["rating_key"]}').DataTable(history_table_options); history_table = $('#history_table-RK-${data["rating_key"]}').DataTable(history_table_options);
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 11] }); var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 12] });
$(colvis.button()).appendTo('div.colvis-button-bar'); $(colvis.button()).appendTo('div.colvis-button-bar');
clearSearchButton('history_table-RK-${data["rating_key"]}', history_table); clearSearchButton('history_table-RK-${data["rating_key"]}', history_table);

View File

@@ -115,7 +115,7 @@ history_table_options = {
"data": "platform", "data": "platform",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== '') { if (cellData !== '') {
$(td).html(cellData); $(td).html(capitalizeFirstLetter(cellData));
} }
}, },
"width": "10%", "width": "10%",
@@ -123,6 +123,17 @@ history_table_options = {
}, },
{ {
"targets": [5], "targets": [5],
"data": "product",
"createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== '') {
$(td).html(cellData);
}
},
"width": "10%",
"className": "no-wrap"
},
{
"targets": [6],
"data": "player", "data": "player",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== '') { if (cellData !== '') {
@@ -137,11 +148,11 @@ history_table_options = {
$(td).html('<div><a href="#" data-target="#info-modal" data-toggle="modal"><div style="float: left;">' + transcode_dec + '&nbsp;' + cellData + '</div></a></div>'); $(td).html('<div><a href="#" data-target="#info-modal" data-toggle="modal"><div style="float: left;">' + transcode_dec + '&nbsp;' + cellData + '</div></a></div>');
} }
}, },
"width": "12%", "width": "10%",
"className": "no-wrap modal-control" "className": "no-wrap modal-control"
}, },
{ {
"targets": [6], "targets": [7],
"data": "full_title", "data": "full_title",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== '') { if (cellData !== '') {
@@ -171,11 +182,11 @@ history_table_options = {
} }
} }
}, },
"width": "33%", "width": "25%",
"className": "datatable-wrap" "className": "datatable-wrap"
}, },
{ {
"targets": [7], "targets": [8],
"data": "started", "data": "started",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData === null) { if (cellData === null) {
@@ -189,7 +200,7 @@ history_table_options = {
"className": "no-wrap" "className": "no-wrap"
}, },
{ {
"targets": [8], "targets": [9],
"data": "paused_counter", "data": "paused_counter",
"render": function (data, type, full) { "render": function (data, type, full) {
if (data !== null) { if (data !== null) {
@@ -203,7 +214,7 @@ history_table_options = {
"className": "no-wrap" "className": "no-wrap"
}, },
{ {
"targets": [9], "targets": [10],
"data": "stopped", "data": "stopped",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData === null || (rowData['state'] != null && rowData['state'] != "stopped")) { if (cellData === null || (rowData['state'] != null && rowData['state'] != "stopped")) {
@@ -217,7 +228,7 @@ history_table_options = {
"className": "no-wrap" "className": "no-wrap"
}, },
{ {
"targets": [10], "targets": [11],
"data": "duration", "data": "duration",
"render": function (data, type, full) { "render": function (data, type, full) {
if (data !== null) { if (data !== null) {
@@ -231,7 +242,7 @@ history_table_options = {
"className": "no-wrap" "className": "no-wrap"
}, },
{ {
"targets": [11], "targets": [12],
"data": "watched_status", "data": "watched_status",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData == 1) { if (cellData == 1) {
@@ -489,7 +500,8 @@ function childTableFormat(rowData) {
'<th align="left" id="friendly_name">User</th>' + '<th align="left" id="friendly_name">User</th>' +
'<th align="left" id="ip_address">IP Address</th>' + '<th align="left" id="ip_address">IP Address</th>' +
'<th align="left" id="platform">Platform</th>' + '<th align="left" id="platform">Platform</th>' +
'<th align="left" id="platform">Player</th>' + '<th align="left" id="product">Product</th>' +
'<th align="left" id="player">Player</th>' +
'<th align="left" id="title">Title</th>' + '<th align="left" id="title">Title</th>' +
'<th align="left" id="started">Started</th>' + '<th align="left" id="started">Started</th>' +
'<th align="left" id="paused_counter">Paused</th>' + '<th align="left" id="paused_counter">Paused</th>' +

View File

@@ -205,6 +205,7 @@ DOCUMENTATION :: END
<th align="left" id="friendly_name">User</th> <th align="left" id="friendly_name">User</th>
<th align="left" id="ip_address">IP Address</th> <th align="left" id="ip_address">IP Address</th>
<th align="left" id="platform">Platform</th> <th align="left" id="platform">Platform</th>
<th align="left" id="product">Product</th>
<th align="left" id="player">Player</th> <th align="left" id="player">Player</th>
<th align="left" id="title">Title</th> <th align="left" id="title">Title</th>
<th align="left" id="started">Started</th> <th align="left" id="started">Started</th>
@@ -385,7 +386,7 @@ DOCUMENTATION :: END
}; };
history_table = $('#history_table-SID-${data["section_id"]}').DataTable(history_table_options); history_table = $('#history_table-SID-${data["section_id"]}').DataTable(history_table_options);
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 11] }); var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 12] });
$(colvis.button()).appendTo('#button-bar-history'); $(colvis.button()).appendTo('#button-bar-history');
clearSearchButton('history_table-SID-${data["section_id"]}', history_table); clearSearchButton('history_table-SID-${data["section_id"]}', history_table);

View File

@@ -184,6 +184,7 @@ DOCUMENTATION :: END
<th align="left" id="friendly_name">User</th> <th align="left" id="friendly_name">User</th>
<th align="left" id="ip_address">IP Address</th> <th align="left" id="ip_address">IP Address</th>
<th align="left" id="platform">Platform</th> <th align="left" id="platform">Platform</th>
<th align="left" id="product">Product</th>
<th align="left" id="player">Player</th> <th align="left" id="player">Player</th>
<th align="left" id="title">Title</th> <th align="left" id="title">Title</th>
<th align="left" id="started">Started</th> <th align="left" id="started">Started</th>
@@ -425,7 +426,7 @@ DOCUMENTATION :: END
history_table = $('#history_table-UID-${data["user_id"]}').DataTable(history_table_options); history_table = $('#history_table-UID-${data["user_id"]}').DataTable(history_table_options);
history_table.column(2).visible(false); history_table.column(2).visible(false);
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 11] }); var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 12] });
$(colvis.button()).appendTo('#button-bar-history'); $(colvis.button()).appendTo('#button-bar-history');
clearSearchButton('history_table-UID-${data["user_id"]}', history_table); clearSearchButton('history_table-UID-${data["user_id"]}', history_table);

View File

@@ -217,9 +217,10 @@ def initialize(config_file):
CONFIG.write() CONFIG.write()
# Check if Tautulli has a jwt_secret # Check if Tautulli has a jwt_secret
if CONFIG.JWT_SECRET == '' or not CONFIG.JWT_SECRET: if CONFIG.JWT_SECRET == '' or not CONFIG.JWT_SECRET or CONFIG.JWT_UPDATE_SECRET:
logger.debug(u"Generating JWT secret...") logger.debug(u"Generating JWT secret...")
CONFIG.JWT_SECRET = generate_uuid() CONFIG.JWT_SECRET = generate_uuid()
CONFIG.JWT_UPDATE_SECRET = False
CONFIG.write() CONFIG.write()
# Get the previous version from the file # Get the previous version from the file

View File

@@ -624,6 +624,7 @@ _CONFIG_DEFINITIONS = {
'XBMC_ON_CONCURRENT': (int, 'XBMC', 0), 'XBMC_ON_CONCURRENT': (int, 'XBMC', 0),
'XBMC_ON_NEWDEVICE': (int, 'XBMC', 0), 'XBMC_ON_NEWDEVICE': (int, 'XBMC', 0),
'JWT_SECRET': (str, 'Advanced', ''), 'JWT_SECRET': (str, 'Advanced', ''),
'JWT_UPDATE_SECRET': (bool_int, 'Advanced', 0),
'SYSTEM_ANALYTICS': (int, 'Advanced', 1), 'SYSTEM_ANALYTICS': (int, 'Advanced', 1),
'WIN_SYS_TRAY': (int, 'General', 1) 'WIN_SYS_TRAY': (int, 'General', 1)
} }

View File

@@ -76,6 +76,7 @@ class DataFactory(object):
'(CASE WHEN users.friendly_name IS NULL OR TRIM(users.friendly_name) = "" \ '(CASE WHEN users.friendly_name IS NULL OR TRIM(users.friendly_name) = "" \
THEN users.username ELSE users.friendly_name END) AS friendly_name', THEN users.username ELSE users.friendly_name END) AS friendly_name',
'platform', 'platform',
'product',
'player', 'player',
'ip_address', 'ip_address',
'session_history.media_type', 'session_history.media_type',
@@ -123,6 +124,7 @@ class DataFactory(object):
'(CASE WHEN friendly_name IS NULL OR TRIM(friendly_name) = "" \ '(CASE WHEN friendly_name IS NULL OR TRIM(friendly_name) = "" \
THEN user ELSE friendly_name END) AS friendly_name', THEN user ELSE friendly_name END) AS friendly_name',
'platform', 'platform',
'product',
'player', 'player',
'ip_address', 'ip_address',
'media_type', 'media_type',
@@ -225,6 +227,7 @@ class DataFactory(object):
'user': item['user'], 'user': item['user'],
'friendly_name': item['friendly_name'], 'friendly_name': item['friendly_name'],
'platform': platform, 'platform': platform,
'product': item['product'],
'player': item['player'], 'player': item['player'],
'ip_address': item['ip_address'], 'ip_address': item['ip_address'],
'media_type': item['media_type'], 'media_type': item['media_type'],

View File

@@ -239,7 +239,7 @@ class Libraries(object):
def __init__(self): def __init__(self):
pass pass
def get_datatables_list(self, kwargs=None): def get_datatables_list(self, kwargs=None, grouping=None):
default_return = {'recordsFiltered': 0, default_return = {'recordsFiltered': 0,
'recordsTotal': 0, 'recordsTotal': 0,
'draw': 0, 'draw': 0,
@@ -250,9 +250,14 @@ class Libraries(object):
custom_where = [['library_sections.deleted_section', 0]] custom_where = [['library_sections.deleted_section', 0]]
if grouping is None:
grouping = plexpy.CONFIG.GROUP_HISTORY_TABLES
if session.get_session_shared_libraries(): if session.get_session_shared_libraries():
custom_where.append(['library_sections.section_id', session.get_session_shared_libraries()]) custom_where.append(['library_sections.section_id', session.get_session_shared_libraries()])
group_by = 'session_history.reference_id' if grouping else 'session_history.id'
columns = ['library_sections.section_id', columns = ['library_sections.section_id',
'library_sections.section_name', 'library_sections.section_name',
'library_sections.section_type', 'library_sections.section_type',
@@ -262,7 +267,7 @@ class Libraries(object):
'library_sections.thumb AS library_thumb', 'library_sections.thumb AS library_thumb',
'library_sections.custom_thumb_url AS custom_thumb', 'library_sections.custom_thumb_url AS custom_thumb',
'library_sections.art', 'library_sections.art',
'COUNT(session_history.id) AS plays', 'COUNT(DISTINCT %s) AS plays' % group_by,
'SUM(CASE WHEN session_history.stopped > 0 THEN (session_history.stopped - session_history.started) \ 'SUM(CASE WHEN session_history.stopped > 0 THEN (session_history.stopped - session_history.started) \
ELSE 0 END) - SUM(CASE WHEN session_history.paused_counter IS NULL THEN 0 ELSE \ ELSE 0 END) - SUM(CASE WHEN session_history.paused_counter IS NULL THEN 0 ELSE \
session_history.paused_counter END) AS duration', session_history.paused_counter END) AS duration',
@@ -533,7 +538,7 @@ class Libraries(object):
# Search results # Search results
search_value = json_data['search']['value'].lower() search_value = json_data['search']['value'].lower()
if search_value: if search_value:
searchable_columns = [d['data'] for d in json_data['columns'] if d['searchable']] searchable_columns = [d['data'] for d in json_data['columns'] if d['searchable']] + ['title']
for row in rows: for row in rows:
for k,v in row.iteritems(): for k,v in row.iteritems():
if k in searchable_columns and search_value in v.lower(): if k in searchable_columns and search_value in v.lower():

View File

@@ -1332,6 +1332,7 @@ def lookup_tvmaze_by_id(rating_key=None, thetvdb_id=None, imdb_id=None):
'tvmaze_json': json.dumps(tvmaze_json)} 'tvmaze_json': json.dumps(tvmaze_json)}
db.upsert(table_name='tvmaze_lookup', key_dict=keys, value_dict=tvmaze_info) db.upsert(table_name='tvmaze_lookup', key_dict=keys, value_dict=tvmaze_info)
tvmaze_info.update(keys)
tvmaze_info.pop('tvmaze_json') tvmaze_info.pop('tvmaze_json')
else: else:
@@ -1394,6 +1395,7 @@ def lookup_themoviedb_by_id(rating_key=None, thetvdb_id=None, imdb_id=None):
db.upsert(table_name='themoviedb_lookup', key_dict=keys, value_dict=themoviedb_info) db.upsert(table_name='themoviedb_lookup', key_dict=keys, value_dict=themoviedb_info)
themoviedb_info.update(keys)
themoviedb_info.pop('themoviedb_json') themoviedb_info.pop('themoviedb_json')
else: else:
@@ -1447,6 +1449,8 @@ def get_themoviedb_info(rating_key=None, media_type=None, themoviedb_id=None):
db.upsert(table_name='themoviedb_lookup', key_dict=keys, value_dict=themoviedb_info) db.upsert(table_name='themoviedb_lookup', key_dict=keys, value_dict=themoviedb_info)
themoviedb_info.update(keys)
else: else:
if err_msg: if err_msg:
logger.error(u"Tautulli NotificationHandler :: {}".format(err_msg)) logger.error(u"Tautulli NotificationHandler :: {}".format(err_msg))

View File

@@ -70,7 +70,7 @@ class Users(object):
def __init__(self): def __init__(self):
pass pass
def get_datatables_list(self, kwargs=None): def get_datatables_list(self, kwargs=None, grouping=None):
default_return = {'recordsFiltered': 0, default_return = {'recordsFiltered': 0,
'recordsTotal': 0, 'recordsTotal': 0,
'draw': 0, 'draw': 0,
@@ -81,18 +81,23 @@ class Users(object):
custom_where = [['users.deleted_user', 0]] custom_where = [['users.deleted_user', 0]]
if grouping is None:
grouping = plexpy.CONFIG.GROUP_HISTORY_TABLES
if session.get_session_user_id(): if session.get_session_user_id():
custom_where.append(['users.user_id', session.get_session_user_id()]) custom_where.append(['users.user_id', session.get_session_user_id()])
if kwargs.get('user_id'): if kwargs.get('user_id'):
custom_where.append(['users.user_id', kwargs.get('user_id')]) custom_where.append(['users.user_id', kwargs.get('user_id')])
group_by = 'session_history.reference_id' if grouping else 'session_history.id'
columns = ['users.user_id', columns = ['users.user_id',
'(CASE WHEN users.friendly_name IS NULL OR TRIM(users.friendly_name) = "" \ '(CASE WHEN users.friendly_name IS NULL OR TRIM(users.friendly_name) = "" \
THEN users.username ELSE users.friendly_name END) AS friendly_name', THEN users.username ELSE users.friendly_name END) AS friendly_name',
'users.thumb AS user_thumb', 'users.thumb AS user_thumb',
'users.custom_avatar_url AS custom_thumb', 'users.custom_avatar_url AS custom_thumb',
'COUNT(session_history.id) AS plays', 'COUNT(DISTINCT %s) AS plays' % group_by,
'SUM(CASE WHEN session_history.stopped > 0 THEN (session_history.stopped - session_history.started) \ 'SUM(CASE WHEN session_history.stopped > 0 THEN (session_history.stopped - session_history.started) \
ELSE 0 END) - SUM(CASE WHEN session_history.paused_counter IS NULL THEN 0 ELSE \ ELSE 0 END) - SUM(CASE WHEN session_history.paused_counter IS NULL THEN 0 ELSE \
session_history.paused_counter END) AS duration', session_history.paused_counter END) AS duration',

View File

@@ -1,2 +1,2 @@
PLEXPY_BRANCH = "master" PLEXPY_BRANCH = "master"
PLEXPY_RELEASE_VERSION = "v2.1.33" PLEXPY_RELEASE_VERSION = "v2.1.34"

View File

@@ -353,7 +353,7 @@ class WebInterface(object):
@requireAuth() @requireAuth()
@sanitize_out() @sanitize_out()
@addtoapi("get_libraries_table") @addtoapi("get_libraries_table")
def get_library_list(self, **kwargs): def get_library_list(self, grouping=None, **kwargs):
""" Get the data on the Tautulli libraries table. """ Get the data on the Tautulli libraries table.
``` ```
@@ -361,6 +361,7 @@ class WebInterface(object):
None None
Optional parameters: Optional parameters:
grouping (int): 0 or 1
order_column (str): "library_thumb", "section_name", "section_type", "count", "parent_count", order_column (str): "library_thumb", "section_name", "section_type", "count", "parent_count",
"child_count", "last_accessed", "last_played", "plays", "duration" "child_count", "last_accessed", "last_played", "plays", "duration"
order_dir (str): "desc" or "asc" order_dir (str): "desc" or "asc"
@@ -423,7 +424,7 @@ class WebInterface(object):
kwargs['json_data'] = build_datatables_json(kwargs, dt_columns, "section_name") kwargs['json_data'] = build_datatables_json(kwargs, dt_columns, "section_name")
library_data = libraries.Libraries() library_data = libraries.Libraries()
library_list = library_data.get_datatables_list(kwargs=kwargs) library_list = library_data.get_datatables_list(kwargs=kwargs, grouping=grouping)
return library_list return library_list
@@ -1016,7 +1017,7 @@ class WebInterface(object):
@requireAuth() @requireAuth()
@sanitize_out() @sanitize_out()
@addtoapi("get_users_table") @addtoapi("get_users_table")
def get_user_list(self, **kwargs): def get_user_list(self, grouping=None, **kwargs):
""" Get the data on Tautulli users table. """ Get the data on Tautulli users table.
``` ```
@@ -1024,6 +1025,7 @@ class WebInterface(object):
None None
Optional parameters: Optional parameters:
grouping (int): 0 or 1
order_column (str): "user_thumb", "friendly_name", "last_seen", "ip_address", "platform", order_column (str): "user_thumb", "friendly_name", "last_seen", "ip_address", "platform",
"player", "last_played", "plays", "duration" "player", "last_played", "plays", "duration"
order_dir (str): "desc" or "asc" order_dir (str): "desc" or "asc"
@@ -1082,7 +1084,7 @@ class WebInterface(object):
kwargs['json_data'] = build_datatables_json(kwargs, dt_columns, "friendly_name") kwargs['json_data'] = build_datatables_json(kwargs, dt_columns, "friendly_name")
user_data = users.Users() user_data = users.Users()
user_list = user_data.get_datatables_list(kwargs=kwargs) user_list = user_data.get_datatables_list(kwargs=kwargs, grouping=grouping)
return user_list return user_list
@@ -1628,8 +1630,9 @@ class WebInterface(object):
"parent_title": "", "parent_title": "",
"paused_counter": 0, "paused_counter": 0,
"percent_complete": 84, "percent_complete": 84,
"platform": "Chrome", "platform": "Windows",
"player": "Plex Web (Chrome)", "product": "Plex for Windows",
"player": "Castle-PC",
"rating_key": 4348, "rating_key": 4348,
"reference_id": 1123, "reference_id": 1123,
"session_key": null, "session_key": null,
@@ -1658,6 +1661,7 @@ class WebInterface(object):
("friendly_name", True, True), ("friendly_name", True, True),
("ip_address", True, True), ("ip_address", True, True),
("platform", True, True), ("platform", True, True),
("product", True, True),
("player", True, True), ("player", True, True),
("full_title", True, True), ("full_title", True, True),
("started", True, False), ("started", True, False),
@@ -2853,10 +2857,16 @@ class WebInterface(object):
else: else:
kwargs['http_password'] = plexpy.CONFIG.HTTP_PASSWORD kwargs['http_password'] = plexpy.CONFIG.HTTP_PASSWORD
# Flag to refresh JWT uuid to log out clients
kwargs['jwt_update_secret'] = True
elif kwargs['http_password'] and kwargs.get('http_hash_password'): elif kwargs['http_password'] and kwargs.get('http_hash_password'):
kwargs['http_password'] = make_hash(kwargs['http_password']) kwargs['http_password'] = make_hash(kwargs['http_password'])
kwargs['http_hashed_password'] = 1 kwargs['http_hashed_password'] = 1
# Flag to refresh JWT uuid to log out clients
kwargs['jwt_update_secret'] = True
elif not kwargs.get('http_hash_password'): elif not kwargs.get('http_hash_password'):
kwargs['http_hashed_password'] = 0 kwargs['http_hashed_password'] = 0
else: else:
@@ -3657,10 +3667,10 @@ class WebInterface(object):
identifier = server['clientIdentifier'] identifier = server['clientIdentifier']
break break
# Fallback to checking /identity endpoint is server is unpublished # Fallback to checking /identity endpoint if the server is unpublished
# Cannot set SSL settings on the PMS if unpublished so 'http' is okay # Cannot set SSL settings on the PMS if unpublished so 'http' is okay
if not identifier: if not identifier:
scheme = 'https' if ssl else 'http' scheme = 'https' if helpers.cast_to_int(ssl) else 'http'
url = '{scheme}://{hostname}:{port}'.format(scheme=scheme, hostname=hostname, port=port) url = '{scheme}://{hostname}:{port}'.format(scheme=scheme, hostname=hostname, port=port)
uri = '/identity' uri = '/identity'