mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-06 21:21:15 -07:00
Massive code cleanup
* Finish up library pages (toggles and notifications) * Update user pages to match library pages * Fix no current activity bif thumbnail at the start of a stream * Improved logging throughout PlexPy
This commit is contained in:
parent
5fedac691d
commit
636f898da8
31 changed files with 2873 additions and 2715 deletions
|
@ -174,42 +174,42 @@ from plexpy import version
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
% if title=="Home":
|
% if title == "Home":
|
||||||
<li class="active"><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
|
<li class="active"><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
|
||||||
% else:
|
% else:
|
||||||
<li><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
|
<li><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
|
||||||
% endif
|
% endif
|
||||||
% if title=="Libraries" or title=="Library":
|
% if title == "Libraries" or title == "Library" or title == "Info":
|
||||||
<li class="active"><a href="libraries">Libraries</a></li>
|
<li class="active"><a href="libraries">Libraries</a></li>
|
||||||
% else:
|
% else:
|
||||||
<li><a href="libraries">Libraries</a></li>
|
<li><a href="libraries">Libraries</a></li>
|
||||||
% endif
|
% endif
|
||||||
% if title=="Users" or title=="User":
|
% if title == "Users" or title == "User":
|
||||||
<li class="active"><a href="users">Users</a></li>
|
<li class="active"><a href="users">Users</a></li>
|
||||||
% else:
|
% else:
|
||||||
<li><a href="users">Users</a></li>
|
<li><a href="users">Users</a></li>
|
||||||
% endif
|
% endif
|
||||||
% if title=="History":
|
% if title == "History":
|
||||||
<li class="active"><a href="history">History</a></li>
|
<li class="active"><a href="history">History</a></li>
|
||||||
% else:
|
% else:
|
||||||
<li><a href="history">History</a></li>
|
<li><a href="history">History</a></li>
|
||||||
% endif
|
% endif
|
||||||
% if title=="Graphs":
|
% if title == "Graphs":
|
||||||
<li class="active"><a href="graphs">Graphs</a></li>
|
<li class="active"><a href="graphs">Graphs</a></li>
|
||||||
% else:
|
% else:
|
||||||
<li><a href="graphs">Graphs</a></li>
|
<li><a href="graphs">Graphs</a></li>
|
||||||
% endif
|
% endif
|
||||||
% if title=="Synced Items":
|
% if title == "Synced Items":
|
||||||
<li class="active"><a href="sync">Synced Items</a></li>
|
<li class="active"><a href="sync">Synced Items</a></li>
|
||||||
% else:
|
% else:
|
||||||
<li><a href="sync">Synced Items</a></li>
|
<li><a href="sync">Synced Items</a></li>
|
||||||
% endif
|
% endif
|
||||||
% if title=="Log":
|
% if title == "Log":
|
||||||
<li class="active"><a href="logs">Logs</a></li>
|
<li class="active"><a href="logs">Logs</a></li>
|
||||||
% else:
|
% else:
|
||||||
<li><a href="logs">Logs</a></li>
|
<li><a href="logs">Logs</a></li>
|
||||||
% endif
|
% endif
|
||||||
% if title=="Settings":
|
% if title == "Settings":
|
||||||
<li class="active"><a href="settings">Settings</a></li>
|
<li class="active"><a href="settings">Settings</a></li>
|
||||||
% else:
|
% else:
|
||||||
<li><a href="settings">Settings</a></li>
|
<li><a href="settings">Settings</a></li>
|
||||||
|
|
|
@ -2463,6 +2463,7 @@ a .home-platforms-instance-list-oval:hover,
|
||||||
}
|
}
|
||||||
#users-to-delete > li,
|
#users-to-delete > li,
|
||||||
#users-to-purge > li,
|
#users-to-purge > li,
|
||||||
|
#libraries-to-delete > li,
|
||||||
#libraries-to-purge > li {
|
#libraries-to-purge > li {
|
||||||
color: #e9a049;
|
color: #e9a049;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,9 +72,9 @@ DOCUMENTATION :: END
|
||||||
<a href="info?rating_key=${a['rating_key']}">
|
<a href="info?rating_key=${a['rating_key']}">
|
||||||
% endif
|
% endif
|
||||||
<div class="dashboard-activity-poster">
|
<div class="dashboard-activity-poster">
|
||||||
% if a['media_type'] == 'movie' and not a['indexes']:
|
% if (a['media_type'] == 'movie' and not a['indexes']) or (a['indexes'] and not a['view_offset']):
|
||||||
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div>
|
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div>
|
||||||
% elif a['media_type'] == 'episode' and not a['indexes']:
|
% elif (a['media_type'] == 'episode' and not a['indexes']) or (a['indexes'] and not a['view_offset']):
|
||||||
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div>
|
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div>
|
||||||
% elif a['indexes']:
|
% elif a['indexes']:
|
||||||
<div class="dashboard-activity-poster-face bif" style="background-image: url(pms_image_proxy?img=${a['bif_thumb']}&width=500&height=280); display: none;"></div>
|
<div class="dashboard-activity-poster-face bif" style="background-image: url(pms_image_proxy?img=${a['bif_thumb']}&width=500&height=280); display: none;"></div>
|
||||||
|
|
|
@ -14,6 +14,8 @@ section_id Returns the library id of the library.
|
||||||
section_name Returns the name of the library.
|
section_name Returns the name of the library.
|
||||||
section_type Returns the type of the library.
|
section_type Returns the type of the library.
|
||||||
library_thumb Returns the thumbnail for the library.
|
library_thumb Returns the thumbnail for the library.
|
||||||
|
custom_thumb Returns the custom thumbnail for the library.
|
||||||
|
library_art Returns the artwork for the library.
|
||||||
count Returns the item count for the library.
|
count Returns the item count for the library.
|
||||||
parent_count Returns the parent item count for the library.
|
parent_count Returns the parent item count for the library.
|
||||||
child_count Returns the child item count for the library.
|
child_count Returns the child item count for the library.
|
||||||
|
@ -40,11 +42,7 @@ DOCUMENTATION :: END
|
||||||
<label for="profile_url">Library Picture URL</label>
|
<label for="profile_url">Library Picture URL</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
% if data['custom_thumb']:
|
|
||||||
<input type="text" class="form-control" id="custom_thumb_url" name="custom_thumb_url" value="${data['custom_thumb']}">
|
|
||||||
% else:
|
|
||||||
<input type="text" class="form-control" id="custom_thumb_url" name="custom_thumb_url" value="${data['library_thumb']}">
|
<input type="text" class="form-control" id="custom_thumb_url" name="custom_thumb_url" value="${data['library_thumb']}">
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">Change the library's picture in PlexPy. To reset to default, leave this field empty and save.</p>
|
<p class="help-block">Change the library's picture in PlexPy. To reset to default, leave this field empty and save.</p>
|
||||||
|
@ -61,6 +59,12 @@ DOCUMENTATION :: END
|
||||||
</label>
|
</label>
|
||||||
<p class="help-block">Uncheck this if you do not want this keep any history on this library's activity.</p>
|
<p class="help-block">Uncheck this if you do not want this keep any history on this library's activity.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" id="do_notify_created" name="do_notify_created" value="1" ${helpers.checked(data['do_notify_created'])}> Enable recently added notifications
|
||||||
|
</label>
|
||||||
|
<p class="help-block">Uncheck this if you do not want to receive recently added notifications for this library.</p>
|
||||||
|
</div>
|
||||||
% if data['section_id']:
|
% if data['section_id']:
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button class="btn btn-danger" id="delete-all-history">Purge</button>
|
<button class="btn btn-danger" id="delete-all-history">Purge</button>
|
||||||
|
@ -96,14 +100,18 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
// Set new friendly name
|
// Save library options
|
||||||
$("#save_library").click(function () {
|
$("#save_library").on('click', function () {
|
||||||
var custom_thumb = $("#custom_thumb_url").val();
|
var custom_thumb = $("#custom_thumb_url").val();
|
||||||
var do_notify = 0;
|
var do_notify = 0;
|
||||||
|
var do_notify_created = 0;
|
||||||
var keep_history = 0;
|
var keep_history = 0;
|
||||||
if ($("#do_notify").is(":checked")) {
|
if ($("#do_notify").is(":checked")) {
|
||||||
do_notify = 1;
|
do_notify = 1;
|
||||||
}
|
}
|
||||||
|
if ($("#do_notify_created").is(":checked")) {
|
||||||
|
do_notify_created = 1;
|
||||||
|
}
|
||||||
if ($("#keep_history").is(":checked")) {
|
if ($("#keep_history").is(":checked")) {
|
||||||
keep_history = 1;
|
keep_history = 1;
|
||||||
}
|
}
|
||||||
|
@ -112,9 +120,10 @@ DOCUMENTATION :: END
|
||||||
url: 'edit_library',
|
url: 'edit_library',
|
||||||
data: {
|
data: {
|
||||||
section_id: '${data["section_id"]}',
|
section_id: '${data["section_id"]}',
|
||||||
|
custom_thumb: custom_thumb,
|
||||||
do_notify: do_notify,
|
do_notify: do_notify,
|
||||||
keep_history: keep_history,
|
do_notify_created: do_notify_created,
|
||||||
custom_thumb: custom_thumb
|
keep_history: keep_history
|
||||||
},
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
async: true,
|
async: true,
|
||||||
|
@ -167,5 +176,4 @@ DOCUMENTATION :: END
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
% endif
|
% endif
|
|
@ -10,21 +10,30 @@ Variable names: data [list]
|
||||||
data :: Usable parameters
|
data :: Usable parameters
|
||||||
|
|
||||||
== Global keys ==
|
== Global keys ==
|
||||||
user Return the real Plex username
|
user_id Returns the user id of the user.
|
||||||
user_id Return the Plex user_id
|
username Returns the user's username.
|
||||||
friendly_name Returns the friendly edited Plex username
|
friendly_name Returns the friendly name of the user.
|
||||||
do_notify Returns bool value for whether the user should trigger notifications
|
email Returns the user's email address.
|
||||||
keep_history Returns bool value for whether the user's activity should be logged
|
user_thumb Returns the thumbnail for the user.
|
||||||
|
is_home_user Returns bool value for whether the user is part of a Plex Home.
|
||||||
|
is_allow_sync Returns bool value for whether the user has sync rights.
|
||||||
|
is_restricted Returns bool value for whether the user account is restricted.
|
||||||
|
do_notify Returns bool value for whether to send notifications for the user.
|
||||||
|
keep_history Returns bool value for whether to keep history for the user.
|
||||||
|
|
||||||
DOCUMENTATION :: END
|
DOCUMENTATION :: END
|
||||||
</%doc>
|
</%doc>
|
||||||
|
|
||||||
% if data is not None:
|
<%!
|
||||||
|
from plexpy import helpers
|
||||||
|
%>
|
||||||
|
|
||||||
|
% if data != None:
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
|
||||||
<h4 class="modal-title">Edit user <strong>${data['user']}</strong></h4>
|
<h4 class="modal-title">Edit user <strong>${data['username']}</strong></h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body" id="modal-text">
|
<div class="modal-body" id="modal-text">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
@ -41,20 +50,20 @@ DOCUMENTATION :: END
|
||||||
<label for="profile_url">Profile Picture URL</label>
|
<label for="profile_url">Profile Picture URL</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input type="text" class="form-control" id="profile_url" name="profile_url" value="${data['thumb']}">
|
<input type="text" class="form-control" id="custom_avatar_url" name="custom_avatar_url" value="${data['user_thumb']}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<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>
|
<p class="help-block">Change the users profile picture in PlexPy. To reset to default, leave this field empty and save.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="do_notify" name="do_notify" value="1" ${data['do_notify']}> Enable notifications
|
<input type="checkbox" id="do_notify" name="do_notify" value="1" ${helpers.checked(data['do_notify'])}> Enable notifications
|
||||||
</label>
|
</label>
|
||||||
<p class="help-block">Uncheck this if you do not want to receive notifications for this user's activity.</p>
|
<p class="help-block">Uncheck this if you do not want to receive notifications for this user's activity.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="keep_history" name="keep_history" value="1" ${data['keep_history']}> Keep history
|
<input type="checkbox" id="keep_history" name="keep_history" value="1" ${helpers.checked(data['keep_history'])}> Keep history
|
||||||
</label>
|
</label>
|
||||||
<p class="help-block">Uncheck this if you do not want this keep any history on this user's activity.</p>
|
<p class="help-block">Uncheck this if you do not want this keep any history on this user's activity.</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -69,7 +78,7 @@ DOCUMENTATION :: END
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<div>
|
<div>
|
||||||
<span id="edit-user-status-message"></span>
|
<span id="edit-user-status-message"></span>
|
||||||
<input type="button" id="save_user_name" class="btn btn-bright" value="Save">
|
<input type="button" id="save_user" class="btn btn-bright" value="Save">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -93,10 +102,10 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
// Set new friendly name
|
// Set user options
|
||||||
$("#save_user_name").click(function() {
|
$("#save_user").on('click', function () {
|
||||||
var friendly_name = $("#friendly_name").val();
|
var friendly_name = $("#friendly_name").val();
|
||||||
var thumb = $("#profile_url").val();
|
var custom_thumb = $("#custom_avatar_url").val();
|
||||||
var do_notify = 0;
|
var do_notify = 0;
|
||||||
var keep_history = 0;
|
var keep_history = 0;
|
||||||
if ($("#do_notify").is(":checked")) {
|
if ($("#do_notify").is(":checked")) {
|
||||||
|
@ -106,35 +115,21 @@ DOCUMENTATION :: END
|
||||||
keep_history = 1;
|
keep_history = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
% if data['user_id']:
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'edit_user',
|
url: 'edit_user',
|
||||||
data: {user_id: '${data['user_id']}', friendly_name: friendly_name, do_notify: do_notify, keep_history: keep_history, thumb: thumb},
|
data: {
|
||||||
|
user_id: '${data["user_id"]}',
|
||||||
|
friendly_name: friendly_name,
|
||||||
|
custom_thumb: custom_thumb,
|
||||||
|
do_notify: do_notify,
|
||||||
|
keep_history: keep_history
|
||||||
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
async: true,
|
async: true,
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
$("#edit-user-status-message").html(data);
|
location.reload();
|
||||||
if ($.trim(friendly_name) !== '') {
|
|
||||||
$('.set-username').html(document.createTextNode(friendly_name));
|
|
||||||
}
|
|
||||||
$("#user-profile-thumb").attr('src', thumb);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
% else:
|
|
||||||
$.ajax({
|
|
||||||
url: 'edit_user',
|
|
||||||
data: {user: '${data['user']}', friendly_name: friendly_name, do_notify: do_notify, keep_history: keep_history, thumb: thumb},
|
|
||||||
cache: false,
|
|
||||||
async: true,
|
|
||||||
success: function(data) {
|
|
||||||
$("#edit-user-status-message").html(data);
|
|
||||||
if ($.trim(friendly_name) !== '') {
|
|
||||||
$(".set-username").html(friendly_name);
|
|
||||||
}
|
|
||||||
$("#user-profile-thumb").attr('src', thumb);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
% endif
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#delete-all-history").on('click', function() {
|
$("#delete-all-history").on('click', function() {
|
||||||
|
@ -142,7 +137,7 @@ DOCUMENTATION :: END
|
||||||
$('#confirm-modal').one('click', '#confirm-purge', function () {
|
$('#confirm-modal').one('click', '#confirm-purge', function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'delete_all_user_history',
|
url: 'delete_all_user_history',
|
||||||
data: {user_id: '${data['user_id']}'},
|
data: { user_id: '${data["user_id"]}' },
|
||||||
cache: false,
|
cache: false,
|
||||||
async: true,
|
async: true,
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
|
@ -155,7 +150,8 @@ DOCUMENTATION :: END
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Move #confirm-modal to parent container
|
// Move #confirm-modal to parent container
|
||||||
if(!($('#edit-user-modal').next().is('#confirm-modal'))) {
|
if(!($('#edit-user-modal').next().is('#confirm-modal'))) {
|
||||||
$('#confirm-modal').appendTo($('#edit-user-modal').parent()); }
|
$('#confirm-modal').appendTo($('#edit-user-modal').parent());
|
||||||
|
}
|
||||||
$('#edit-user-modal > #confirm-modal').remove();
|
$('#edit-user-modal > #confirm-modal').remove();
|
||||||
|
|
||||||
$('#edit-user-modal').css('z-index', '1050');
|
$('#edit-user-modal').css('z-index', '1050');
|
||||||
|
@ -179,5 +175,4 @@ DOCUMENTATION :: END
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
% endif
|
% endif
|
|
@ -18,8 +18,8 @@ duration Returns the standard runtime of the media.
|
||||||
content_rating Returns the age rating for the media.
|
content_rating Returns the age rating for the media.
|
||||||
summary Returns a brief description of the media plot.
|
summary Returns a brief description of the media plot.
|
||||||
grandparent_title Returns the name of the show, or artist.
|
grandparent_title Returns the name of the show, or artist.
|
||||||
parent_index Returns the index number of the season.
|
parent_media_index Returns the index number of the season.
|
||||||
index Returns the index number of the episode, or track.
|
media_index Returns the index number of the episode, or track.
|
||||||
parent_thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
|
parent_thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
|
||||||
writers Returns an array of writers.
|
writers Returns an array of writers.
|
||||||
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
|
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
|
||||||
|
@ -54,29 +54,29 @@ DOCUMENTATION :: END
|
||||||
<div class="summary-navbar-list">
|
<div class="summary-navbar-list">
|
||||||
<ul class="list-unstyled breadcrumb">
|
<ul class="list-unstyled breadcrumb">
|
||||||
% if data['media_type'] == 'movie':
|
% if data['media_type'] == 'movie':
|
||||||
<li><a href="library?section_id=${data['library_id']}">${data['library_title']}</a></li>
|
<li><a href="library?section_id=${data['library_id']}">${data['library_name']}</a></li>
|
||||||
<li class="active">${data['title']}</li>
|
<li class="active">${data['title']}</li>
|
||||||
% elif data['media_type'] == 'show':
|
% elif data['media_type'] == 'show':
|
||||||
<li><a href="library?section_id=${data['library_id']}">${data['library_title']}</a></li>
|
<li><a href="library?section_id=${data['library_id']}">${data['library_name']}</a></li>
|
||||||
<li class="active">${data['title']}</li>
|
<li class="active">${data['title']}</li>
|
||||||
% elif data['media_type'] == 'season':
|
% elif data['media_type'] == 'season':
|
||||||
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['library_id']}">${data['library_title']}</a></li>
|
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['library_id']}">${data['library_name']}</a></li>
|
||||||
<li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li>
|
<li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li>
|
||||||
<li class="active">Season ${data['media_index']}</li>
|
<li class="active">Season ${data['media_index']}</li>
|
||||||
% elif data['media_type'] == 'episode':
|
% elif data['media_type'] == 'episode':
|
||||||
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['library_id']}">${data['library_title']}</a></li>
|
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['library_id']}">${data['library_name']}</a></li>
|
||||||
<li class="hidden-xs hidden-sm"><a href="info?rating_key=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></li>
|
<li class="hidden-xs hidden-sm"><a href="info?rating_key=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></li>
|
||||||
<li><a href="info?rating_key=${data['parent_rating_key']}">Season ${data['parent_media_index']}</a></li>
|
<li><a href="info?rating_key=${data['parent_rating_key']}">Season ${data['parent_media_index']}</a></li>
|
||||||
<li class="active">Episode ${data['media_index']} - ${data['title']}</li>
|
<li class="active">Episode ${data['media_index']} - ${data['title']}</li>
|
||||||
% elif data['media_type'] == 'artist':
|
% elif data['media_type'] == 'artist':
|
||||||
<li><a href="library?section_id=${data['library_id']}">${data['library_title']}</a></li>
|
<li><a href="library?section_id=${data['library_id']}">${data['library_name']}</a></li>
|
||||||
<li class="active">${data['title']}</li>
|
<li class="active">${data['title']}</li>
|
||||||
% elif data['media_type'] == 'album':
|
% elif data['media_type'] == 'album':
|
||||||
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['library_id']}">${data['library_title']}</a></li>
|
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['library_id']}">${data['library_name']}</a></li>
|
||||||
<li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li>
|
<li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li>
|
||||||
<li class="active">${data['title']}</li>
|
<li class="active">${data['title']}</li>
|
||||||
% elif data['media_type'] == 'track':
|
% elif data['media_type'] == 'track':
|
||||||
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['library_id']}">${data['library_title']}</a></li>
|
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['library_id']}">${data['library_name']}</a></li>
|
||||||
<li class="hidden-xs hidden-sm"><a href="info?rating_key=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></li>
|
<li class="hidden-xs hidden-sm"><a href="info?rating_key=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></li>
|
||||||
<li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li>
|
<li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li>
|
||||||
<li class="active">Track ${data['media_index']} - ${data['title']}</li>
|
<li class="active">Track ${data['media_index']} - ${data['title']}</li>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
var libraries_to_delete = [];
|
||||||
var libraries_to_purge = [];
|
var libraries_to_purge = [];
|
||||||
|
|
||||||
libraries_list_table_options = {
|
libraries_list_table_options = {
|
||||||
|
@ -23,9 +24,12 @@ libraries_list_table_options = {
|
||||||
"data": null,
|
"data": null,
|
||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
$(td).html('<div class="edit-library-toggles">' +
|
$(td).html('<div class="edit-library-toggles">' +
|
||||||
|
'<button class="btn btn-xs btn-warning delete-library" data-id="' + rowData['section_id'] + '" data-toggle="button"><i class="fa fa-trash-o fa-fw"></i> Delete</button> ' +
|
||||||
'<button class="btn btn-xs btn-warning purge-library" data-id="' + rowData['section_id'] + '" data-toggle="button"><i class="fa fa-eraser fa-fw"></i> Purge</button>   ' +
|
'<button class="btn btn-xs btn-warning purge-library" data-id="' + rowData['section_id'] + '" data-toggle="button"><i class="fa fa-eraser fa-fw"></i> Purge</button>   ' +
|
||||||
'<input type="checkbox" id="do_notify-' + rowData['section_id'] + '" name="do_notify" value="1" ' + rowData['do_notify'] + '><label class="edit-tooltip" for="do_notify-' + rowData['section_id'] + '" data-toggle="tooltip" title="Toggle Notifications"><i class="fa fa-bell fa-lg fa-fw"></i></label> ' +
|
'<input type="checkbox" id="do_notify-' + rowData['section_id'] + '" name="do_notify" value="1" ' + rowData['do_notify'] + '><label class="edit-tooltip" for="do_notify-' + rowData['section_id'] + '" data-toggle="tooltip" title="Toggle Notifications"><i class="fa fa-bell fa-lg fa-fw"></i></label> ' +
|
||||||
'<input type="checkbox" id="keep_history-' + rowData['section_id'] + '" name="keep_history" value="1" ' + rowData['keep_history'] + '><label class="edit-tooltip" for="keep_history-' + rowData['section_id'] + '" data-toggle="tooltip" title="Toggle History"><i class="fa fa-history fa-lg fa-fw"></i></label> ');
|
'<input type="checkbox" id="keep_history-' + rowData['section_id'] + '" name="keep_history" value="1" ' + rowData['keep_history'] + '><label class="edit-tooltip" for="keep_history-' + rowData['section_id'] + '" data-toggle="tooltip" title="Toggle History"><i class="fa fa-history fa-lg fa-fw"></i></label> ' +
|
||||||
|
'<input type="checkbox" id="do_notify_created-' + rowData['section_id'] + '" name="do_notify_created" value="1" ' + rowData['do_notify_created'] + '><label class="edit-tooltip" for="do_notify_created-' + rowData['section_id'] + '" data-toggle="tooltip" title="Toggle Recently Added"><i class="fa fa-download fa-lg fa-fw"></i></label> ' +
|
||||||
|
'</div>');
|
||||||
},
|
},
|
||||||
"width": "7%",
|
"width": "7%",
|
||||||
"className": "edit-control no-wrap hidden",
|
"className": "edit-control no-wrap hidden",
|
||||||
|
@ -37,10 +41,10 @@ libraries_list_table_options = {
|
||||||
"data": "library_thumb",
|
"data": "library_thumb",
|
||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
if (cellData === '') {
|
if (cellData === '') {
|
||||||
$(td).html('<a href="library?section_id=' + rowData['section_id'] + '"><div class="libraries-poster-face" style="background-image: url(pms_image_proxy?img=' + rowData['library_thumb'] + '&width=80&height=80&fallback=poster);"></div></a>');
|
$(td).html('<a href="library?section_id=' + rowData['section_id'] + '"><div class="libraries-poster-face" style="background-image: url(interfaces/default/images/cover.png);"></div></a>');
|
||||||
} else {
|
} else {
|
||||||
if (rowData['custom_thumb']) {
|
if (rowData['library_thumb'].substring(0, 4) == "http") {
|
||||||
$(td).html('<a href="library?section_id=' + rowData['section_id'] + '"><div class="libraries-poster-face" style="background-image: url(' + rowData['custom_thumb'] + ');"></div></a>');
|
$(td).html('<a href="library?section_id=' + rowData['section_id'] + '"><div class="libraries-poster-face" style="background-image: url(' + rowData['library_thumb'] + ');"></div></a>');
|
||||||
} else {
|
} else {
|
||||||
$(td).html('<a href="library?section_id=' + rowData['section_id'] + '"><div class="libraries-poster-face" style="background-image: url(pms_image_proxy?img=' + rowData['library_thumb'] + '&width=80&height=80&fallback=poster);"></div></a>');
|
$(td).html('<a href="library?section_id=' + rowData['section_id'] + '"><div class="libraries-poster-face" style="background-image: url(pms_image_proxy?img=' + rowData['library_thumb'] + '&width=80&height=80&fallback=poster);"></div></a>');
|
||||||
}
|
}
|
||||||
|
@ -56,7 +60,9 @@ libraries_list_table_options = {
|
||||||
"data": "section_name",
|
"data": "section_name",
|
||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
if (cellData !== '') {
|
if (cellData !== '') {
|
||||||
$(td).html('<div data-id="' + rowData['section_id'] + '"><a href="library?section_id=' + rowData['section_id'] + '">' + cellData + '</a></div>');
|
$(td).html('<div data-id="' + rowData['section_id'] + '">' +
|
||||||
|
'<a href="library?section_id=' + rowData['section_id'] + '">' + cellData + '</a>' +
|
||||||
|
'</div>');
|
||||||
} else {
|
} else {
|
||||||
$(td).html(cellData);
|
$(td).html(cellData);
|
||||||
}
|
}
|
||||||
|
@ -198,8 +204,11 @@ libraries_list_table_options = {
|
||||||
showMsg(msg, false, false, 0)
|
showMsg(msg, false, false, 0)
|
||||||
},
|
},
|
||||||
"rowCallback": function (row, rowData) {
|
"rowCallback": function (row, rowData) {
|
||||||
|
if ($.inArray(rowData['section_id'], libraries_to_delete) !== -1) {
|
||||||
|
$(row).find('button.delete-library[data-id="' + rowData['section_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
|
}
|
||||||
if ($.inArray(rowData['section_id'], libraries_to_purge) !== -1) {
|
if ($.inArray(rowData['section_id'], libraries_to_purge) !== -1) {
|
||||||
$(row).find('button[data-id="' + rowData['section_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger');
|
$(row).find('button.purge-library[data-id="' + rowData['section_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,10 +219,14 @@ $('#libraries_list_table').on('change', 'td.edit-control > .edit-library-toggles
|
||||||
var rowData = row.data();
|
var rowData = row.data();
|
||||||
|
|
||||||
var do_notify = 0;
|
var do_notify = 0;
|
||||||
|
var do_notify_created = 0;
|
||||||
var keep_history = 0;
|
var keep_history = 0;
|
||||||
if ($('#do_notify-' + rowData['section_id']).is(':checked')) {
|
if ($('#do_notify-' + rowData['section_id']).is(':checked')) {
|
||||||
do_notify = 1;
|
do_notify = 1;
|
||||||
}
|
}
|
||||||
|
if ($('#do_notify_created-' + rowData['section_id']).is(':checked')) {
|
||||||
|
do_notify_created = 1;
|
||||||
|
}
|
||||||
if ($('#keep_history-' + rowData['section_id']).is(':checked')) {
|
if ($('#keep_history-' + rowData['section_id']).is(':checked')) {
|
||||||
keep_history = 1;
|
keep_history = 1;
|
||||||
}
|
}
|
||||||
|
@ -228,6 +241,7 @@ $('#libraries_list_table').on('change', 'td.edit-control > .edit-library-toggles
|
||||||
data: {
|
data: {
|
||||||
section_id: rowData['section_id'],
|
section_id: rowData['section_id'],
|
||||||
do_notify: do_notify,
|
do_notify: do_notify,
|
||||||
|
do_notify_created: do_notify_created,
|
||||||
keep_history: keep_history,
|
keep_history: keep_history,
|
||||||
custom_thumb: custom_thumb
|
custom_thumb: custom_thumb
|
||||||
},
|
},
|
||||||
|
@ -240,17 +254,44 @@ $('#libraries_list_table').on('change', 'td.edit-control > .edit-library-toggles
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#libraries_list_table').on('click', 'td.edit-control > .edit-library-toggles > button.delete-library', function () {
|
||||||
|
var tr = $(this).parents('tr');
|
||||||
|
var row = libraries_list_table.row(tr);
|
||||||
|
var rowData = row.data();
|
||||||
|
|
||||||
|
var index_delete = $.inArray(rowData['section_id'], libraries_to_delete);
|
||||||
|
var index_purge = $.inArray(rowData['section_id'], libraries_to_purge);
|
||||||
|
|
||||||
|
if (index_delete === -1) {
|
||||||
|
libraries_to_delete.push(rowData['section_id']);
|
||||||
|
if (index_purge === -1) {
|
||||||
|
tr.find('button.purge-library').click();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
libraries_to_delete.splice(index_delete, 1);
|
||||||
|
if (index_purge != -1) {
|
||||||
|
tr.find('button.purge-library').click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$(this).toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
$('#libraries_list_table').on('click', 'td.edit-control > .edit-library-toggles > button.purge-library', function () {
|
$('#libraries_list_table').on('click', 'td.edit-control > .edit-library-toggles > button.purge-library', function () {
|
||||||
var tr = $(this).parents('tr');
|
var tr = $(this).parents('tr');
|
||||||
var row = libraries_list_table.row(tr);
|
var row = libraries_list_table.row(tr);
|
||||||
var rowData = row.data();
|
var rowData = row.data();
|
||||||
|
|
||||||
|
var index_delete = $.inArray(rowData['section_id'], libraries_to_delete);
|
||||||
var index_purge = $.inArray(rowData['section_id'], libraries_to_purge);
|
var index_purge = $.inArray(rowData['section_id'], libraries_to_purge);
|
||||||
|
|
||||||
if (index_purge === -1) {
|
if (index_purge === -1) {
|
||||||
libraries_to_purge.push(rowData['section_id']);
|
libraries_to_purge.push(rowData['section_id']);
|
||||||
} else {
|
} else {
|
||||||
libraries_to_purge.splice(index_purge, 1);
|
libraries_to_purge.splice(index_purge, 1);
|
||||||
|
if (index_delete != -1) {
|
||||||
|
tr.find('button.delete-library').click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$(this).toggleClass('btn-warning').toggleClass('btn-danger');
|
$(this).toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
});
|
});
|
|
@ -23,12 +23,12 @@ users_list_table_options = {
|
||||||
"targets": [0],
|
"targets": [0],
|
||||||
"data": null,
|
"data": null,
|
||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
$(td).html('<div class="edit-user-toggles"><button class="btn btn-xs btn-warning delete-user" data-id="' + rowData['user_id'] + '" data-toggle="button"><i class="fa fa-trash-o fa-fw"></i> Delete</button> ' +
|
$(td).html('<div class="edit-user-toggles">' +
|
||||||
|
'<button class="btn btn-xs btn-warning delete-user" data-id="' + rowData['user_id'] + '" data-toggle="button"><i class="fa fa-trash-o fa-fw"></i> Delete</button> ' +
|
||||||
'<button class="btn btn-xs btn-warning purge-user" data-id="' + rowData['user_id'] + '" data-toggle="button"><i class="fa fa-eraser fa-fw"></i> Purge</button>   ' +
|
'<button class="btn btn-xs btn-warning purge-user" data-id="' + rowData['user_id'] + '" data-toggle="button"><i class="fa fa-eraser fa-fw"></i> Purge</button>   ' +
|
||||||
'<input type="checkbox" id="do_notify-' + rowData['user_id'] + '" name="do_notify" value="1" ' + rowData['do_notify'] + '><label class="edit-tooltip" for="do_notify-' + rowData['user_id'] + '" data-toggle="tooltip" title="Toggle Notifications"><i class="fa fa-bell fa-lg fa-fw"></i></label> ' +
|
'<input type="checkbox" id="do_notify-' + rowData['user_id'] + '" name="do_notify" value="1" ' + rowData['do_notify'] + '><label class="edit-tooltip" for="do_notify-' + rowData['user_id'] + '" data-toggle="tooltip" title="Toggle Notifications"><i class="fa fa-bell fa-lg fa-fw"></i></label> ' +
|
||||||
'<input type="checkbox" id="keep_history-' + rowData['user_id'] + '" name="keep_history" value="1" ' + rowData['keep_history'] + '><label class="edit-tooltip" for="keep_history-' + rowData['user_id'] + '" data-toggle="tooltip" title="Toggle History"><i class="fa fa-history fa-lg fa-fw"></i></label> ');
|
'<input type="checkbox" id="keep_history-' + rowData['user_id'] + '" name="keep_history" value="1" ' + rowData['keep_history'] + '><label class="edit-tooltip" for="keep_history-' + rowData['user_id'] + '" data-toggle="tooltip" title="Toggle History"><i class="fa fa-history fa-lg fa-fw"></i></label> ' +
|
||||||
// Show/hide user currently doesn't work
|
'</div>');
|
||||||
//'<input type="checkbox" id="show_hide-' + rowData['user_id'] + '" name="show_hide" value="1" checked><label class="edit-tooltip" for="show_hide-' + rowData['user_id'] + '" data-toggle="tooltip" title="Show/Hide User"><i class="fa fa-eye fa-lg fa-fw"></i></label>');
|
|
||||||
},
|
},
|
||||||
"width": "7%",
|
"width": "7%",
|
||||||
"className": "edit-control no-wrap hidden",
|
"className": "edit-control no-wrap hidden",
|
||||||
|
@ -42,7 +42,7 @@ users_list_table_options = {
|
||||||
if (cellData === '') {
|
if (cellData === '') {
|
||||||
$(td).html('<a href="user?user_id=' + rowData['user_id'] + '"><div class="users-poster-face" style="background-image: url(interfaces/default/images/gravatar-default-80x80.png);"></div></a>');
|
$(td).html('<a href="user?user_id=' + rowData['user_id'] + '"><div class="users-poster-face" style="background-image: url(interfaces/default/images/gravatar-default-80x80.png);"></div></a>');
|
||||||
} else {
|
} else {
|
||||||
$(td).html('<a href="user?user_id=' + rowData['user_id'] + '"><div class="users-poster-face" style="background-image: url(' + cellData + ');"></div></a>');
|
$(td).html('<a href="user?user_id=' + rowData['user_id'] + '"><div class="users-poster-face" style="background-image: url(' + rowData['user_thumb'] + ');"></div></a>');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"orderable": false,
|
"orderable": false,
|
||||||
|
@ -55,13 +55,10 @@ users_list_table_options = {
|
||||||
"data": "friendly_name",
|
"data": "friendly_name",
|
||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
if (cellData !== '') {
|
if (cellData !== '') {
|
||||||
if (rowData['user_id'] > 0) {
|
$(td).html('<div class="edit-user-name" data-id="' + rowData['user_id'] + '">' +
|
||||||
$(td).html('<div class="edit-user-name" data-id="' + rowData['user_id'] + '"><a href="user?user_id=' + rowData['user_id'] + '">' + cellData + '</a>' +
|
'<a href="user?user_id=' + rowData['user_id'] + '">' + cellData + '</a>' +
|
||||||
'<input type="text" class="hidden" value="' + cellData + '"></div>');
|
'<input type="text" class="hidden" value="' + cellData + '">' +
|
||||||
} else {
|
'</div>');
|
||||||
$(td).html('<div class="edit-user-name" data-id="' + rowData['user_id'] + '"><a href="user?user=' + rowData['user'] + '">' + cellData + '</a>' +
|
|
||||||
'<input type="text" class="hidden" value="' + cellData + '"></div>');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$(td).html(cellData);
|
$(td).html(cellData);
|
||||||
}
|
}
|
||||||
|
@ -206,8 +203,11 @@ users_list_table_options = {
|
||||||
showMsg(msg, false, false, 0)
|
showMsg(msg, false, false, 0)
|
||||||
},
|
},
|
||||||
"rowCallback": function (row, rowData) {
|
"rowCallback": function (row, rowData) {
|
||||||
|
if ($.inArray(rowData['user_id'], users_to_delete) !== -1) {
|
||||||
|
$(row).find('button.delete-user[data-id="' + rowData['user_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
|
}
|
||||||
if ($.inArray(rowData['user_id'], users_to_purge) !== -1) {
|
if ($.inArray(rowData['user_id'], users_to_purge) !== -1) {
|
||||||
$(row).find('button[data-id="' + rowData['user_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger');
|
$(row).find('button.purge-user[data-id="' + rowData['user_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,15 +43,16 @@
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
|
||||||
<h4 class="modal-title" id="myModalLabel">Confirm Purge</h4>
|
<h4 class="modal-title" id="myModalLabel">Confirm Delete/Purge</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body" style="text-align: center;">
|
<div class="modal-body" style="text-align: center;">
|
||||||
|
<ul id="libraries-to-delete" class="list-unstyled"></ul>
|
||||||
<ul id="libraries-to-purge" class="list-unstyled"></ul>
|
<ul id="libraries-to-purge" class="list-unstyled"></ul>
|
||||||
<p>This is permanent and cannot be undone!</p>
|
<p>This is permanent and cannot be undone!</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-dark" data-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-dark" data-dismiss="modal">Cancel</button>
|
||||||
<button type="button" class="btn btn-danger btn-ok" data-dismiss="modal" id="confirm-purge">Confirm</button>
|
<button type="button" class="btn btn-danger btn-ok" data-dismiss="modal" id="confirm-delete">Confirm</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -83,7 +84,8 @@
|
||||||
|
|
||||||
$('#row-edit-mode').on('click', function () {
|
$('#row-edit-mode').on('click', function () {
|
||||||
$('#row-edit-mode-alert').fadeIn(200);
|
$('#row-edit-mode-alert').fadeIn(200);
|
||||||
$('#libraries_to_purge').html('');
|
$('#libraries-to-delete').html('');
|
||||||
|
$('#libraries-to-purge').html('');
|
||||||
|
|
||||||
if ($(this).hasClass('active')) {
|
if ($(this).hasClass('active')) {
|
||||||
if (libraries_to_purge.length > 0) {
|
if (libraries_to_purge.length > 0) {
|
||||||
|
@ -91,6 +93,17 @@
|
||||||
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
libraries_to_purge = $.grep(libraries_to_purge, function (value) {
|
||||||
|
return $.inArray(value, libraries_to_delete) < 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (libraries_to_delete.length > 0) {
|
||||||
|
$('#libraries-to-delete').prepend('<p>Are you REALLY sure you want to delete the following libraries:</p>')
|
||||||
|
for (var i = 0; i < libraries_to_delete.length; i++) {
|
||||||
|
$('#libraries-to-delete').append('<li>' + $('div[data-id=' + libraries_to_delete[i] + ']').text() + '</li>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (libraries_to_purge.length > 0) {
|
if (libraries_to_purge.length > 0) {
|
||||||
$('#libraries-to-purge').prepend('<p>Are you REALLY sure you want to purge all history for the following libraries:</p>')
|
$('#libraries-to-purge').prepend('<p>Are you REALLY sure you want to purge all history for the following libraries:</p>')
|
||||||
for (var i = 0; i < libraries_to_purge.length; i++) {
|
for (var i = 0; i < libraries_to_purge.length; i++) {
|
||||||
|
@ -99,7 +112,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#confirm-modal').modal();
|
$('#confirm-modal').modal();
|
||||||
$('#confirm-modal').one('click', '#confirm-purge', function () {
|
$('#confirm-modal').one('click', '#confirm-delete', function () {
|
||||||
|
for (var i = 0; i < libraries_to_delete.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: 'delete_library',
|
||||||
|
data: { section_id: libraries_to_delete[i] },
|
||||||
|
cache: false,
|
||||||
|
async: true,
|
||||||
|
success: function (data) {
|
||||||
|
var msg = "Library deleted";
|
||||||
|
showMsg(msg, false, true, 2000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
for (var i = 0; i < libraries_to_purge.length; i++) {
|
for (var i = 0; i < libraries_to_purge.length; i++) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'delete_all_library_history',
|
url: 'delete_all_library_history',
|
||||||
|
@ -122,6 +147,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
libraries_to_delete = [];
|
||||||
libraries_to_purge = [];
|
libraries_to_purge = [];
|
||||||
$('.edit-control').each(function () {
|
$('.edit-control').each(function () {
|
||||||
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
|
@ -137,13 +163,13 @@
|
||||||
cache: false,
|
cache: false,
|
||||||
async: true,
|
async: true,
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
showMsg('<i class="fa fa-refresh"></i> Libraries list refresh started...', false, true, 2000, false)
|
showMsg('<i class="fa fa-refresh"></i> Libraries list refresh started...', false, true, 2000, false);
|
||||||
},
|
},
|
||||||
complete: function (data) {
|
complete: function (data) {
|
||||||
showMsg('<i class="fa fa-check"></i> Libraries list refreshed.', false, true, 2000, false)
|
showMsg('<i class="fa fa-check"></i> Libraries list refreshed.', false, true, 2000, false);
|
||||||
},
|
},
|
||||||
error: function (jqXHR, textStatus, errorThrown) {
|
error: function (jqXHR, textStatus, errorThrown) {
|
||||||
showMsg('<i class="fa fa-exclamation-circle"></i> Unable to refresh libraries list.',false,true,2000,true)
|
showMsg('<i class="fa fa-exclamation-circle"></i> Unable to refresh libraries list.', false, true, 2000, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,6 +13,8 @@ section_id Returns the library id of the library.
|
||||||
section_name Returns the name of the library.
|
section_name Returns the name of the library.
|
||||||
section_type Returns the type of the library.
|
section_type Returns the type of the library.
|
||||||
library_thumb Returns the thumbnail for the library.
|
library_thumb Returns the thumbnail for the library.
|
||||||
|
custom_thumb Returns the custom thumbnail for the library.
|
||||||
|
library_art Returns the artwork for the library.
|
||||||
count Returns the item count for the library.
|
count Returns the item count for the library.
|
||||||
parent_count Returns the parent item count for the library.
|
parent_count Returns the parent item count for the library.
|
||||||
child_count Returns the child item count for the library.
|
child_count Returns the child item count for the library.
|
||||||
|
@ -31,8 +33,8 @@ DOCUMENTATION :: END
|
||||||
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
% if data != None:
|
|
||||||
<%def name="body()">
|
<%def name="body()">
|
||||||
|
% if data:
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="art-face" style="background-image:url(pms_image_proxy?img=${data['library_art']}&width=1920&height=1080)"></div>
|
<div class="art-face" style="background-image:url(pms_image_proxy?img=${data['library_art']}&width=1920&height=1080)"></div>
|
||||||
|
@ -50,12 +52,11 @@ DOCUMENTATION :: END
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="table-card-back">
|
<div class="table-card-back">
|
||||||
<div class="user-info-wrapper">
|
<div class="user-info-wrapper">
|
||||||
% if data['custom_thumb']:
|
% if data['library_thumb'][:4] == 'http':
|
||||||
<div class="library-info-poster-face" id="user-gravatar" style="background-image: url(${data['custom_thumb']});">
|
<div class="library-info-poster-face" style="background-image: url(${data['library_thumb']});"></div>
|
||||||
% else:
|
% else:
|
||||||
<div class="library-info-poster-face" id="user-gravatar" style="background-image: url(pms_image_proxy?img=${data['library_thumb']}&width=80&height=80&fallback=poster);">
|
<div class="library-info-poster-face" style="background-image: url(pms_image_proxy?img=${data['library_thumb']}&width=80&height=80&fallback=cover);"></div>
|
||||||
% endif
|
% endif
|
||||||
</div>
|
|
||||||
<div class="user-info-username">
|
<div class="user-info-username">
|
||||||
<span class="set-username">${data['section_name']}</span>
|
<span class="set-username">${data['section_name']}</span>
|
||||||
<span id="edit-library-tooltip" data-target="tooltip" title="Edit library details">
|
<span id="edit-library-tooltip" data-target="tooltip" title="Edit library details">
|
||||||
|
@ -201,6 +202,27 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<footer></footer>
|
<footer></footer>
|
||||||
|
% else:
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="summary-container">
|
||||||
|
<div class="summary-navbar">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="summary-navbar-list">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-content-wrapper">
|
||||||
|
<div class='col-md-12'>
|
||||||
|
<div style="text-align: center; margin-top: 20px;">
|
||||||
|
<i class="fa fa-exclamation-triangle"></i> Error retrieving library information. Please see the logs for more details.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
|
@ -208,12 +230,13 @@ DOCUMENTATION :: END
|
||||||
<script src="interfaces/default/js/dataTables.colVis.js"></script>
|
<script src="interfaces/default/js/dataTables.colVis.js"></script>
|
||||||
<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:
|
||||||
<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>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
% if data['section_id']:
|
% if str(data['section_id']).isdigit():
|
||||||
var section_id = ${data['section_id']};
|
var section_id = ${data['section_id']};
|
||||||
% else:
|
% else:
|
||||||
var section_id = null;
|
var section_id = null;
|
||||||
|
@ -348,18 +371,7 @@ DOCUMENTATION :: END
|
||||||
recentlyWatched();
|
recentlyWatched();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
$('div.art-face').animate({ opacity: 0.2 }, { duration: 1000 });
|
$('div.art-face').animate({ opacity: 0.2 }, { duration: 1000 });
|
||||||
</script>
|
</script>
|
||||||
</%def>
|
|
||||||
% else:
|
|
||||||
<div class="clear"></div>
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span10 offset1">
|
|
||||||
<h3>Error retrieving library information. Please see the logs for more details.</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
% endif
|
||||||
|
</%def>
|
|
@ -18,7 +18,7 @@ total_plays Returns the play count for the user.
|
||||||
DOCUMENTATION :: END
|
DOCUMENTATION :: END
|
||||||
</%doc>
|
</%doc>
|
||||||
|
|
||||||
% if data != None:
|
% if data:
|
||||||
% for a in data:
|
% for a in data:
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<div class="user-player-instance">
|
<div class="user-player-instance">
|
||||||
|
@ -38,6 +38,6 @@ DOCUMENTATION :: END
|
||||||
</ul>
|
</ul>
|
||||||
% endfor
|
% endfor
|
||||||
% else:
|
% else:
|
||||||
<div class="text-muted">Unable to retrieve data from database. Please check your <a href="settings">settings</a>.
|
<div class="text-muted">Unable to retrieve data from database.
|
||||||
</div><br>
|
</div><br>
|
||||||
% endif
|
% endif
|
|
@ -800,7 +800,7 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
|
||||||
% for agent in available_notification_agents:
|
% for agent in available_notification_agents:
|
||||||
<li>
|
<li>
|
||||||
<span>
|
<span>
|
||||||
% if agent['on_play'] or agent['on_stop'] or agent['on_pause'] or agent['on_resume'] or agent['on_buffer'] or agent['on_watched'] or agent['on_created'] or agent['on_extdown'] or agent['on_intdown']:
|
% if any(k[:2] == 'on' and v == 1 for k, v in agent.iteritems()):
|
||||||
<a href="javascript:void(0)" data-target="#notification-triggers-modal" data-id="${agent['id']}" class="toggle-notification-triggers-modal toggle-left active" data-toggle="modal"><i class="fa fa-lg fa-bell"></i></a>
|
<a href="javascript:void(0)" data-target="#notification-triggers-modal" data-id="${agent['id']}" class="toggle-notification-triggers-modal toggle-left active" data-toggle="modal"><i class="fa fa-lg fa-bell"></i></a>
|
||||||
% else:
|
% else:
|
||||||
<a href="javascript:void(0)" data-target="#notification-triggers-modal" data-id="${agent['id']}" class="toggle-notification-triggers-modal toggle-left" data-toggle="modal"><i class="fa fa-lg fa-bell"></i></a>
|
<a href="javascript:void(0)" data-target="#notification-triggers-modal" data-id="${agent['id']}" class="toggle-notification-triggers-modal toggle-left" data-toggle="modal"><i class="fa fa-lg fa-bell"></i></a>
|
||||||
|
@ -1167,6 +1167,10 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
|
||||||
<td><strong>{title}</strong></td>
|
<td><strong>{title}</strong></td>
|
||||||
<td>The full title of the item being played.</td>
|
<td>The full title of the item being played.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{library_name}</strong></td>
|
||||||
|
<td>The library title of the item being played.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{show_name}</strong></td>
|
<td><strong>{show_name}</strong></td>
|
||||||
<td>The title of the TV series being played.</td>
|
<td>The title of the TV series being played.</td>
|
||||||
|
|
|
@ -13,10 +13,12 @@ user_id Returns the user id of the user.
|
||||||
username Returns the user's username.
|
username Returns the user's username.
|
||||||
friendly_name Returns the friendly name of the user.
|
friendly_name Returns the friendly name of the user.
|
||||||
email Returns the user's email address.
|
email Returns the user's email address.
|
||||||
thumb Returns the thumbnail for the user.
|
user_thumb Returns the thumbnail for the user.
|
||||||
is_home_user Returns bool value for whether the user is part of a Plex Home.
|
is_home_user Returns bool value for whether the user is part of a Plex Home.
|
||||||
is_allow_sync Returns bool value for whether the user has sync rights.
|
is_allow_sync Returns bool value for whether the user has sync rights.
|
||||||
is_restricted Returns bool value for whether the user account is restricted.
|
is_restricted Returns bool value for whether the user account is restricted.
|
||||||
|
do_notify Returns bool value for whether to send notifications for the user.
|
||||||
|
keep_history Returns bool value for whether to keep history for the user.
|
||||||
|
|
||||||
DOCUMENTATION :: END
|
DOCUMENTATION :: END
|
||||||
|
|
||||||
|
@ -33,17 +35,28 @@ from plexpy import helpers
|
||||||
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
% if user != None:
|
|
||||||
<%def name="body()">
|
<%def name="body()">
|
||||||
|
% if data:
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="summary-container">
|
||||||
|
<div class="summary-navbar">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="summary-navbar-list">
|
||||||
|
<ul class="list-unstyled breadcrumb"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-content-wrapper">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="table-card-back">
|
<div class="table-card-back">
|
||||||
<div class="user-info-wrapper">
|
<div class="user-info-wrapper">
|
||||||
<div class="user-info-poster-face" id="user-gravatar" style="background-image: url(${data['thumb']});">
|
<div class="user-info-poster-face" style="background-image: url(${data['user_thumb']});"></div>
|
||||||
</div>
|
|
||||||
<div class="user-info-username">
|
<div class="user-info-username">
|
||||||
<span class="set-username">${data['friendly_name']}</span> <span id="edit-user-tooltip" data-target="tooltip" title="Edit user details"><a href="#" data-toggle="modal" data-target="#edit-user-modal" id="toggle-edit-user-modal"><i class="fa fa-pencil"></i></a></span>
|
<span class="set-username">${data['friendly_name']}</span>
|
||||||
|
<span id="edit-user-tooltip" data-target="tooltip" title="Edit user details">
|
||||||
|
<a href="#" data-toggle="modal" data-target="#edit-user-modal" id="toggle-edit-user-modal"><i class="fa fa-pencil"></i></a>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-info-nav">
|
<div class="user-info-nav">
|
||||||
<ul class="user-info-nav">
|
<ul class="user-info-nav">
|
||||||
|
@ -56,12 +69,10 @@ from plexpy import helpers
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div id="edit-user-modal" class="modal fade" tabindex="-1" role="dialog"
|
<div id="edit-user-modal" class="modal fade" tabindex="-1" role="dialog"
|
||||||
aria-labelledby="edit-user-modal">
|
aria-labelledby="edit-user-modal">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="tab-content">
|
||||||
<div class="tab-content">
|
|
||||||
<div class="tab-pane active" id="profile">
|
<div class="tab-pane active" id="profile">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -121,9 +132,11 @@ from plexpy import helpers
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="table-card-header">
|
<div class="table-card-header">
|
||||||
<div class="header-bar">
|
<div class="header-bar">
|
||||||
<span><i class="fa fa-map-marker"></i> IP Addresses for <strong>
|
<span>
|
||||||
|
<i class="fa fa-map-marker"></i> IP Addresses for <strong>
|
||||||
<span class="set-username">${data['friendly_name']}</span>
|
<span class="set-username">${data['friendly_name']}</span>
|
||||||
</strong></span>
|
</strong>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="table-card-back">
|
<div class="table-card-back">
|
||||||
|
@ -150,9 +163,11 @@ from plexpy import helpers
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class='table-card-header'>
|
<div class='table-card-header'>
|
||||||
<div class="header-bar">
|
<div class="header-bar">
|
||||||
<span><i class="fa fa-history"></i> Watch History for <strong>
|
<span>
|
||||||
|
<i class="fa fa-history"></i> Watch History for <strong>
|
||||||
<span class="set-username">${data['friendly_name']}</span>
|
<span class="set-username">${data['friendly_name']}</span>
|
||||||
</strong></span>
|
</strong>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
<div class="colvis-button-bar hidden-xs" id="button-bar-history"></div>
|
<div class="colvis-button-bar hidden-xs" id="button-bar-history"></div>
|
||||||
|
@ -180,8 +195,7 @@ from plexpy import helpers
|
||||||
<th align='left' id="percent_complete"></th>
|
<th align='left' id="percent_complete"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody></tbody>
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -194,9 +208,11 @@ from plexpy import helpers
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class='table-card-header'>
|
<div class='table-card-header'>
|
||||||
<div class="header-bar">
|
<div class="header-bar">
|
||||||
<span><i class="fa fa-cloud-download"></i> Synced Items for <strong>
|
<span>
|
||||||
|
<i class="fa fa-cloud-download"></i> Synced Items for <strong>
|
||||||
<span class="set-username">${data['friendly_name']}</span>
|
<span class="set-username">${data['friendly_name']}</span>
|
||||||
</strong></span>
|
</strong>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="colvis-button-bar hidden-xs" id="button-bar-sync">
|
<div class="colvis-button-bar hidden-xs" id="button-bar-sync">
|
||||||
</div>
|
</div>
|
||||||
|
@ -218,8 +234,7 @@ from plexpy import helpers
|
||||||
<th align='left' id="sync_percent_complete">Complete</th>
|
<th align='left' id="sync_percent_complete">Complete</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody></tbody>
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -248,8 +263,33 @@ from plexpy import helpers
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<footer></footer>
|
<footer></footer>
|
||||||
|
% else:
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="summary-container">
|
||||||
|
<div class="summary-navbar">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="summary-navbar-list">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-content-wrapper">
|
||||||
|
<div class='col-md-12'>
|
||||||
|
<div style="text-align: center; margin-top: 20px;">
|
||||||
|
<i class="fa fa-exclamation-triangle"></i> Error retrieving user information. Please see the logs for more details.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
|
@ -257,6 +297,7 @@ from plexpy import helpers
|
||||||
<script src="interfaces/default/js/dataTables.colVis.js"></script>
|
<script src="interfaces/default/js/dataTables.colVis.js"></script>
|
||||||
<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:
|
||||||
<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/user_ips.js"></script>
|
<script src="interfaces/default/js/tables/user_ips.js"></script>
|
||||||
|
@ -264,7 +305,7 @@ from plexpy import helpers
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
% if data['user_id']:
|
% if str(data['user_id']).isdigit():
|
||||||
var user_id = ${data['user_id']};
|
var user_id = ${data['user_id']};
|
||||||
% else:
|
% else:
|
||||||
var user_id = null;
|
var user_id = null;
|
||||||
|
@ -303,7 +344,6 @@ from plexpy import helpers
|
||||||
return {
|
return {
|
||||||
'json_data': JSON.stringify( d ),
|
'json_data': JSON.stringify( d ),
|
||||||
'user_id': user_id,
|
'user_id': user_id,
|
||||||
'user': username,
|
|
||||||
'media_type': media_type
|
'media_type': media_type
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -348,12 +388,11 @@ from plexpy import helpers
|
||||||
$( "#ip-tab-btn" ).one( "click", function() {
|
$( "#ip-tab-btn" ).one( "click", function() {
|
||||||
// Build user IP table
|
// Build user IP table
|
||||||
user_ip_table_options.ajax = {
|
user_ip_table_options.ajax = {
|
||||||
"url": "get_user_ips",
|
url: 'get_user_ips',
|
||||||
type: 'post',
|
type: 'post',
|
||||||
data: function ( d ) {
|
data: function ( d ) {
|
||||||
return { 'json_data': JSON.stringify( d ),
|
return { 'json_data': JSON.stringify( d ),
|
||||||
'user_id': user_id,
|
'user_id': user_id
|
||||||
'user': username
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,10 +404,9 @@ from plexpy import helpers
|
||||||
$( "#sync-tab-btn" ).one( "click", function() {
|
$( "#sync-tab-btn" ).one( "click", function() {
|
||||||
// Build user sync table
|
// Build user sync table
|
||||||
sync_table_options.ajax = {
|
sync_table_options.ajax = {
|
||||||
"url": "get_sync",
|
url: 'get_sync',
|
||||||
"data": function(d) {
|
data: function(d) {
|
||||||
d.user_id = user_id;
|
d.user_id = user_id;
|
||||||
d.user = username;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sync_table = $('#sync_table').DataTable(sync_table_options);
|
sync_table = $('#sync_table').DataTable(sync_table_options);
|
||||||
|
@ -385,7 +423,7 @@ from plexpy import helpers
|
||||||
$("#edit-user-tooltip").tooltip('hide');
|
$("#edit-user-tooltip").tooltip('hide');
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'edit_user_dialog',
|
url: 'edit_user_dialog',
|
||||||
data: { user_id: user_id, user: username },
|
data: { user_id: user_id },
|
||||||
cache: false,
|
cache: false,
|
||||||
async: true,
|
async: true,
|
||||||
complete: function(xhr, status) {
|
complete: function(xhr, status) {
|
||||||
|
@ -441,17 +479,14 @@ from plexpy import helpers
|
||||||
containerSize = 1;
|
containerSize = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
% if data['user_id']:
|
|
||||||
var user_id = ${data['user_id']};
|
|
||||||
% else:
|
|
||||||
var user_id = null;
|
|
||||||
% endif
|
|
||||||
|
|
||||||
// Populate recently watched
|
// Populate recently watched
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'get_user_recently_watched',
|
url: 'get_user_recently_watched',
|
||||||
async: true,
|
async: true,
|
||||||
data: { user_id: user_id, user: username, limit: containerSize },
|
data: {
|
||||||
|
user_id: user_id,
|
||||||
|
limit: containerSize
|
||||||
|
},
|
||||||
complete: function(xhr, status) {
|
complete: function(xhr, status) {
|
||||||
$("#user-recently-watched").html(xhr.responseText);
|
$("#user-recently-watched").html(xhr.responseText);
|
||||||
}
|
}
|
||||||
|
@ -464,14 +499,5 @@ from plexpy import helpers
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</%def>
|
|
||||||
% else:
|
|
||||||
<div class="clear"></div>
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span10 offset1">
|
|
||||||
<h3>Error retrieving user information. Please see the logs for more details.</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
% endif
|
||||||
|
</%def>
|
|
@ -18,7 +18,7 @@ total_plays Returns the play count for the player.
|
||||||
DOCUMENTATION :: END
|
DOCUMENTATION :: END
|
||||||
</%doc>
|
</%doc>
|
||||||
|
|
||||||
% if data != None:
|
% if data:
|
||||||
% for a in data:
|
% for a in data:
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<div class="user-player-instance">
|
<div class="user-player-instance">
|
||||||
|
@ -39,6 +39,6 @@ DOCUMENTATION :: END
|
||||||
</script>
|
</script>
|
||||||
% endfor
|
% endfor
|
||||||
% else:
|
% else:
|
||||||
<div class="text-muted">Unable to retrieve data from database. Please check your <a href="settings">settings</a>.
|
<div class="text-muted">Unable to retrieve data from database.
|
||||||
</div><br>
|
</div><br>
|
||||||
% endif
|
% endif
|
|
@ -28,7 +28,7 @@ year Returns the movie release year.
|
||||||
DOCUMENTATION :: END
|
DOCUMENTATION :: END
|
||||||
</%doc>
|
</%doc>
|
||||||
|
|
||||||
% if data != None:
|
% if data:
|
||||||
<div class="dashboard-recent-media-row">
|
<div class="dashboard-recent-media-row">
|
||||||
<ul class="dashboard-recent-media list-unstyled">
|
<ul class="dashboard-recent-media list-unstyled">
|
||||||
% for item in data:
|
% for item in data:
|
||||||
|
@ -84,6 +84,6 @@ DOCUMENTATION :: END
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="text-muted">Unable to retrieve data from database. Please check your <a href="settings">settings</a>.
|
<div class="text-muted">Unable to retrieve data from database.
|
||||||
</div><br>
|
</div><br>
|
||||||
% endif
|
% endif
|
|
@ -16,7 +16,7 @@ total_plays Returns the play count for the watch stat period..
|
||||||
DOCUMENTATION :: END
|
DOCUMENTATION :: END
|
||||||
</%doc>
|
</%doc>
|
||||||
|
|
||||||
% if data != None:
|
% if data:
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
% for a in data:
|
% for a in data:
|
||||||
<div class='user-overview-stats-instance'>
|
<div class='user-overview-stats-instance'>
|
||||||
|
@ -43,6 +43,6 @@ DOCUMENTATION :: END
|
||||||
% endfor
|
% endfor
|
||||||
</ul>
|
</ul>
|
||||||
% else:
|
% else:
|
||||||
<div class="text-muted">Unable to retrieve data from database. Please check your <a href="settings">settings</a>.
|
<div class="text-muted">Unable to retrieve data from database.
|
||||||
</div><br>
|
</div><br>
|
||||||
% endif
|
% endif
|
|
@ -177,13 +177,13 @@
|
||||||
cache: false,
|
cache: false,
|
||||||
async: true,
|
async: true,
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
showMsg('<i class="fa fa-check"></i> Users list refresh started...',false,true,2000,false)
|
showMsg('<i class="fa fa-check"></i> Users list refresh started...', false, true, 2000, false);
|
||||||
},
|
},
|
||||||
complete: function (data) {
|
complete: function (data) {
|
||||||
showMsg('<i class="fa fa-check"></i> Users list refreshed.', false, true, 2000, false)
|
showMsg('<i class="fa fa-check"></i> Users list refreshed.', false, true, 2000, false);
|
||||||
},
|
},
|
||||||
error: function (jqXHR, textStatus, errorThrown) {
|
error: function (jqXHR, textStatus, errorThrown) {
|
||||||
showMsg('<i class="fa fa-exclamation-circle"></i> Unable to refresh users list.',false,true,2000,true)
|
showMsg('<i class="fa fa-exclamation-circle"></i> Unable to refresh users list.', false, true, 2000, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -377,7 +377,7 @@ def dbcheck():
|
||||||
# sessions table :: This is a temp table that logs currently active sessions
|
# sessions table :: This is a temp table that logs currently active sessions
|
||||||
c_db.execute(
|
c_db.execute(
|
||||||
'CREATE TABLE IF NOT EXISTS sessions (id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
'CREATE TABLE IF NOT EXISTS sessions (id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||||
'session_key INTEGER, rating_key INTEGER, media_type TEXT, started INTEGER, '
|
'session_key INTEGER, rating_key INTEGER, library_id INTEGER, media_type TEXT, started INTEGER, '
|
||||||
'paused_counter INTEGER DEFAULT 0, state TEXT, user_id INTEGER, user TEXT, friendly_name TEXT, '
|
'paused_counter INTEGER DEFAULT 0, state TEXT, user_id INTEGER, user TEXT, friendly_name TEXT, '
|
||||||
'ip_address TEXT, machine_id TEXT, player TEXT, platform TEXT, title TEXT, parent_title TEXT, '
|
'ip_address TEXT, machine_id TEXT, player TEXT, platform TEXT, title TEXT, parent_title TEXT, '
|
||||||
'grandparent_title TEXT, parent_rating_key INTEGER, grandparent_rating_key INTEGER, '
|
'grandparent_title TEXT, parent_rating_key INTEGER, grandparent_rating_key INTEGER, '
|
||||||
|
@ -441,7 +441,8 @@ def dbcheck():
|
||||||
'CREATE TABLE IF NOT EXISTS library_sections (id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
'CREATE TABLE IF NOT EXISTS library_sections (id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||||
'server_id TEXT, section_id INTEGER UNIQUE, section_name TEXT, section_type TEXT, '
|
'server_id TEXT, section_id INTEGER UNIQUE, section_name TEXT, section_type TEXT, '
|
||||||
'thumb TEXT, custom_thumb_url TEXT, art TEXT, count INTEGER, parent_count INTEGER, child_count INTEGER, '
|
'thumb TEXT, custom_thumb_url TEXT, art TEXT, count INTEGER, parent_count INTEGER, child_count INTEGER, '
|
||||||
'do_notify INTEGER DEFAULT 1, keep_history INTEGER DEFAULT 1)'
|
'do_notify INTEGER DEFAULT 1, do_notify_created INTEGER DEFAULT 1, keep_history INTEGER DEFAULT 1, '
|
||||||
|
'deleted_section INTEGER DEFAULT 0)'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Upgrade sessions table from earlier versions
|
# Upgrade sessions table from earlier versions
|
||||||
|
@ -591,6 +592,15 @@ def dbcheck():
|
||||||
'ALTER TABLE sessions ADD COLUMN last_paused INTEGER'
|
'ALTER TABLE sessions ADD COLUMN last_paused INTEGER'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Upgrade sessions table from earlier versions
|
||||||
|
try:
|
||||||
|
c_db.execute('SELECT library_id from sessions')
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
logger.debug(u"Altering database. Updating database table sessions.")
|
||||||
|
c_db.execute(
|
||||||
|
'ALTER TABLE sessions ADD COLUMN library_id INTEGER'
|
||||||
|
)
|
||||||
|
|
||||||
# Upgrade session_history table from earlier versions
|
# Upgrade session_history table from earlier versions
|
||||||
try:
|
try:
|
||||||
c_db.execute('SELECT reference_id from session_history')
|
c_db.execute('SELECT reference_id from session_history')
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
import time
|
import time
|
||||||
import plexpy
|
import plexpy
|
||||||
|
|
||||||
from plexpy import logger, pmsconnect, activity_processor, threading, notification_handler
|
from plexpy import logger, pmsconnect, activity_processor, threading, notification_handler, helpers
|
||||||
|
|
||||||
|
|
||||||
class ActivityHandler(object):
|
class ActivityHandler(object):
|
||||||
|
@ -165,8 +165,6 @@ class ActivityHandler(object):
|
||||||
# This function receives events from our websocket connection
|
# This function receives events from our websocket connection
|
||||||
def process(self):
|
def process(self):
|
||||||
if self.is_valid_session():
|
if self.is_valid_session():
|
||||||
from plexpy import helpers
|
|
||||||
|
|
||||||
ap = activity_processor.ActivityProcessor()
|
ap = activity_processor.ActivityProcessor()
|
||||||
db_session = ap.get_session_by_key(session_key=self.get_session_key())
|
db_session = ap.get_session_by_key(session_key=self.get_session_key())
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from plexpy import logger, pmsconnect, plextv, notification_handler, database, helpers, activity_processor
|
from plexpy import logger, pmsconnect, plextv, notification_handler, database, helpers, activity_processor, libraries
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
import plexpy
|
import plexpy
|
||||||
|
@ -46,16 +46,7 @@ def check_active_sessions(ws_request=False):
|
||||||
media_container = session_list['sessions']
|
media_container = session_list['sessions']
|
||||||
|
|
||||||
# Check our temp table for what we must do with the new streams
|
# Check our temp table for what we must do with the new streams
|
||||||
db_streams = monitor_db.select('SELECT started, session_key, rating_key, media_type, title, parent_title, '
|
db_streams = monitor_db.select('SELECT * FROM sessions')
|
||||||
'grandparent_title, user_id, user, friendly_name, ip_address, player, '
|
|
||||||
'platform, machine_id, parent_rating_key, grandparent_rating_key, state, '
|
|
||||||
'view_offset, duration, video_decision, audio_decision, width, height, '
|
|
||||||
'container, video_codec, audio_codec, bitrate, video_resolution, '
|
|
||||||
'video_framerate, aspect_ratio, audio_channels, transcode_protocol, '
|
|
||||||
'transcode_container, transcode_video_codec, transcode_audio_codec, '
|
|
||||||
'transcode_audio_channels, transcode_width, transcode_height, '
|
|
||||||
'paused_counter, last_paused '
|
|
||||||
'FROM sessions')
|
|
||||||
for stream in db_streams:
|
for stream in db_streams:
|
||||||
if any(d['session_key'] == str(stream['session_key']) and d['rating_key'] == str(stream['rating_key'])
|
if any(d['session_key'] == str(stream['session_key']) and d['rating_key'] == str(stream['rating_key'])
|
||||||
for d in media_container):
|
for d in media_container):
|
||||||
|
@ -196,10 +187,16 @@ def check_recently_added():
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
recently_added_list = pms_connect.get_recently_added_details(count='10')
|
recently_added_list = pms_connect.get_recently_added_details(count='10')
|
||||||
|
|
||||||
|
library_data = libraries.Libraries()
|
||||||
if recently_added_list:
|
if recently_added_list:
|
||||||
recently_added = recently_added_list['recently_added']
|
recently_added = recently_added_list['recently_added']
|
||||||
|
|
||||||
for item in recently_added:
|
for item in recently_added:
|
||||||
|
library_details = library_data.get_details(section_id=item['library_id'])
|
||||||
|
|
||||||
|
if not library_details['do_notify_created']:
|
||||||
|
continue
|
||||||
|
|
||||||
metadata = []
|
metadata = []
|
||||||
|
|
||||||
if 0 < time_threshold - int(item['added_at']) <= time_interval:
|
if 0 < time_threshold - int(item['added_at']) <= time_interval:
|
||||||
|
@ -220,8 +217,12 @@ def check_recently_added():
|
||||||
% str(item['rating_key']))
|
% str(item['rating_key']))
|
||||||
|
|
||||||
if metadata:
|
if metadata:
|
||||||
|
|
||||||
if not plexpy.CONFIG.NOTIFY_RECENTLY_ADDED_GRANDPARENT:
|
if not plexpy.CONFIG.NOTIFY_RECENTLY_ADDED_GRANDPARENT:
|
||||||
for item in metadata:
|
for item in metadata:
|
||||||
|
|
||||||
|
library_details = library_data.get_details(section_id=item['library_id'])
|
||||||
|
|
||||||
if 0 < time_threshold - int(item['added_at']) <= time_interval:
|
if 0 < time_threshold - int(item['added_at']) <= time_interval:
|
||||||
logger.debug(u"PlexPy Monitor :: Library item %s has been added to Plex." % str(item['rating_key']))
|
logger.debug(u"PlexPy Monitor :: Library item %s has been added to Plex." % str(item['rating_key']))
|
||||||
# Fire off notifications
|
# Fire off notifications
|
||||||
|
|
|
@ -29,6 +29,7 @@ class ActivityProcessor(object):
|
||||||
def write_session(self, session=None, notify=True):
|
def write_session(self, session=None, notify=True):
|
||||||
if session:
|
if session:
|
||||||
values = {'session_key': session['session_key'],
|
values = {'session_key': session['session_key'],
|
||||||
|
'library_id': session['library_id'],
|
||||||
'rating_key': session['rating_key'],
|
'rating_key': session['rating_key'],
|
||||||
'media_type': session['media_type'],
|
'media_type': session['media_type'],
|
||||||
'state': session['state'],
|
'state': session['state'],
|
||||||
|
@ -97,10 +98,13 @@ class ActivityProcessor(object):
|
||||||
self.db.upsert('sessions', ip_address, keys)
|
self.db.upsert('sessions', ip_address, keys)
|
||||||
|
|
||||||
def write_session_history(self, session=None, import_metadata=None, is_import=False, import_ignore_interval=0):
|
def write_session_history(self, session=None, import_metadata=None, is_import=False, import_ignore_interval=0):
|
||||||
from plexpy import users
|
from plexpy import users, libraries
|
||||||
|
|
||||||
user_data = users.Users()
|
user_data = users.Users()
|
||||||
user_details = user_data.get_user_friendly_name(user=session['user'])
|
user_details = user_data.get_details(user_id=session['user_id'])
|
||||||
|
|
||||||
|
library_data = libraries.Libraries()
|
||||||
|
library_details = library_data.get_details(section_id=session['library_id'])
|
||||||
|
|
||||||
if session:
|
if session:
|
||||||
logging_enabled = False
|
logging_enabled = False
|
||||||
|
@ -155,7 +159,10 @@ class ActivityProcessor(object):
|
||||||
|
|
||||||
if not user_details['keep_history'] and not is_import:
|
if not user_details['keep_history'] and not is_import:
|
||||||
logging_enabled = False
|
logging_enabled = False
|
||||||
logger.debug(u"PlexPy ActivityProcessor :: History logging for user '%s' is disabled." % session['user'])
|
logger.debug(u"PlexPy ActivityProcessor :: History logging for user '%s' is disabled." % user_details['username'])
|
||||||
|
elif not library_details['keep_history'] and not is_import:
|
||||||
|
logging_enabled = False
|
||||||
|
logger.debug(u"PlexPy ActivityProcessor :: History logging for library '%s' is disabled." % library_details['section_name'])
|
||||||
|
|
||||||
if logging_enabled:
|
if logging_enabled:
|
||||||
# logger.debug(u"PlexPy ActivityProcessor :: Attempting to write to session_history table...")
|
# logger.debug(u"PlexPy ActivityProcessor :: Attempting to write to session_history table...")
|
||||||
|
@ -331,15 +338,7 @@ class ActivityProcessor(object):
|
||||||
|
|
||||||
def get_session_by_key(self, session_key=None):
|
def get_session_by_key(self, session_key=None):
|
||||||
if str(session_key).isdigit():
|
if str(session_key).isdigit():
|
||||||
result = self.db.select('SELECT started, session_key, rating_key, media_type, title, parent_title, '
|
result = self.db.select('SELECT * '
|
||||||
'grandparent_title, user_id, user, friendly_name, ip_address, player, '
|
|
||||||
'platform, machine_id, parent_rating_key, grandparent_rating_key, state, '
|
|
||||||
'view_offset, duration, video_decision, audio_decision, width, height, '
|
|
||||||
'container, video_codec, audio_codec, bitrate, video_resolution, '
|
|
||||||
'video_framerate, aspect_ratio, audio_channels, transcode_protocol, '
|
|
||||||
'transcode_container, transcode_video_codec, transcode_audio_codec, '
|
|
||||||
'transcode_audio_channels, transcode_width, transcode_height, '
|
|
||||||
'paused_counter, last_paused '
|
|
||||||
'FROM sessions WHERE session_key = ? LIMIT 1', args=[session_key])
|
'FROM sessions WHERE session_key = ? LIMIT 1', args=[session_key])
|
||||||
for session in result:
|
for session in result:
|
||||||
if session:
|
if session:
|
||||||
|
|
|
@ -323,7 +323,7 @@ class Api(object):
|
||||||
custom_where = [['strftime("%Y-%m-%d", datetime(date, "unixepoch", "localtime"))', start_date]]
|
custom_where = [['strftime("%Y-%m-%d", datetime(date, "unixepoch", "localtime"))', start_date]]
|
||||||
|
|
||||||
data_factory = datafactory.DataFactory()
|
data_factory = datafactory.DataFactory()
|
||||||
history = data_factory.get_history(kwargs=kwargs, custom_where=custom_where)
|
history = data_factory.get_datatables_history(kwargs=kwargs, custom_where=custom_where)
|
||||||
|
|
||||||
self.data = history
|
self.data = history
|
||||||
return self.data
|
return self.data
|
||||||
|
|
|
@ -26,7 +26,7 @@ class DataFactory(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_history(self, kwargs=None, custom_where=None, grouping=0, watched_percent=85):
|
def get_datatables_history(self, kwargs=None, custom_where=None, grouping=0, watched_percent=85):
|
||||||
data_tables = datatables.DataTables()
|
data_tables = datatables.DataTables()
|
||||||
|
|
||||||
group_by = ['session_history.reference_id'] if grouping else ['session_history.id']
|
group_by = ['session_history.reference_id'] if grouping else ['session_history.id']
|
||||||
|
@ -81,8 +81,8 @@ class DataFactory(object):
|
||||||
['session_history.id', 'session_history_metadata.id'],
|
['session_history.id', 'session_history_metadata.id'],
|
||||||
['session_history.id', 'session_history_media_info.id']],
|
['session_history.id', 'session_history_media_info.id']],
|
||||||
kwargs=kwargs)
|
kwargs=kwargs)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_history.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_history: %s." % e)
|
||||||
return {'recordsFiltered': 0,
|
return {'recordsFiltered': 0,
|
||||||
'recordsTotal': 0,
|
'recordsTotal': 0,
|
||||||
'draw': 0,
|
'draw': 0,
|
||||||
|
@ -185,8 +185,8 @@ class DataFactory(object):
|
||||||
'ORDER BY %s DESC ' \
|
'ORDER BY %s DESC ' \
|
||||||
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_home_stats: top_tv.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_tv: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -229,8 +229,8 @@ class DataFactory(object):
|
||||||
'ORDER BY users_watched DESC, %s DESC ' \
|
'ORDER BY users_watched DESC, %s DESC ' \
|
||||||
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_home_stats: popular_tv.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_tv: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -270,8 +270,8 @@ class DataFactory(object):
|
||||||
'ORDER BY %s DESC ' \
|
'ORDER BY %s DESC ' \
|
||||||
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_home_stats: top_movies.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_movies: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -313,8 +313,8 @@ class DataFactory(object):
|
||||||
'ORDER BY users_watched DESC, %s DESC ' \
|
'ORDER BY users_watched DESC, %s DESC ' \
|
||||||
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_home_stats: popular_movies.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_movies: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -354,8 +354,8 @@ class DataFactory(object):
|
||||||
'ORDER BY %s DESC ' \
|
'ORDER BY %s DESC ' \
|
||||||
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_home_stats: top_music.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_music: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -398,8 +398,8 @@ class DataFactory(object):
|
||||||
'ORDER BY users_watched DESC, %s DESC ' \
|
'ORDER BY users_watched DESC, %s DESC ' \
|
||||||
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_home_stats: popular_music.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_music: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -424,13 +424,13 @@ class DataFactory(object):
|
||||||
elif stat == 'top_users':
|
elif stat == 'top_users':
|
||||||
top_users = []
|
top_users = []
|
||||||
try:
|
try:
|
||||||
query = 'SELECT t.user, t.user_id, t.custom_avatar_url as thumb, ' \
|
query = 'SELECT t.user, t.user_id, t.user_thumb, t.custom_thumb, ' \
|
||||||
'(CASE WHEN t.friendly_name IS NULL THEN t.username ELSE t.friendly_name END) ' \
|
'(CASE WHEN t.friendly_name IS NULL THEN t.username ELSE t.friendly_name END) ' \
|
||||||
' AS friendly_name, ' \
|
' AS friendly_name, ' \
|
||||||
'MAX(t.started) AS last_watch, COUNT(t.id) AS total_plays, SUM(t.d) AS total_duration ' \
|
'MAX(t.started) AS last_watch, COUNT(t.id) AS total_plays, SUM(t.d) AS total_duration ' \
|
||||||
'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \
|
'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \
|
||||||
' (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) ' \
|
' (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) ' \
|
||||||
' AS d ' \
|
' AS d, users.thumb AS user_thumb, users.custom_avatar_url AS custom_thumb ' \
|
||||||
' FROM session_history ' \
|
' FROM session_history ' \
|
||||||
' JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
|
' JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
|
||||||
' LEFT OUTER JOIN users ON session_history.user_id = users.user_id ' \
|
' LEFT OUTER JOIN users ON session_history.user_id = users.user_id ' \
|
||||||
|
@ -441,15 +441,17 @@ class DataFactory(object):
|
||||||
'ORDER BY %s DESC ' \
|
'ORDER BY %s DESC ' \
|
||||||
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_home_stats: top_users.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_users: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
if not item['thumb'] or item['thumb'] == '':
|
if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
|
||||||
user_thumb = common.DEFAULT_USER_THUMB
|
user_thumb = item['custom_thumb']
|
||||||
|
elif item['user_thumb']:
|
||||||
|
user_thumb = item['user_thumb']
|
||||||
else:
|
else:
|
||||||
user_thumb = item['thumb']
|
user_thumb = common.DEFAULT_USER_THUMB
|
||||||
|
|
||||||
row = {'user': item['user'],
|
row = {'user': item['user'],
|
||||||
'user_id': item['user_id'],
|
'user_id': item['user_id'],
|
||||||
|
@ -490,8 +492,8 @@ class DataFactory(object):
|
||||||
'ORDER BY %s DESC ' \
|
'ORDER BY %s DESC ' \
|
||||||
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_home_stats: top_platforms.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_platforms: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -542,8 +544,8 @@ class DataFactory(object):
|
||||||
'ORDER BY last_watch DESC ' \
|
'ORDER BY last_watch DESC ' \
|
||||||
'LIMIT %s' % (time_range, group_by, notify_watched_percent, stats_count)
|
'LIMIT %s' % (time_range, group_by, notify_watched_percent, stats_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_home_stats: last_watched.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: last_watched: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -645,8 +647,8 @@ class DataFactory(object):
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
if result:
|
if result:
|
||||||
most_concurrent.append(calc_most_concurrent(title, result))
|
most_concurrent.append(calc_most_concurrent(title, result))
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_home_stats: most_concurrent.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: most_concurrent: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
home_stats.append({'stat_id': stat,
|
home_stats.append({'stat_id': stat,
|
||||||
|
@ -664,10 +666,10 @@ class DataFactory(object):
|
||||||
try:
|
try:
|
||||||
query = 'SELECT section_id, section_name, section_type, thumb, count, parent_count, child_count ' \
|
query = 'SELECT section_id, section_name, section_type, thumb, count, parent_count, child_count ' \
|
||||||
'FROM library_sections ' \
|
'FROM library_sections ' \
|
||||||
'WHERE section_id = %s' % id
|
'WHERE section_id = %s ' % id
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_library_stats.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_library_stats: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -725,86 +727,6 @@ class DataFactory(object):
|
||||||
|
|
||||||
return stream_output
|
return stream_output
|
||||||
|
|
||||||
def get_recently_watched(self, user=None, user_id=None, library_id=None, limit='10'):
|
|
||||||
monitor_db = database.MonitorDatabase()
|
|
||||||
recently_watched = []
|
|
||||||
|
|
||||||
if not limit.isdigit():
|
|
||||||
limit = '10'
|
|
||||||
|
|
||||||
try:
|
|
||||||
if user_id:
|
|
||||||
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
|
|
||||||
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
|
|
||||||
'year, started, user ' \
|
|
||||||
'FROM session_history_metadata ' \
|
|
||||||
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
|
|
||||||
'WHERE user_id = ? ' \
|
|
||||||
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
|
|
||||||
' ELSE session_history.rating_key END) ' \
|
|
||||||
'ORDER BY started DESC LIMIT ?'
|
|
||||||
result = monitor_db.select(query, args=[user_id, limit])
|
|
||||||
elif user:
|
|
||||||
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
|
|
||||||
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
|
|
||||||
'year, started, user ' \
|
|
||||||
'FROM session_history_metadata ' \
|
|
||||||
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
|
|
||||||
'WHERE user = ? ' \
|
|
||||||
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
|
|
||||||
' ELSE session_history.rating_key END) ' \
|
|
||||||
'ORDER BY started DESC LIMIT ?'
|
|
||||||
result = monitor_db.select(query, args=[user, limit])
|
|
||||||
elif library_id:
|
|
||||||
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
|
|
||||||
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
|
|
||||||
'year, started, user ' \
|
|
||||||
'FROM session_history_metadata ' \
|
|
||||||
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
|
|
||||||
'WHERE library_id = ? ' \
|
|
||||||
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
|
|
||||||
' ELSE session_history.rating_key END) ' \
|
|
||||||
'ORDER BY started DESC LIMIT ?'
|
|
||||||
result = monitor_db.select(query, args=[library_id, limit])
|
|
||||||
else:
|
|
||||||
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
|
|
||||||
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
|
|
||||||
'year, started, user ' \
|
|
||||||
'FROM session_history_metadata ' \
|
|
||||||
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
|
|
||||||
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
|
|
||||||
' ELSE session_history.rating_key END) ' \
|
|
||||||
'ORDER BY started DESC LIMIT ?'
|
|
||||||
result = monitor_db.select(query, args=[limit])
|
|
||||||
except:
|
|
||||||
logger.warn("Unable to execute database query for get_recently_watched.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
for row in result:
|
|
||||||
if row['media_type'] == 'episode' and row['parent_thumb']:
|
|
||||||
thumb = row['parent_thumb']
|
|
||||||
elif row['media_type'] == 'episode':
|
|
||||||
thumb = row['grandparent_thumb']
|
|
||||||
else:
|
|
||||||
thumb = row['thumb']
|
|
||||||
|
|
||||||
recent_output = {'row_id': row['id'],
|
|
||||||
'type': row['media_type'],
|
|
||||||
'rating_key': row['rating_key'],
|
|
||||||
'title': row['title'],
|
|
||||||
'parent_title': row['parent_title'],
|
|
||||||
'grandparent_title': row['grandparent_title'],
|
|
||||||
'thumb': thumb,
|
|
||||||
'media_index': row['media_index'],
|
|
||||||
'parent_media_index': row['parent_media_index'],
|
|
||||||
'year': row['year'],
|
|
||||||
'time': row['started'],
|
|
||||||
'user': row['user']
|
|
||||||
}
|
|
||||||
recently_watched.append(recent_output)
|
|
||||||
|
|
||||||
return recently_watched
|
|
||||||
|
|
||||||
def get_metadata_details(self, rating_key):
|
def get_metadata_details(self, rating_key):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
@ -866,89 +788,52 @@ class DataFactory(object):
|
||||||
'directors': directors,
|
'directors': directors,
|
||||||
'genres': genres,
|
'genres': genres,
|
||||||
'actors': actors,
|
'actors': actors,
|
||||||
'library_title': item['section_name'],
|
'library_name': item['section_name'],
|
||||||
'library_id': item['library_id']
|
'library_id': item['library_id']
|
||||||
}
|
}
|
||||||
|
|
||||||
return metadata
|
return metadata
|
||||||
|
|
||||||
def delete_session_history_rows(self, row_id=None):
|
def get_total_duration(self, custom_where=None):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
if row_id.isdigit():
|
# Split up custom wheres
|
||||||
logger.info(u"PlexPy DataFactory :: Deleting row id %s from the session history database." % row_id)
|
if custom_where:
|
||||||
session_history_del = \
|
where = 'WHERE ' + ' AND '.join([w[0] + ' = "' + w[1] + '"' for w in custom_where])
|
||||||
monitor_db.action('DELETE FROM session_history WHERE id = ?', [row_id])
|
|
||||||
session_history_media_info_del = \
|
|
||||||
monitor_db.action('DELETE FROM session_history_media_info WHERE id = ?', [row_id])
|
|
||||||
session_history_metadata_del = \
|
|
||||||
monitor_db.action('DELETE FROM session_history_metadata WHERE id = ?', [row_id])
|
|
||||||
|
|
||||||
return 'Deleted rows %s.' % row_id
|
|
||||||
else:
|
else:
|
||||||
return 'Unable to delete rows. Input row not valid.'
|
where = ''
|
||||||
|
|
||||||
def delete_all_user_history(self, user_id=None):
|
try:
|
||||||
|
query = 'SELECT SUM(CASE WHEN stopped > 0 THEN (stopped - started) ELSE 0 END) - ' \
|
||||||
|
'SUM(CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) AS total_duration ' \
|
||||||
|
'FROM session_history ' \
|
||||||
|
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
|
||||||
|
'%s ' % where
|
||||||
|
result = monitor_db.select(query)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_total_duration: %s." % e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
for item in result:
|
||||||
|
total_duration = item['total_duration']
|
||||||
|
|
||||||
|
return total_duration
|
||||||
|
|
||||||
|
def get_session_ip(self, session_key=''):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
if user_id.isdigit():
|
if session_key:
|
||||||
logger.info(u"PlexPy DataFactory :: Deleting all history for user id %s from database." % user_id)
|
query = 'SELECT ip_address FROM sessions WHERE session_key = %d' % int(session_key)
|
||||||
session_history_media_info_del = \
|
result = monitor_db.select(query)
|
||||||
monitor_db.action('DELETE FROM '
|
|
||||||
'session_history_media_info '
|
|
||||||
'WHERE session_history_media_info.id IN (SELECT session_history_media_info.id '
|
|
||||||
'FROM session_history_media_info '
|
|
||||||
'JOIN session_history ON session_history_media_info.id = session_history.id '
|
|
||||||
'WHERE session_history.user_id = ?)', [user_id])
|
|
||||||
session_history_metadata_del = \
|
|
||||||
monitor_db.action('DELETE FROM '
|
|
||||||
'session_history_metadata '
|
|
||||||
'WHERE session_history_metadata.id IN (SELECT session_history_metadata.id '
|
|
||||||
'FROM session_history_metadata '
|
|
||||||
'JOIN session_history ON session_history_metadata.id = session_history.id '
|
|
||||||
'WHERE session_history.user_id = ?)', [user_id])
|
|
||||||
session_history_del = \
|
|
||||||
monitor_db.action('DELETE FROM '
|
|
||||||
'session_history '
|
|
||||||
'WHERE session_history.user_id = ?', [user_id])
|
|
||||||
|
|
||||||
return 'Deleted all items for user_id %s.' % user_id
|
|
||||||
else:
|
else:
|
||||||
return 'Unable to delete items. Input user_id not valid.'
|
return None
|
||||||
|
|
||||||
def delete_user(self, user_id=None):
|
ip_address = 'N/A'
|
||||||
monitor_db = database.MonitorDatabase()
|
|
||||||
|
|
||||||
if user_id.isdigit():
|
for item in result:
|
||||||
self.delete_all_user_history(user_id)
|
ip_address = item['ip_address']
|
||||||
logger.info(u"PlexPy DataFactory :: Deleting user with id %s from database." % user_id)
|
|
||||||
monitor_db.action('UPDATE users SET deleted_user = 1 WHERE user_id = ?', [user_id])
|
|
||||||
monitor_db.action('UPDATE users SET keep_history = 0 WHERE user_id = ?', [user_id])
|
|
||||||
monitor_db.action('UPDATE users SET do_notify = 0 WHERE user_id = ?', [user_id])
|
|
||||||
|
|
||||||
return 'Deleted user with id %s.' % user_id
|
return ip_address
|
||||||
else:
|
|
||||||
return 'Unable to delete user. Input user_id not valid.'
|
|
||||||
|
|
||||||
def undelete_user(self, user_id=None, username=None):
|
|
||||||
monitor_db = database.MonitorDatabase()
|
|
||||||
|
|
||||||
if user_id and user_id.isdigit():
|
|
||||||
logger.info(u"PlexPy DataFactory :: Re-adding user with id %s to database." % user_id)
|
|
||||||
monitor_db.action('UPDATE users SET deleted_user = 0 WHERE user_id = ?', [user_id])
|
|
||||||
monitor_db.action('UPDATE users SET keep_history = 1 WHERE user_id = ?', [user_id])
|
|
||||||
monitor_db.action('UPDATE users SET do_notify = 1 WHERE user_id = ?', [user_id])
|
|
||||||
|
|
||||||
return 'Re-added user with id %s.' % user_id
|
|
||||||
elif username:
|
|
||||||
logger.info(u"PlexPy DataFactory :: Re-adding user with username %s to database." % username)
|
|
||||||
monitor_db.action('UPDATE users SET deleted_user = 0 WHERE username = ?', [username])
|
|
||||||
monitor_db.action('UPDATE users SET keep_history = 1 WHERE username = ?', [username])
|
|
||||||
monitor_db.action('UPDATE users SET do_notify = 1 WHERE username = ?', [username])
|
|
||||||
|
|
||||||
return 'Re-added user with username %s.' % username
|
|
||||||
else:
|
|
||||||
return 'Unable to re-add user. Input user_id or username not valid.'
|
|
||||||
|
|
||||||
def get_search_query(self, rating_key=''):
|
def get_search_query(self, rating_key=''):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
@ -1037,8 +922,8 @@ class DataFactory(object):
|
||||||
|
|
||||||
grandparent_rating_key = result[0]['grandparent_rating_key']
|
grandparent_rating_key = result[0]['grandparent_rating_key']
|
||||||
|
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_rating_keys_list.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_rating_keys_list: %s." % e)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \
|
query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \
|
||||||
|
@ -1081,6 +966,22 @@ class DataFactory(object):
|
||||||
|
|
||||||
return key_list
|
return key_list
|
||||||
|
|
||||||
|
def delete_session_history_rows(self, row_id=None):
|
||||||
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
if row_id.isdigit():
|
||||||
|
logger.info(u"PlexPy DataFactory :: Deleting row id %s from the session history database." % row_id)
|
||||||
|
session_history_del = \
|
||||||
|
monitor_db.action('DELETE FROM session_history WHERE id = ?', [row_id])
|
||||||
|
session_history_media_info_del = \
|
||||||
|
monitor_db.action('DELETE FROM session_history_media_info WHERE id = ?', [row_id])
|
||||||
|
session_history_metadata_del = \
|
||||||
|
monitor_db.action('DELETE FROM session_history_metadata WHERE id = ?', [row_id])
|
||||||
|
|
||||||
|
return 'Deleted rows %s.' % row_id
|
||||||
|
else:
|
||||||
|
return 'Unable to delete rows. Input row not valid.'
|
||||||
|
|
||||||
def update_metadata(self, old_key_list='', new_key_list='', media_type=''):
|
def update_metadata(self, old_key_list='', new_key_list='', media_type=''):
|
||||||
from plexpy import pmsconnect
|
from plexpy import pmsconnect
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
|
@ -1134,8 +1035,6 @@ class DataFactory(object):
|
||||||
return 'Updated metadata in database.'
|
return 'Updated metadata in database.'
|
||||||
else:
|
else:
|
||||||
return 'Unable to update metadata in database. No changes were made.'
|
return 'Unable to update metadata in database. No changes were made.'
|
||||||
# for debugging
|
|
||||||
#return mapping
|
|
||||||
|
|
||||||
def update_metadata_details(self, old_rating_key='', new_rating_key='', metadata=None):
|
def update_metadata_details(self, old_rating_key='', new_rating_key='', metadata=None):
|
||||||
|
|
||||||
|
@ -1176,31 +1075,6 @@ class DataFactory(object):
|
||||||
|
|
||||||
monitor_db.action(query=query, args=args)
|
monitor_db.action(query=query, args=args)
|
||||||
|
|
||||||
def get_total_duration(self, custom_where=None):
|
|
||||||
monitor_db = database.MonitorDatabase()
|
|
||||||
|
|
||||||
# Split up custom wheres
|
|
||||||
if custom_where:
|
|
||||||
where = 'WHERE ' + ' AND '.join([w[0] + ' = "' + w[1] + '"' for w in custom_where])
|
|
||||||
else:
|
|
||||||
where = ''
|
|
||||||
|
|
||||||
try:
|
|
||||||
query = 'SELECT SUM(CASE WHEN stopped > 0 THEN (stopped - started) ELSE 0 END) - ' \
|
|
||||||
'SUM(CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) AS total_duration ' \
|
|
||||||
'FROM session_history ' \
|
|
||||||
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
|
|
||||||
'%s ' % where
|
|
||||||
result = monitor_db.select(query)
|
|
||||||
except:
|
|
||||||
logger.warn("Unable to execute database query for get_total_duration.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
for item in result:
|
|
||||||
total_duration = item['total_duration']
|
|
||||||
|
|
||||||
return total_duration
|
|
||||||
|
|
||||||
def update_library_ids(self):
|
def update_library_ids(self):
|
||||||
from plexpy import pmsconnect
|
from plexpy import pmsconnect
|
||||||
|
|
||||||
|
@ -1210,8 +1084,8 @@ class DataFactory(object):
|
||||||
try:
|
try:
|
||||||
query = 'SELECT id, rating_key FROM session_history_metadata WHERE library_id IS NULL'
|
query = 'SELECT id, rating_key FROM session_history_metadata WHERE library_id IS NULL'
|
||||||
result = monitor_db.select(query=query)
|
result = monitor_db.select(query=query)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for update_library_id.")
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for update_library_id: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -1231,59 +1105,3 @@ class DataFactory(object):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_library_sections(self):
|
|
||||||
monitor_db = database.MonitorDatabase()
|
|
||||||
|
|
||||||
try:
|
|
||||||
query = 'SELECT section_id, section_name FROM library_sections'
|
|
||||||
result = monitor_db.select(query=query)
|
|
||||||
except:
|
|
||||||
logger.warn("Unable to execute database query for get_library_sections.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
libraries = []
|
|
||||||
for item in result:
|
|
||||||
library = {'section_id': item['section_id'],
|
|
||||||
'section_name': item['section_name']
|
|
||||||
}
|
|
||||||
libraries.append(library)
|
|
||||||
|
|
||||||
return libraries
|
|
||||||
|
|
||||||
|
|
||||||
def update_library_sections(self):
|
|
||||||
from plexpy import pmsconnect
|
|
||||||
|
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
|
||||||
library_sections = pms_connect.get_server_children()
|
|
||||||
|
|
||||||
if library_sections:
|
|
||||||
if library_sections['libraries_count'] != '0':
|
|
||||||
monitor_db = database.MonitorDatabase()
|
|
||||||
|
|
||||||
for section in library_sections['libraries_list']:
|
|
||||||
section_keys = {'section_id': section['key']}
|
|
||||||
section_values = {'section_id': section['key'],
|
|
||||||
'section_name': section['title'],
|
|
||||||
'section_type': section['type']}
|
|
||||||
|
|
||||||
monitor_db.upsert('library_sections', key_dict=section_keys, value_dict=section_values)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_session_ip(self, session_key=''):
|
|
||||||
monitor_db = database.MonitorDatabase()
|
|
||||||
|
|
||||||
if session_key:
|
|
||||||
query = 'SELECT ip_address FROM sessions WHERE session_key = %d' % int(session_key)
|
|
||||||
result = monitor_db.select(query)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
ip_address = 'N/A'
|
|
||||||
|
|
||||||
for item in result:
|
|
||||||
ip_address = item['ip_address']
|
|
||||||
|
|
||||||
return ip_address
|
|
|
@ -14,6 +14,7 @@
|
||||||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from plexpy import logger, datatables, common, database, helpers
|
from plexpy import logger, datatables, common, database, helpers
|
||||||
|
import plexpy
|
||||||
|
|
||||||
|
|
||||||
class Libraries(object):
|
class Libraries(object):
|
||||||
|
@ -21,22 +22,23 @@ class Libraries(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_library_list(self, kwargs=None):
|
def get_datatables_list(self, kwargs=None):
|
||||||
data_tables = datatables.DataTables()
|
data_tables = datatables.DataTables()
|
||||||
|
|
||||||
|
custom_where = ['library_sections.deleted_section', 0]
|
||||||
|
|
||||||
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',
|
||||||
'library_sections.count as count',
|
'library_sections.count',
|
||||||
'library_sections.parent_count',
|
'library_sections.parent_count',
|
||||||
'library_sections.child_count',
|
'library_sections.child_count',
|
||||||
'library_sections.thumb AS library_thumb',
|
'library_sections.thumb AS library_thumb',
|
||||||
'(CASE WHEN library_sections.custom_thumb_url == library_sections.thumb \
|
'library_sections.custom_thumb_url AS custom_thumb',
|
||||||
THEN NULL ELSE custom_thumb_url END) AS custom_thumb',
|
|
||||||
'library_sections.art',
|
'library_sections.art',
|
||||||
'COUNT(session_history.id) as plays',
|
'COUNT(session_history.id) AS plays',
|
||||||
'MAX(session_history.started) as last_accessed',
|
'MAX(session_history.started) AS last_accessed',
|
||||||
'session_history_metadata.full_title as last_watched',
|
'session_history_metadata.full_title AS last_watched',
|
||||||
'session_history_metadata.thumb',
|
'session_history_metadata.thumb',
|
||||||
'session_history_metadata.parent_thumb',
|
'session_history_metadata.parent_thumb',
|
||||||
'session_history_metadata.grandparent_thumb',
|
'session_history_metadata.grandparent_thumb',
|
||||||
|
@ -44,12 +46,13 @@ class Libraries(object):
|
||||||
'session_history.rating_key',
|
'session_history.rating_key',
|
||||||
'session_history_media_info.video_decision',
|
'session_history_media_info.video_decision',
|
||||||
'library_sections.do_notify',
|
'library_sections.do_notify',
|
||||||
|
'library_sections.do_notify_created',
|
||||||
'library_sections.keep_history'
|
'library_sections.keep_history'
|
||||||
]
|
]
|
||||||
try:
|
try:
|
||||||
query = data_tables.ssp_query(table_name='library_sections',
|
query = data_tables.ssp_query(table_name='library_sections',
|
||||||
columns=columns,
|
columns=columns,
|
||||||
custom_where=[],
|
custom_where=[custom_where],
|
||||||
group_by=['library_sections.section_id'],
|
group_by=['library_sections.section_id'],
|
||||||
join_types=['LEFT OUTER JOIN',
|
join_types=['LEFT OUTER JOIN',
|
||||||
'LEFT OUTER JOIN',
|
'LEFT OUTER JOIN',
|
||||||
|
@ -61,8 +64,8 @@ class Libraries(object):
|
||||||
['session_history_metadata.id', 'session_history.id'],
|
['session_history_metadata.id', 'session_history.id'],
|
||||||
['session_history_metadata.id', 'session_history_media_info.id']],
|
['session_history_metadata.id', 'session_history_media_info.id']],
|
||||||
kwargs=kwargs)
|
kwargs=kwargs)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query for get_library_list.")
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_list: %s." % e)
|
||||||
return {'recordsFiltered': 0,
|
return {'recordsFiltered': 0,
|
||||||
'recordsTotal': 0,
|
'recordsTotal': 0,
|
||||||
'draw': 0,
|
'draw': 0,
|
||||||
|
@ -80,23 +83,30 @@ class Libraries(object):
|
||||||
else:
|
else:
|
||||||
thumb = item['thumb']
|
thumb = item['thumb']
|
||||||
|
|
||||||
row = {'plays': item['plays'],
|
if item['custom_thumb'] and item['custom_thumb'] != item['library_thumb']:
|
||||||
|
library_thumb = item['custom_thumb']
|
||||||
|
elif item['library_thumb']:
|
||||||
|
library_thumb = item['library_thumb']
|
||||||
|
else:
|
||||||
|
library_thumb = common.DEFAULT_COVER_THUMB
|
||||||
|
|
||||||
|
row = {'section_id': item['section_id'],
|
||||||
|
'section_name': item['section_name'],
|
||||||
|
'section_type': item['section_type'].capitalize(),
|
||||||
|
'count': item['count'],
|
||||||
|
'parent_count': item['parent_count'],
|
||||||
|
'child_count': item['child_count'],
|
||||||
|
'library_thumb': library_thumb,
|
||||||
|
'library_art': item['art'],
|
||||||
|
'plays': item['plays'],
|
||||||
'last_accessed': item['last_accessed'],
|
'last_accessed': item['last_accessed'],
|
||||||
'last_watched': item['last_watched'],
|
'last_watched': item['last_watched'],
|
||||||
'thumb': thumb,
|
'thumb': thumb,
|
||||||
'media_type': item['media_type'],
|
'media_type': item['media_type'],
|
||||||
'rating_key': item['rating_key'],
|
'rating_key': item['rating_key'],
|
||||||
'video_decision': item['video_decision'],
|
'video_decision': item['video_decision'],
|
||||||
'section_id': item['section_id'],
|
|
||||||
'section_name': item['section_name'],
|
|
||||||
'section_type': item['section_type'].capitalize(),
|
|
||||||
'count': item['count'],
|
|
||||||
'parent_count': item['parent_count'],
|
|
||||||
'library_thumb': item['library_thumb'],
|
|
||||||
'custom_thumb': item['custom_thumb'],
|
|
||||||
'library_art': item['art'],
|
|
||||||
'child_count': item['child_count'],
|
|
||||||
'do_notify': helpers.checked(item['do_notify']),
|
'do_notify': helpers.checked(item['do_notify']),
|
||||||
|
'do_notify_created': helpers.checked(item['do_notify_created']),
|
||||||
'keep_history': helpers.checked(item['keep_history'])
|
'keep_history': helpers.checked(item['keep_history'])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,107 +120,130 @@ class Libraries(object):
|
||||||
|
|
||||||
return dict
|
return dict
|
||||||
|
|
||||||
def set_library_config(self, section_id=None, do_notify=1, keep_history=1, custom_thumb=''):
|
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()
|
||||||
|
|
||||||
key_dict = {'section_id': section_id}
|
key_dict = {'section_id': section_id}
|
||||||
value_dict = {'do_notify': do_notify,
|
value_dict = {'custom_thumb_url': custom_thumb,
|
||||||
'keep_history': keep_history,
|
'do_notify': do_notify,
|
||||||
'custom_thumb_url': custom_thumb}
|
'do_notify_created': do_notify_created,
|
||||||
|
'keep_history': keep_history}
|
||||||
try:
|
try:
|
||||||
monitor_db.upsert('library_sections', value_dict, key_dict)
|
monitor_db.upsert('library_sections', value_dict, key_dict)
|
||||||
except:
|
except:
|
||||||
logger.warn("Unable to execute database query for set_user_friendly_name.")
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for set_config: %s." % e)
|
||||||
|
|
||||||
def get_library_details(self, section_id=None):
|
def get_details(self, section_id=None):
|
||||||
from plexpy import pmsconnect
|
from plexpy import pmsconnect
|
||||||
|
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
try:
|
||||||
if section_id:
|
if section_id:
|
||||||
query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
|
query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
|
||||||
'thumb AS library_thumb, (CASE WHEN library_sections.custom_thumb_url == library_sections.thumb ' \
|
'thumb AS library_thumb, custom_thumb_url AS custom_thumb, art, ' \
|
||||||
' THEN NULL ELSE custom_thumb_url END) AS custom_thumb, art, do_notify, keep_history ' \
|
'do_notify, do_notify_created, keep_history ' \
|
||||||
'FROM library_sections ' \
|
'FROM library_sections ' \
|
||||||
'WHERE section_id = ? '
|
'WHERE section_id = ? '
|
||||||
result = monitor_db.select(query, args=[section_id])
|
result = monitor_db.select(query, args=[section_id])
|
||||||
else:
|
else:
|
||||||
result = None
|
result = []
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_details: %s." % e)
|
||||||
|
result = []
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
library_details = {}
|
library_details = {}
|
||||||
for item in result:
|
for item in result:
|
||||||
|
if item['custom_thumb'] and item['custom_thumb'] != item['library_thumb']:
|
||||||
|
library_thumb = item['custom_thumb']
|
||||||
|
elif item['library_thumb']:
|
||||||
|
library_thumb = item['library_thumb']
|
||||||
|
else:
|
||||||
|
library_thumb = common.DEFAULT_COVER_THUMB
|
||||||
|
|
||||||
library_details = {'section_id': item['section_id'],
|
library_details = {'section_id': item['section_id'],
|
||||||
'section_name': item['section_name'],
|
'section_name': item['section_name'],
|
||||||
'section_type': item['section_type'],
|
'section_type': item['section_type'],
|
||||||
'library_thumb': item['library_thumb'],
|
'library_thumb': library_thumb,
|
||||||
'custom_thumb': item['custom_thumb'],
|
|
||||||
'library_art': item['art'],
|
'library_art': item['art'],
|
||||||
'count': item['count'],
|
'count': item['count'],
|
||||||
'parent_count': item['parent_count'],
|
'parent_count': item['parent_count'],
|
||||||
'child_count': item['child_count'],
|
'child_count': item['child_count'],
|
||||||
'do_notify': item['do_notify'],
|
'do_notify': item['do_notify'],
|
||||||
|
'do_notify_created': item['do_notify_created'],
|
||||||
'keep_history': item['keep_history']
|
'keep_history': item['keep_history']
|
||||||
}
|
}
|
||||||
return library_details
|
return library_details
|
||||||
else:
|
else:
|
||||||
logger.warn(u"PlexPy :: Unable to retrieve library from local database. Requesting library list refresh.")
|
logger.warn(u"PlexPy Libraries :: Unable to retrieve library from local database. Requesting library list refresh.")
|
||||||
# Let's first refresh the user list to make sure the user isn't newly added and not in the db yet
|
# Let's first refresh the user list to make sure the user isn't newly added and not in the db yet
|
||||||
|
try:
|
||||||
if section_id:
|
if section_id:
|
||||||
# Refresh libraries
|
# Refresh libraries
|
||||||
pmsconnect.refresh_libraries()
|
pmsconnect.refresh_libraries()
|
||||||
query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
|
query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
|
||||||
'thumb AS library_thumb, (CASE WHEN library_sections.custom_thumb_url == library_sections.thumb ' \
|
'thumb AS library_thumb, custom_thumb_url AS custom_thumb, art, ' \
|
||||||
' THEN NULL ELSE custom_thumb_url END) AS custom_thumb, art, do_notify, keep_history ' \
|
'do_notify, do_notify_created, keep_history ' \
|
||||||
'FROM library_sections ' \
|
'FROM library_sections ' \
|
||||||
'WHERE section_id = ? '
|
'WHERE section_id = ? '
|
||||||
result = monitor_db.select(query, args=[section_id])
|
result = monitor_db.select(query, args=[section_id])
|
||||||
else:
|
else:
|
||||||
result = None
|
result = []
|
||||||
|
except:
|
||||||
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_details: %s." % e)
|
||||||
|
result = []
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
library_details = {}
|
library_details = {}
|
||||||
for item in result:
|
for item in result:
|
||||||
|
if item['custom_thumb'] and item['custom_thumb'] != item['library_thumb']:
|
||||||
|
library_thumb = item['custom_thumb']
|
||||||
|
elif item['library_thumb']:
|
||||||
|
library_thumb = item['library_thumb']
|
||||||
|
else:
|
||||||
|
library_thumb = common.DEFAULT_COVER_THUMB
|
||||||
|
|
||||||
library_details = {'section_id': item['section_id'],
|
library_details = {'section_id': item['section_id'],
|
||||||
'section_name': item['section_name'],
|
'section_name': item['section_name'],
|
||||||
'section_type': item['section_type'],
|
'section_type': item['section_type'],
|
||||||
'library_thumb': item['library_thumb'],
|
'library_thumb': library_thumb,
|
||||||
'custom_thumb': item['custom_thumb'],
|
|
||||||
'library_art': item['art'],
|
'library_art': item['art'],
|
||||||
'count': item['count'],
|
'count': item['count'],
|
||||||
'parent_count': item['parent_count'],
|
'parent_count': item['parent_count'],
|
||||||
'child_count': item['child_count'],
|
'child_count': item['child_count'],
|
||||||
'do_notify': item['do_notify'],
|
'do_notify': item['do_notify'],
|
||||||
|
'do_notify_created': item['do_notify_created'],
|
||||||
'keep_history': item['keep_history']
|
'keep_history': item['keep_history']
|
||||||
}
|
}
|
||||||
return user_details
|
return library_details
|
||||||
else:
|
else:
|
||||||
# If there is no library data we must return something
|
# If there is no library data we must return something
|
||||||
# Use "Local" user to retain compatibility with PlexWatch database value
|
# Use "Local" user to retain compatibility with PlexWatch database value
|
||||||
return {'section_id': None,
|
return {'section_id': None,
|
||||||
'section_name': '',
|
'section_name': 'Local',
|
||||||
'section_type': '',
|
'section_type': '',
|
||||||
'library_thumb': '',
|
'library_thumb': common.DEFAULT_COVER_THUMB,
|
||||||
'custom_thumb': '',
|
|
||||||
'library_art': '',
|
'library_art': '',
|
||||||
'count': 0,
|
'count': 0,
|
||||||
'parent_count': 0,
|
'parent_count': 0,
|
||||||
'child_count': 0,
|
'child_count': 0,
|
||||||
'do_notify': 0,
|
'do_notify': 0,
|
||||||
|
'do_notify_created': 0,
|
||||||
'keep_history': 0
|
'keep_history': 0
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_library_watch_time_stats(self, library_id=None):
|
def get_watch_time_stats(self, library_id=None):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
time_queries = [1, 7, 30, 0]
|
time_queries = [1, 7, 30, 0]
|
||||||
library_watch_time_stats = []
|
library_watch_time_stats = []
|
||||||
|
|
||||||
for days in time_queries:
|
for days in time_queries:
|
||||||
|
try:
|
||||||
if days > 0:
|
if days > 0:
|
||||||
if library_id:
|
if str(library_id).isdigit():
|
||||||
query = 'SELECT (SUM(stopped - started) - ' \
|
query = 'SELECT (SUM(stopped - started) - ' \
|
||||||
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
||||||
'COUNT(session_history.id) AS total_plays ' \
|
'COUNT(session_history.id) AS total_plays ' \
|
||||||
|
@ -220,6 +253,9 @@ class Libraries(object):
|
||||||
'AND library_id = ?' % days
|
'AND library_id = ?' % days
|
||||||
result = monitor_db.select(query, args=[library_id])
|
result = monitor_db.select(query, args=[library_id])
|
||||||
else:
|
else:
|
||||||
|
result = []
|
||||||
|
else:
|
||||||
|
if str(library_id).isdigit():
|
||||||
query = 'SELECT (SUM(stopped - started) - ' \
|
query = 'SELECT (SUM(stopped - started) - ' \
|
||||||
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
||||||
'COUNT(session_history.id) AS total_plays ' \
|
'COUNT(session_history.id) AS total_plays ' \
|
||||||
|
@ -227,6 +263,11 @@ class Libraries(object):
|
||||||
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
|
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
|
||||||
'WHERE library_id = ?'
|
'WHERE library_id = ?'
|
||||||
result = monitor_db.select(query, args=[library_id])
|
result = monitor_db.select(query, args=[library_id])
|
||||||
|
else:
|
||||||
|
result = []
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_watch_time_stats: %s." % e)
|
||||||
|
result = []
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
if item['total_time']:
|
if item['total_time']:
|
||||||
|
@ -245,13 +286,13 @@ class Libraries(object):
|
||||||
|
|
||||||
return library_watch_time_stats
|
return library_watch_time_stats
|
||||||
|
|
||||||
def get_library_user_stats(self, library_id=None):
|
def get_user_stats(self, library_id=None):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
user_stats = []
|
user_stats = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if library_id:
|
if str(library_id).isdigit():
|
||||||
query = 'SELECT (CASE WHEN users.friendly_name IS NULL THEN users.username ' \
|
query = 'SELECT (CASE WHEN users.friendly_name IS NULL THEN users.username ' \
|
||||||
'ELSE users.friendly_name END) AS user, users.user_id, users.thumb, COUNT(user) AS user_count ' \
|
'ELSE users.friendly_name END) AS user, users.user_id, users.thumb, COUNT(user) AS user_count ' \
|
||||||
'FROM session_history ' \
|
'FROM session_history ' \
|
||||||
|
@ -261,9 +302,11 @@ class Libraries(object):
|
||||||
'GROUP BY user ' \
|
'GROUP BY user ' \
|
||||||
'ORDER BY user_count DESC'
|
'ORDER BY user_count DESC'
|
||||||
result = monitor_db.select(query, args=[library_id])
|
result = monitor_db.select(query, args=[library_id])
|
||||||
except:
|
else:
|
||||||
logger.warn("Unable to execute database query for get_library_user_stats.")
|
result = []
|
||||||
return None
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_user_stats: %s." % e)
|
||||||
|
result = []
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
row = {'user': item['user'],
|
row = {'user': item['user'],
|
||||||
|
@ -275,9 +318,79 @@ class Libraries(object):
|
||||||
|
|
||||||
return user_stats
|
return user_stats
|
||||||
|
|
||||||
def delete_all_library_history(self, section_id=None):
|
def get_recently_watched(self, library_id=None, limit='10'):
|
||||||
|
monitor_db = database.MonitorDatabase()
|
||||||
|
recently_watched = []
|
||||||
|
|
||||||
|
if not limit.isdigit():
|
||||||
|
limit = '10'
|
||||||
|
|
||||||
|
try:
|
||||||
|
if str(library_id).isdigit():
|
||||||
|
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
|
||||||
|
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
|
||||||
|
'year, started, user ' \
|
||||||
|
'FROM session_history_metadata ' \
|
||||||
|
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
|
||||||
|
'WHERE library_id = ? ' \
|
||||||
|
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
|
||||||
|
' ELSE session_history.rating_key END) ' \
|
||||||
|
'ORDER BY started DESC LIMIT ?'
|
||||||
|
result = monitor_db.select(query, args=[library_id, limit])
|
||||||
|
else:
|
||||||
|
result = []
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_recently_watched: %s." % e)
|
||||||
|
result = []
|
||||||
|
|
||||||
|
for row in result:
|
||||||
|
if row['media_type'] == 'episode' and row['parent_thumb']:
|
||||||
|
thumb = row['parent_thumb']
|
||||||
|
elif row['media_type'] == 'episode':
|
||||||
|
thumb = row['grandparent_thumb']
|
||||||
|
else:
|
||||||
|
thumb = row['thumb']
|
||||||
|
|
||||||
|
recent_output = {'row_id': row['id'],
|
||||||
|
'type': row['media_type'],
|
||||||
|
'rating_key': row['rating_key'],
|
||||||
|
'title': row['title'],
|
||||||
|
'parent_title': row['parent_title'],
|
||||||
|
'grandparent_title': row['grandparent_title'],
|
||||||
|
'thumb': thumb,
|
||||||
|
'media_index': row['media_index'],
|
||||||
|
'parent_media_index': row['parent_media_index'],
|
||||||
|
'year': row['year'],
|
||||||
|
'time': row['started'],
|
||||||
|
'user': row['user']
|
||||||
|
}
|
||||||
|
recently_watched.append(recent_output)
|
||||||
|
|
||||||
|
return recently_watched
|
||||||
|
|
||||||
|
def get_sections(self):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
try:
|
||||||
|
query = 'SELECT section_id, section_name FROM library_sections WHERE deleted_section = 0'
|
||||||
|
result = monitor_db.select(query=query)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_sections: %s." % e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
libraries = []
|
||||||
|
for item in result:
|
||||||
|
library = {'section_id': item['section_id'],
|
||||||
|
'section_name': item['section_name']
|
||||||
|
}
|
||||||
|
libraries.append(library)
|
||||||
|
|
||||||
|
return libraries
|
||||||
|
|
||||||
|
def delete_all_history(self, section_id=None):
|
||||||
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
try:
|
||||||
if section_id.isdigit():
|
if section_id.isdigit():
|
||||||
logger.info(u"PlexPy Libraries :: Deleting all history for library id %s from database." % section_id)
|
logger.info(u"PlexPy Libraries :: Deleting all history for library id %s from database." % section_id)
|
||||||
session_history_media_info_del = \
|
session_history_media_info_del = \
|
||||||
|
@ -299,6 +412,57 @@ class Libraries(object):
|
||||||
'session_history_metadata '
|
'session_history_metadata '
|
||||||
'WHERE session_history_metadata.library_id = ?', [section_id])
|
'WHERE session_history_metadata.library_id = ?', [section_id])
|
||||||
|
|
||||||
return 'Deleted all items for library_id %s.' % section_id
|
return 'Deleted all items for section_id %s.' % section_id
|
||||||
else:
|
else:
|
||||||
return 'Unable to delete items. Input library_id not valid.'
|
return 'Unable to delete items, section_id not valid.'
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for delete_all_history: %s." % e)
|
||||||
|
|
||||||
|
def delete(self, section_id=None):
|
||||||
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if section_id.isdigit():
|
||||||
|
self.delete_all_history(section_id)
|
||||||
|
logger.info(u"PlexPy Libraries :: Deleting library with id %s from database." % section_id)
|
||||||
|
monitor_db.action('UPDATE library_sections SET deleted_section = 1 WHERE section_id = ?', [section_id])
|
||||||
|
monitor_db.action('UPDATE library_sections SET keep_history = 0 WHERE section_id = ?', [section_id])
|
||||||
|
monitor_db.action('UPDATE library_sections SET do_notify = 0 WHERE section_id = ?', [section_id])
|
||||||
|
monitor_db.action('UPDATE library_sections SET do_notify_created = 0 WHERE section_id = ?', [section_id])
|
||||||
|
|
||||||
|
library_cards = plexpy.CONFIG.HOME_LIBRARY_CARDS
|
||||||
|
if section_id in library_cards:
|
||||||
|
library_cards.remove(section_id)
|
||||||
|
plexpy.CONFIG.__setattr__('HOME_LIBRARY_CARDS', library_cards)
|
||||||
|
plexpy.CONFIG.write()
|
||||||
|
|
||||||
|
return 'Deleted library with id %s.' % section_id
|
||||||
|
else:
|
||||||
|
return 'Unable to delete library, section_id not valid.'
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for delete: %s." % e)
|
||||||
|
|
||||||
|
def undelete(self, section_id=None, section_name=None):
|
||||||
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if section_id and section_id.isdigit():
|
||||||
|
logger.info(u"PlexPy Libraries :: Re-adding library with id %s to database." % section_id)
|
||||||
|
monitor_db.action('UPDATE library_sections SET deleted_section = 0 WHERE section_id = ?', [section_id])
|
||||||
|
monitor_db.action('UPDATE library_sections SET keep_history = 1 WHERE section_id = ?', [section_id])
|
||||||
|
monitor_db.action('UPDATE library_sections SET do_notify = 1 WHERE section_id = ?', [section_id])
|
||||||
|
monitor_db.action('UPDATE library_sections SET do_notify_created = 1 WHERE section_id = ?', [section_id])
|
||||||
|
|
||||||
|
return 'Re-added library with id %s.' % section_id
|
||||||
|
elif section_name:
|
||||||
|
logger.info(u"PlexPy Libraries :: Re-adding library with name %s to database." % section_name)
|
||||||
|
monitor_db.action('UPDATE library_sections SET deleted_section = 0 WHERE section_name = ?', [section_name])
|
||||||
|
monitor_db.action('UPDATE library_sections SET keep_history = 1 WHERE section_name = ?', [section_name])
|
||||||
|
monitor_db.action('UPDATE library_sections SET do_notify = 1 WHERE section_name = ?', [section_name])
|
||||||
|
monitor_db.action('UPDATE library_sections SET do_notify_created = 1 WHERE section_name = ?', [section_name])
|
||||||
|
|
||||||
|
return 'Re-added library with section_name %s.' % section_name
|
||||||
|
else:
|
||||||
|
return 'Unable to re-add library, section_id or section_name not valid.'
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Libraries :: Unable to execute database query for undelete: %s." % e)
|
|
@ -16,20 +16,28 @@
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
import re
|
||||||
|
|
||||||
from plexpy import logger, config, notifiers, database, helpers, plextv, pmsconnect
|
from plexpy import logger, config, notifiers, database, helpers, plextv, pmsconnect
|
||||||
import plexpy
|
import plexpy
|
||||||
|
|
||||||
|
|
||||||
def notify(stream_data=None, notify_action=None):
|
def notify(stream_data=None, notify_action=None):
|
||||||
from plexpy import users
|
from plexpy import users, libraries
|
||||||
|
|
||||||
if stream_data and notify_action:
|
if stream_data and notify_action:
|
||||||
# Check if notifications enabled for user
|
# Check if notifications enabled for user and library
|
||||||
user_data = users.Users()
|
user_data = users.Users()
|
||||||
user_details = user_data.get_user_friendly_name(user=stream_data['user'])
|
user_details = user_data.get_details(user_id=stream_data['user_id'])
|
||||||
|
|
||||||
|
library_data = libraries.Libraries()
|
||||||
|
library_details = library_data.get_details(section_id=stream_data['library_id'])
|
||||||
|
|
||||||
if not user_details['do_notify']:
|
if not user_details['do_notify']:
|
||||||
|
# logger.debug(u"PlexPy NotificationHandler :: Notifications for user '%s' is disabled." % user_details['username'])
|
||||||
|
return
|
||||||
|
elif not library_details['do_notify']:
|
||||||
|
# logger.debug(u"PlexPy NotificationHandler :: Notifications for library '%s' is disabled." % library_details['section_name'])
|
||||||
return
|
return
|
||||||
|
|
||||||
if (stream_data['media_type'] == 'movie' and plexpy.CONFIG.MOVIE_NOTIFY_ENABLE) \
|
if (stream_data['media_type'] == 'movie' and plexpy.CONFIG.MOVIE_NOTIFY_ENABLE) \
|
||||||
|
@ -195,10 +203,10 @@ def notify(stream_data=None, notify_action=None):
|
||||||
elif stream_data['media_type'] == 'clip':
|
elif stream_data['media_type'] == 'clip':
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
#logger.debug(u"PlexPy Notifier :: Notify called with unsupported media type.")
|
#logger.debug(u"PlexPy NotificationHandler :: Notify called with unsupported media type.")
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
logger.debug(u"PlexPy Notifier :: Notify called but incomplete data received.")
|
logger.debug(u"PlexPy NotificationHandler :: Notify called but incomplete data received.")
|
||||||
|
|
||||||
|
|
||||||
def notify_timeline(timeline_data=None, notify_action=None):
|
def notify_timeline(timeline_data=None, notify_action=None):
|
||||||
|
@ -256,7 +264,7 @@ def notify_timeline(timeline_data=None, notify_action=None):
|
||||||
notify_action=notify_action,
|
notify_action=notify_action,
|
||||||
script_args=notify_strings[2])
|
script_args=notify_strings[2])
|
||||||
else:
|
else:
|
||||||
logger.debug(u"PlexPy Notifier :: Notify timeline called but incomplete data received.")
|
logger.debug(u"PlexPy NotificationHandler :: Notify timeline called but incomplete data received.")
|
||||||
|
|
||||||
|
|
||||||
def get_notify_state(session):
|
def get_notify_state(session):
|
||||||
|
@ -334,11 +342,10 @@ def set_notify_state(session, state, agent_info):
|
||||||
|
|
||||||
monitor_db.upsert(table_name='notify_log', key_dict=keys, value_dict=values)
|
monitor_db.upsert(table_name='notify_log', key_dict=keys, value_dict=values)
|
||||||
else:
|
else:
|
||||||
logger.error('PlexPy Notifier :: Unable to set notify state.')
|
logger.error(u"PlexPy NotificationHandler :: Unable to set notify state.")
|
||||||
|
|
||||||
|
|
||||||
def build_notify_text(session=None, timeline=None, state=None):
|
def build_notify_text(session=None, timeline=None, state=None):
|
||||||
|
|
||||||
# Get the server name
|
# Get the server name
|
||||||
server_name = plexpy.CONFIG.PMS_NAME
|
server_name = plexpy.CONFIG.PMS_NAME
|
||||||
|
|
||||||
|
@ -350,7 +357,7 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
updated_at = server_times[0]['updated_at']
|
updated_at = server_times[0]['updated_at']
|
||||||
server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at)))
|
server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at)))
|
||||||
else:
|
else:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to retrieve server uptime.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to retrieve server uptime.")
|
||||||
server_uptime = 'N/A'
|
server_uptime = 'N/A'
|
||||||
|
|
||||||
# Get metadata feed for item
|
# Get metadata feed for item
|
||||||
|
@ -367,7 +374,7 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
if metadata_list:
|
if metadata_list:
|
||||||
metadata = metadata_list['metadata']
|
metadata = metadata_list['metadata']
|
||||||
else:
|
else:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to retrieve metadata for rating_key %s" % str(rating_key))
|
logger.error(u"PlexPy NotificationHandler :: Unable to retrieve metadata for rating_key %s" % str(rating_key))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# Check for exclusion tags
|
# Check for exclusion tags
|
||||||
|
@ -547,15 +554,16 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
'transcode_audio_codec': transcode_audio_codec,
|
'transcode_audio_codec': transcode_audio_codec,
|
||||||
'transcode_audio_channels': transcode_audio_channels,
|
'transcode_audio_channels': transcode_audio_channels,
|
||||||
'title': full_title,
|
'title': full_title,
|
||||||
|
'library_name': metadata['library_name'],
|
||||||
'show_name': show_name,
|
'show_name': show_name,
|
||||||
'episode_name': episode_name,
|
'episode_name': episode_name,
|
||||||
'artist_name': artist_name,
|
'artist_name': artist_name,
|
||||||
'album_name': album_name,
|
'album_name': album_name,
|
||||||
'track_name': track_name,
|
'track_name': track_name,
|
||||||
'season_num': metadata['parent_index'].zfill(1),
|
'season_num': metadata['parent_media_index'].zfill(1),
|
||||||
'season_num00': metadata['parent_index'].zfill(2),
|
'season_num00': metadata['parent_media_index'].zfill(2),
|
||||||
'episode_num': metadata['index'].zfill(1),
|
'episode_num': metadata['media_index'].zfill(1),
|
||||||
'episode_num00': metadata['index'].zfill(2),
|
'episode_num00': metadata['media_index'].zfill(2),
|
||||||
'year': metadata['year'],
|
'year': metadata['year'],
|
||||||
'studio': metadata['studio'],
|
'studio': metadata['studio'],
|
||||||
'content_rating': metadata['content_rating'],
|
'content_rating': metadata['content_rating'],
|
||||||
|
@ -597,16 +605,16 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
try:
|
try:
|
||||||
subject_text = unicode(on_start_subject).format(**available_params)
|
subject_text = unicode(on_start_subject).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body_text = unicode(on_start_body).format(**available_params)
|
body_text = unicode(on_start_body).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
|
||||||
|
|
||||||
return [subject_text, body_text, script_args]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
|
@ -621,16 +629,16 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
try:
|
try:
|
||||||
subject_text = unicode(on_stop_subject).format(**available_params)
|
subject_text = unicode(on_stop_subject).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body_text = unicode(on_stop_body).format(**available_params)
|
body_text = unicode(on_stop_body).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
|
||||||
|
|
||||||
return [subject_text, body_text, script_args]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
|
@ -645,16 +653,16 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
try:
|
try:
|
||||||
subject_text = unicode(on_pause_subject).format(**available_params)
|
subject_text = unicode(on_pause_subject).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body_text = unicode(on_pause_body).format(**available_params)
|
body_text = unicode(on_pause_body).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
|
||||||
|
|
||||||
return [subject_text, body_text, script_args]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
|
@ -669,16 +677,16 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
try:
|
try:
|
||||||
subject_text = unicode(on_resume_subject).format(**available_params)
|
subject_text = unicode(on_resume_subject).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body_text = unicode(on_resume_body).format(**available_params)
|
body_text = unicode(on_resume_body).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
|
||||||
|
|
||||||
return [subject_text, body_text, script_args]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
|
@ -693,16 +701,16 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
try:
|
try:
|
||||||
subject_text = unicode(on_buffer_subject).format(**available_params)
|
subject_text = unicode(on_buffer_subject).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body_text = unicode(on_buffer_body).format(**available_params)
|
body_text = unicode(on_buffer_body).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
|
||||||
|
|
||||||
return [subject_text, body_text, script_args]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
|
@ -717,16 +725,16 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
try:
|
try:
|
||||||
subject_text = unicode(on_watched_subject).format(**available_params)
|
subject_text = unicode(on_watched_subject).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body_text = unicode(on_watched_body).format(**available_params)
|
body_text = unicode(on_watched_body).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
|
||||||
|
|
||||||
return [subject_text, body_text, script_args]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
|
@ -739,16 +747,16 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
try:
|
try:
|
||||||
subject_text = unicode(on_created_subject).format(**available_params)
|
subject_text = unicode(on_created_subject).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body_text = unicode(on_created_body).format(**available_params)
|
body_text = unicode(on_created_body).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
|
||||||
|
|
||||||
return [subject_text, body_text, script_args]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
|
@ -769,7 +777,7 @@ def build_server_notify_text(state=None):
|
||||||
updated_at = server_times[0]['updated_at']
|
updated_at = server_times[0]['updated_at']
|
||||||
server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at)))
|
server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at)))
|
||||||
else:
|
else:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to retrieve server uptime.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to retrieve server uptime.")
|
||||||
server_uptime = 'N/A'
|
server_uptime = 'N/A'
|
||||||
|
|
||||||
on_extdown_subject = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_SUBJECT_TEXT
|
on_extdown_subject = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_SUBJECT_TEXT
|
||||||
|
@ -812,14 +820,14 @@ def build_server_notify_text(state=None):
|
||||||
try:
|
try:
|
||||||
subject_text = unicode(on_extdown_subject).format(**available_params)
|
subject_text = unicode(on_extdown_subject).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body_text = unicode(on_extdown_body).format(**available_params)
|
body_text = unicode(on_extdown_body).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
||||||
|
|
||||||
|
@ -835,16 +843,16 @@ def build_server_notify_text(state=None):
|
||||||
try:
|
try:
|
||||||
subject_text = unicode(on_intdown_subject).format(**available_params)
|
subject_text = unicode(on_intdown_subject).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body_text = unicode(on_intdown_body).format(**available_params)
|
body_text = unicode(on_intdown_body).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
|
||||||
|
|
||||||
return [subject_text, body_text, script_args]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
|
@ -857,16 +865,16 @@ def build_server_notify_text(state=None):
|
||||||
try:
|
try:
|
||||||
subject_text = unicode(on_extup_subject).format(**available_params)
|
subject_text = unicode(on_extup_subject).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body_text = unicode(on_extup_body).format(**available_params)
|
body_text = unicode(on_extup_body).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
|
||||||
|
|
||||||
return [subject_text, body_text, script_args]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
|
@ -879,16 +887,16 @@ def build_server_notify_text(state=None):
|
||||||
try:
|
try:
|
||||||
subject_text = unicode(on_intup_subject).format(**available_params)
|
subject_text = unicode(on_intup_subject).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
body_text = unicode(on_intup_body).format(**available_params)
|
body_text = unicode(on_intup_body).format(**available_params)
|
||||||
except LookupError, e:
|
except LookupError, e:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
|
||||||
except:
|
except:
|
||||||
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
|
||||||
|
|
||||||
return [subject_text, body_text, script_args]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
|
@ -899,7 +907,5 @@ def build_server_notify_text(state=None):
|
||||||
|
|
||||||
|
|
||||||
def strip_tag(data):
|
def strip_tag(data):
|
||||||
import re
|
|
||||||
|
|
||||||
p = re.compile(r'<.*?>')
|
p = re.compile(r'<.*?>')
|
||||||
return p.sub('', data)
|
return p.sub('', data)
|
||||||
|
|
|
@ -525,10 +525,10 @@ class GROWL(object):
|
||||||
try:
|
try:
|
||||||
growl.register()
|
growl.register()
|
||||||
except gntp.notifier.errors.NetworkError:
|
except gntp.notifier.errors.NetworkError:
|
||||||
logger.warning(u'Growl notification failed: network error')
|
logger.warn(u"PlexPy Notifier :: Growl notification failed: network error")
|
||||||
return
|
return
|
||||||
except gntp.notifier.errors.AuthError:
|
except gntp.notifier.errors.AuthError:
|
||||||
logger.warning(u'Growl notification failed: authentication error')
|
logger.warn(u"PlexPy Notifier :: Growl notification failed: authentication error")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Fix message
|
# Fix message
|
||||||
|
@ -548,11 +548,11 @@ class GROWL(object):
|
||||||
description=message,
|
description=message,
|
||||||
icon=image
|
icon=image
|
||||||
)
|
)
|
||||||
|
logger.info(u"PlexPy Notifier :: Growl notification sent.")
|
||||||
except gntp.notifier.errors.NetworkError:
|
except gntp.notifier.errors.NetworkError:
|
||||||
logger.warning(u'Growl notification failed: network error')
|
logger.warn(u"PlexPy Notifier :: Growl notification failed: network error")
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.info(u"Growl notifications sent.")
|
|
||||||
|
|
||||||
def updateLibrary(self):
|
def updateLibrary(self):
|
||||||
# For uniformity reasons not removed
|
# For uniformity reasons not removed
|
||||||
|
@ -617,13 +617,13 @@ class PROWL(object):
|
||||||
request_status = response.status
|
request_status = response.status
|
||||||
|
|
||||||
if request_status == 200:
|
if request_status == 200:
|
||||||
logger.info(u"Prowl notifications sent.")
|
logger.info(u"PlexPy Notifier :: Prowl notification sent.")
|
||||||
return True
|
return True
|
||||||
elif request_status == 401:
|
elif request_status == 401:
|
||||||
logger.info(u"Prowl auth failed: %s" % response.reason)
|
logger.warn(u"PlexPy Notifier :: Prowl notification failed: %s" % response.reason)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
logger.info(u"Prowl notification failed.")
|
logger.warn(u"PlexPy Notifier :: Prowl notification failed.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def updateLibrary(self):
|
def updateLibrary(self):
|
||||||
|
@ -698,7 +698,7 @@ class XBMC(object):
|
||||||
time = "3000" # in ms
|
time = "3000" # in ms
|
||||||
|
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
logger.info('Sending notification command to XMBC @ ' + host)
|
logger.info(u"PlexPy Notifier :: Sending notification command to XMBC @ " + host)
|
||||||
try:
|
try:
|
||||||
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']
|
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']
|
||||||
|
|
||||||
|
@ -713,15 +713,17 @@ class XBMC(object):
|
||||||
|
|
||||||
if not request:
|
if not request:
|
||||||
raise Exception
|
raise Exception
|
||||||
|
else:
|
||||||
|
logger.info(u"PlexPy Notifier :: XBMC notification sent.")
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error('Error sending notification request to XBMC')
|
logger.warn(u"PlexPy Notifier :: XBMC notification filed.")
|
||||||
|
|
||||||
def return_config_options(self):
|
def return_config_options(self):
|
||||||
config_option = [{'label': 'XBMC Host:Port',
|
config_option = [{'label': 'XBMC Host:Port',
|
||||||
'value': self.hosts,
|
'value': self.hosts,
|
||||||
'name': 'xbmc_host',
|
'name': 'xbmc_host',
|
||||||
'description': 'Host running XBMC (e.g. http://localhost:8080). Separate multiple hosts with commas.',
|
'description': 'Host running XBMC (e.g. http://localhost:8080). Separate multiple hosts with commas (,).',
|
||||||
'input_type': 'text'
|
'input_type': 'text'
|
||||||
},
|
},
|
||||||
{'label': 'XBMC Username',
|
{'label': 'XBMC Username',
|
||||||
|
@ -763,12 +765,12 @@ class Plex(object):
|
||||||
base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
|
base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
|
||||||
req.add_header("Authorization", "Basic %s" % base64string)
|
req.add_header("Authorization", "Basic %s" % base64string)
|
||||||
|
|
||||||
logger.info('Plex url: %s' % url)
|
# logger.info(u"PlexPy Notifier :: Plex url: %s" % url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
handle = urllib2.urlopen(req)
|
handle = urllib2.urlopen(req)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn('Error opening Plex url: %s' % e)
|
logger.error(u"PlexPy Notifier :: Error opening Plex url: %s" % e)
|
||||||
return
|
return
|
||||||
|
|
||||||
response = handle.read().decode(plexpy.SYS_ENCODING)
|
response = handle.read().decode(plexpy.SYS_ENCODING)
|
||||||
|
@ -784,7 +786,7 @@ class Plex(object):
|
||||||
time = "3000" # in ms
|
time = "3000" # in ms
|
||||||
|
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
logger.info('Sending notification command to Plex Media Server @ ' + host)
|
logger.info(u"PlexPy Notifier :: Sending notification command to Plex Media Server @ " + host)
|
||||||
try:
|
try:
|
||||||
notification = header + "," + message + "," + time
|
notification = header + "," + message + "," + time
|
||||||
notifycommand = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' + notification + ')'}
|
notifycommand = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' + notification + ')'}
|
||||||
|
@ -792,9 +794,11 @@ class Plex(object):
|
||||||
|
|
||||||
if not request:
|
if not request:
|
||||||
raise Exception
|
raise Exception
|
||||||
|
else:
|
||||||
|
logger.info(u"PlexPy Notifier :: Plex notification sent.")
|
||||||
|
|
||||||
except:
|
except:
|
||||||
logger.warn('Error sending notification request to Plex Media Server')
|
logger.warn(u"PlexPy Notifier :: Plex notification failed.")
|
||||||
|
|
||||||
def return_config_options(self):
|
def return_config_options(self):
|
||||||
config_option = [{'label': 'Plex Client Host:Port',
|
config_option = [{'label': 'Plex Client Host:Port',
|
||||||
|
@ -855,9 +859,10 @@ class NMA(object):
|
||||||
response = p.push(title, event, message, priority=nma_priority, batch_mode=batch)
|
response = p.push(title, event, message, priority=nma_priority, batch_mode=batch)
|
||||||
|
|
||||||
if not response[api][u'code'] == u'200':
|
if not response[api][u'code'] == u'200':
|
||||||
logger.error(u'Could not send notification to NotifyMyAndroid')
|
logger.warn(u"PlexPy Notifier :: NotifyMyAndroid notification failed.")
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
|
logger.info(u"PlexPy Notifier :: NotifyMyAndroid notification sent.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def return_config_options(self):
|
def return_config_options(self):
|
||||||
|
@ -918,13 +923,13 @@ class PUSHBULLET(object):
|
||||||
# logger.debug(u"PushBullet response body: %r" % response.read())
|
# logger.debug(u"PushBullet response body: %r" % response.read())
|
||||||
|
|
||||||
if request_status == 200:
|
if request_status == 200:
|
||||||
logger.info(u"PushBullet notifications sent.")
|
logger.info(u"PlexPy Notifier :: PushBullet notification sent.")
|
||||||
return True
|
return True
|
||||||
elif request_status >= 400 and request_status < 500:
|
elif request_status >= 400 and request_status < 500:
|
||||||
logger.info(u"PushBullet request failed: %s" % response.reason)
|
logger.warn(u"PlexPy Notifier :: PushBullet notification failed: %s" % response.reason)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
logger.info(u"PushBullet notification failed serverside.")
|
logger.warn(u"PlexPy Notifier :: PushBullet notification failed.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def test(self, apikey, deviceid):
|
def test(self, apikey, deviceid):
|
||||||
|
@ -952,10 +957,10 @@ class PUSHBULLET(object):
|
||||||
devices.update({'': ''})
|
devices.update({'': ''})
|
||||||
return devices
|
return devices
|
||||||
elif request_status >= 400 and request_status < 500:
|
elif request_status >= 400 and request_status < 500:
|
||||||
logger.info(u"Unable to retrieve Pushbullet devices list: %s" % response.reason)
|
logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushbullet devices list: %s" % response.reason)
|
||||||
return {'': ''}
|
return {'': ''}
|
||||||
else:
|
else:
|
||||||
logger.info(u"Unable to retrieve Pushbullet devices list.")
|
logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushbullet devices list.")
|
||||||
return {'': ''}
|
return {'': ''}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -1020,13 +1025,13 @@ class PUSHALOT(object):
|
||||||
# logger.debug(u"Pushalot response body: %r" % response.read())
|
# logger.debug(u"Pushalot response body: %r" % response.read())
|
||||||
|
|
||||||
if request_status == 200:
|
if request_status == 200:
|
||||||
logger.info(u"Pushalot notifications sent.")
|
logger.info(u"PlexPy Notifier :: Pushalot notification sent.")
|
||||||
return True
|
return True
|
||||||
elif request_status == 410:
|
elif request_status == 410:
|
||||||
logger.info(u"Pushalot auth failed: %s" % response.reason)
|
logger.warn(u"PlexPy Notifier :: Pushalot notification failed: %s" % response.reason)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
logger.info(u"Pushalot notification failed.")
|
logger.warn(u"PlexPy Notifier :: Pushalot notification failed.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def return_config_options(self):
|
def return_config_options(self):
|
||||||
|
@ -1077,13 +1082,13 @@ class PUSHOVER(object):
|
||||||
# logger.debug(u"Pushover response body: %r" % response.read())
|
# logger.debug(u"Pushover response body: %r" % response.read())
|
||||||
|
|
||||||
if request_status == 200:
|
if request_status == 200:
|
||||||
logger.info(u"Pushover notifications sent.")
|
logger.info(u"PlexPy Notifier :: Pushover notification sent.")
|
||||||
return True
|
return True
|
||||||
elif request_status >= 400 and request_status < 500:
|
elif request_status >= 400 and request_status < 500:
|
||||||
logger.info(u"Pushover request failed: %s" % response.reason)
|
logger.warn(u"PlexPy Notifier :: Pushover notification failed: %s" % response.reason)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
logger.info(u"Pushover notification failed.")
|
logger.warn(u"PlexPy Notifier :: Pushover notification failed.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def updateLibrary(self):
|
def updateLibrary(self):
|
||||||
|
@ -1111,10 +1116,10 @@ class PUSHOVER(object):
|
||||||
sounds.update({'': ''})
|
sounds.update({'': ''})
|
||||||
return sounds
|
return sounds
|
||||||
elif request_status >= 400 and request_status < 500:
|
elif request_status >= 400 and request_status < 500:
|
||||||
logger.info(u"Unable to retrieve Pushover notification sounds list: %s" % response.reason)
|
logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushover notification sounds list: %s" % response.reason)
|
||||||
return {'': ''}
|
return {'': ''}
|
||||||
else:
|
else:
|
||||||
logger.info(u"Unable to retrieve Pushover notification sounds list.")
|
logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushover notification sounds list.")
|
||||||
return {'': ''}
|
return {'': ''}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -1177,12 +1182,12 @@ class TwitterNotifier(object):
|
||||||
oauth_consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
|
oauth_consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
|
||||||
oauth_client = oauth.Client(oauth_consumer)
|
oauth_client = oauth.Client(oauth_consumer)
|
||||||
|
|
||||||
logger.info('Requesting temp token from Twitter')
|
logger.info("PlexPy Notifier :: Requesting temp token from Twitter")
|
||||||
|
|
||||||
resp, content = oauth_client.request(self.REQUEST_TOKEN_URL, 'GET')
|
resp, content = oauth_client.request(self.REQUEST_TOKEN_URL, 'GET')
|
||||||
|
|
||||||
if resp['status'] != '200':
|
if resp['status'] != '200':
|
||||||
logger.info('Invalid respond from Twitter requesting temp token: %s' % resp['status'])
|
logger.warn("PlexPy Notifier :: Invalid respond from Twitter requesting temp token: %s" % resp['status'])
|
||||||
else:
|
else:
|
||||||
request_token = dict(parse_qsl(content))
|
request_token = dict(parse_qsl(content))
|
||||||
|
|
||||||
|
@ -1201,25 +1206,25 @@ class TwitterNotifier(object):
|
||||||
token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret'])
|
token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret'])
|
||||||
token.set_verifier(key)
|
token.set_verifier(key)
|
||||||
|
|
||||||
logger.info('Generating and signing request for an access token using key ' + key)
|
# logger.debug(u"Generating and signing request for an access token using key " + key)
|
||||||
|
|
||||||
oauth_consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
|
oauth_consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
|
||||||
# logger.debug('oauth_consumer: ' + str(oauth_consumer))
|
# logger.debug(u"oauth_consumer: " + str(oauth_consumer))
|
||||||
oauth_client = oauth.Client(oauth_consumer, token)
|
oauth_client = oauth.Client(oauth_consumer, token)
|
||||||
# logger.info('oauth_client: ' + str(oauth_client))
|
# logger.debug(u"oauth_client: " + str(oauth_client))
|
||||||
resp, content = oauth_client.request(self.ACCESS_TOKEN_URL, method='POST', body='oauth_verifier=%s' % key)
|
resp, content = oauth_client.request(self.ACCESS_TOKEN_URL, method='POST', body='oauth_verifier=%s' % key)
|
||||||
# logger.info('resp, content: ' + str(resp) + ',' + str(content))
|
# logger.debug(u"resp, content: " + str(resp) + ',' + str(content))
|
||||||
|
|
||||||
access_token = dict(parse_qsl(content))
|
access_token = dict(parse_qsl(content))
|
||||||
# logger.info('access_token: ' + str(access_token))
|
# logger.debug(u"access_token: " + str(access_token))
|
||||||
|
|
||||||
# logger.info('resp[status] = ' + str(resp['status']))
|
# logger.debug(u"resp[status] = " + str(resp['status']))
|
||||||
if resp['status'] != '200':
|
if resp['status'] != '200':
|
||||||
logger.info('The request for a token with did not succeed: ' + str(resp['status']), logger.ERROR)
|
logger.error(u"PlexPy Notifier :: The request for a Twitter token did not succeed: " + str(resp['status']), logger.ERROR)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
logger.info('Your Twitter Access Token key: %s' % access_token['oauth_token'])
|
# logger.info(u"PlexPy Notifier :: Your Twitter Access Token key: %s" % access_token['oauth_token'])
|
||||||
logger.info('Access Token secret: %s' % access_token['oauth_token_secret'])
|
# logger.info(u"PlexPy Notifier :: Access Token secret: %s" % access_token['oauth_token_secret'])
|
||||||
plexpy.CONFIG.TWITTER_USERNAME = access_token['oauth_token']
|
plexpy.CONFIG.TWITTER_USERNAME = access_token['oauth_token']
|
||||||
plexpy.CONFIG.TWITTER_PASSWORD = access_token['oauth_token_secret']
|
plexpy.CONFIG.TWITTER_PASSWORD = access_token['oauth_token_secret']
|
||||||
plexpy.CONFIG.write()
|
plexpy.CONFIG.write()
|
||||||
|
@ -1231,15 +1236,15 @@ class TwitterNotifier(object):
|
||||||
access_token_key = plexpy.CONFIG.TWITTER_USERNAME
|
access_token_key = plexpy.CONFIG.TWITTER_USERNAME
|
||||||
access_token_secret = plexpy.CONFIG.TWITTER_PASSWORD
|
access_token_secret = plexpy.CONFIG.TWITTER_PASSWORD
|
||||||
|
|
||||||
# logger.info(u"Sending tweet: " + message)
|
# logger.info(u"PlexPy Notifier :: Sending tweet: " + message)
|
||||||
|
|
||||||
api = twitter.Api(username, password, access_token_key, access_token_secret)
|
api = twitter.Api(username, password, access_token_key, access_token_secret)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
api.PostUpdate(message)
|
api.PostUpdate(message)
|
||||||
logger.info(u"Twitter notifications sent.")
|
logger.info(u"PlexPy Notifier :: Twitter notification sent")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.info(u"Error sending Tweet: %s" % e)
|
logger.warn(u"PlexPy Notifier :: Twitter notification failed: %s" % e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -1335,13 +1340,13 @@ class OSX_NOTIFY(object):
|
||||||
|
|
||||||
notification_center = NSUserNotificationCenter.defaultUserNotificationCenter()
|
notification_center = NSUserNotificationCenter.defaultUserNotificationCenter()
|
||||||
notification_center.deliverNotification_(notification)
|
notification_center.deliverNotification_(notification)
|
||||||
logger.info(u"OSX Notify notifications sent.")
|
logger.info(u"PlexPy Notifier :: OSX Notify notification sent.")
|
||||||
|
|
||||||
del pool
|
del pool
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn('Error sending OS X Notification: %s' % e)
|
logger.warn(u"PlexPy Notifier :: OSX notification failed: %s" % e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def swizzled_bundleIdentifier(self, original, swizzled):
|
def swizzled_bundleIdentifier(self, original, swizzled):
|
||||||
|
@ -1382,26 +1387,15 @@ class BOXCAR(object):
|
||||||
req = urllib2.Request(self.url)
|
req = urllib2.Request(self.url)
|
||||||
handle = urllib2.urlopen(req, data)
|
handle = urllib2.urlopen(req, data)
|
||||||
handle.close()
|
handle.close()
|
||||||
logger.info(u"Boxcar2 notifications sent.")
|
logger.info(u"PlexPy Notifier :: Boxcar2 notification sent.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except urllib2.URLError as e:
|
except urllib2.URLError as e:
|
||||||
logger.warn('Error sending Boxcar2 Notification: %s' % e)
|
logger.warn(u"PlexPy Notifier :: Boxcar2 notification failed: %s" % e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def return_config_options(self):
|
def get_sounds(self):
|
||||||
config_option = [{'label': 'Boxcar Access Token',
|
sounds = {'': '',
|
||||||
'value': plexpy.CONFIG.BOXCAR_TOKEN,
|
|
||||||
'name': 'boxcar_token',
|
|
||||||
'description': 'Your Boxcar access token.',
|
|
||||||
'input_type': 'text'
|
|
||||||
},
|
|
||||||
{'label': 'Sound',
|
|
||||||
'value': self.sound,
|
|
||||||
'name': 'boxcar_sound',
|
|
||||||
'description': 'Set the notification sound. Leave blank for the default sound.',
|
|
||||||
'input_type': 'select',
|
|
||||||
'select_options': {'': '',
|
|
||||||
'beep-crisp': 'Beep (Crisp)',
|
'beep-crisp': 'Beep (Crisp)',
|
||||||
'beep-soft': 'Beep (Soft)',
|
'beep-soft': 'Beep (Soft)',
|
||||||
'bell-modern': 'Bell (Modern)',
|
'bell-modern': 'Bell (Modern)',
|
||||||
|
@ -1420,7 +1414,7 @@ class BOXCAR(object):
|
||||||
'flourish': 'Flourish',
|
'flourish': 'Flourish',
|
||||||
'harp': 'Harp',
|
'harp': 'Harp',
|
||||||
'light': 'Light',
|
'light': 'Light',
|
||||||
'magic-chime': 'Magic Chime',
|
'magic-chime':'Magic Chime',
|
||||||
'magic-coin': 'Magic Coin',
|
'magic-coin': 'Magic Coin',
|
||||||
'no-sound': 'No Sound',
|
'no-sound': 'No Sound',
|
||||||
'notifier-1': 'Notifier (1)',
|
'notifier-1': 'Notifier (1)',
|
||||||
|
@ -1431,6 +1425,22 @@ class BOXCAR(object):
|
||||||
'score': 'Score',
|
'score': 'Score',
|
||||||
'success': 'Success',
|
'success': 'Success',
|
||||||
'up': 'Up'}
|
'up': 'Up'}
|
||||||
|
|
||||||
|
return sounds
|
||||||
|
|
||||||
|
def return_config_options(self):
|
||||||
|
config_option = [{'label': 'Boxcar Access Token',
|
||||||
|
'value': plexpy.CONFIG.BOXCAR_TOKEN,
|
||||||
|
'name': 'boxcar_token',
|
||||||
|
'description': 'Your Boxcar access token.',
|
||||||
|
'input_type': 'text'
|
||||||
|
},
|
||||||
|
{'label': 'Sound',
|
||||||
|
'value': self.sound,
|
||||||
|
'name': 'boxcar_sound',
|
||||||
|
'description': 'Set the notification sound. Leave blank for the default sound.',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.get_sounds()
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1471,11 +1481,11 @@ class Email(object):
|
||||||
mailserver.sendmail(plexpy.CONFIG.EMAIL_FROM, recipients, message.as_string())
|
mailserver.sendmail(plexpy.CONFIG.EMAIL_FROM, recipients, message.as_string())
|
||||||
mailserver.quit()
|
mailserver.quit()
|
||||||
|
|
||||||
logger.info(u"Email notifications sent.")
|
logger.info(u"PlexPy Notifier :: Email notification sent.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
logger.warn('Error sending Email: %s' % e)
|
logger.warn(u"PlexPy Notifier :: Email notification failed: %s" % e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def return_config_options(self):
|
def return_config_options(self):
|
||||||
|
@ -1558,7 +1568,7 @@ class IFTTT(object):
|
||||||
data = {'value1': subject.encode("utf-8"),
|
data = {'value1': subject.encode("utf-8"),
|
||||||
'value2': message.encode("utf-8")}
|
'value2': message.encode("utf-8")}
|
||||||
|
|
||||||
# logger.debug("Ifttt SENDING: %s" % json.dumps(data))
|
# logger.debug(u"Ifttt SENDING: %s" % json.dumps(data))
|
||||||
|
|
||||||
http_handler.request("POST",
|
http_handler.request("POST",
|
||||||
"/trigger/%s/with/key/%s" % (self.event, self.apikey),
|
"/trigger/%s/with/key/%s" % (self.event, self.apikey),
|
||||||
|
@ -1571,13 +1581,13 @@ class IFTTT(object):
|
||||||
# logger.debug(u"Ifttt response body: %r" % response.read())
|
# logger.debug(u"Ifttt response body: %r" % response.read())
|
||||||
|
|
||||||
if request_status == 200:
|
if request_status == 200:
|
||||||
logger.info(u"Ifttt notifications sent.")
|
logger.info(u"PlexPy Notifier :: Ifttt notification sent.")
|
||||||
return True
|
return True
|
||||||
elif request_status >= 400 and request_status < 500:
|
elif request_status >= 400 and request_status < 500:
|
||||||
logger.info(u"Ifttt request failed: %s" % response.reason)
|
logger.warn(u"PlexPy Notifier :: Ifttt notification failed: %s" % response.reason)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
logger.info(u"Ifttt notification failed serverside.")
|
logger.warn(u"PlexPy Notifier :: Ifttt notification failed.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
|
@ -1631,13 +1641,13 @@ class TELEGRAM(object):
|
||||||
request_status = response.status
|
request_status = response.status
|
||||||
|
|
||||||
if request_status == 200:
|
if request_status == 200:
|
||||||
logger.info(u"Telegram notifications sent.")
|
logger.info(u"PlexPy Notifier :: Telegram notification sent.")
|
||||||
return True
|
return True
|
||||||
elif request_status >= 400 and request_status < 500:
|
elif request_status >= 400 and request_status < 500:
|
||||||
logger.info(u"Telegram request failed: %s" % response.reason)
|
logger.warn(u"PlexPy Notifier :: Telegram notification failed: %s" % response.reason)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
logger.info(u"Telegram notification failed serverside.")
|
logger.warn(u"PlexPy Notifier :: Telegram notification failed.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def updateLibrary(self):
|
def updateLibrary(self):
|
||||||
|
@ -1708,13 +1718,13 @@ class SLACK(object):
|
||||||
request_status = response.status
|
request_status = response.status
|
||||||
|
|
||||||
if request_status == 200:
|
if request_status == 200:
|
||||||
logger.info(u"Slack notifications sent.")
|
logger.info(u"PlexPy Notifier :: Slack notification sent.")
|
||||||
return True
|
return True
|
||||||
elif request_status >= 400 and request_status < 500:
|
elif request_status >= 400 and request_status < 500:
|
||||||
logger.info(u"Slack request failed: %s" % response.reason)
|
logger.warn(u"PlexPy Notifier :: Slack notification failed: %s" % response.reason)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
logger.info(u"Slack notification failed serverside.")
|
logger.warn(u"PlexPy Notifier :: Slack notification failed.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def updateLibrary(self):
|
def updateLibrary(self):
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from plexpy import logger, helpers, users, http_handler, database
|
from plexpy import logger, helpers, http_handler, database, users
|
||||||
import xmltodict
|
import xmltodict
|
||||||
import json
|
import json
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
|
@ -26,7 +26,7 @@ import plexpy
|
||||||
|
|
||||||
|
|
||||||
def refresh_users():
|
def refresh_users():
|
||||||
logger.info("Requesting users list refresh...")
|
logger.info(u"PlexPy PlexTV :: Requesting users list refresh...")
|
||||||
result = PlexTV().get_full_users_list()
|
result = PlexTV().get_full_users_list()
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
@ -55,13 +55,13 @@ def refresh_users():
|
||||||
|
|
||||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||||
|
|
||||||
logger.info("Users list refreshed.")
|
logger.info(u"PlexPy PlexTV :: Users list refreshed.")
|
||||||
else:
|
else:
|
||||||
logger.warn("Unable to refresh users list.")
|
logger.warn(u"PlexPy PlexTV :: Unable to refresh users list.")
|
||||||
|
|
||||||
|
|
||||||
def get_real_pms_url():
|
def get_real_pms_url():
|
||||||
logger.info("Requesting URLs for server...")
|
logger.info(u"PlexPy PlexTV :: Requesting URLs for server...")
|
||||||
|
|
||||||
# Reset any current PMS_URL value
|
# Reset any current PMS_URL value
|
||||||
plexpy.CONFIG.__setattr__('PMS_URL', '')
|
plexpy.CONFIG.__setattr__('PMS_URL', '')
|
||||||
|
@ -85,15 +85,15 @@ def get_real_pms_url():
|
||||||
if plexpy.CONFIG.PMS_IS_REMOTE and item['local'] == '0':
|
if plexpy.CONFIG.PMS_IS_REMOTE and item['local'] == '0':
|
||||||
plexpy.CONFIG.__setattr__('PMS_URL', item['uri'])
|
plexpy.CONFIG.__setattr__('PMS_URL', item['uri'])
|
||||||
plexpy.CONFIG.write()
|
plexpy.CONFIG.write()
|
||||||
logger.info("Server URL retrieved.")
|
logger.info(u"PlexPy PlexTV :: Server URL retrieved.")
|
||||||
if not plexpy.CONFIG.PMS_IS_REMOTE and item['local'] == '1':
|
if not plexpy.CONFIG.PMS_IS_REMOTE and item['local'] == '1':
|
||||||
plexpy.CONFIG.__setattr__('PMS_URL', item['uri'])
|
plexpy.CONFIG.__setattr__('PMS_URL', item['uri'])
|
||||||
plexpy.CONFIG.write()
|
plexpy.CONFIG.write()
|
||||||
logger.info("Server URL retrieved.")
|
logger.info(u"PlexPy PlexTV :: Server URL retrieved.")
|
||||||
else:
|
else:
|
||||||
plexpy.CONFIG.__setattr__('PMS_URL', fallback_url)
|
plexpy.CONFIG.__setattr__('PMS_URL', fallback_url)
|
||||||
plexpy.CONFIG.write()
|
plexpy.CONFIG.write()
|
||||||
logger.warn("Unable to retrieve server URLs. Using user-defined value.")
|
logger.warn(u"PlexPy PlexTV :: Unable to retrieve server URLs. Using user-defined value.")
|
||||||
else:
|
else:
|
||||||
plexpy.CONFIG.__setattr__('PMS_URL', fallback_url)
|
plexpy.CONFIG.__setattr__('PMS_URL', fallback_url)
|
||||||
plexpy.CONFIG.write()
|
plexpy.CONFIG.write()
|
||||||
|
@ -213,7 +213,7 @@ class PlexTV(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_parse = minidom.parseString(own_account)
|
xml_parse = minidom.parseString(own_account)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
logger.warn("Error parsing XML for Plex account details: %s" % e)
|
logger.warn("Error parsing XML for Plex account details: %s" % e)
|
||||||
return []
|
return []
|
||||||
except:
|
except:
|
||||||
|
@ -238,7 +238,7 @@ class PlexTV(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_parse = minidom.parseString(friends_list)
|
xml_parse = minidom.parseString(friends_list)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
logger.warn("Error parsing XML for Plex friends list: %s" % e)
|
logger.warn("Error parsing XML for Plex friends list: %s" % e)
|
||||||
except:
|
except:
|
||||||
logger.warn("Error parsing XML for Plex friends list.")
|
logger.warn("Error parsing XML for Plex friends list.")
|
||||||
|
@ -269,7 +269,7 @@ class PlexTV(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_parse = minidom.parseString(sync_list)
|
xml_parse = minidom.parseString(sync_list)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
logger.warn("Error parsing XML for Plex sync lists: %s" % e)
|
logger.warn("Error parsing XML for Plex sync lists: %s" % e)
|
||||||
return []
|
return []
|
||||||
except:
|
except:
|
||||||
|
@ -383,7 +383,7 @@ class PlexTV(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_parse = minidom.parseString(plextv_resources)
|
xml_parse = minidom.parseString(plextv_resources)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
logger.warn("Error parsing XML for Plex resources: %s" % e)
|
logger.warn("Error parsing XML for Plex resources: %s" % e)
|
||||||
return []
|
return []
|
||||||
except:
|
except:
|
||||||
|
@ -430,6 +430,25 @@ class PlexTV(object):
|
||||||
|
|
||||||
return server_urls
|
return server_urls
|
||||||
|
|
||||||
|
def get_server_times(self):
|
||||||
|
servers = self.get_plextv_server_list(output_format='xml')
|
||||||
|
server_times = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
xml_head = servers.getElementsByTagName('Server')
|
||||||
|
except:
|
||||||
|
logger.warn("Error parsing XML for Plex servers.")
|
||||||
|
return []
|
||||||
|
|
||||||
|
for a in xml_head:
|
||||||
|
if helpers.get_xml_attr(a, 'machineIdentifier') == plexpy.CONFIG.PMS_IDENTIFIER:
|
||||||
|
server_times.append({"created_at": helpers.get_xml_attr(a, 'createdAt'),
|
||||||
|
"updated_at": helpers.get_xml_attr(a, 'updatedAt')
|
||||||
|
})
|
||||||
|
break
|
||||||
|
|
||||||
|
return server_times
|
||||||
|
|
||||||
def discover(self):
|
def discover(self):
|
||||||
""" Query plex for all servers online. Returns the ones you own in a selectize format """
|
""" Query plex for all servers online. Returns the ones you own in a selectize format """
|
||||||
result = self.get_plextv_resources(include_https=True, output_format='raw')
|
result = self.get_plextv_resources(include_https=True, output_format='raw')
|
||||||
|
@ -464,22 +483,3 @@ class PlexTV(object):
|
||||||
return clean_servers
|
return clean_servers
|
||||||
|
|
||||||
return json.dumps(clean_servers, indent=4)
|
return json.dumps(clean_servers, indent=4)
|
||||||
|
|
||||||
def get_server_times(self):
|
|
||||||
servers = self.get_plextv_server_list(output_format='xml')
|
|
||||||
server_times = []
|
|
||||||
|
|
||||||
try:
|
|
||||||
xml_head = servers.getElementsByTagName('Server')
|
|
||||||
except:
|
|
||||||
logger.warn("Error parsing XML for Plex servers.")
|
|
||||||
return []
|
|
||||||
|
|
||||||
for a in xml_head:
|
|
||||||
if helpers.get_xml_attr(a, 'machineIdentifier') == plexpy.CONFIG.PMS_IDENTIFIER:
|
|
||||||
server_times.append({"created_at": helpers.get_xml_attr(a, 'createdAt'),
|
|
||||||
"updated_at": helpers.get_xml_attr(a, 'updatedAt')
|
|
||||||
})
|
|
||||||
break
|
|
||||||
|
|
||||||
return server_times
|
|
|
@ -26,12 +26,12 @@ def extract_plexwatch_xml(xml=None):
|
||||||
try:
|
try:
|
||||||
xml_parse = minidom.parseString(clean_xml)
|
xml_parse = minidom.parseString(clean_xml)
|
||||||
except:
|
except:
|
||||||
logger.warn("Error parsing XML for Plexwatch database.")
|
logger.warn(u"PlexPy Importer :: Error parsing XML for Plexwatch database.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
xml_head = xml_parse.getElementsByTagName('opt')
|
xml_head = xml_parse.getElementsByTagName('opt')
|
||||||
if not xml_head:
|
if not xml_head:
|
||||||
logger.warn("Error parsing XML for Plexwatch database.")
|
logger.warn(u"PlexPy Importer :: Error parsing XML for Plexwatch database.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for a in xml_head:
|
for a in xml_head:
|
||||||
|
@ -205,23 +205,23 @@ def validate_database(database=None, table_name=None):
|
||||||
try:
|
try:
|
||||||
connection = sqlite3.connect(database, timeout=20)
|
connection = sqlite3.connect(database, timeout=20)
|
||||||
except sqlite3.OperationalError:
|
except sqlite3.OperationalError:
|
||||||
logger.error('PlexPy Importer :: Invalid database specified.')
|
logger.error(u"PlexPy Importer :: Invalid database specified.")
|
||||||
return 'Invalid database specified.'
|
return 'Invalid database specified.'
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.error('PlexPy Importer :: Invalid database specified.')
|
logger.error(u"PlexPy Importer :: Invalid database specified.")
|
||||||
return 'Invalid database specified.'
|
return 'Invalid database specified.'
|
||||||
except:
|
except:
|
||||||
logger.error('PlexPy Importer :: Uncaught exception.')
|
logger.error(u"PlexPy Importer :: Uncaught exception.")
|
||||||
return 'Uncaught exception.'
|
return 'Uncaught exception.'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
connection.execute('SELECT ratingKey from %s' % table_name)
|
connection.execute('SELECT ratingKey from %s' % table_name)
|
||||||
connection.close()
|
connection.close()
|
||||||
except sqlite3.OperationalError:
|
except sqlite3.OperationalError:
|
||||||
logger.error('PlexPy Importer :: Invalid database specified.')
|
logger.error(u"PlexPy Importer :: Invalid database specified.")
|
||||||
return 'Invalid database specified.'
|
return 'Invalid database specified.'
|
||||||
except:
|
except:
|
||||||
logger.error('PlexPy Importer :: Uncaught exception.')
|
logger.error(u"PlexPy Importer :: Uncaught exception.")
|
||||||
return 'Uncaught exception.'
|
return 'Uncaught exception.'
|
||||||
|
|
||||||
return 'success'
|
return 'success'
|
||||||
|
@ -232,16 +232,16 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
|
||||||
connection = sqlite3.connect(database, timeout=20)
|
connection = sqlite3.connect(database, timeout=20)
|
||||||
connection.row_factory = sqlite3.Row
|
connection.row_factory = sqlite3.Row
|
||||||
except sqlite3.OperationalError:
|
except sqlite3.OperationalError:
|
||||||
logger.error('PlexPy Importer :: Invalid filename.')
|
logger.error(u"PlexPy Importer :: Invalid filename.")
|
||||||
return None
|
return None
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.error('PlexPy Importer :: Invalid filename.')
|
logger.error(u"PlexPy Importer :: Invalid filename.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
connection.execute('SELECT ratingKey from %s' % table_name)
|
connection.execute('SELECT ratingKey from %s' % table_name)
|
||||||
except sqlite3.OperationalError:
|
except sqlite3.OperationalError:
|
||||||
logger.error('PlexPy Importer :: Database specified does not contain the required fields.')
|
logger.error(u"PlexPy Importer :: Database specified does not contain the required fields.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
logger.debug(u"PlexPy Importer :: PlexWatch data import in progress...")
|
logger.debug(u"PlexPy Importer :: PlexWatch data import in progress...")
|
||||||
|
|
|
@ -20,7 +20,7 @@ import plexpy
|
||||||
import urllib2
|
import urllib2
|
||||||
|
|
||||||
def get_server_friendly_name():
|
def get_server_friendly_name():
|
||||||
logger.info("Requesting name from server...")
|
logger.info(u"PlexPy Pmsconnect :: Requesting name from server...")
|
||||||
server_name = PmsConnect().get_server_pref(pref='FriendlyName')
|
server_name = PmsConnect().get_server_pref(pref='FriendlyName')
|
||||||
|
|
||||||
# If friendly name is blank
|
# If friendly name is blank
|
||||||
|
@ -34,11 +34,12 @@ def get_server_friendly_name():
|
||||||
if server_name and server_name != plexpy.CONFIG.PMS_NAME:
|
if server_name and server_name != plexpy.CONFIG.PMS_NAME:
|
||||||
plexpy.CONFIG.__setattr__('PMS_NAME', server_name)
|
plexpy.CONFIG.__setattr__('PMS_NAME', server_name)
|
||||||
plexpy.CONFIG.write()
|
plexpy.CONFIG.write()
|
||||||
|
logger.info(u"PlexPy Pmsconnect :: Server name retrieved.")
|
||||||
|
|
||||||
return server_name
|
return server_name
|
||||||
|
|
||||||
def refresh_libraries():
|
def refresh_libraries():
|
||||||
logger.info("Requesting libraries list refresh...")
|
logger.info(u"PlexPy Pmsconnect :: Requesting libraries list refresh...")
|
||||||
library_sections = PmsConnect().get_library_details()
|
library_sections = PmsConnect().get_library_details()
|
||||||
|
|
||||||
server_id = plexpy.CONFIG.PMS_IDENTIFIER
|
server_id = plexpy.CONFIG.PMS_IDENTIFIER
|
||||||
|
@ -48,7 +49,7 @@ def refresh_libraries():
|
||||||
else:
|
else:
|
||||||
populate_cards = False
|
populate_cards = False
|
||||||
|
|
||||||
cards = []
|
library_keys = []
|
||||||
|
|
||||||
if library_sections:
|
if library_sections:
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
@ -64,20 +65,21 @@ def refresh_libraries():
|
||||||
'art': section['art'],
|
'art': section['art'],
|
||||||
'count': section['count'],
|
'count': section['count'],
|
||||||
'parent_count': section.get('parent_count', None),
|
'parent_count': section.get('parent_count', None),
|
||||||
'child_count': section.get('child_count', None)
|
'child_count': section.get('child_count', None),
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor_db.upsert('library_sections', key_dict=section_keys, value_dict=section_values)
|
monitor_db.upsert('library_sections', key_dict=section_keys, value_dict=section_values)
|
||||||
|
|
||||||
cards.append(section['key'])
|
library_keys.append(section['key'])
|
||||||
|
|
||||||
|
|
||||||
if populate_cards:
|
if populate_cards:
|
||||||
plexpy.CONFIG.__setattr__('HOME_LIBRARY_CARDS', cards)
|
plexpy.CONFIG.__setattr__('HOME_LIBRARY_CARDS', library_keys)
|
||||||
plexpy.CONFIG.write()
|
plexpy.CONFIG.write()
|
||||||
|
|
||||||
logger.info("Libraries list refreshed.")
|
logger.info(u"PlexPy Pmsconnect :: Libraries list refreshed.")
|
||||||
else:
|
else:
|
||||||
logger.warn("Unable to refresh libraries list.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to refresh libraries list.")
|
||||||
|
|
||||||
|
|
||||||
class PmsConnect(object):
|
class PmsConnect(object):
|
||||||
|
@ -100,6 +102,7 @@ class PmsConnect(object):
|
||||||
port=port,
|
port=port,
|
||||||
token=plexpy.CONFIG.PMS_TOKEN)
|
token=plexpy.CONFIG.PMS_TOKEN)
|
||||||
|
|
||||||
|
def get_sessions(self, output_format=''):
|
||||||
"""
|
"""
|
||||||
Return current sessions.
|
Return current sessions.
|
||||||
|
|
||||||
|
@ -107,7 +110,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_sessions(self, output_format=''):
|
|
||||||
uri = '/status/sessions'
|
uri = '/status/sessions'
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -116,6 +118,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_metadata(self, rating_key='', output_format=''):
|
||||||
"""
|
"""
|
||||||
Return metadata for request item.
|
Return metadata for request item.
|
||||||
|
|
||||||
|
@ -124,7 +127,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_metadata(self, rating_key='', output_format=''):
|
|
||||||
uri = '/library/metadata/' + rating_key
|
uri = '/library/metadata/' + rating_key
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -133,6 +135,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_metadata_children(self, rating_key='', output_format=''):
|
||||||
"""
|
"""
|
||||||
Return metadata for children of the request item.
|
Return metadata for children of the request item.
|
||||||
|
|
||||||
|
@ -141,7 +144,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_metadata_children(self, rating_key='', output_format=''):
|
|
||||||
uri = '/library/metadata/' + rating_key + '/children'
|
uri = '/library/metadata/' + rating_key + '/children'
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -150,6 +152,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_recently_added(self, count='0', output_format=''):
|
||||||
"""
|
"""
|
||||||
Return list of recently added items.
|
Return list of recently added items.
|
||||||
|
|
||||||
|
@ -158,7 +161,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_recently_added(self, count='0', output_format=''):
|
|
||||||
uri = '/library/recentlyAdded?X-Plex-Container-Start=0&X-Plex-Container-Size=' + count
|
uri = '/library/recentlyAdded?X-Plex-Container-Start=0&X-Plex-Container-Size=' + count
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -167,6 +169,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_children_list(self, rating_key='', output_format=''):
|
||||||
"""
|
"""
|
||||||
Return list of children in requested library item.
|
Return list of children in requested library item.
|
||||||
|
|
||||||
|
@ -175,7 +178,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_children_list(self, rating_key='', output_format=''):
|
|
||||||
uri = '/library/metadata/' + rating_key + '/children'
|
uri = '/library/metadata/' + rating_key + '/children'
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -184,6 +186,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_server_list(self, output_format=''):
|
||||||
"""
|
"""
|
||||||
Return list of local servers.
|
Return list of local servers.
|
||||||
|
|
||||||
|
@ -191,7 +194,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_server_list(self, output_format=''):
|
|
||||||
uri = '/servers'
|
uri = '/servers'
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -200,6 +202,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_server_prefs(self, output_format=''):
|
||||||
"""
|
"""
|
||||||
Return the local servers preferences.
|
Return the local servers preferences.
|
||||||
|
|
||||||
|
@ -207,7 +210,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_server_prefs(self, output_format=''):
|
|
||||||
uri = '/:/prefs'
|
uri = '/:/prefs'
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -216,6 +218,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_local_server_identity(self, output_format=''):
|
||||||
"""
|
"""
|
||||||
Return the local server identity.
|
Return the local server identity.
|
||||||
|
|
||||||
|
@ -223,7 +226,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_local_server_identity(self, output_format=''):
|
|
||||||
uri = '/identity'
|
uri = '/identity'
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -232,6 +234,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_libraries_list(self, output_format=''):
|
||||||
"""
|
"""
|
||||||
Return list of libraries on server.
|
Return list of libraries on server.
|
||||||
|
|
||||||
|
@ -239,7 +242,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_libraries_list(self, output_format=''):
|
|
||||||
uri = '/library/sections'
|
uri = '/library/sections'
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -248,6 +250,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_library_list(self, section_key='', list_type='all', count='0', sort_type='', output_format=''):
|
||||||
"""
|
"""
|
||||||
Return list of items in library on server.
|
Return list of items in library on server.
|
||||||
|
|
||||||
|
@ -255,7 +258,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_library_list(self, section_key='', list_type='all', count='0', sort_type='', output_format=''):
|
|
||||||
uri = '/library/sections/' + section_key + '/' + list_type +'?X-Plex-Container-Start=0&X-Plex-Container-Size=' + count + sort_type
|
uri = '/library/sections/' + section_key + '/' + list_type +'?X-Plex-Container-Start=0&X-Plex-Container-Size=' + count + sort_type
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -264,6 +266,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_sync_item(self, sync_id=None, output_format=''):
|
||||||
"""
|
"""
|
||||||
Return sync item details.
|
Return sync item details.
|
||||||
|
|
||||||
|
@ -272,7 +275,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_sync_item(self, sync_id=None, output_format=''):
|
|
||||||
uri = '/sync/items/' + sync_id
|
uri = '/sync/items/' + sync_id
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -281,6 +283,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_sync_transcode_queue(self, output_format=''):
|
||||||
"""
|
"""
|
||||||
Return sync transcode queue.
|
Return sync transcode queue.
|
||||||
|
|
||||||
|
@ -288,7 +291,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_sync_transcode_queue(self, output_format=''):
|
|
||||||
uri = '/sync/transcodeQueue'
|
uri = '/sync/transcodeQueue'
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -297,6 +299,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_search(self, query='', track='', output_format=''):
|
||||||
"""
|
"""
|
||||||
Return search results.
|
Return search results.
|
||||||
|
|
||||||
|
@ -304,7 +307,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_search(self, query='', track='', output_format=''):
|
|
||||||
uri = '/search?query=' + urllib2.quote(query.encode('utf8')) + track
|
uri = '/search?query=' + urllib2.quote(query.encode('utf8')) + track
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -313,6 +315,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_account(self, output_format=''):
|
||||||
"""
|
"""
|
||||||
Return account details.
|
Return account details.
|
||||||
|
|
||||||
|
@ -320,7 +323,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_account(self, output_format=''):
|
|
||||||
uri = '/myplex/account'
|
uri = '/myplex/account'
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
|
@ -329,6 +331,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def put_refresh_reachability(self):
|
||||||
"""
|
"""
|
||||||
Refresh Plex remote access port mapping.
|
Refresh Plex remote access port mapping.
|
||||||
|
|
||||||
|
@ -336,13 +339,14 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: None
|
Output: None
|
||||||
"""
|
"""
|
||||||
def put_refresh_reachability(self):
|
|
||||||
uri = '/myplex/refreshReachability'
|
uri = '/myplex/refreshReachability'
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
request_type='PUT')
|
request_type='PUT')
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_recently_added_details(self, count='0'):
|
||||||
"""
|
"""
|
||||||
Return processed and validated list of recently added items.
|
Return processed and validated list of recently added items.
|
||||||
|
|
||||||
|
@ -350,13 +354,12 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_recently_added_details(self, count='0'):
|
|
||||||
recent = self.get_recently_added(count, output_format='xml')
|
recent = self.get_recently_added(count, output_format='xml')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = recent.getElementsByTagName('MediaContainer')
|
xml_head = recent.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_recently_added.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_recently_added: %s." % e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
recents_list = []
|
recents_list = []
|
||||||
|
@ -377,7 +380,7 @@ class PmsConnect(object):
|
||||||
'title': helpers.get_xml_attr(item, 'title'),
|
'title': helpers.get_xml_attr(item, 'title'),
|
||||||
'parent_title': helpers.get_xml_attr(item, 'parentTitle'),
|
'parent_title': helpers.get_xml_attr(item, 'parentTitle'),
|
||||||
'library_id': helpers.get_xml_attr(item, 'librarySectionID'),
|
'library_id': helpers.get_xml_attr(item, 'librarySectionID'),
|
||||||
'library_title': helpers.get_xml_attr(item, 'librarySectionTitle'),
|
'library_name': helpers.get_xml_attr(item, 'librarySectionTitle'),
|
||||||
'thumb': helpers.get_xml_attr(item, 'thumb'),
|
'thumb': helpers.get_xml_attr(item, 'thumb'),
|
||||||
'added_at': helpers.get_xml_attr(item, 'addedAt')
|
'added_at': helpers.get_xml_attr(item, 'addedAt')
|
||||||
}
|
}
|
||||||
|
@ -394,7 +397,7 @@ class PmsConnect(object):
|
||||||
'title': helpers.get_xml_attr(item, 'title'),
|
'title': helpers.get_xml_attr(item, 'title'),
|
||||||
'parent_title': helpers.get_xml_attr(item, 'parentTitle'),
|
'parent_title': helpers.get_xml_attr(item, 'parentTitle'),
|
||||||
'library_id': helpers.get_xml_attr(item, 'librarySectionID'),
|
'library_id': helpers.get_xml_attr(item, 'librarySectionID'),
|
||||||
'library_title': helpers.get_xml_attr(item, 'librarySectionTitle'),
|
'library_name': helpers.get_xml_attr(item, 'librarySectionTitle'),
|
||||||
'year': helpers.get_xml_attr(item, 'year'),
|
'year': helpers.get_xml_attr(item, 'year'),
|
||||||
'thumb': helpers.get_xml_attr(item, 'thumb'),
|
'thumb': helpers.get_xml_attr(item, 'thumb'),
|
||||||
'added_at': helpers.get_xml_attr(item, 'addedAt')
|
'added_at': helpers.get_xml_attr(item, 'addedAt')
|
||||||
|
@ -406,6 +409,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=''):
|
||||||
"""
|
"""
|
||||||
Return processed and validated metadata list for requested item.
|
Return processed and validated metadata list for requested item.
|
||||||
|
|
||||||
|
@ -413,13 +417,12 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_metadata_details(self, rating_key=''):
|
|
||||||
metadata = self.get_metadata(str(rating_key), output_format='xml')
|
metadata = self.get_metadata(str(rating_key), output_format='xml')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = metadata.getElementsByTagName('MediaContainer')
|
xml_head = metadata.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_metadata.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_metadata: %s: %s." % e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
metadata_list = []
|
metadata_list = []
|
||||||
|
@ -440,11 +443,11 @@ class PmsConnect(object):
|
||||||
metadata_main = a.getElementsByTagName('Track')[0]
|
metadata_main = a.getElementsByTagName('Track')[0]
|
||||||
metadata_type = helpers.get_xml_attr(metadata_main, 'type')
|
metadata_type = helpers.get_xml_attr(metadata_main, 'type')
|
||||||
else:
|
else:
|
||||||
logger.debug(u"Metadata failed")
|
logger.debug(u"PlexPy Pmsconnect :: Metadata failed")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
library_id = helpers.get_xml_attr(a, 'librarySectionID')
|
library_id = helpers.get_xml_attr(a, 'librarySectionID')
|
||||||
library_title = helpers.get_xml_attr(a, 'librarySectionTitle')
|
library_name = helpers.get_xml_attr(a, 'librarySectionTitle')
|
||||||
|
|
||||||
genres = []
|
genres = []
|
||||||
actors = []
|
actors = []
|
||||||
|
@ -470,7 +473,7 @@ class PmsConnect(object):
|
||||||
if metadata_type == 'movie':
|
if metadata_type == 'movie':
|
||||||
metadata = {'media_type': metadata_type,
|
metadata = {'media_type': metadata_type,
|
||||||
'library_id': library_id,
|
'library_id': library_id,
|
||||||
'library_title': library_title,
|
'library_name': library_name,
|
||||||
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||||
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
||||||
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
||||||
|
@ -505,7 +508,7 @@ class PmsConnect(object):
|
||||||
elif metadata_type == 'show':
|
elif metadata_type == 'show':
|
||||||
metadata = {'media_type': metadata_type,
|
metadata = {'media_type': metadata_type,
|
||||||
'library_id': library_id,
|
'library_id': library_id,
|
||||||
'library_title': library_title,
|
'library_name': library_name,
|
||||||
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||||
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
||||||
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
||||||
|
@ -542,7 +545,7 @@ class PmsConnect(object):
|
||||||
show_details = self.get_metadata_details(parent_rating_key)
|
show_details = self.get_metadata_details(parent_rating_key)
|
||||||
metadata = {'media_type': metadata_type,
|
metadata = {'media_type': metadata_type,
|
||||||
'library_id': library_id,
|
'library_id': library_id,
|
||||||
'library_title': library_title,
|
'library_name': library_name,
|
||||||
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||||
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
||||||
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
||||||
|
@ -579,7 +582,7 @@ class PmsConnect(object):
|
||||||
show_details = self.get_metadata_details(grandparent_rating_key)
|
show_details = self.get_metadata_details(grandparent_rating_key)
|
||||||
metadata = {'media_type': metadata_type,
|
metadata = {'media_type': metadata_type,
|
||||||
'library_id': library_id,
|
'library_id': library_id,
|
||||||
'library_title': library_title,
|
'library_name': library_name,
|
||||||
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||||
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
||||||
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
||||||
|
@ -614,7 +617,7 @@ class PmsConnect(object):
|
||||||
elif metadata_type == 'artist':
|
elif metadata_type == 'artist':
|
||||||
metadata = {'media_type': metadata_type,
|
metadata = {'media_type': metadata_type,
|
||||||
'library_id': library_id,
|
'library_id': library_id,
|
||||||
'library_title': library_title,
|
'library_name': library_name,
|
||||||
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||||
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
||||||
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
||||||
|
@ -651,7 +654,7 @@ class PmsConnect(object):
|
||||||
artist_details = self.get_metadata_details(parent_rating_key)
|
artist_details = self.get_metadata_details(parent_rating_key)
|
||||||
metadata = {'media_type': metadata_type,
|
metadata = {'media_type': metadata_type,
|
||||||
'library_id': library_id,
|
'library_id': library_id,
|
||||||
'library_title': library_title,
|
'library_name': library_name,
|
||||||
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||||
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
||||||
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
||||||
|
@ -688,7 +691,7 @@ class PmsConnect(object):
|
||||||
album_details = self.get_metadata_details(parent_rating_key)
|
album_details = self.get_metadata_details(parent_rating_key)
|
||||||
metadata = {'media_type': metadata_type,
|
metadata = {'media_type': metadata_type,
|
||||||
'library_id': library_id,
|
'library_id': library_id,
|
||||||
'library_title': library_title,
|
'library_name': library_name,
|
||||||
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||||
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
||||||
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
||||||
|
@ -725,6 +728,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return metadata_list
|
return metadata_list
|
||||||
|
|
||||||
|
def get_metadata_children_details(self, rating_key=''):
|
||||||
"""
|
"""
|
||||||
Return processed and validated metadata list for all children of requested item.
|
Return processed and validated metadata list for all children of requested item.
|
||||||
|
|
||||||
|
@ -732,13 +736,12 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_metadata_children_details(self, rating_key=''):
|
|
||||||
metadata = self.get_metadata_children(str(rating_key), output_format='xml')
|
metadata = self.get_metadata_children(str(rating_key), output_format='xml')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = metadata.getElementsByTagName('MediaContainer')
|
xml_head = metadata.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_metadata_children.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_metadata_children: %s." % e)
|
||||||
|
|
||||||
metadata_list = []
|
metadata_list = []
|
||||||
|
|
||||||
|
@ -767,6 +770,7 @@ class PmsConnect(object):
|
||||||
output = {'metadata': metadata_list}
|
output = {'metadata': metadata_list}
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def get_library_metadata_details(self, library_id=''):
|
||||||
"""
|
"""
|
||||||
Return processed and validated metadata list for requested library.
|
Return processed and validated metadata list for requested library.
|
||||||
|
|
||||||
|
@ -774,13 +778,12 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_library_metadata_details(self, library_id=''):
|
|
||||||
libraries_data = self.get_libraries_list(output_format='xml')
|
libraries_data = self.get_libraries_list(output_format='xml')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = libraries_data.getElementsByTagName('MediaContainer')
|
xml_head = libraries_data.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_library_metadata_details.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_library_metadata_details: %s." % e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
metadata_list = []
|
metadata_list = []
|
||||||
|
@ -814,18 +817,18 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return metadata_list
|
return metadata_list
|
||||||
|
|
||||||
|
def get_current_activity(self):
|
||||||
"""
|
"""
|
||||||
Return processed and validated session list.
|
Return processed and validated session list.
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_current_activity(self):
|
|
||||||
session_data = self.get_sessions(output_format='xml')
|
session_data = self.get_sessions(output_format='xml')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = session_data.getElementsByTagName('MediaContainer')
|
xml_head = session_data.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_sessions.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_sessions: %s." % e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
session_list = []
|
session_list = []
|
||||||
|
@ -863,6 +866,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def get_session_each(self, stream_type='', session=None):
|
||||||
"""
|
"""
|
||||||
Return selected data from current sessions.
|
Return selected data from current sessions.
|
||||||
This function processes and validates session data
|
This function processes and validates session data
|
||||||
|
@ -871,7 +875,6 @@ class PmsConnect(object):
|
||||||
session { the session dictionary }
|
session { the session dictionary }
|
||||||
Output: dict
|
Output: dict
|
||||||
"""
|
"""
|
||||||
def get_session_each(self, stream_type='', session=None):
|
|
||||||
session_output = None
|
session_output = None
|
||||||
user_data = users.Users()
|
user_data = users.Users()
|
||||||
|
|
||||||
|
@ -905,7 +908,7 @@ class PmsConnect(object):
|
||||||
transcode_container = ''
|
transcode_container = ''
|
||||||
transcode_protocol = ''
|
transcode_protocol = ''
|
||||||
|
|
||||||
user_details = user_data.get_user_details(
|
user_details = user_data.get_details(
|
||||||
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
|
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
|
||||||
|
|
||||||
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Track'):
|
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Track'):
|
||||||
|
@ -914,6 +917,7 @@ class PmsConnect(object):
|
||||||
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')
|
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')
|
||||||
|
|
||||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||||
|
'library_id': helpers.get_xml_attr(session, 'librarySectionID'),
|
||||||
'media_index': helpers.get_xml_attr(session, 'index'),
|
'media_index': helpers.get_xml_attr(session, 'index'),
|
||||||
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
|
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
|
||||||
'art': helpers.get_xml_attr(session, 'art'),
|
'art': helpers.get_xml_attr(session, 'art'),
|
||||||
|
@ -924,7 +928,7 @@ class PmsConnect(object):
|
||||||
'user': user_details['username'],
|
'user': user_details['username'],
|
||||||
'user_id': user_details['user_id'],
|
'user_id': user_details['user_id'],
|
||||||
'friendly_name': user_details['friendly_name'],
|
'friendly_name': user_details['friendly_name'],
|
||||||
'user_thumb': user_details['thumb'],
|
'user_thumb': user_details['user_thumb'],
|
||||||
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
|
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
|
||||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
||||||
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||||
|
@ -1025,7 +1029,7 @@ class PmsConnect(object):
|
||||||
else:
|
else:
|
||||||
use_indexes = 0
|
use_indexes = 0
|
||||||
|
|
||||||
user_details = user_data.get_user_details(
|
user_details = user_data.get_details(
|
||||||
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
|
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
|
||||||
|
|
||||||
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Video'):
|
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Video'):
|
||||||
|
@ -1035,6 +1039,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
if helpers.get_xml_attr(session, 'type') == 'episode':
|
if helpers.get_xml_attr(session, 'type') == 'episode':
|
||||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||||
|
'library_id': helpers.get_xml_attr(session, 'librarySectionID'),
|
||||||
'media_index': helpers.get_xml_attr(session, 'index'),
|
'media_index': helpers.get_xml_attr(session, 'index'),
|
||||||
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
|
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
|
||||||
'art': helpers.get_xml_attr(session, 'art'),
|
'art': helpers.get_xml_attr(session, 'art'),
|
||||||
|
@ -1045,7 +1050,7 @@ class PmsConnect(object):
|
||||||
'user': user_details['username'],
|
'user': user_details['username'],
|
||||||
'user_id': user_details['user_id'],
|
'user_id': user_details['user_id'],
|
||||||
'friendly_name': user_details['friendly_name'],
|
'friendly_name': user_details['friendly_name'],
|
||||||
'user_thumb': user_details['thumb'],
|
'user_thumb': user_details['user_thumb'],
|
||||||
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
|
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
|
||||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
||||||
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||||
|
@ -1092,6 +1097,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
elif helpers.get_xml_attr(session, 'type') == 'movie':
|
elif helpers.get_xml_attr(session, 'type') == 'movie':
|
||||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||||
|
'library_id': helpers.get_xml_attr(session, 'librarySectionID'),
|
||||||
'media_index': helpers.get_xml_attr(session, 'index'),
|
'media_index': helpers.get_xml_attr(session, 'index'),
|
||||||
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
|
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
|
||||||
'art': helpers.get_xml_attr(session, 'art'),
|
'art': helpers.get_xml_attr(session, 'art'),
|
||||||
|
@ -1102,7 +1108,7 @@ class PmsConnect(object):
|
||||||
'user': user_details['username'],
|
'user': user_details['username'],
|
||||||
'user_id': user_details['user_id'],
|
'user_id': user_details['user_id'],
|
||||||
'friendly_name': user_details['friendly_name'],
|
'friendly_name': user_details['friendly_name'],
|
||||||
'user_thumb': user_details['thumb'],
|
'user_thumb': user_details['user_thumb'],
|
||||||
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
|
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
|
||||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
||||||
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||||
|
@ -1149,6 +1155,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
elif helpers.get_xml_attr(session, 'type') == 'clip':
|
elif helpers.get_xml_attr(session, 'type') == 'clip':
|
||||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||||
|
'library_id': helpers.get_xml_attr(session, 'librarySectionID'),
|
||||||
'media_index': helpers.get_xml_attr(session, 'index'),
|
'media_index': helpers.get_xml_attr(session, 'index'),
|
||||||
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
|
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
|
||||||
'art': helpers.get_xml_attr(session, 'art'),
|
'art': helpers.get_xml_attr(session, 'art'),
|
||||||
|
@ -1159,7 +1166,7 @@ class PmsConnect(object):
|
||||||
'user': user_details['username'],
|
'user': user_details['username'],
|
||||||
'user_id': user_details['user_id'],
|
'user_id': user_details['user_id'],
|
||||||
'friendly_name': user_details['friendly_name'],
|
'friendly_name': user_details['friendly_name'],
|
||||||
'user_thumb': user_details['thumb'],
|
'user_thumb': user_details['user_thumb'],
|
||||||
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
|
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
|
||||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
||||||
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||||
|
@ -1230,7 +1237,7 @@ class PmsConnect(object):
|
||||||
transcode_container = ''
|
transcode_container = ''
|
||||||
transcode_protocol = ''
|
transcode_protocol = ''
|
||||||
|
|
||||||
user_details = user_data.get_user_details(
|
user_details = user_data.get_details(
|
||||||
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
|
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
|
||||||
|
|
||||||
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Photo'):
|
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Photo'):
|
||||||
|
@ -1239,6 +1246,7 @@ class PmsConnect(object):
|
||||||
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')
|
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')
|
||||||
|
|
||||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||||
|
'library_id': helpers.get_xml_attr(session, 'librarySectionID'),
|
||||||
'media_index': helpers.get_xml_attr(session, 'index'),
|
'media_index': helpers.get_xml_attr(session, 'index'),
|
||||||
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
|
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
|
||||||
'art': helpers.get_xml_attr(session, 'art'),
|
'art': helpers.get_xml_attr(session, 'art'),
|
||||||
|
@ -1249,7 +1257,7 @@ class PmsConnect(object):
|
||||||
'user': user_details['username'],
|
'user': user_details['username'],
|
||||||
'user_id': user_details['user_id'],
|
'user_id': user_details['user_id'],
|
||||||
'friendly_name': user_details['friendly_name'],
|
'friendly_name': user_details['friendly_name'],
|
||||||
'user_thumb': user_details['thumb'],
|
'user_thumb': user_details['user_thumb'],
|
||||||
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
|
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
|
||||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
||||||
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||||
|
@ -1292,7 +1300,7 @@ class PmsConnect(object):
|
||||||
}
|
}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.warn(u"No known stream types found in session list.")
|
logger.warn(u"PlexPy Pmsconnect :: No known stream types found in session list.")
|
||||||
|
|
||||||
# Rename Mystery platform names
|
# Rename Mystery platform names
|
||||||
session_output['platform'] = common.PLATFORM_NAME_OVERRIDES.get(session_output['platform'],
|
session_output['platform'] = common.PLATFORM_NAME_OVERRIDES.get(session_output['platform'],
|
||||||
|
@ -1300,18 +1308,18 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return session_output
|
return session_output
|
||||||
|
|
||||||
|
def get_item_children(self, rating_key=''):
|
||||||
"""
|
"""
|
||||||
Return processed and validated children list.
|
Return processed and validated children list.
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_item_children(self, rating_key=''):
|
|
||||||
children_data = self.get_children_list(rating_key, output_format='xml')
|
children_data = self.get_children_list(rating_key, output_format='xml')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = children_data.getElementsByTagName('MediaContainer')
|
xml_head = children_data.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_children_list.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_children_list: %s." % e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
children_list = []
|
children_list = []
|
||||||
|
@ -1319,7 +1327,7 @@ class PmsConnect(object):
|
||||||
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':
|
||||||
logger.debug(u"No children data.")
|
logger.debug(u"PlexPy Pmsconnect :: No children data.")
|
||||||
children_list = {'children_count': '0',
|
children_list = {'children_count': '0',
|
||||||
'children_list': []
|
'children_list': []
|
||||||
}
|
}
|
||||||
|
@ -1353,18 +1361,18 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def get_servers_info(self):
|
||||||
"""
|
"""
|
||||||
Return the list of local servers.
|
Return the list of local servers.
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_servers_info(self):
|
|
||||||
recent = self.get_server_list(output_format='xml')
|
recent = self.get_server_list(output_format='xml')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = recent.getElementsByTagName('Server')
|
xml_head = recent.getElementsByTagName('Server')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_server_list.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_server_list: %s." % e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
server_info = []
|
server_info = []
|
||||||
|
@ -1380,18 +1388,18 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return server_info
|
return server_info
|
||||||
|
|
||||||
|
def get_server_identity(self):
|
||||||
"""
|
"""
|
||||||
Return the local machine identity.
|
Return the local machine identity.
|
||||||
|
|
||||||
Output: dict
|
Output: dict
|
||||||
"""
|
"""
|
||||||
def get_server_identity(self):
|
|
||||||
identity = self.get_local_server_identity(output_format='xml')
|
identity = self.get_local_server_identity(output_format='xml')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = identity.getElementsByTagName('MediaContainer')
|
xml_head = identity.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_local_server_identity.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_local_server_identity: %s." % e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
server_identity = {}
|
server_identity = {}
|
||||||
|
@ -1402,6 +1410,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return server_identity
|
return server_identity
|
||||||
|
|
||||||
|
def get_server_pref(self, pref=None):
|
||||||
"""
|
"""
|
||||||
Return a specified server preference.
|
Return a specified server preference.
|
||||||
|
|
||||||
|
@ -1409,14 +1418,13 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: string
|
Output: string
|
||||||
"""
|
"""
|
||||||
def get_server_pref(self, pref=None):
|
|
||||||
if pref:
|
if pref:
|
||||||
prefs = self.get_server_prefs(output_format='xml')
|
prefs = self.get_server_prefs(output_format='xml')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = prefs.getElementsByTagName('Setting')
|
xml_head = prefs.getElementsByTagName('Setting')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_local_server_name.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_local_server_name: %s." % e)
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
pref_value = 'None'
|
pref_value = 'None'
|
||||||
|
@ -1427,21 +1435,21 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return pref_value
|
return pref_value
|
||||||
else:
|
else:
|
||||||
logger.debug(u"Server preferences queried but no parameter received.")
|
logger.debug(u"PlexPy Pmsconnect :: Server preferences queried but no parameter received.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_server_children(self):
|
||||||
"""
|
"""
|
||||||
Return processed and validated server libraries list.
|
Return processed and validated server libraries list.
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_server_children(self):
|
|
||||||
libraries_data = self.get_libraries_list(output_format='xml')
|
libraries_data = self.get_libraries_list(output_format='xml')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = libraries_data.getElementsByTagName('MediaContainer')
|
xml_head = libraries_data.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_libraries_list.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_libraries_list: %s." % e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
libraries_list = []
|
libraries_list = []
|
||||||
|
@ -1449,7 +1457,7 @@ class PmsConnect(object):
|
||||||
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':
|
||||||
logger.debug(u"No libraries data.")
|
logger.debug(u"PlexPy Pmsconnect :: No libraries data.")
|
||||||
libraries_list = {'libraries_count': '0',
|
libraries_list = {'libraries_count': '0',
|
||||||
'libraries_list': []
|
'libraries_list': []
|
||||||
}
|
}
|
||||||
|
@ -1473,6 +1481,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def get_library_children(self, library_type='', section_key='', list_type='all', sort_type = ''):
|
||||||
"""
|
"""
|
||||||
Return processed and validated server library items list.
|
Return processed and validated server library items list.
|
||||||
|
|
||||||
|
@ -1481,7 +1490,6 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_library_children(self, library_type='', section_key='', list_type='all', sort_type = ''):
|
|
||||||
|
|
||||||
# Currently only grab the library with 1 items so 'size' is not 0
|
# Currently only grab the library with 1 items so 'size' is not 0
|
||||||
count = '1'
|
count = '1'
|
||||||
|
@ -1511,8 +1519,8 @@ class PmsConnect(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = library_data.getElementsByTagName('MediaContainer')
|
xml_head = library_data.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_library_children.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_library_children: %s." % e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
library_list = []
|
library_list = []
|
||||||
|
@ -1520,7 +1528,7 @@ class PmsConnect(object):
|
||||||
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':
|
||||||
logger.debug(u"No library data.")
|
logger.debug(u"PlexPy Pmsconnect :: No library data.")
|
||||||
library_list = {'library_count': '0',
|
library_list = {'library_count': '0',
|
||||||
'library_list': []
|
'library_list': []
|
||||||
}
|
}
|
||||||
|
@ -1543,12 +1551,12 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def get_library_details(self):
|
||||||
"""
|
"""
|
||||||
Return processed and validated library statistics.
|
Return processed and validated library statistics.
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_library_details(self):
|
|
||||||
server_libraries = self.get_server_children()
|
server_libraries = self.get_server_children()
|
||||||
|
|
||||||
server_library_stats = []
|
server_library_stats = []
|
||||||
|
@ -1614,6 +1622,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return server_library_stats
|
return server_library_stats
|
||||||
|
|
||||||
|
def get_image(self, img=None, width=None, height=None):
|
||||||
"""
|
"""
|
||||||
Return image data as array.
|
Return image data as array.
|
||||||
Array contains the image content type and image binary
|
Array contains the image content type and image binary
|
||||||
|
@ -1623,7 +1632,6 @@ class PmsConnect(object):
|
||||||
height { the image height }
|
height { the image height }
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_image(self, img=None, width=None, height=None):
|
|
||||||
if img:
|
if img:
|
||||||
if width.isdigit() and height.isdigit():
|
if width.isdigit() and height.isdigit():
|
||||||
uri = '/photo/:/transcode?url=http://127.0.0.1:32400' + img + '&width=' + width + '&height=' + height
|
uri = '/photo/:/transcode?url=http://127.0.0.1:32400' + img + '&width=' + width + '&height=' + height
|
||||||
|
@ -1637,15 +1645,15 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return [request, content_type]
|
return [request, content_type]
|
||||||
else:
|
else:
|
||||||
logger.error("Image proxy queries but no input received.")
|
logger.error(u"PlexPy Pmsconnect :: Image proxy queries but no input received.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_search_results(self, query=''):
|
||||||
"""
|
"""
|
||||||
Return processed list of search results.
|
Return processed list of search results.
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_search_results(self, query=''):
|
|
||||||
search_results = self.get_search(query=query, output_format='xml')
|
search_results = self.get_search(query=query, output_format='xml')
|
||||||
search_results_tracks = self.get_search(query=query, track='&type=10', output_format='xml')
|
search_results_tracks = self.get_search(query=query, track='&type=10', output_format='xml')
|
||||||
|
|
||||||
|
@ -1659,8 +1667,8 @@ class PmsConnect(object):
|
||||||
xml_head += search_results_tracks.getElementsByTagName('MediaContainer')
|
xml_head += search_results_tracks.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_search_result_details.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_search_result_details: %s." % e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
search_results_count = 0
|
search_results_count = 0
|
||||||
|
@ -1678,7 +1686,7 @@ class PmsConnect(object):
|
||||||
if a.getAttribute('size'):
|
if a.getAttribute('size'):
|
||||||
totalSize += int(a.getAttribute('size'))
|
totalSize += int(a.getAttribute('size'))
|
||||||
if totalSize == 0:
|
if totalSize == 0:
|
||||||
logger.debug(u"No search results.")
|
logger.debug(u"PlexPy Pmsconnect :: No search results.")
|
||||||
search_results_list = {'results_count': search_results_count,
|
search_results_list = {'results_count': search_results_count,
|
||||||
'results_list': []
|
'results_list': []
|
||||||
}
|
}
|
||||||
|
@ -1733,12 +1741,12 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def get_rating_keys_list(self, rating_key='', media_type=''):
|
||||||
"""
|
"""
|
||||||
Return processed list of grandparent/parent/child rating keys.
|
Return processed list of grandparent/parent/child rating keys.
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
def get_rating_keys_list(self, rating_key='', media_type=''):
|
|
||||||
|
|
||||||
if media_type == 'movie':
|
if media_type == 'movie':
|
||||||
key_list = {0: {'rating_key': int(rating_key)}}
|
key_list = {0: {'rating_key': int(rating_key)}}
|
||||||
|
@ -1750,7 +1758,7 @@ class PmsConnect(object):
|
||||||
match_type = 'index'
|
match_type = 'index'
|
||||||
|
|
||||||
library_id = None
|
library_id = None
|
||||||
library_title = None
|
library_name = None
|
||||||
|
|
||||||
# get grandparent rating key
|
# get grandparent rating key
|
||||||
if media_type == 'season' or media_type == 'album':
|
if media_type == 'season' or media_type == 'album':
|
||||||
|
@ -1758,9 +1766,9 @@ class PmsConnect(object):
|
||||||
metadata = self.get_metadata_details(rating_key=rating_key)
|
metadata = self.get_metadata_details(rating_key=rating_key)
|
||||||
rating_key = metadata['metadata']['parent_rating_key']
|
rating_key = metadata['metadata']['parent_rating_key']
|
||||||
library_id = metadata['metadata']['library_id']
|
library_id = metadata['metadata']['library_id']
|
||||||
library_title = metadata['metadata']['library_title']
|
library_name = metadata['metadata']['library_name']
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to get parent_rating_key for get_rating_keys_list.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to get parent_rating_key for get_rating_keys_list: %s." % e)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
elif media_type == 'episode' or media_type == 'track':
|
elif media_type == 'episode' or media_type == 'track':
|
||||||
|
@ -1768,9 +1776,9 @@ class PmsConnect(object):
|
||||||
metadata = self.get_metadata_details(rating_key=rating_key)
|
metadata = self.get_metadata_details(rating_key=rating_key)
|
||||||
rating_key = metadata['metadata']['grandparent_rating_key']
|
rating_key = metadata['metadata']['grandparent_rating_key']
|
||||||
library_id = metadata['metadata']['library_id']
|
library_id = metadata['metadata']['library_id']
|
||||||
library_title = metadata['metadata']['library_title']
|
library_name = metadata['metadata']['library_name']
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to get grandparent_rating_key for get_rating_keys_list.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to get grandparent_rating_key for get_rating_keys_list: %s." % e)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
# get parent_rating_keys
|
# get parent_rating_keys
|
||||||
|
@ -1778,8 +1786,8 @@ class PmsConnect(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = metadata.getElementsByTagName('MediaContainer')
|
xml_head = metadata.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_rating_keys_list.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_rating_keys_list: %s." % e)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
for a in xml_head:
|
for a in xml_head:
|
||||||
|
@ -1806,8 +1814,8 @@ class PmsConnect(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = metadata.getElementsByTagName('MediaContainer')
|
xml_head = metadata.getElementsByTagName('MediaContainer')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_rating_keys_list.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_rating_keys_list: %s." % e)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
for a in xml_head:
|
for a in xml_head:
|
||||||
|
@ -1843,7 +1851,7 @@ class PmsConnect(object):
|
||||||
{'rating_key': int(rating_key),
|
{'rating_key': int(rating_key),
|
||||||
'children': parents },
|
'children': parents },
|
||||||
'library_id': library_id,
|
'library_id': library_id,
|
||||||
'library_title': library_title
|
'library_name': library_name
|
||||||
}
|
}
|
||||||
|
|
||||||
return key_list
|
return key_list
|
||||||
|
@ -1855,8 +1863,8 @@ class PmsConnect(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = account_data.getElementsByTagName('MyPlex')
|
xml_head = account_data.getElementsByTagName('MyPlex')
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to parse XML for get_server_response.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_server_response: %s." % e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
server_response = {}
|
server_response = {}
|
||||||
|
|
586
plexpy/users.py
586
plexpy/users.py
|
@ -21,28 +21,28 @@ class Users(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_user_list(self, kwargs=None):
|
def get_datatables_list(self, kwargs=None):
|
||||||
data_tables = datatables.DataTables()
|
data_tables = datatables.DataTables()
|
||||||
|
|
||||||
custom_where = ['users.deleted_user', 0]
|
custom_where = ['users.deleted_user', 0]
|
||||||
|
|
||||||
columns = ['users.user_id as user_id',
|
columns = ['users.user_id',
|
||||||
'users.custom_avatar_url as user_thumb',
|
'users.username',
|
||||||
'(case when users.friendly_name is null then users.username else \
|
'users.friendly_name',
|
||||||
users.friendly_name end) as friendly_name',
|
'users.thumb AS user_thumb',
|
||||||
'MAX(session_history.started) as last_seen',
|
'users.custom_avatar_url AS custom_thumb',
|
||||||
'session_history.ip_address as ip_address',
|
'COUNT(session_history.id) AS plays',
|
||||||
'COUNT(session_history.id) as plays',
|
'MAX(session_history.started) AS last_seen',
|
||||||
'session_history.platform as platform',
|
'session_history_metadata.full_title AS last_watched',
|
||||||
'session_history.player as player',
|
'session_history.ip_address',
|
||||||
'session_history_metadata.full_title as last_watched',
|
'session_history.platform',
|
||||||
|
'session_history.player',
|
||||||
'session_history_metadata.thumb',
|
'session_history_metadata.thumb',
|
||||||
'session_history_metadata.parent_thumb',
|
'session_history_metadata.parent_thumb',
|
||||||
'session_history_metadata.grandparent_thumb',
|
'session_history_metadata.grandparent_thumb',
|
||||||
'session_history_metadata.media_type',
|
'session_history_metadata.media_type',
|
||||||
'session_history.rating_key as rating_key',
|
'session_history.rating_key',
|
||||||
'session_history_media_info.video_decision',
|
'session_history_media_info.video_decision',
|
||||||
'users.username as user',
|
|
||||||
'users.do_notify as do_notify',
|
'users.do_notify as do_notify',
|
||||||
'users.keep_history as keep_history'
|
'users.keep_history as keep_history'
|
||||||
]
|
]
|
||||||
|
@ -61,8 +61,8 @@ class Users(object):
|
||||||
['session_history.id', 'session_history_metadata.id'],
|
['session_history.id', 'session_history_metadata.id'],
|
||||||
['session_history.id', 'session_history_media_info.id']],
|
['session_history.id', 'session_history_media_info.id']],
|
||||||
kwargs=kwargs)
|
kwargs=kwargs)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query.")
|
logger.warn(u"PlexPy Users :: Unable to execute database query for get_list: %s." % e)
|
||||||
return {'recordsFiltered': 0,
|
return {'recordsFiltered': 0,
|
||||||
'recordsTotal': 0,
|
'recordsTotal': 0,
|
||||||
'draw': 0,
|
'draw': 0,
|
||||||
|
@ -80,28 +80,30 @@ class Users(object):
|
||||||
else:
|
else:
|
||||||
thumb = item['thumb']
|
thumb = item['thumb']
|
||||||
|
|
||||||
if not item['user_thumb'] or item['user_thumb'] == '':
|
if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
|
||||||
user_thumb = common.DEFAULT_USER_THUMB
|
user_thumb = item['custom_thumb']
|
||||||
else:
|
elif item['user_thumb']:
|
||||||
user_thumb = item['user_thumb']
|
user_thumb = item['user_thumb']
|
||||||
|
else:
|
||||||
|
user_thumb = common.DEFAULT_USER_THUMB
|
||||||
|
|
||||||
# Rename Mystery platform names
|
# Rename Mystery platform names
|
||||||
platform = common.PLATFORM_NAME_OVERRIDES.get(item['platform'], item['platform'])
|
platform = common.PLATFORM_NAME_OVERRIDES.get(item['platform'], item['platform'])
|
||||||
|
|
||||||
row = {'plays': item['plays'],
|
row = {'user_id': item['user_id'],
|
||||||
'last_seen': item['last_seen'],
|
'username': item['username'],
|
||||||
'friendly_name': item['friendly_name'],
|
'friendly_name': item['friendly_name'],
|
||||||
|
'user_thumb': user_thumb,
|
||||||
|
'plays': item['plays'],
|
||||||
|
'last_seen': item['last_seen'],
|
||||||
|
'last_watched': item['last_watched'],
|
||||||
'ip_address': item['ip_address'],
|
'ip_address': item['ip_address'],
|
||||||
'platform': platform,
|
'platform': platform,
|
||||||
'player': item['player'],
|
'player': item['player'],
|
||||||
'last_watched': item['last_watched'],
|
|
||||||
'thumb': thumb,
|
'thumb': thumb,
|
||||||
'media_type': item['media_type'],
|
'media_type': item['media_type'],
|
||||||
'rating_key': item['rating_key'],
|
'rating_key': item['rating_key'],
|
||||||
'video_decision': item['video_decision'],
|
'video_decision': item['video_decision'],
|
||||||
'user_thumb': user_thumb,
|
|
||||||
'user': item['user'],
|
|
||||||
'user_id': item['user_id'],
|
|
||||||
'do_notify': helpers.checked(item['do_notify']),
|
'do_notify': helpers.checked(item['do_notify']),
|
||||||
'keep_history': helpers.checked(item['keep_history'])
|
'keep_history': helpers.checked(item['keep_history'])
|
||||||
}
|
}
|
||||||
|
@ -116,35 +118,34 @@ class Users(object):
|
||||||
|
|
||||||
return dict
|
return dict
|
||||||
|
|
||||||
def get_user_unique_ips(self, kwargs=None, custom_where=None):
|
def get_datatables_unique_ips(self, user_id=None, kwargs=None):
|
||||||
data_tables = datatables.DataTables()
|
data_tables = datatables.DataTables()
|
||||||
|
|
||||||
# Change custom_where column name due to ambiguous column name after JOIN
|
custom_where = ['users.user_id', user_id]
|
||||||
custom_where[0][0] = 'custom_user_id' if custom_where[0][0] == 'user_id' else custom_where[0][0]
|
|
||||||
|
|
||||||
columns = ['session_history.id',
|
columns = ['session_history.id',
|
||||||
'session_history.started as last_seen',
|
'session_history.started AS last_seen',
|
||||||
'session_history.ip_address as ip_address',
|
'session_history.ip_address',
|
||||||
'COUNT(session_history.id) as play_count',
|
'COUNT(session_history.id) AS play_count',
|
||||||
'session_history.platform as platform',
|
'session_history.platform',
|
||||||
'session_history.player as player',
|
'session_history.player',
|
||||||
'session_history_metadata.full_title as last_watched',
|
'session_history_metadata.full_title AS last_watched',
|
||||||
'session_history_metadata.thumb',
|
'session_history_metadata.thumb',
|
||||||
'session_history_metadata.parent_thumb',
|
'session_history_metadata.parent_thumb',
|
||||||
'session_history_metadata.grandparent_thumb',
|
'session_history_metadata.grandparent_thumb',
|
||||||
'session_history_metadata.media_type',
|
'session_history_metadata.media_type',
|
||||||
'session_history.rating_key as rating_key',
|
'session_history.rating_key',
|
||||||
'session_history_media_info.video_decision',
|
'session_history_media_info.video_decision',
|
||||||
'session_history.user as user',
|
'session_history.user',
|
||||||
'session_history.user_id as custom_user_id',
|
'session_history.user_id as custom_user_id',
|
||||||
'(case when users.friendly_name is null then users.username else \
|
'(CASE WHEN users.friendly_name IS NULL THEN users.username ELSE \
|
||||||
users.friendly_name end) as friendly_name'
|
users.friendly_name END) AS friendly_name'
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
query = data_tables.ssp_query(table_name='session_history',
|
query = data_tables.ssp_query(table_name='session_history',
|
||||||
columns=columns,
|
columns=columns,
|
||||||
custom_where=custom_where,
|
custom_where=[custom_where],
|
||||||
group_by=['ip_address'],
|
group_by=['ip_address'],
|
||||||
join_types=['JOIN',
|
join_types=['JOIN',
|
||||||
'JOIN',
|
'JOIN',
|
||||||
|
@ -156,8 +157,8 @@ class Users(object):
|
||||||
['session_history.id', 'session_history_metadata.id'],
|
['session_history.id', 'session_history_metadata.id'],
|
||||||
['session_history.id', 'session_history_media_info.id']],
|
['session_history.id', 'session_history_media_info.id']],
|
||||||
kwargs=kwargs)
|
kwargs=kwargs)
|
||||||
except:
|
except Exception as e:
|
||||||
logger.warn("Unable to execute database query.")
|
logger.warn(u"PlexPy Users :: Unable to execute database query for get_unique_ips: %s." % e)
|
||||||
return {'recordsFiltered': 0,
|
return {'recordsFiltered': 0,
|
||||||
'recordsTotal': 0,
|
'recordsTotal': 0,
|
||||||
'draw': 0,
|
'draw': 0,
|
||||||
|
@ -178,18 +179,18 @@ class Users(object):
|
||||||
# Rename Mystery platform names
|
# Rename Mystery platform names
|
||||||
platform = common.PLATFORM_NAME_OVERRIDES.get(item["platform"], item["platform"])
|
platform = common.PLATFORM_NAME_OVERRIDES.get(item["platform"], item["platform"])
|
||||||
|
|
||||||
row = {"id": item['id'],
|
row = {'id': item['id'],
|
||||||
"last_seen": item['last_seen'],
|
'last_seen': item['last_seen'],
|
||||||
"ip_address": item['ip_address'],
|
'ip_address': item['ip_address'],
|
||||||
"play_count": item['play_count'],
|
'play_count': item['play_count'],
|
||||||
"platform": platform,
|
'platform': platform,
|
||||||
"player": item['player'],
|
'player': item['player'],
|
||||||
"last_watched": item['last_watched'],
|
'last_watched': item['last_watched'],
|
||||||
"thumb": thumb,
|
'thumb': thumb,
|
||||||
"media_type": item['media_type'],
|
'media_type': item['media_type'],
|
||||||
"rating_key": item['rating_key'],
|
'rating_key': item['rating_key'],
|
||||||
"video_decision": item['video_decision'],
|
'video_decision': item['video_decision'],
|
||||||
"friendly_name": item['friendly_name']
|
'friendly_name': item['friendly_name']
|
||||||
}
|
}
|
||||||
|
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
@ -202,286 +203,169 @@ class Users(object):
|
||||||
|
|
||||||
return dict
|
return dict
|
||||||
|
|
||||||
# TODO: The getter and setter for this needs to become a config getter/setter for more than just friendlyname
|
def set_config(self, user_id=None, friendly_name='', custom_thumb='', do_notify=1, keep_history=1):
|
||||||
def set_user_friendly_name(self, user=None, user_id=None, friendly_name=None, do_notify=0, keep_history=1):
|
if str(user_id).isdigit():
|
||||||
if user_id:
|
|
||||||
if friendly_name.strip() == '':
|
|
||||||
friendly_name = None
|
|
||||||
|
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
control_value_dict = {"user_id": user_id}
|
key_dict = {'user_id': user_id}
|
||||||
new_value_dict = {"friendly_name": friendly_name,
|
value_dict = {'friendly_name': friendly_name,
|
||||||
"do_notify": do_notify,
|
'custom_avatar_url': custom_thumb,
|
||||||
"keep_history": keep_history}
|
'do_notify': do_notify,
|
||||||
|
'keep_history': keep_history}
|
||||||
try:
|
try:
|
||||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
monitor_db.upsert('users', value_dict, key_dict)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
logger.debug(u"Uncaught exception %s" % e)
|
logger.warn(u"PlexPy Users :: Unable to execute database query for set_config: %s." % e)
|
||||||
if user:
|
|
||||||
if friendly_name.strip() == '':
|
|
||||||
friendly_name = None
|
|
||||||
|
|
||||||
monitor_db = database.MonitorDatabase()
|
def get_details(self, user_id=None, user=None):
|
||||||
|
|
||||||
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) as friendly_name,' \
|
|
||||||
'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]['username'],
|
|
||||||
'friendly_name': result[0]['friendly_name'],
|
|
||||||
'thumb': result[0]['thumb'],
|
|
||||||
'do_notify': helpers.checked(result[0]['do_notify']),
|
|
||||||
'keep_history': helpers.checked(result[0]['keep_history'])
|
|
||||||
}
|
|
||||||
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) as friendly_name,' \
|
|
||||||
'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]['user_id'],
|
|
||||||
'user': user,
|
|
||||||
'friendly_name': result[0]['friendly_name'],
|
|
||||||
'thumb': result[0]['thumb'],
|
|
||||||
'do_notify': helpers.checked(result[0]['do_notify']),
|
|
||||||
'keep_history': helpers.checked(result[0]['keep_history'])}
|
|
||||||
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['user_id']
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
except:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_user_details(self, user=None, user_id=None):
|
|
||||||
from plexpy import plextv
|
from plexpy import plextv
|
||||||
|
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
if user:
|
try:
|
||||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
if str(user_id).isdigit():
|
||||||
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
|
||||||
|
'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
|
||||||
'FROM users ' \
|
'FROM users ' \
|
||||||
'WHERE username = ? ' \
|
'WHERE user_id = ? '
|
||||||
'UNION ALL ' \
|
result = monitor_db.select(query, args=[user_id])
|
||||||
'SELECT null, user, null, null, null, null, null, null, null ' \
|
elif user:
|
||||||
'FROM session_history ' \
|
query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
|
||||||
'WHERE user = ? ' \
|
'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
|
||||||
'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 ' \
|
'FROM users ' \
|
||||||
'WHERE user_id = ? ' \
|
'WHERE username = ? '
|
||||||
'UNION ALL ' \
|
result = monitor_db.select(query, args=[user])
|
||||||
'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:
|
else:
|
||||||
result = None
|
result = []
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Users :: Unable to execute database query for get_details: %s." % e)
|
||||||
|
result = []
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
user_details = {}
|
user_details = {}
|
||||||
for item in result:
|
for item in result:
|
||||||
if not item['friendly_name']:
|
if item['friendly_name']:
|
||||||
friendly_name = item['username']
|
|
||||||
else:
|
|
||||||
friendly_name = item['friendly_name']
|
friendly_name = item['friendly_name']
|
||||||
if not item['thumb'] or item['thumb'] == '':
|
|
||||||
user_thumb = common.DEFAULT_USER_THUMB
|
|
||||||
else:
|
else:
|
||||||
user_thumb = item['thumb']
|
friendly_name = item['username']
|
||||||
|
|
||||||
user_details = {"user_id": item['user_id'],
|
if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
|
||||||
"username": item['username'],
|
user_thumb = item['custom_thumb']
|
||||||
"friendly_name": friendly_name,
|
elif item['user_thumb']:
|
||||||
"email": item['email'],
|
user_thumb = item['user_thumb']
|
||||||
"thumb": user_thumb,
|
else:
|
||||||
"is_home_user": item['is_home_user'],
|
user_thumb = common.DEFAULT_USER_THUMB
|
||||||
"is_allow_sync": item['is_allow_sync'],
|
|
||||||
"is_restricted": item['is_restricted'],
|
user_details = {'user_id': item['user_id'],
|
||||||
"do_notify": item['do_notify']
|
'username': item['username'],
|
||||||
|
'friendly_name': friendly_name,
|
||||||
|
'user_thumb': user_thumb,
|
||||||
|
'email': item['email'],
|
||||||
|
'is_home_user': item['is_home_user'],
|
||||||
|
'is_allow_sync': item['is_allow_sync'],
|
||||||
|
'is_restricted': item['is_restricted'],
|
||||||
|
'do_notify': item['do_notify'],
|
||||||
|
'keep_history': item['keep_history']
|
||||||
}
|
}
|
||||||
return user_details
|
return user_details
|
||||||
else:
|
else:
|
||||||
logger.warn(u"PlexPy :: Unable to retrieve user from local database. Requesting user list refresh.")
|
logger.warn(u"PlexPy Users :: 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
|
# Let's first refresh the user list to make sure the user isn't newly added and not in the db yet
|
||||||
if user:
|
try:
|
||||||
|
if str(user_id).isdigit():
|
||||||
# Refresh users
|
# Refresh users
|
||||||
plextv.refresh_users()
|
plextv.refresh_users()
|
||||||
query = 'SELECT user_id, username, friendly_name, email, ' \
|
query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
|
||||||
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
|
'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
|
||||||
'FROM users ' \
|
'FROM users ' \
|
||||||
'WHERE username = ? ' \
|
'WHERE user_id = ? '
|
||||||
'UNION ALL ' \
|
result = monitor_db.select(query, args=[user_id])
|
||||||
'SELECT null, user, null, null, null, null, null, null, null ' \
|
elif user:
|
||||||
'FROM session_history ' \
|
query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
|
||||||
'WHERE user = ? ' \
|
'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
|
||||||
'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 ' \
|
'FROM users ' \
|
||||||
'WHERE user_id = ? ' \
|
'WHERE username = ? '
|
||||||
'UNION ALL ' \
|
result = monitor_db.select(query, args=[user])
|
||||||
'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:
|
else:
|
||||||
result = None
|
result = []
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Users :: Unable to execute database query for get_details: %s." % e)
|
||||||
|
result = []
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
user_details = {}
|
user_details = {}
|
||||||
for item in result:
|
for item in result:
|
||||||
if not item['friendly_name']:
|
if item['friendly_name']:
|
||||||
friendly_name = item['username']
|
|
||||||
else:
|
|
||||||
friendly_name = item['friendly_name']
|
friendly_name = item['friendly_name']
|
||||||
if not item['thumb'] or item['thumb'] == '':
|
|
||||||
user_thumb = common.DEFAULT_USER_THUMB
|
|
||||||
else:
|
else:
|
||||||
user_thumb = item['thumb']
|
friendly_name = item['username']
|
||||||
|
|
||||||
user_details = {"user_id": item['user_id'],
|
if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
|
||||||
"username": item['username'],
|
user_thumb = item['custom_thumb']
|
||||||
"friendly_name": friendly_name,
|
elif item['user_thumb']:
|
||||||
"email": item['email'],
|
user_thumb = item['user_thumb']
|
||||||
"thumb": user_thumb,
|
else:
|
||||||
"is_home_user": item['is_home_user'],
|
user_thumb = common.DEFAULT_USER_THUMB
|
||||||
"is_allow_sync": item['is_allow_sync'],
|
|
||||||
"is_restricted": item['is_restricted'],
|
user_details = {'user_id': item['user_id'],
|
||||||
"do_notify": item['do_notify']
|
'username': item['username'],
|
||||||
|
'friendly_name': friendly_name,
|
||||||
|
'user_thumb': user_thumb,
|
||||||
|
'email': item['email'],
|
||||||
|
'is_home_user': item['is_home_user'],
|
||||||
|
'is_allow_sync': item['is_allow_sync'],
|
||||||
|
'is_restricted': item['is_restricted'],
|
||||||
|
'do_notify': item['do_notify'],
|
||||||
|
'keep_history': item['keep_history']
|
||||||
}
|
}
|
||||||
return user_details
|
return user_details
|
||||||
else:
|
else:
|
||||||
# If there is no user data we must return something
|
# If there is no user data we must return something
|
||||||
# Use "Local" user to retain compatibility with PlexWatch database value
|
# Use "Local" user to retain compatibility with PlexWatch database value
|
||||||
return {"user_id": None,
|
return {'user_id': None,
|
||||||
"username": 'Local',
|
'username': 'Local',
|
||||||
"friendly_name": 'Local',
|
'friendly_name': 'Local',
|
||||||
"email": '',
|
'user_thumb': common.DEFAULT_USER_THUMB,
|
||||||
"thumb": '',
|
'email': '',
|
||||||
"is_home_user": 0,
|
'is_home_user': 0,
|
||||||
"is_allow_sync": 0,
|
'is_allow_sync': 0,
|
||||||
"is_restricted": 0,
|
'is_restricted': 0,
|
||||||
"do_notify": 0
|
'do_notify': 0,
|
||||||
|
'keep_history': 0
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_user_watch_time_stats(self, user=None, user_id=None):
|
def get_watch_time_stats(self, user_id=None):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
time_queries = [1, 7, 30, 0]
|
time_queries = [1, 7, 30, 0]
|
||||||
user_watch_time_stats = []
|
user_watch_time_stats = []
|
||||||
|
|
||||||
for days in time_queries:
|
for days in time_queries:
|
||||||
|
try:
|
||||||
if days > 0:
|
if days > 0:
|
||||||
if user_id:
|
if str(user_id).isdigit():
|
||||||
query = 'SELECT (SUM(stopped - started) - ' \
|
query = 'SELECT (SUM(stopped - started) - ' \
|
||||||
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
' SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
||||||
'COUNT(id) AS total_plays ' \
|
'COUNT(id) AS total_plays ' \
|
||||||
'FROM session_history ' \
|
'FROM session_history ' \
|
||||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||||
'AND user_id = ?' % days
|
'AND user_id = ?' % days
|
||||||
result = monitor_db.select(query, args=[user_id])
|
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:
|
else:
|
||||||
|
result = []
|
||||||
|
else:
|
||||||
|
if str(user_id).isdigit():
|
||||||
query = 'SELECT (SUM(stopped - started) - ' \
|
query = 'SELECT (SUM(stopped - started) - ' \
|
||||||
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
' SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
|
||||||
'COUNT(id) AS total_plays ' \
|
'COUNT(id) AS total_plays ' \
|
||||||
'FROM session_history ' \
|
'FROM session_history ' \
|
||||||
'WHERE user = ?'
|
'WHERE user_id = ?'
|
||||||
result = monitor_db.select(query, args=[user])
|
result = monitor_db.select(query, args=[user_id])
|
||||||
|
else:
|
||||||
|
result = []
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Users :: Unable to execute database query for get_watch_time_stats: %s." % e)
|
||||||
|
result = []
|
||||||
|
|
||||||
for item in result:
|
for item in result:
|
||||||
if item['total_time']:
|
if item['total_time']:
|
||||||
|
@ -500,14 +384,14 @@ class Users(object):
|
||||||
|
|
||||||
return user_watch_time_stats
|
return user_watch_time_stats
|
||||||
|
|
||||||
def get_user_player_stats(self, user=None, user_id=None):
|
def get_player_stats(self, user_id=None):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
player_stats = []
|
player_stats = []
|
||||||
result_id = 0
|
result_id = 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if user_id:
|
if str(user_id).isdigit():
|
||||||
query = 'SELECT player, COUNT(player) as player_count, platform ' \
|
query = 'SELECT player, COUNT(player) as player_count, platform ' \
|
||||||
'FROM session_history ' \
|
'FROM session_history ' \
|
||||||
'WHERE user_id = ? ' \
|
'WHERE user_id = ? ' \
|
||||||
|
@ -515,15 +399,10 @@ class Users(object):
|
||||||
'ORDER BY player_count DESC'
|
'ORDER BY player_count DESC'
|
||||||
result = monitor_db.select(query, args=[user_id])
|
result = monitor_db.select(query, args=[user_id])
|
||||||
else:
|
else:
|
||||||
query = 'SELECT player, COUNT(player) as player_count, platform ' \
|
result = []
|
||||||
'FROM session_history ' \
|
except Exception as e:
|
||||||
'WHERE user = ? ' \
|
logger.warn(u"PlexPy Users :: Unable to execute database query for get_player_stats: %s." % e)
|
||||||
'GROUP BY player ' \
|
result = []
|
||||||
'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:
|
for item in result:
|
||||||
# Rename Mystery platform names
|
# Rename Mystery platform names
|
||||||
|
@ -538,3 +417,140 @@ class Users(object):
|
||||||
result_id += 1
|
result_id += 1
|
||||||
|
|
||||||
return player_stats
|
return player_stats
|
||||||
|
|
||||||
|
def get_recently_watched(self, user_id=None, limit='10'):
|
||||||
|
monitor_db = database.MonitorDatabase()
|
||||||
|
recently_watched = []
|
||||||
|
|
||||||
|
if not limit.isdigit():
|
||||||
|
limit = '10'
|
||||||
|
|
||||||
|
try:
|
||||||
|
if str(user_id).isdigit():
|
||||||
|
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
|
||||||
|
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
|
||||||
|
'year, started, user ' \
|
||||||
|
'FROM session_history_metadata ' \
|
||||||
|
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
|
||||||
|
'WHERE user_id = ? ' \
|
||||||
|
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
|
||||||
|
' ELSE session_history.rating_key END) ' \
|
||||||
|
'ORDER BY started DESC LIMIT ?'
|
||||||
|
result = monitor_db.select(query, args=[user_id, limit])
|
||||||
|
else:
|
||||||
|
result = []
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Users :: Unable to execute database query for get_recently_watched: %s." % e)
|
||||||
|
result = []
|
||||||
|
|
||||||
|
for row in result:
|
||||||
|
if row['media_type'] == 'episode' and row['parent_thumb']:
|
||||||
|
thumb = row['parent_thumb']
|
||||||
|
elif row['media_type'] == 'episode':
|
||||||
|
thumb = row['grandparent_thumb']
|
||||||
|
else:
|
||||||
|
thumb = row['thumb']
|
||||||
|
|
||||||
|
recent_output = {'row_id': row['id'],
|
||||||
|
'type': row['media_type'],
|
||||||
|
'rating_key': row['rating_key'],
|
||||||
|
'title': row['title'],
|
||||||
|
'parent_title': row['parent_title'],
|
||||||
|
'grandparent_title': row['grandparent_title'],
|
||||||
|
'thumb': thumb,
|
||||||
|
'media_index': row['media_index'],
|
||||||
|
'parent_media_index': row['parent_media_index'],
|
||||||
|
'year': row['year'],
|
||||||
|
'time': row['started'],
|
||||||
|
'user': row['user']
|
||||||
|
}
|
||||||
|
recently_watched.append(recent_output)
|
||||||
|
|
||||||
|
return recently_watched
|
||||||
|
|
||||||
|
def delete_all_history(self, user_id=None):
|
||||||
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if str(user_id).isdigit():
|
||||||
|
logger.info(u"PlexPy DataFactory :: Deleting all history for user id %s from database." % user_id)
|
||||||
|
session_history_media_info_del = \
|
||||||
|
monitor_db.action('DELETE FROM '
|
||||||
|
'session_history_media_info '
|
||||||
|
'WHERE session_history_media_info.id IN (SELECT session_history_media_info.id '
|
||||||
|
'FROM session_history_media_info '
|
||||||
|
'JOIN session_history ON session_history_media_info.id = session_history.id '
|
||||||
|
'WHERE session_history.user_id = ?)', [user_id])
|
||||||
|
session_history_metadata_del = \
|
||||||
|
monitor_db.action('DELETE FROM '
|
||||||
|
'session_history_metadata '
|
||||||
|
'WHERE session_history_metadata.id IN (SELECT session_history_metadata.id '
|
||||||
|
'FROM session_history_metadata '
|
||||||
|
'JOIN session_history ON session_history_metadata.id = session_history.id '
|
||||||
|
'WHERE session_history.user_id = ?)', [user_id])
|
||||||
|
session_history_del = \
|
||||||
|
monitor_db.action('DELETE FROM '
|
||||||
|
'session_history '
|
||||||
|
'WHERE session_history.user_id = ?', [user_id])
|
||||||
|
|
||||||
|
return 'Deleted all items for user_id %s.' % user_id
|
||||||
|
else:
|
||||||
|
return 'Unable to delete items. Input user_id not valid.'
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Users :: Unable to execute database query for delete_all_history: %s." % e)
|
||||||
|
|
||||||
|
def delete(self, user_id=None):
|
||||||
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if str(user_id).isdigit():
|
||||||
|
self.delete_all_history(user_id)
|
||||||
|
logger.info(u"PlexPy DataFactory :: Deleting user with id %s from database." % user_id)
|
||||||
|
monitor_db.action('UPDATE users SET deleted_user = 1 WHERE user_id = ?', [user_id])
|
||||||
|
monitor_db.action('UPDATE users SET keep_history = 0 WHERE user_id = ?', [user_id])
|
||||||
|
monitor_db.action('UPDATE users SET do_notify = 0 WHERE user_id = ?', [user_id])
|
||||||
|
|
||||||
|
return 'Deleted user with id %s.' % user_id
|
||||||
|
else:
|
||||||
|
return 'Unable to delete user, user_id not valid.'
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Users :: Unable to execute database query for delete: %s." % e)
|
||||||
|
|
||||||
|
def undelete(self, user_id=None, username=None):
|
||||||
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if user_id and str(user_id).isdigit():
|
||||||
|
logger.info(u"PlexPy DataFactory :: Re-adding user with id %s to database." % user_id)
|
||||||
|
monitor_db.action('UPDATE users SET deleted_user = 0 WHERE user_id = ?', [user_id])
|
||||||
|
monitor_db.action('UPDATE users SET keep_history = 1 WHERE user_id = ?', [user_id])
|
||||||
|
monitor_db.action('UPDATE users SET do_notify = 1 WHERE user_id = ?', [user_id])
|
||||||
|
|
||||||
|
return 'Re-added user with id %s.' % user_id
|
||||||
|
elif username:
|
||||||
|
logger.info(u"PlexPy DataFactory :: Re-adding user with username %s to database." % username)
|
||||||
|
monitor_db.action('UPDATE users SET deleted_user = 0 WHERE username = ?', [username])
|
||||||
|
monitor_db.action('UPDATE users SET keep_history = 1 WHERE username = ?', [username])
|
||||||
|
monitor_db.action('UPDATE users SET do_notify = 1 WHERE username = ?', [username])
|
||||||
|
|
||||||
|
return 'Re-added user with username %s.' % username
|
||||||
|
else:
|
||||||
|
return 'Unable to re-add user, user_id or username not valid.'
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"PlexPy Users :: Unable to execute database query for undelete: %s." % e)
|
||||||
|
|
||||||
|
# Keep method for PlexWatch import
|
||||||
|
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['user_id']
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return None
|
2321
plexpy/webserve.py
2321
plexpy/webserve.py
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue