mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-08 14:10:52 -07:00
Get file sizes for media info table
This commit is contained in:
parent
c0f0cb0d9e
commit
35528ef602
7 changed files with 309 additions and 97 deletions
|
@ -10,6 +10,9 @@ $.ajax({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var get_file_sizes = false;
|
||||||
|
var refresh_child_tables = false;
|
||||||
|
|
||||||
media_info_table_options = {
|
media_info_table_options = {
|
||||||
"destroy": true,
|
"destroy": true,
|
||||||
"language": {
|
"language": {
|
||||||
|
@ -99,7 +102,7 @@ media_info_table_options = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"width": "26%"
|
"width": "24%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"targets": [2],
|
"targets": [2],
|
||||||
|
@ -184,10 +187,12 @@ media_info_table_options = {
|
||||||
"data": "file_size",
|
"data": "file_size",
|
||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
if (cellData !== null && cellData !== '') {
|
if (cellData !== null && cellData !== '') {
|
||||||
$(td).html(Math.round(cellData / 1024 / 1000).toString() + ' MB');
|
$(td).html(Math.round(cellData / 1024 / 1024).toString() + ' MiB');
|
||||||
|
} else {
|
||||||
|
if (rowData['section_type'] != 'photo') { get_file_sizes = true; }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"width": "5%",
|
"width": "7%",
|
||||||
"className": "no-wrap hidden-md hidden-sm hidden-xs",
|
"className": "no-wrap hidden-md hidden-sm hidden-xs",
|
||||||
"searchable": false
|
"searchable": false
|
||||||
},
|
},
|
||||||
|
@ -244,6 +249,25 @@ media_info_table_options = {
|
||||||
createChildTableMedia(this, rowData)
|
createChildTableMedia(this, rowData)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (get_file_sizes) {
|
||||||
|
$('#get_file_sizes_message').show();
|
||||||
|
$('#refresh-media-info-table').prop('disabled', true);
|
||||||
|
$.ajax({
|
||||||
|
url: 'get_media_info_file_sizes',
|
||||||
|
async: true,
|
||||||
|
data: { section_id: section_id },
|
||||||
|
complete: function (xhr, status) {
|
||||||
|
response = JSON.parse(xhr.responseText)
|
||||||
|
if (response.success == true) {
|
||||||
|
$('#get_file_sizes_message').hide();
|
||||||
|
$('#refresh-media-info-table').prop('disabled', false);
|
||||||
|
media_info_table.draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
get_file_sizes = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"preDrawCallback": function(settings) {
|
"preDrawCallback": function(settings) {
|
||||||
var msg = "<i class='fa fa-refresh fa-spin'></i> Fetching rows...";
|
var msg = "<i class='fa fa-refresh fa-spin'></i> Fetching rows...";
|
||||||
|
@ -314,7 +338,8 @@ function childTableOptionsMedia(rowData) {
|
||||||
json_data: JSON.stringify(d),
|
json_data: JSON.stringify(d),
|
||||||
section_id: rowData['section_id'],
|
section_id: rowData['section_id'],
|
||||||
section_type: section_type,
|
section_type: section_type,
|
||||||
rating_key: rowData['rating_key']
|
rating_key: rowData['rating_key'],
|
||||||
|
refresh: refresh_child_tables
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,6 +368,26 @@ function childTableOptionsMedia(rowData) {
|
||||||
createChildTableMedia(this, childrowData)
|
createChildTableMedia(this, childrowData)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (get_file_sizes) {
|
||||||
|
$('#refresh-media-info-table').prop('disabled', true);
|
||||||
|
$.ajax({
|
||||||
|
url: 'get_media_info_file_sizes',
|
||||||
|
async: true,
|
||||||
|
data: {
|
||||||
|
section_id: section_id,
|
||||||
|
rating_key: rowData['rating_key']
|
||||||
|
},
|
||||||
|
complete: function (xhr, status) {
|
||||||
|
response = JSON.parse(xhr.responseText)
|
||||||
|
if (response.success == true) {
|
||||||
|
$('#refresh-media-info-table').prop('disabled', false);
|
||||||
|
media_info_child_table[rowData['rating_key']].draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
get_file_sizes = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$(this).closest('div.slider').slideDown();
|
$(this).closest('div.slider').slideDown();
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
<%def name="body()">
|
<%def name="body()">
|
||||||
<div class='container-fluid'>
|
<div class='container-fluid'>
|
||||||
% if config['update_section_ids'] == 1:
|
% if config['update_section_ids'] == 1:
|
||||||
<div id="update_section_ids_mssage" style="text-align: center; margin-top: 20px;">
|
<div id="update_section_ids_message" style="text-align: center; margin-top: 20px;">
|
||||||
<i class="fa fa-exclamation-triangle"></i> PlexPy needs to update the Library IDs in your databse. Click the "<strong>Refresh libraries</strong>" button below to begin the update.
|
<i class="fa fa-exclamation-triangle"></i> PlexPy needs to update the Library IDs in your databse. Click the "<strong>Refresh libraries</strong>" button below to begin the update.
|
||||||
</div>
|
</div>
|
||||||
% elif config['update_section_ids'] == -1:
|
% elif config['update_section_ids'] == -1:
|
||||||
<div id="update_section_ids_mssage" style="text-align: center; margin-top: 20px;">
|
<div id="update_section_ids_message" style="text-align: center; margin-top: 20px;">
|
||||||
<i class="fa fa-refresh fa-spin"></i> PlexPy is updating library IDs in the database. This could take a few minutes depending on the size of your database.
|
<i class="fa fa-refresh fa-spin"></i> PlexPy is updating library IDs in the database. This could take a few minutes depending on the size of your database.
|
||||||
<br />
|
<br />
|
||||||
You may leave this page and come back later.
|
You may leave this page and come back later.
|
||||||
|
@ -23,7 +23,11 @@
|
||||||
<span><i class="fa fa-book"></i> All Libraries</span>
|
<span><i class="fa fa-book"></i> All Libraries</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
|
% if config['update_section_ids'] == -1:
|
||||||
|
<button class="btn btn-dark refresh-libraries-button" id="refresh-libraries-list" disabled><i class="fa fa-refresh"></i> Refresh libraries</button>
|
||||||
|
% else:
|
||||||
<button class="btn btn-dark refresh-libraries-button" id="refresh-libraries-list"><i class="fa fa-refresh"></i> Refresh libraries</button>
|
<button class="btn btn-dark refresh-libraries-button" id="refresh-libraries-list"><i class="fa fa-refresh"></i> Refresh libraries</button>
|
||||||
|
% endif
|
||||||
<button class="btn btn-danger btn-edit" data-toggle="button" aria-pressed="false" autocomplete="off" id="row-edit-mode">
|
<button class="btn btn-danger btn-edit" data-toggle="button" aria-pressed="false" autocomplete="off" id="row-edit-mode">
|
||||||
<i class="fa fa-pencil"></i> Edit mode
|
<i class="fa fa-pencil"></i> Edit mode
|
||||||
</button> 
|
</button> 
|
||||||
|
@ -172,7 +176,7 @@
|
||||||
|
|
||||||
$("#refresh-libraries-list").click(function () {
|
$("#refresh-libraries-list").click(function () {
|
||||||
if ("${config['update_section_ids']}" == "1") {
|
if ("${config['update_section_ids']}" == "1") {
|
||||||
$('#update_section_ids_mssage').html(
|
$('#update_section_ids_message').html(
|
||||||
'<i class="fa fa-refresh fa-spin"></i> PlexPy is updating library IDs in the database. This could take a few minutes depending on the size of your database.' +
|
'<i class="fa fa-refresh fa-spin"></i> PlexPy is updating library IDs in the database. This could take a few minutes depending on the size of your database.' +
|
||||||
'<br />' +
|
'<br />' +
|
||||||
'You may leave this page and come back later.');
|
'You may leave this page and come back later.');
|
||||||
|
@ -194,9 +198,5 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if ("${config['update_section_ids']}" == "-1") {
|
|
||||||
$("#refresh-libraries-list").prop('disabled', true);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
</%def>
|
</%def>
|
|
@ -196,6 +196,15 @@ DOCUMENTATION :: END
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
% if data['section_id'] in config['get_file_sizes']['section_ids']:
|
||||||
|
<div id="get_file_sizes_message" style="text-align: center; margin-top: 20px;">
|
||||||
|
% else:
|
||||||
|
<div id="get_file_sizes_message" style="text-align: center; margin-top: 20px; display: none;">
|
||||||
|
% endif
|
||||||
|
<i class="fa fa-refresh fa-spin"></i> PlexPy is getting the file sizes for the library's media info. This could take a few minutes depending on the size of your library.
|
||||||
|
<br />
|
||||||
|
You may leave this page and come back later.
|
||||||
|
</div>
|
||||||
<div class='table-card-header'>
|
<div class='table-card-header'>
|
||||||
<div class="header-bar">
|
<div class="header-bar">
|
||||||
<span>
|
<span>
|
||||||
|
@ -205,9 +214,15 @@ DOCUMENTATION :: END
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
|
% if data['section_id'] in config['get_file_sizes']['section_ids']:
|
||||||
|
<button class="btn btn-dark refresh-media-info-table-button" id="refresh-media-info-table" style="margin-right: 5px;" disabled>
|
||||||
|
<i class="fa fa-refresh"></i> Refresh media info
|
||||||
|
</button>
|
||||||
|
% else:
|
||||||
<button class="btn btn-dark refresh-media-info-table-button" id="refresh-media-info-table" style="margin-right: 5px;">
|
<button class="btn btn-dark refresh-media-info-table-button" id="refresh-media-info-table" style="margin-right: 5px;">
|
||||||
<i class="fa fa-refresh"></i> Refresh media info
|
<i class="fa fa-refresh"></i> Refresh media info
|
||||||
</button>
|
</button>
|
||||||
|
% endif
|
||||||
<div class="colvis-button-bar hidden-xs" id="button-bar-media-info"></div>
|
<div class="colvis-button-bar hidden-xs" id="button-bar-media-info"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -293,20 +308,20 @@ DOCUMENTATION :: END
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.min.js"></script>
|
<script src="interfaces/default/js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.pagination.js"></script>
|
<script src="interfaces/default/js/dataTables.bootstrap.pagination.js"></script>
|
||||||
% if data:
|
% if data:
|
||||||
|
<script>
|
||||||
|
% if str(data['section_id']).isdigit():
|
||||||
|
var section_id = ${data['section_id']};
|
||||||
|
% else:
|
||||||
|
var section_id = null;
|
||||||
|
% endif
|
||||||
|
var section_name = '${data['section_name'].replace("'", "\\'")}';
|
||||||
|
var refresh_table = false;
|
||||||
|
</script>
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
||||||
<script src="interfaces/default/js/tables/history_table.js"></script>
|
<script src="interfaces/default/js/tables/history_table.js"></script>
|
||||||
<script src="interfaces/default/js/tables/media_info_table.js"></script>
|
<script src="interfaces/default/js/tables/media_info_table.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
% if str(data['section_id']).isdigit():
|
|
||||||
var section_id = ${data['section_id']};
|
|
||||||
% else:
|
|
||||||
var section_id = null;
|
|
||||||
% endif
|
|
||||||
|
|
||||||
var section_name = '${data['section_name'].replace("'", "\\'")}';
|
|
||||||
|
|
||||||
$("#edit-library-tooltip").tooltip();
|
$("#edit-library-tooltip").tooltip();
|
||||||
|
|
||||||
// Populate watch time stats
|
// Populate watch time stats
|
||||||
|
@ -357,7 +372,8 @@ DOCUMENTATION :: END
|
||||||
data: function ( d ) {
|
data: function ( d ) {
|
||||||
return {
|
return {
|
||||||
json_data: JSON.stringify( d ),
|
json_data: JSON.stringify( d ),
|
||||||
section_id: section_id
|
section_id: section_id,
|
||||||
|
refresh: refresh_table
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,15 +393,11 @@ DOCUMENTATION :: END
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#refresh-media-info-table").click(function () {
|
$("#refresh-media-info-table").click(function () {
|
||||||
$.ajax({
|
media_info_child_table = {};
|
||||||
url: 'delete_datatable_media_info_cache',
|
refresh_table = true;
|
||||||
cache: false,
|
refresh_child_tables = true;
|
||||||
async: true,
|
media_info_table.draw();
|
||||||
data: { section_id: section_id },
|
refresh_table = false;
|
||||||
complete: function(xhr, status) {
|
|
||||||
media_info_table.draw()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load edit library modal
|
// Load edit library modal
|
||||||
|
|
|
@ -97,6 +97,7 @@ _CONFIG_DEFINITIONS = {
|
||||||
'FACEBOOK_ON_INTUP': (int, 'Facebook', 0),
|
'FACEBOOK_ON_INTUP': (int, 'Facebook', 0),
|
||||||
'FIRST_RUN_COMPLETE': (int, 'General', 0),
|
'FIRST_RUN_COMPLETE': (int, 'General', 0),
|
||||||
'FREEZE_DB': (int, 'General', 0),
|
'FREEZE_DB': (int, 'General', 0),
|
||||||
|
'GET_FILE_SIZES': (dict, 'General', {'section_ids': [], 'rating_keys': []}),
|
||||||
'GIT_BRANCH': (str, 'General', 'master'),
|
'GIT_BRANCH': (str, 'General', 'master'),
|
||||||
'GIT_PATH': (str, 'General', ''),
|
'GIT_PATH': (str, 'General', ''),
|
||||||
'GIT_USER': (str, 'General', 'drzoidberg33'),
|
'GIT_USER': (str, 'General', 'drzoidberg33'),
|
||||||
|
|
|
@ -49,7 +49,7 @@ def update_section_ids():
|
||||||
|
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
|
|
||||||
error_keys = []
|
error_keys = set()
|
||||||
for item in result:
|
for item in result:
|
||||||
id = item['id']
|
id = item['id']
|
||||||
rating_key = item['rating_key']
|
rating_key = item['rating_key']
|
||||||
|
@ -61,7 +61,7 @@ def update_section_ids():
|
||||||
section_values = {'section_id': metadata['section_id']}
|
section_values = {'section_id': metadata['section_id']}
|
||||||
monitor_db.upsert('session_history_metadata', key_dict=section_keys, value_dict=section_values)
|
monitor_db.upsert('session_history_metadata', key_dict=section_keys, value_dict=section_values)
|
||||||
else:
|
else:
|
||||||
error_keys.append(rating_key)
|
error_keys.add(rating_key)
|
||||||
|
|
||||||
if error_keys:
|
if error_keys:
|
||||||
logger.debug(u"PlexPy Libraries :: Updated all section_id's in database except for rating_keys: %s." %
|
logger.debug(u"PlexPy Libraries :: Updated all section_id's in database except for rating_keys: %s." %
|
||||||
|
@ -180,7 +180,7 @@ class Libraries(object):
|
||||||
|
|
||||||
return dict
|
return dict
|
||||||
|
|
||||||
def get_datatables_media_info(self, section_id=None, section_type=None, rating_key=None, kwargs=None):
|
def get_datatables_media_info(self, section_id=None, section_type=None, rating_key=None, refresh=False, kwargs=None):
|
||||||
from plexpy import pmsconnect
|
from plexpy import pmsconnect
|
||||||
import json, os
|
import json, os
|
||||||
|
|
||||||
|
@ -209,6 +209,11 @@ class Libraries(object):
|
||||||
# Get play counts from the database
|
# Get play counts from the database
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
if plexpy.CONFIG.GROUP_HISTORY_TABLES:
|
||||||
|
count_by = 'reference_id'
|
||||||
|
else:
|
||||||
|
count_by = 'id'
|
||||||
|
|
||||||
if section_type == 'show' or section_type == 'artist':
|
if section_type == 'show' or section_type == 'artist':
|
||||||
group_by = 'grandparent_rating_key'
|
group_by = 'grandparent_rating_key'
|
||||||
elif section_type == 'season' or section_type == 'album':
|
elif section_type == 'season' or section_type == 'album':
|
||||||
|
@ -217,12 +222,12 @@ class Libraries(object):
|
||||||
group_by = 'rating_key'
|
group_by = 'rating_key'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
query = 'SELECT MAX(session_history.started) AS last_watched, COUNT(session_history.id) AS play_count, ' \
|
query = 'SELECT MAX(session_history.started) AS last_watched, COUNT(DISTINCT session_history.%s) AS play_count, ' \
|
||||||
'session_history.rating_key, session_history.parent_rating_key, session_history.grandparent_rating_key ' \
|
'session_history.rating_key, session_history.parent_rating_key, session_history.grandparent_rating_key ' \
|
||||||
'FROM session_history ' \
|
'FROM session_history ' \
|
||||||
'JOIN session_history_metadata ON session_history.id = session_history_metadata.id ' \
|
'JOIN session_history_metadata ON session_history.id = session_history_metadata.id ' \
|
||||||
'WHERE session_history_metadata.section_id = ? ' \
|
'WHERE session_history_metadata.section_id = ? ' \
|
||||||
'GROUP BY session_history.%s ' % group_by
|
'GROUP BY session_history.%s ' % (count_by, group_by)
|
||||||
result = monitor_db.select(query, args=[section_id])
|
result = monitor_db.select(query, args=[section_id])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_datatables_media_info2: %s." % e)
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_datatables_media_info2: %s." % e)
|
||||||
|
@ -257,16 +262,17 @@ class Libraries(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# If no cache was imported, get all library children items
|
# If no cache was imported, get all library children items
|
||||||
if not rows:
|
cached_rating_keys = [d['rating_key'] for d in rows]
|
||||||
|
if refresh or not rows:
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
|
|
||||||
if rating_key:
|
if rating_key:
|
||||||
library_children = pms_connect.get_library_children(rating_key=rating_key,
|
library_children = pms_connect.get_library_children_details(rating_key=rating_key,
|
||||||
get_media_info=True)
|
get_media_info=True)
|
||||||
elif section_id:
|
elif section_id:
|
||||||
library_children = pms_connect.get_library_children(section_id=section_id,
|
library_children = pms_connect.get_library_children_details(section_id=section_id,
|
||||||
section_type=section_type,
|
section_type=section_type,
|
||||||
get_media_info=True)
|
get_media_info=True)
|
||||||
|
|
||||||
if library_children:
|
if library_children:
|
||||||
library_count = library_children['library_count']
|
library_count = library_children['library_count']
|
||||||
|
@ -275,30 +281,30 @@ class Libraries(object):
|
||||||
logger.warn(u"PlexPy Libraries :: Unable to get a list of library items.")
|
logger.warn(u"PlexPy Libraries :: Unable to get a list of library items.")
|
||||||
return default_return
|
return default_return
|
||||||
|
|
||||||
rows = []
|
|
||||||
for item in children_list:
|
for item in children_list:
|
||||||
row = {'section_id': library_details['section_id'],
|
if item['rating_key'] not in cached_rating_keys:
|
||||||
'section_type': library_details['section_type'],
|
row = {'section_id': library_details['section_id'],
|
||||||
'added_at': item['added_at'],
|
'section_type': library_details['section_type'],
|
||||||
'media_type': item['media_type'],
|
'added_at': item['added_at'],
|
||||||
'rating_key': item['rating_key'],
|
'media_type': item['media_type'],
|
||||||
'parent_rating_key': item['parent_rating_key'],
|
'rating_key': item['rating_key'],
|
||||||
'grandparent_rating_key': item['grandparent_rating_key'],
|
'parent_rating_key': item['parent_rating_key'],
|
||||||
'title': item['title'],
|
'grandparent_rating_key': item['grandparent_rating_key'],
|
||||||
'year': item['year'],
|
'title': item['title'],
|
||||||
'media_index': item['media_index'],
|
'year': item['year'],
|
||||||
'parent_media_index': item['parent_media_index'],
|
'media_index': item['media_index'],
|
||||||
'thumb': item['thumb'],
|
'parent_media_index': item['parent_media_index'],
|
||||||
'container': item.get('container', ''),
|
'thumb': item['thumb'],
|
||||||
'bitrate': item.get('bitrate', ''),
|
'container': item.get('container', ''),
|
||||||
'video_codec': item.get('video_codec', ''),
|
'bitrate': item.get('bitrate', ''),
|
||||||
'video_resolution': item.get('video_resolution', ''),
|
'video_codec': item.get('video_codec', ''),
|
||||||
'video_framerate': item.get('video_framerate', ''),
|
'video_resolution': item.get('video_resolution', ''),
|
||||||
'audio_codec': item.get('audio_codec', ''),
|
'video_framerate': item.get('video_framerate', ''),
|
||||||
'audio_channels': item.get('audio_channels', ''),
|
'audio_codec': item.get('audio_codec', ''),
|
||||||
'file_size': item.get('file_size', '')
|
'audio_channels': item.get('audio_channels', ''),
|
||||||
}
|
'file_size': item.get('file_size', '')
|
||||||
rows.append(row)
|
}
|
||||||
|
rows.append(row)
|
||||||
|
|
||||||
if not rows:
|
if not rows:
|
||||||
return default_return
|
return default_return
|
||||||
|
@ -334,10 +340,11 @@ class Libraries(object):
|
||||||
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']]
|
||||||
for k,v in [row.iteritems() for row in rows]:
|
for row in rows:
|
||||||
if k in searchable_columns and search_value in v.lower():
|
for k,v in row.iteritems():
|
||||||
results.append(row)
|
if k in searchable_columns and search_value in v.lower():
|
||||||
break
|
results.append(row)
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
results = rows
|
results = rows
|
||||||
|
|
||||||
|
@ -369,6 +376,85 @@ class Libraries(object):
|
||||||
|
|
||||||
return dict
|
return dict
|
||||||
|
|
||||||
|
def get_media_info_file_sizes(self, section_id=None, rating_key=None):
|
||||||
|
from plexpy import pmsconnect
|
||||||
|
import json, os
|
||||||
|
|
||||||
|
if section_id and not str(section_id).isdigit():
|
||||||
|
logger.warn(u"PlexPy Libraries :: Datatable media info file size called by invalid section_id provided.")
|
||||||
|
return False
|
||||||
|
elif rating_key and not str(rating_key).isdigit():
|
||||||
|
logger.warn(u"PlexPy Libraries :: Datatable media info file size called by invalid rating_key provided.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Get the library details
|
||||||
|
library_details = self.get_details(section_id=section_id)
|
||||||
|
if library_details['section_id'] == None:
|
||||||
|
logger.debug(u"PlexPy Libraries :: Library section_id %s not found." % section_id)
|
||||||
|
return False
|
||||||
|
if library_details['section_type'] == 'photo':
|
||||||
|
return False
|
||||||
|
|
||||||
|
rows = []
|
||||||
|
# Import media info cache from json file
|
||||||
|
if rating_key:
|
||||||
|
#logger.debug(u"PlexPy Libraries :: Getting file sizes for rating_key %s." % rating_key)
|
||||||
|
try:
|
||||||
|
inFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info-%s_%s.json' % (section_id, rating_key))
|
||||||
|
with open(inFilePath, 'r') as inFile:
|
||||||
|
rows = json.load(inFile)
|
||||||
|
except IOError as e:
|
||||||
|
#logger.debug(u"PlexPy Libraries :: No JSON file for rating_key %s." % rating_key)
|
||||||
|
#logger.debug(u"PlexPy Libraries :: Refreshing data and creating new JSON file for rating_key %s." % rating_key)
|
||||||
|
pass
|
||||||
|
elif section_id:
|
||||||
|
logger.debug(u"PlexPy Libraries :: Getting file sizes for section_id %s." % section_id)
|
||||||
|
try:
|
||||||
|
inFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info-%s.json' % section_id)
|
||||||
|
with open(inFilePath, 'r') as inFile:
|
||||||
|
rows = json.load(inFile)
|
||||||
|
except IOError as e:
|
||||||
|
#logger.debug(u"PlexPy Libraries :: No JSON file for library section_id %s." % section_id)
|
||||||
|
#logger.debug(u"PlexPy Libraries :: Refreshing data and creating new JSON file for section_id %s." % section_id)
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Get the total file size for each item
|
||||||
|
for item in rows:
|
||||||
|
if item['rating_key'] and not item['file_size']:
|
||||||
|
file_size = 0
|
||||||
|
|
||||||
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
|
child_metadata = pms_connect.get_metadata_children_details(rating_key=item['rating_key'],
|
||||||
|
get_children=True,
|
||||||
|
get_media_info=True)
|
||||||
|
metadata_list = child_metadata['metadata']
|
||||||
|
|
||||||
|
for child_metadata in metadata_list:
|
||||||
|
child_file_size = helpers.cast_to_int(child_metadata['file_size'])
|
||||||
|
if child_file_size > 0:
|
||||||
|
file_size += child_file_size
|
||||||
|
|
||||||
|
item['file_size'] = file_size
|
||||||
|
|
||||||
|
# Cache the media info to a json file
|
||||||
|
if rating_key:
|
||||||
|
outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info-%s_%s.json' % (section_id, rating_key))
|
||||||
|
with open(outFilePath, 'w') as outFile:
|
||||||
|
json.dump(rows, outFile)
|
||||||
|
elif section_id:
|
||||||
|
outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info-%s.json' % section_id)
|
||||||
|
with open(outFilePath, 'w') as outFile:
|
||||||
|
json.dump(rows, outFile)
|
||||||
|
|
||||||
|
if rating_key:
|
||||||
|
#logger.debug(u"PlexPy Libraries :: File sizes updated for rating_key %s." % rating_key)
|
||||||
|
pass
|
||||||
|
elif section_id:
|
||||||
|
logger.debug(u"PlexPy Libraries :: File sizes updated for section_id %s." % section_id)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def set_config(self, section_id=None, custom_thumb='', do_notify=1, keep_history=1, do_notify_created=1):
|
def set_config(self, section_id=None, custom_thumb='', do_notify=1, keep_history=1, do_notify_created=1):
|
||||||
if section_id:
|
if section_id:
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
|
@ -457,7 +457,7 @@ class PmsConnect(object):
|
||||||
output = {'recently_added': sorted(recents_list, key=lambda k: k['added_at'], reverse=True)}
|
output = {'recently_added': sorted(recents_list, key=lambda k: k['added_at'], reverse=True)}
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def get_metadata_details(self, rating_key=''):
|
def get_metadata_details(self, rating_key='', get_media_info=False):
|
||||||
"""
|
"""
|
||||||
Return processed and validated metadata list for requested item.
|
Return processed and validated metadata list for requested item.
|
||||||
|
|
||||||
|
@ -774,9 +774,24 @@ class PmsConnect(object):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if get_media_info:
|
||||||
|
item_media = metadata_main.getElementsByTagName('Media')
|
||||||
|
for media in item_media:
|
||||||
|
media_info = {'container': helpers.get_xml_attr(media, 'container'),
|
||||||
|
'bitrate': helpers.get_xml_attr(media, 'bitrate'),
|
||||||
|
'video_codec': helpers.get_xml_attr(media, 'videoCodec'),
|
||||||
|
'video_resolution': helpers.get_xml_attr(media, 'videoResolution'),
|
||||||
|
'video_framerate': helpers.get_xml_attr(media, 'videoFrameRate'),
|
||||||
|
'audio_codec': helpers.get_xml_attr(media, 'audioCodec'),
|
||||||
|
'audio_channels': helpers.get_xml_attr(media, 'audioChannels'),
|
||||||
|
'file': helpers.get_xml_attr(media.getElementsByTagName('Part')[0], 'file'),
|
||||||
|
'file_size': helpers.get_xml_attr(media.getElementsByTagName('Part')[0], 'size'),
|
||||||
|
}
|
||||||
|
metadata.update(media_info)
|
||||||
|
|
||||||
return metadata_list
|
return metadata_list
|
||||||
|
|
||||||
def get_metadata_children_details(self, rating_key=''):
|
def get_metadata_children_details(self, rating_key='', get_children=False, get_media_info=False):
|
||||||
"""
|
"""
|
||||||
Return processed and validated metadata list for all children of requested item.
|
Return processed and validated metadata list for all children of requested item.
|
||||||
|
|
||||||
|
@ -790,20 +805,21 @@ class PmsConnect(object):
|
||||||
xml_head = metadata.getElementsByTagName('MediaContainer')
|
xml_head = metadata.getElementsByTagName('MediaContainer')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_metadata_children: %s." % e)
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_metadata_children: %s." % e)
|
||||||
|
return {'metadata': []}
|
||||||
|
|
||||||
metadata_list = []
|
metadata_list = []
|
||||||
|
|
||||||
for a in xml_head:
|
for a in xml_head:
|
||||||
if a.getAttribute('size'):
|
if a.getAttribute('size'):
|
||||||
if a.getAttribute('size') == '0':
|
if a.getAttribute('size') == '0':
|
||||||
metadata_list = {'metadata': None}
|
metadata_list = {'metadata': []}
|
||||||
return metadata_list
|
return metadata_list
|
||||||
|
|
||||||
if a.getElementsByTagName('Video'):
|
if a.getElementsByTagName('Video'):
|
||||||
metadata_main = a.getElementsByTagName('Video')
|
metadata_main = a.getElementsByTagName('Video')
|
||||||
for item in metadata_main:
|
for item in metadata_main:
|
||||||
child_rating_key = helpers.get_xml_attr(item, 'ratingKey')
|
child_rating_key = helpers.get_xml_attr(item, 'ratingKey')
|
||||||
metadata = self.get_metadata_details(str(child_rating_key))
|
metadata = self.get_metadata_details(str(child_rating_key), get_media_info)
|
||||||
if metadata:
|
if metadata:
|
||||||
metadata_list.append(metadata['metadata'])
|
metadata_list.append(metadata['metadata'])
|
||||||
|
|
||||||
|
@ -811,10 +827,19 @@ class PmsConnect(object):
|
||||||
metadata_main = a.getElementsByTagName('Track')
|
metadata_main = a.getElementsByTagName('Track')
|
||||||
for item in metadata_main:
|
for item in metadata_main:
|
||||||
child_rating_key = helpers.get_xml_attr(item, 'ratingKey')
|
child_rating_key = helpers.get_xml_attr(item, 'ratingKey')
|
||||||
metadata = self.get_metadata_details(str(child_rating_key))
|
metadata = self.get_metadata_details(str(child_rating_key), get_media_info)
|
||||||
if metadata:
|
if metadata:
|
||||||
metadata_list.append(metadata['metadata'])
|
metadata_list.append(metadata['metadata'])
|
||||||
|
|
||||||
|
elif get_children and a.getElementsByTagName('Directory'):
|
||||||
|
dir_main = a.getElementsByTagName('Directory')
|
||||||
|
metadata_main = [d for d in dir_main if helpers.get_xml_attr(d, 'ratingKey')]
|
||||||
|
for item in metadata_main:
|
||||||
|
child_rating_key = helpers.get_xml_attr(item, 'ratingKey')
|
||||||
|
metadata = self.get_metadata_children_details(str(child_rating_key), get_children, get_media_info)
|
||||||
|
if metadata:
|
||||||
|
metadata_list.extend(metadata['metadata'])
|
||||||
|
|
||||||
output = {'metadata': metadata_list}
|
output = {'metadata': metadata_list}
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
@ -1529,7 +1554,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def get_library_children(self, section_id='', section_type='', list_type='all', count='', rating_key='', get_media_info=False):
|
def get_library_children_details(self, section_id='', section_type='', list_type='all', count='', rating_key='', get_media_info=False):
|
||||||
"""
|
"""
|
||||||
Return processed and validated server library items list.
|
Return processed and validated server library items list.
|
||||||
|
|
||||||
|
@ -1662,7 +1687,7 @@ class PmsConnect(object):
|
||||||
for library in libraries_list:
|
for library in libraries_list:
|
||||||
section_type = library['section_type']
|
section_type = library['section_type']
|
||||||
section_id = library['section_id']
|
section_id = library['section_id']
|
||||||
children_list = self.get_library_children(section_id=section_id, section_type=section_type, count='1')
|
children_list = self.get_library_children_details(section_id=section_id, section_type=section_type, count='1')
|
||||||
|
|
||||||
if children_list['library_count'] != '0':
|
if children_list['library_count'] != '0':
|
||||||
library_stats = {'section_id': library['section_id'],
|
library_stats = {'section_id': library['section_id'],
|
||||||
|
@ -1674,29 +1699,29 @@ class PmsConnect(object):
|
||||||
}
|
}
|
||||||
|
|
||||||
if section_type == 'show':
|
if section_type == 'show':
|
||||||
parent_list = self.get_library_children(section_id=section_id, section_type='season', count='1')
|
parent_list = self.get_library_children_details(section_id=section_id, section_type='season', count='1')
|
||||||
parent_stats = {'parent_count': parent_list['library_count']}
|
parent_stats = {'parent_count': parent_list['library_count']}
|
||||||
library_stats.update(parent_stats)
|
library_stats.update(parent_stats)
|
||||||
|
|
||||||
child_list = self.get_library_children(section_id=section_id, section_type='episode', count='1')
|
child_list = self.get_library_children_details(section_id=section_id, section_type='episode', count='1')
|
||||||
child_stats = {'child_count': child_list['library_count']}
|
child_stats = {'child_count': child_list['library_count']}
|
||||||
library_stats.update(child_stats)
|
library_stats.update(child_stats)
|
||||||
|
|
||||||
if section_type == 'artist':
|
if section_type == 'artist':
|
||||||
parent_list = self.get_library_children(section_id=section_id, section_type='album', count='1')
|
parent_list = self.get_library_children_details(section_id=section_id, section_type='album', count='1')
|
||||||
parent_stats = {'parent_count': parent_list['library_count']}
|
parent_stats = {'parent_count': parent_list['library_count']}
|
||||||
library_stats.update(parent_stats)
|
library_stats.update(parent_stats)
|
||||||
|
|
||||||
child_list = self.get_library_children(section_id=section_id, section_type='track', count='1')
|
child_list = self.get_library_children_details(section_id=section_id, section_type='track', count='1')
|
||||||
child_stats = {'child_count': child_list['library_count']}
|
child_stats = {'child_count': child_list['library_count']}
|
||||||
library_stats.update(child_stats)
|
library_stats.update(child_stats)
|
||||||
|
|
||||||
if section_type == 'photo':
|
if section_type == 'photo':
|
||||||
parent_list = self.get_library_children(section_id=section_id, section_type='photoAlbum', count='1')
|
parent_list = self.get_library_children_details(section_id=section_id, section_type='photoAlbum', count='1')
|
||||||
parent_stats = {'parent_count': parent_list['library_count']}
|
parent_stats = {'parent_count': parent_list['library_count']}
|
||||||
library_stats.update(parent_stats)
|
library_stats.update(parent_stats)
|
||||||
|
|
||||||
child_list = self.get_library_children(section_id=section_id, section_type='picture', count='1')
|
child_list = self.get_library_children_details(section_id=section_id, section_type='picture', count='1')
|
||||||
child_stats = {'child_count': child_list['library_count']}
|
child_stats = {'child_count': child_list['library_count']}
|
||||||
library_stats.update(child_stats)
|
library_stats.update(child_stats)
|
||||||
|
|
||||||
|
|
|
@ -257,18 +257,22 @@ class WebInterface(object):
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def library(self, section_id=None):
|
def library(self, section_id=None):
|
||||||
|
config = {
|
||||||
|
"get_file_sizes": plexpy.CONFIG.GET_FILE_SIZES
|
||||||
|
}
|
||||||
|
|
||||||
library_data = libraries.Libraries()
|
library_data = libraries.Libraries()
|
||||||
if section_id:
|
if section_id:
|
||||||
try:
|
try:
|
||||||
library_details = library_data.get_details(section_id=section_id)
|
library_details = library_data.get_details(section_id=section_id)
|
||||||
except:
|
except:
|
||||||
logger.warn(u"Unable to retrieve library details for section_id %s " % section_id)
|
logger.warn(u"Unable to retrieve library details for section_id %s " % section_id)
|
||||||
return serve_template(templatename="library.html", title="Library", data=None)
|
return serve_template(templatename="library.html", title="Library", data=None, config=config)
|
||||||
else:
|
else:
|
||||||
logger.debug(u"Library page requested but no section_id received.")
|
logger.debug(u"Library page requested but no section_id received.")
|
||||||
return serve_template(templatename="library.html", title="Library", data=None)
|
return serve_template(templatename="library.html", title="Library", data=None, config=config)
|
||||||
|
|
||||||
return serve_template(templatename="library.html", title="Library", data=library_details)
|
return serve_template(templatename="library.html", title="Library", data=library_details, config=config)
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def edit_library_dialog(self, section_id=None, **kwargs):
|
def edit_library_dialog(self, section_id=None, **kwargs):
|
||||||
|
@ -353,22 +357,56 @@ class WebInterface(object):
|
||||||
return serve_template(templatename="library_recently_added.html", data=None, title="Recently Added")
|
return serve_template(templatename="library_recently_added.html", data=None, title="Recently Added")
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def get_library_media_info(self, section_id=None, section_type=None, rating_key=None, **kwargs):
|
def get_library_media_info(self, section_id=None, section_type=None, rating_key=None, refresh='', **kwargs):
|
||||||
|
|
||||||
|
if refresh == 'true':
|
||||||
|
refresh = True
|
||||||
|
else:
|
||||||
|
refresh = False
|
||||||
|
|
||||||
library_data = libraries.Libraries()
|
library_data = libraries.Libraries()
|
||||||
result = library_data.get_datatables_media_info(section_id=section_id,
|
result = library_data.get_datatables_media_info(section_id=section_id,
|
||||||
section_type=section_type,
|
section_type=section_type,
|
||||||
rating_key=rating_key,
|
rating_key=rating_key,
|
||||||
|
refresh=refresh,
|
||||||
kwargs=kwargs)
|
kwargs=kwargs)
|
||||||
|
|
||||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
def get_media_info_file_sizes(self, section_id=None, rating_key=None):
|
||||||
|
get_file_sizes = plexpy.CONFIG.GET_FILE_SIZES
|
||||||
|
section_ids = set(get_file_sizes['section_ids'])
|
||||||
|
rating_keys = set(get_file_sizes['rating_keys'])
|
||||||
|
|
||||||
|
if (section_id and section_id not in section_ids) or (rating_key and rating_key not in rating_keys):
|
||||||
|
if section_id:
|
||||||
|
section_ids.add(section_id)
|
||||||
|
elif rating_key:
|
||||||
|
rating_keys.add(rating_key)
|
||||||
|
plexpy.CONFIG.GET_FILE_SIZES = {'section_ids': list(section_ids), 'rating_keys': list(rating_keys)}
|
||||||
|
|
||||||
|
library_data = libraries.Libraries()
|
||||||
|
result = library_data.get_media_info_file_sizes(section_id=section_id,
|
||||||
|
rating_key=rating_key)
|
||||||
|
|
||||||
|
if section_id:
|
||||||
|
section_ids.remove(section_id)
|
||||||
|
elif rating_key:
|
||||||
|
rating_keys.remove(rating_key)
|
||||||
|
plexpy.CONFIG.GET_FILE_SIZES = {'section_ids': list(section_ids), 'rating_keys': list(rating_keys)}
|
||||||
|
else:
|
||||||
|
result = False
|
||||||
|
|
||||||
|
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||||
|
return json.dumps({'success': result})
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def get_library_unwatched(self, section_id=None, section_type=None, **kwargs):
|
def get_library_unwatched(self, section_id=None, section_type=None, **kwargs):
|
||||||
|
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
result = pms_connect.get_library_children(section_id=section_id,
|
result = pms_connect.get_library_children_details(section_id=section_id,
|
||||||
section_type=section_type,
|
section_type=section_type,
|
||||||
get_media_info=True,
|
get_media_info=True,
|
||||||
kwargs=kwargs)
|
kwargs=kwargs)
|
||||||
|
@ -438,17 +476,22 @@ class WebInterface(object):
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def delete_datatable_media_info_cache(self, section_id, **kwargs):
|
def delete_datatable_media_info_cache(self, section_id, **kwargs):
|
||||||
library_data = libraries.Libraries()
|
get_file_sizes = plexpy.CONFIG.GET_FILE_SIZES
|
||||||
|
section_ids = set(get_file_sizes['section_ids'])
|
||||||
|
|
||||||
if section_id:
|
if section_id not in section_ids:
|
||||||
delete_row = library_data.delete_datatable_media_info_cache(section_id=section_id)
|
if section_id:
|
||||||
|
library_data = libraries.Libraries()
|
||||||
|
delete_row = library_data.delete_datatable_media_info_cache(section_id=section_id)
|
||||||
|
|
||||||
if delete_row:
|
if delete_row:
|
||||||
|
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||||
|
return json.dumps({'message': delete_row})
|
||||||
|
else:
|
||||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||||
return json.dumps({'message': delete_row})
|
return json.dumps({'message': 'no data received'})
|
||||||
else:
|
else:
|
||||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
return json.dumps({'message': 'Cannot refresh library while getting file sizes.'})
|
||||||
return json.dumps({'message': 'no data received'})
|
|
||||||
|
|
||||||
##### Users #####
|
##### Users #####
|
||||||
|
|
||||||
|
@ -1406,7 +1449,7 @@ class WebInterface(object):
|
||||||
##### Info #####
|
##### Info #####
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def info(self, rating_key=None, source=None, **kwargs):
|
def info(self, rating_key=None, source=None, query=None, **kwargs):
|
||||||
metadata = None
|
metadata = None
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
|
@ -1425,7 +1468,7 @@ class WebInterface(object):
|
||||||
if metadata:
|
if metadata:
|
||||||
return serve_template(templatename="info.html", data=metadata, title="Info", config=config)
|
return serve_template(templatename="info.html", data=metadata, title="Info", config=config)
|
||||||
else:
|
else:
|
||||||
return self.update_metadata(rating_key)
|
return self.update_metadata(rating_key, query)
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def get_item_children(self, rating_key='', **kwargs):
|
def get_item_children(self, rating_key='', **kwargs):
|
||||||
|
@ -1518,7 +1561,7 @@ class WebInterface(object):
|
||||||
|
|
||||||
data_factory = datafactory.DataFactory()
|
data_factory = datafactory.DataFactory()
|
||||||
query = data_factory.get_search_query(rating_key=rating_key)
|
query = data_factory.get_search_query(rating_key=rating_key)
|
||||||
if query_string:
|
if query and query_string:
|
||||||
query['query_string'] = query_string
|
query['query_string'] = query_string
|
||||||
|
|
||||||
if query:
|
if query:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue