New pause, resume and buffer notification options.

Reworked notification config in settings menu.
This commit is contained in:
Tim 2015-08-15 14:37:27 +02:00
parent b7baf1a05d
commit a96482ee3c
9 changed files with 532 additions and 131 deletions

View file

@ -1368,7 +1368,7 @@ input[type="color"],
}
.stacked-configs > li > span > a.toggle-left {
color: #444;
padding-right: 2px;
padding-right: 8px;
}
.stacked-configs > li > span > a:hover {
color: #eee;

View file

@ -0,0 +1,98 @@
<%!
from plexpy import helpers
%>
% if data:
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
<h4 class="modal-title" id="notification-triggers-modal-header">${data['name']} Notification Triggers</h4>
</div>
<div class="modal-body">
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<p class="help-block">
Watched notifications are only applicable for video items.
</p>
<div class="checkbox">
<label>
<input type="checkbox" data-size="small" data-id="${data['id']}" data-config-name="${data['config_prefix']}_on_play" ${helpers.checked(data['on_play'])} class="toggle-switches">
Notify on playback start
</label>
<p class="help-block">Trigger notification when a new media item is started.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" data-size="small" data-id="${data['id']}" data-config-name="${data['config_prefix']}_on_stop" ${helpers.checked(data['on_stop'])} class="toggle-switches">
Notify on playback stop
</label>
<p class="help-block">Trigger notification when a media item is stopped.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" data-size="small" data-id="${data['id']}" data-config-name="${data['config_prefix']}_on_pause" ${helpers.checked(data['on_pause'])} class="toggle-switches">
Notify on playback pause
</label>
<p class="help-block">Trigger notification when a media item is paused.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" data-size="small" data-id="${data['id']}" data-config-name="${data['config_prefix']}_on_resume" ${helpers.checked(data['on_resume'])} class="toggle-switches">
Notify on playback resume
</label>
<p class="help-block">Trigger notification when a media item is resumed from a paused state.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" data-size="small" data-id="${data['id']}" data-config-name="${data['config_prefix']}_on_watched" ${helpers.checked(data['on_watched'])} class="toggle-switches">
Notify on watched
</label>
<p class="help-block">Trigger notification when a video item reaches the defined watch percentage.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" data-size="small" data-id="${data['id']}" data-config-name="${data['config_prefix']}_on_buffer" ${helpers.checked(data['on_buffer'])} class="toggle-switches">
Notify on buffer warning
</label>
<p class="help-block">Trigger notification when a media item triggers the defined buffer threshold.</p>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-bright" data-dismiss="modal" value="Close">
</div>
</div>
</div>
<script>
$('.toggle-switches').click(function() {
var configToggle = $(this).data('id');
var toggle = $(this);
if ($(this).is(":checked")) {
var data = {};
data[$(this).data('config-name')] = 1;
$.ajax({
url: 'set_notification_config',
data: data,
async: true,
success: function(data) {
console.log('success');
}
});
} else {
var data = {};
data[$(this).data('config-name')] = 0;
$.ajax({
url: 'set_notification_config',
data: data,
async: true,
success: function(data) {
console.log('success');
}
});
}
});
</script>
% endif

View file

@ -5,6 +5,8 @@ from plexpy import notifiers
available_notification_agents = notifiers.available_notification_agents()
%>
<%def name="headIncludes()">
</%def>
<%def name="headerIncludes()">
</%def>
@ -79,7 +81,7 @@ available_notification_agents = notifiers.available_notification_agents()
</div>
<p class="help-block">Set your preferred time format. <a href="javascript:void(0)" data-target="#dateTimeOptionsModal" data-toggle="modal">Click here</a> to see the parameter list.</p>
</div>
<input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully">
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-2">
<div class="padded-header">
@ -127,7 +129,7 @@ available_notification_agents = notifiers.available_notification_agents()
</div>
</div>
<input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully">
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-3">
@ -179,7 +181,7 @@ available_notification_agents = notifiers.available_notification_agents()
<p class="help-block">Current API key: <strong><br/>${config['api_key']}</strong></p>
</div>
<input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully">
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-4">
@ -260,7 +262,7 @@ available_notification_agents = notifiers.available_notification_agents()
<p class="help-block">Refresh the user list when PlexPy starts.</p>
</div>
<input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully">
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-6">
<div class="padded-header">
@ -304,7 +306,7 @@ available_notification_agents = notifiers.available_notification_agents()
</div>
<p class="help-block"><a href="javascript:void(0)" id="toggle-plexwatch-import-modal" data-target="#plexwatch-import-modal" data-toggle="modal">Click here to Import an existing Plexwatch database.</a></p>
<input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully">
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-7">
@ -359,7 +361,30 @@ available_notification_agents = notifiers.available_notification_agents()
</p>
</div>
<input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully">
<div class="padded-header">
<h3>Buffer Warnings</h3>
</div>
<p class="help-block">Note: Buffer warnings only work on certain Plex clients. Android and PlexWeb do not report buffer events accurately or at all.</p>
<div class="form-group">
<label for="buffer_threshold">Buffer Threshold</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="buffer_threshold" name="buffer_threshold" value="${config['buffer_threshold']}" data-parsley-range="[1,50]" data-parsley-trigger="change" required>
</div>
</div>
<p class="help-block">How many buffer events should we wait before triggering the first warning. Buffer events increment on each monitor ping if play state is buffering.</p>
</div>
<div class="form-group">
<label for="buffer_wait">Buffer Wait</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="buffer_wait" name="buffer_wait" value="${config['buffer_wait']}" data-parsley-min="0" data-parsley-trigger="change" required>
</div>
</div>
<p class="help-block">The value (in seconds) PlexPy should wait before triggering the next buffer warning. 0 to always trigger.</p>
</div>
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-8">
@ -438,6 +463,40 @@ available_notification_agents = notifiers.available_notification_agents()
</li>
</ul>
</li>
<li>
<div class="link"><i class="fa fa-pause"></i>Playback Pause<i class="fa fa-chevron-down"></i></div>
<ul class="submenu">
<li>
<div class="form-group">
<label for="notify_on_pause_subject_text">Subject Line</label>
<input class="form-control" type="text" id="notify_on_pause_subject_text" name="notify_on_pause_subject_text" value="${config['notify_on_pause_subject_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom subject line.</p>
</div>
<div class="form-group">
<label for="notify_on_pause_body_text">Message Body</label>
<input class="form-control" type="text" id="notify_on_pause_body_text" name="notify_on_pause_body_text" value="${config['notify_on_pause_body_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom body.</p>
</div>
</li>
</ul>
</li>
<li>
<div class="link"><i class="fa fa-play"></i>Playback Resume<i class="fa fa-chevron-down"></i></div>
<ul class="submenu">
<li>
<div class="form-group">
<label for="notify_on_resume_subject_text">Subject Line</label>
<input class="form-control" type="text" id="notify_on_resume_subject_text" name="notify_on_resume_subject_text" value="${config['notify_on_resume_subject_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom subject line.</p>
</div>
<div class="form-group">
<label for="notify_on_resume_body_text">Message Body</label>
<input class="form-control" type="text" id="notify_on_resume_body_text" name="notify_on_resume_body_text" value="${config['notify_on_resume_body_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom body.</p>
</div>
</li>
</ul>
</li>
<li>
<div class="link"><i class="fa fa-eye"></i>Watched<i class="fa fa-chevron-down"></i></div>
<ul class="submenu">
@ -455,9 +514,26 @@ available_notification_agents = notifiers.available_notification_agents()
</li>
</ul>
</li>
<li>
<div class="link"><i class="fa fa-spinner"></i>Buffer Warnings<i class="fa fa-chevron-down"></i></div>
<ul class="submenu">
<li>
<div class="form-group">
<label for="notify_on_buffer_subject_text">Subject Line</label>
<input class="form-control" type="text" id="notify_on_buffer_subject_text" name="notify_on_buffer_subject_text" value="${config['notify_on_buffer_subject_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom subject line.</p>
</div>
<div class="form-group">
<label for="notify_on_buffer_body_text">Message Body</label>
<input class="form-control" type="text" id="notify_on_buffer_body_text" name="notify_on_buffer_body_text" value="${config['notify_on_buffer_body_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom body.</p>
</div>
</li>
</ul>
</li>
</ul>
<input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully">
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-9">
@ -465,18 +541,18 @@ available_notification_agents = notifiers.available_notification_agents()
<h3>Notification Agents</h3>
</div>
<p class="help-block">
Toggle the desired notification option and configure it by selecting the settings icon to the right.
Watched notifications are only applicable for video items.
Toggle the desired notification options by clicking the bolt icon and configure it by selecting the settings icon to the right.
</p>
<br/>
<ul class="stacked-configs list-unstyled">
% for agent in available_notification_agents:
<li>
<span>
<!--<input type="checkbox" name="${agent['config_prefix']}_enabled" id="${agent['config_prefix']}" value="1" ${agent['state']}> ${agent['name']}-->
<a class="toggle-left notify-toggle-icon" href="javascript:void(0)" data-toggle="tooltip" data-placement="top" title data-title="Notify on playback start" data-id="${agent['id']}" data-config-name="${agent['config_prefix']}_on_play" data-config-value="${agent['on_play']}"><i class="fa fa-play"></i></a>
<a class="toggle-left notify-toggle-icon" href="javascript:void(0)" data-toggle="tooltip" data-placement="top" title data-title="Notify on stop" data-id="${agent['id']}" data-config-name="${agent['config_prefix']}_on_stop" data-config-value="${agent['on_stop']}"><i class="fa fa-stop"></i></a>
<a class="toggle-left notify-toggle-icon" href="javascript:void(0)" data-toggle="tooltip" data-placement="top" title data-title="Notify on watched" data-id="${agent['id']}" data-config-name="${agent['config_prefix']}_on_watched" data-config-value="${agent['on_watched']}"><i class="fa fa-eye"></i></a>
% if agent['on_play'] or agent['on_stop'] or agent['on_pause'] or agent['on_resume'] or agent['on_buffer'] or agent['on_watched']:
<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-flash"></i></a>
% 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-flash"></i></a>
% endif
${agent['name']}
% if agent['has_config']:
<a href="javascript:void(0)" rel="tooltip" data-target="#notification-config-modal" data-placement="top" title data-title="Open configuration" data-id="${agent['id']}" class="toggle-notification-config-modal toggle-right" data-toggle="modal"><i class="fa fa-lg fa-cog"></i></a>
@ -661,7 +737,8 @@ available_notification_agents = notifiers.available_notification_agents()
</div>
</div>
<div id="plexwatch-import-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="plexwatch-import-modal"></div>
<div id="notification-config-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notification-setting-modal"></div>
<div id="notification-config-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notification-config-modal"></div>
<div id="notification-triggers-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notification-triggers-modal"></div>
<div id="notify-text-sub-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notify-text-sub-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
@ -977,7 +1054,7 @@ $(document).ready(function() {
});
});
// Load PlexWatch import modal
// Load notification agent config modal
$(".toggle-notification-config-modal").click(function() {
var configId = $(this).data('id');
$.ajax({
@ -991,100 +1068,18 @@ $(document).ready(function() {
});
});
$('.notify-toggle-icon').tooltip();
$('.notify-toggle-icon').each(function() {
if ($(this).data('config-value') == 1) {
$(this).addClass("active");
}
});
$('.notify-toggle-icon').click(function() {
var configToggle = $(this).data('id');
var toggle = $(this);
if ($(this).hasClass("active")) {
var data = {};
data[$(this).data('config-name')] = 0;
$.ajax({
url: 'set_notification_config',
data: data,
async: true,
success: function(data) {
toggle.removeClass("active");
}
});
} else {
var data = {};
data[$(this).data('config-name')] = 1;
$.ajax({
url: 'set_notification_config',
data: data,
async: true,
success: function(data) {
toggle.addClass("active");
}
});
}
});
if ($("#tv_notify_enable").is(":checked"))
{
$("#tv_notify_options").show();
}
else
{
$("#tv_notify_options").hide();
}
$("#tv_notify_enable").click(function(){
if ($("#tv_notify_enable").is(":checked"))
{
$("#tv_notify_options").slideDown();
}
else
{
$("#tv_notify_options").slideUp();
}
});
if ($("#movie_notify_enable").is(":checked"))
{
$("#movie_notify_options").show();
}
else
{
$("#movie_notify_options").hide();
}
$("#movie_notify_enable").click(function(){
if ($("#movie_notify_enable").is(":checked"))
{
$("#movie_notify_options").slideDown();
}
else
{
$("#movie_notify_options").slideUp();
}
});
if ($("#music_notify_enable").is(":checked"))
{
$("#music_notify_options").show();
}
else
{
$("#music_notify_options").hide();
}
$("#music_notify_enable").click(function(){
if ($("#music_notify_enable").is(":checked"))
{
$("#music_notify_options").slideDown();
}
else
{
$("#music_notify_options").slideUp();
// Load notification triggers config modal
$(".toggle-notification-triggers-modal").click(function() {
var configId = $(this).data('id');
$.ajax({
url: 'get_notification_agent_triggers',
data: { config_id: configId },
cache: false,
async: true,
complete: function(xhr, status) {
$("#notification-triggers-modal").html(xhr.responseText);
}
});
});
$('#osxnotifyregister').click(function () {

View file

@ -348,7 +348,8 @@ def dbcheck():
'bitrate INTEGER, video_resolution TEXT, video_framerate TEXT, aspect_ratio TEXT, '
'audio_channels INTEGER, transcode_protocol TEXT, transcode_container TEXT, '
'transcode_video_codec TEXT, transcode_audio_codec TEXT, transcode_audio_channels INTEGER,'
'transcode_width INTEGER, transcode_height INTEGER)'
'transcode_width INTEGER, transcode_height INTEGER, buffer_count INTEGER DEFAULT 0, '
'buffer_last_triggered INTEGER)'
)
# session_history table :: This is a history table which logs essential stream details
@ -529,7 +530,8 @@ def dbcheck():
c_db.execute(
'CREATE TABLE IF NOT EXISTS notify_log (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'session_key INTEGER, rating_key INTEGER, user_id INTEGER, user TEXT, '
'agent_id INTEGER, agent_name TEXT, on_play INTEGER, on_stop INTEGER, on_watched INTEGER)'
'agent_id INTEGER, agent_name TEXT, on_play INTEGER, on_stop INTEGER, on_watched INTEGER, '
'on_pause INTEGER, on_resume INTEGER, on_buffer INTEGER)'
)
# Upgrade sessions table from earlier versions
@ -550,6 +552,33 @@ def dbcheck():
'ALTER TABLE users ADD COLUMN keep_history INTEGER DEFAULT 1'
)
# Upgrade sessions table from earlier versions
try:
c_db.execute('SELECT on_pause from notify_log')
except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.")
c_db.execute(
'ALTER TABLE notify_log ADD COLUMN on_pause INTEGER'
)
c_db.execute(
'ALTER TABLE notify_log ADD COLUMN on_resume INTEGER'
)
c_db.execute(
'ALTER TABLE notify_log ADD COLUMN on_buffer INTEGER'
)
# Upgrade sessions table from earlier versions
try:
c_db.execute('SELECT buffer_count from sessions')
except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.")
c_db.execute(
'ALTER TABLE sessions ADD COLUMN buffer_count INTEGER DEFAULT 0'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN buffer_last_triggered INTEGER'
)
conn_db.commit()
c_db.close()

View file

@ -39,7 +39,12 @@ _CONFIG_DEFINITIONS = {
'BOXCAR_TOKEN': (str, 'Boxcar', ''),
'BOXCAR_ON_PLAY': (int, 'Boxcar', 0),
'BOXCAR_ON_STOP': (int, 'Boxcar', 0),
'BOXCAR_ON_PAUSE': (int, 'Boxcar', 0),
'BOXCAR_ON_RESUME': (int, 'Boxcar', 0),
'BOXCAR_ON_BUFFER': (int, 'Boxcar', 0),
'BOXCAR_ON_WATCHED': (int, 'Boxcar', 0),
'BUFFER_THRESHOLD': (int, 'Monitoring', 3),
'BUFFER_WAIT': (int, 'Monitoring', 900),
'CACHE_DIR': (str, 'General', ''),
'CACHE_SIZEMB': (int, 'Advanced', 32),
'CHECK_GITHUB': (int, 'General', 1),
@ -58,6 +63,9 @@ _CONFIG_DEFINITIONS = {
'EMAIL_TLS': (int, 'Email', 0),
'EMAIL_ON_PLAY': (int, 'Email', 0),
'EMAIL_ON_STOP': (int, 'Email', 0),
'EMAIL_ON_PAUSE': (int, 'Email', 0),
'EMAIL_ON_RESUME': (int, 'Email', 0),
'EMAIL_ON_BUFFER': (int, 'Email', 0),
'EMAIL_ON_WATCHED': (int, 'Email', 0),
'ENABLE_HTTPS': (int, 'General', 0),
'FIRST_RUN_COMPLETE': (int, 'General', 0),
@ -70,6 +78,9 @@ _CONFIG_DEFINITIONS = {
'GROWL_PASSWORD': (str, 'Growl', ''),
'GROWL_ON_PLAY': (int, 'Growl', 0),
'GROWL_ON_STOP': (int, 'Growl', 0),
'GROWL_ON_PAUSE': (int, 'Growl', 0),
'GROWL_ON_RESUME': (int, 'Growl', 0),
'GROWL_ON_BUFFER': (int, 'Growl', 0),
'GROWL_ON_WATCHED': (int, 'Growl', 0),
'HOME_STATS_LENGTH': (int, 'General', 30),
'HTTPS_CERT': (str, 'General', ''),
@ -101,18 +112,30 @@ _CONFIG_DEFINITIONS = {
'NMA_PRIORITY': (int, 'NMA', 0),
'NMA_ON_PLAY': (int, 'NMA', 0),
'NMA_ON_STOP': (int, 'NMA', 0),
'NMA_ON_PAUSE': (int, 'NMA', 0),
'NMA_ON_RESUME': (int, 'NMA', 0),
'NMA_ON_BUFFER': (int, 'NMA', 0),
'NMA_ON_WATCHED': (int, 'NMA', 0),
'NOTIFY_WATCHED_PERCENT': (int, 'Monitoring', 85),
'NOTIFY_ON_START_SUBJECT_TEXT': (str, 'Monitoring', 'PlexPy ({server_name})'),
'NOTIFY_ON_START_BODY_TEXT': (str, 'Monitoring', '{user} ({player}) started playing {title}.'),
'NOTIFY_ON_STOP_SUBJECT_TEXT': (str, 'Monitoring', 'PlexPy ({server_name})'),
'NOTIFY_ON_STOP_BODY_TEXT': (str, 'Monitoring', '{user} ({player}) has stopped {title}.'),
'NOTIFY_ON_PAUSE_SUBJECT_TEXT': (str, 'Monitoring', 'PlexPy ({server_name})'),
'NOTIFY_ON_PAUSE_BODY_TEXT': (str, 'Monitoring', '{user} ({player}) has paused {title}.'),
'NOTIFY_ON_RESUME_SUBJECT_TEXT': (str, 'Monitoring', 'PlexPy ({server_name})'),
'NOTIFY_ON_RESUME_BODY_TEXT': (str, 'Monitoring', '{user} ({player}) has resumed {title}.'),
'NOTIFY_ON_BUFFER_SUBJECT_TEXT': (str, 'Monitoring', 'PlexPy ({server_name})'),
'NOTIFY_ON_BUFFER_BODY_TEXT': (str, 'Monitoring', '{user} ({player}) is buffering {title}.'),
'NOTIFY_ON_WATCHED_SUBJECT_TEXT': (str, 'Monitoring', 'PlexPy ({server_name})'),
'NOTIFY_ON_WATCHED_BODY_TEXT': (str, 'Monitoring', '{user} ({player}) has watched {title}.'),
'OSX_NOTIFY_APP': (str, 'OSX_Notify', '/Applications/PlexPy'),
'OSX_NOTIFY_ENABLED': (int, 'OSX_Notify', 0),
'OSX_NOTIFY_ON_PLAY': (int, 'OSX_Notify', 0),
'OSX_NOTIFY_ON_STOP': (int, 'OSX_Notify', 0),
'OSX_NOTIFY_ON_PAUSE': (int, 'OSX_Notify', 0),
'OSX_NOTIFY_ON_RESUME': (int, 'OSX_Notify', 0),
'OSX_NOTIFY_ON_BUFFER': (int, 'OSX_Notify', 0),
'OSX_NOTIFY_ON_WATCHED': (int, 'OSX_Notify', 0),
'PLEX_CLIENT_HOST': (str, 'Plex', ''),
'PLEX_ENABLED': (int, 'Plex', 0),
@ -120,17 +143,26 @@ _CONFIG_DEFINITIONS = {
'PLEX_USERNAME': (str, 'Plex', ''),
'PLEX_ON_PLAY': (int, 'Plex', 0),
'PLEX_ON_STOP': (int, 'Plex', 0),
'PLEX_ON_PAUSE': (int, 'Plex', 0),
'PLEX_ON_RESUME': (int, 'Plex', 0),
'PLEX_ON_BUFFER': (int, 'Plex', 0),
'PLEX_ON_WATCHED': (int, 'Plex', 0),
'PROWL_ENABLED': (int, 'Prowl', 0),
'PROWL_KEYS': (str, 'Prowl', ''),
'PROWL_PRIORITY': (int, 'Prowl', 0),
'PROWL_ON_PLAY': (int, 'Prowl', 0),
'PROWL_ON_STOP': (int, 'Prowl', 0),
'PROWL_ON_PAUSE': (int, 'Prowl', 0),
'PROWL_ON_RESUME': (int, 'Prowl', 0),
'PROWL_ON_BUFFER': (int, 'Prowl', 0),
'PROWL_ON_WATCHED': (int, 'Prowl', 0),
'PUSHALOT_APIKEY': (str, 'Pushalot', ''),
'PUSHALOT_ENABLED': (int, 'Pushalot', 0),
'PUSHALOT_ON_PLAY': (int, 'Pushalot', 0),
'PUSHALOT_ON_STOP': (int, 'Pushalot', 0),
'PUSHALOT_ON_PAUSE': (int, 'Pushalot', 0),
'PUSHALOT_ON_RESUME': (int, 'Pushalot', 0),
'PUSHALOT_ON_BUFFER': (int, 'Pushalot', 0),
'PUSHALOT_ON_WATCHED': (int, 'Pushalot', 0),
'PUSHBULLET_APIKEY': (str, 'PushBullet', ''),
'PUSHBULLET_DEVICEID': (str, 'PushBullet', ''),
@ -138,6 +170,9 @@ _CONFIG_DEFINITIONS = {
'PUSHBULLET_ENABLED': (int, 'PushBullet', 0),
'PUSHBULLET_ON_PLAY': (int, 'PushBullet', 0),
'PUSHBULLET_ON_STOP': (int, 'PushBullet', 0),
'PUSHBULLET_ON_PAUSE': (int, 'PushBullet', 0),
'PUSHBULLET_ON_RESUME': (int, 'PushBullet', 0),
'PUSHBULLET_ON_BUFFER': (int, 'PushBullet', 0),
'PUSHBULLET_ON_WATCHED': (int, 'PushBullet', 0),
'PUSHOVER_APITOKEN': (str, 'Pushover', ''),
'PUSHOVER_ENABLED': (int, 'Pushover', 0),
@ -145,6 +180,9 @@ _CONFIG_DEFINITIONS = {
'PUSHOVER_PRIORITY': (int, 'Pushover', 0),
'PUSHOVER_ON_PLAY': (int, 'Pushover', 0),
'PUSHOVER_ON_STOP': (int, 'Pushover', 0),
'PUSHOVER_ON_PAUSE': (int, 'Pushover', 0),
'PUSHOVER_ON_RESUME': (int, 'Pushover', 0),
'PUSHOVER_ON_BUFFER': (int, 'Pushover', 0),
'PUSHOVER_ON_WATCHED': (int, 'Pushover', 0),
'REFRESH_USERS_INTERVAL': (int, 'Monitoring', 12),
'REFRESH_USERS_ON_STARTUP': (int, 'Monitoring', 1),
@ -165,6 +203,9 @@ _CONFIG_DEFINITIONS = {
'XBMC_USERNAME': (str, 'XBMC', ''),
'XBMC_ON_PLAY': (int, 'XBMC', 0),
'XBMC_ON_STOP': (int, 'XBMC', 0),
'XBMC_ON_PAUSE': (int, 'XBMC', 0),
'XBMC_ON_RESUME': (int, 'XBMC', 0),
'XBMC_ON_BUFFER': (int, 'XBMC', 0),
'XBMC_ON_WATCHED': (int, 'XBMC', 0)
}
# pylint:disable=R0902

View file

@ -59,6 +59,11 @@ def check_active_sessions():
# Push it on it's own thread so we don't hold up our db actions
threading.Thread(target=notification_handler.notify,
kwargs=dict(stream_data=stream, notify_action='pause')).start()
if session['state'] == 'playing' and stream['state'] == 'paused':
# Push any notifications -
# Push it on it's own thread so we don't hold up our db actions
threading.Thread(target=notification_handler.notify,
kwargs=dict(stream_data=stream, notify_action='resume')).start()
if stream['state'] == 'paused':
# The stream is still paused so we need to increment the paused_counter
# Using the set config parameter as the interval, probably not the most accurate but
@ -67,6 +72,47 @@ def check_active_sessions():
monitor_db.action('UPDATE sessions SET paused_counter = ? '
'WHERE session_key = ? AND rating_key = ?',
[paused_counter, stream['session_key'], stream['rating_key']])
if session['state'] == 'buffering':
# The stream is buffering so we need to increment the buffer_count
# We're going just increment on every monitor ping,
# would be difficult to keep track otherwise
monitor_db.action('UPDATE sessions SET buffer_count = buffer_count + 1 '
'WHERE session_key = ? AND rating_key = ?',
[stream['session_key'], stream['rating_key']])
# Check the current buffer count and last buffer to determine if we should notify
buffer_values = monitor_db.select('SELECT buffer_count, buffer_last_triggered '
'FROM sessions '
'WHERE session_key = ? AND rating_key = ?',
[stream['session_key'], stream['rating_key']])
if buffer_values[0]['buffer_count'] >= plexpy.CONFIG.BUFFER_THRESHOLD:
# Push any notifications -
# Push it on it's own thread so we don't hold up our db actions
# Our first buffer notification
if buffer_values[0]['buffer_count'] == plexpy.CONFIG.BUFFER_THRESHOLD:
logger.info(u"PlexPy Monitor :: User '%s' has triggered a buffer warning."
% stream['user'])
# Set the buffer trigger time
monitor_db.action('UPDATE sessions '
'SET buffer_last_triggered = strftime("%s","now") '
'WHERE session_key = ? AND rating_key = ?',
[stream['session_key'], stream['rating_key']])
threading.Thread(target=notification_handler.notify,
kwargs=dict(stream_data=stream, notify_action='buffer')).start()
else:
# Subsequent buffer notifications after wait time
if int(time.time()) > buffer_values[0]['buffer_last_triggered'] + \
plexpy.CONFIG.BUFFER_WAIT:
logger.info(u"PlexPy Monitor :: User '%s' has triggered multiple buffer warnings."
% stream['user'])
threading.Thread(target=notification_handler.notify,
kwargs=dict(stream_data=stream, notify_action='buffer')).start()
logger.debug(u"PlexPy Monitor :: Stream buffering. Count is now %s. Last triggered %s."
% (buffer_values[0][0], buffer_values[0][1]))
# Check if the user has reached the offset in the media we defined as the "watched" percent
# Don't trigger if state is buffer as some clients push the progress to the end when
# buffering on start.

View file

@ -52,6 +52,33 @@ def notify(stream_data=None, notify_action=None):
set_notify_state(session=stream_data, state='stop', agent_info=agent)
elif agent['on_pause'] and notify_action == 'pause':
# Build and send notification
notify_strings = build_notify_text(session=stream_data, state=notify_action)
notifiers.send_notification(config_id=agent['id'],
subject=notify_strings[0],
body=notify_strings[1])
set_notify_state(session=stream_data, state='pause', agent_info=agent)
elif agent['on_resume'] and notify_action == 'resume':
# Build and send notification
notify_strings = build_notify_text(session=stream_data, state=notify_action)
notifiers.send_notification(config_id=agent['id'],
subject=notify_strings[0],
body=notify_strings[1])
set_notify_state(session=stream_data, state='resume', agent_info=agent)
elif agent['on_buffer'] and notify_action == 'buffer':
# Build and send notification
notify_strings = build_notify_text(session=stream_data, state=notify_action)
notifiers.send_notification(config_id=agent['id'],
subject=notify_strings[0],
body=notify_strings[1])
set_notify_state(session=stream_data, state='buffer', agent_info=agent)
elif agent['on_watched'] and notify_action == 'watched':
# Get the current states for notifications from our db
notify_states = get_notify_state(session=stream_data)
@ -100,6 +127,33 @@ def notify(stream_data=None, notify_action=None):
# Set the notification state in the db
set_notify_state(session=stream_data, state='stop', agent_info=agent)
elif agent['on_pause'] and notify_action == 'pause':
# Build and send notification
notify_strings = build_notify_text(session=stream_data, state=notify_action)
notifiers.send_notification(config_id=agent['id'],
subject=notify_strings[0],
body=notify_strings[1])
# Set the notification state in the db
set_notify_state(session=stream_data, state='pause', agent_info=agent)
elif agent['on_resume'] and notify_action == 'resume':
# Build and send notification
notify_strings = build_notify_text(session=stream_data, state=notify_action)
notifiers.send_notification(config_id=agent['id'],
subject=notify_strings[0],
body=notify_strings[1])
# Set the notification state in the db
set_notify_state(session=stream_data, state='resume', agent_info=agent)
elif agent['on_buffer'] and notify_action == 'buffer':
# Build and send notification
notify_strings = build_notify_text(session=stream_data, state=notify_action)
notifiers.send_notification(config_id=agent['id'],
subject=notify_strings[0],
body=notify_strings[1])
# Set the notification state in the db
set_notify_state(session=stream_data, state='buffer', agent_info=agent)
elif stream_data['media_type'] == 'clip':
pass
else:
@ -110,7 +164,7 @@ def notify(stream_data=None, notify_action=None):
def get_notify_state(session):
monitor_db = database.MonitorDatabase()
result = monitor_db.select('SELECT on_play, on_stop, on_watched, agent_id '
result = monitor_db.select('SELECT on_play, on_stop, on_pause, on_resume, on_buffer, on_watched, agent_id '
'FROM notify_log '
'WHERE session_key = ? '
'AND rating_key = ? '
@ -121,8 +175,11 @@ def get_notify_state(session):
for item in result:
notify_state = {'on_play': item[0],
'on_stop': item[1],
'on_watched': item[2],
'agent_id': item[3]}
'on_pause': item[2],
'on_resume': item[3],
'on_buffer': item[4],
'on_watched': item[5],
'agent_id': item[6]}
notify_states.append(notify_state)
return notify_states
@ -136,6 +193,12 @@ def set_notify_state(session, state, agent_info):
values = {'on_play': int(time.time())}
elif state == 'stop':
values = {'on_stop': int(time.time())}
elif state == 'pause':
values = {'on_pause': int(time.time())}
elif state == 'resume':
values = {'on_resume': int(time.time())}
elif state == 'buffer':
values = {'on_buffer': int(time.time())}
elif state == 'watched':
values = {'on_watched': int(time.time())}
else:
@ -173,34 +236,28 @@ def build_notify_text(session, state):
if session['media_type'] == 'episode':
# Regex pattern to remove the text in the tags we don't want
pattern = re.compile('<movie>[^>]+.</movie>|<music>[^>]+.</music>', re.IGNORECASE)
# Remove the unwanted tags and strip any unmatch tags too.
on_start_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT))
on_start_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT))
on_stop_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT))
on_stop_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT))
on_watched_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT))
on_watched_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT))
elif session['media_type'] == 'movie':
# Regex pattern to remove the text in the tags we don't want
pattern = re.compile('<tv>[^>]+.</tv>|<music>[^>]+.</music>', re.IGNORECASE)
# Remove the unwanted tags and strip any unmatch tags too.
on_start_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT))
on_start_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT))
on_stop_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT))
on_stop_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT))
on_watched_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT))
on_watched_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT))
elif session['media_type'] == 'track':
# Regex pattern to remove the text in the tags we don't want
pattern = re.compile('<tv>[^>]+.</tv>|<movie>[^>]+.</movie>', re.IGNORECASE)
else:
pattern = None
if session['media_type'] == 'episode' or session['media_type'] == 'movie' or session['media_type'] == 'track' \
and pattern:
# Remove the unwanted tags and strip any unmatch tags too.
on_start_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT))
on_start_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT))
on_stop_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT))
on_stop_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT))
on_pause_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT))
on_pause_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT))
on_resume_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT))
on_resume_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT))
on_buffer_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT))
on_buffer_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT))
on_watched_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT))
on_watched_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT))
else:
@ -208,6 +265,12 @@ def build_notify_text(session, state):
on_start_body = plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT
on_stop_subject = plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT
on_stop_body = plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT
on_pause_subject = plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT
on_pause_body = plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT
on_resume_subject = plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT
on_resume_body = plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT
on_buffer_subject = plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT
on_buffer_body = plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT
on_watched_subject = plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT
on_watched_body = plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT
@ -310,6 +373,78 @@ def build_notify_text(session, state):
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text]
else:
return [subject_text, body_text]
elif state == 'pause':
# Default body text
body_text = '%s (%s) has paused %s' % (session['friendly_name'],
session['player'],
full_title)
if on_pause_subject and on_pause_body:
try:
subject_text = on_pause_subject.format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = on_pause_body.format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text]
else:
return [subject_text, body_text]
elif state == 'resume':
# Default body text
body_text = '%s (%s) has resumed %s' % (session['friendly_name'],
session['player'],
full_title)
if on_resume_subject and on_resume_body:
try:
subject_text = on_resume_subject.format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = on_resume_body.format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text]
else:
return [subject_text, body_text]
elif state == 'buffer':
# Default body text
body_text = '%s (%s) is buffering %s' % (session['friendly_name'],
session['player'],
full_title)
if on_buffer_subject and on_buffer_body:
try:
subject_text = on_buffer_subject.format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = on_buffer_body.format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text]
else:
return [subject_text, body_text]

View file

@ -59,6 +59,9 @@ def available_notification_agents():
'state': checked(plexpy.CONFIG.GROWL_ENABLED),
'on_play': plexpy.CONFIG.GROWL_ON_PLAY,
'on_stop': plexpy.CONFIG.GROWL_ON_STOP,
'on_pause': plexpy.CONFIG.GROWL_ON_PAUSE,
'on_resume': plexpy.CONFIG.GROWL_ON_RESUME,
'on_buffer': plexpy.CONFIG.GROWL_ON_BUFFER,
'on_watched': plexpy.CONFIG.GROWL_ON_WATCHED
},
{'name': 'Prowl',
@ -68,6 +71,9 @@ def available_notification_agents():
'state': checked(plexpy.CONFIG.PROWL_ENABLED),
'on_play': plexpy.CONFIG.PROWL_ON_PLAY,
'on_stop': plexpy.CONFIG.PROWL_ON_STOP,
'on_pause': plexpy.CONFIG.PROWL_ON_PAUSE,
'on_resume': plexpy.CONFIG.PROWL_ON_RESUME,
'on_buffer': plexpy.CONFIG.PROWL_ON_BUFFER,
'on_watched': plexpy.CONFIG.PROWL_ON_WATCHED
},
{'name': 'XBMC',
@ -77,6 +83,9 @@ def available_notification_agents():
'state': checked(plexpy.CONFIG.XBMC_ENABLED),
'on_play': plexpy.CONFIG.XBMC_ON_PLAY,
'on_stop': plexpy.CONFIG.XBMC_ON_STOP,
'on_pause': plexpy.CONFIG.XBMC_ON_PAUSE,
'on_resume': plexpy.CONFIG.XBMC_ON_RESUME,
'on_buffer': plexpy.CONFIG.XBMC_ON_BUFFER,
'on_watched': plexpy.CONFIG.XBMC_ON_WATCHED
},
{'name': 'Plex',
@ -86,6 +95,9 @@ def available_notification_agents():
'state': checked(plexpy.CONFIG.PLEX_ENABLED),
'on_play': plexpy.CONFIG.PLEX_ON_PLAY,
'on_stop': plexpy.CONFIG.PLEX_ON_STOP,
'on_pause': plexpy.CONFIG.PLEX_ON_PAUSE,
'on_resume': plexpy.CONFIG.PLEX_ON_RESUME,
'on_buffer': plexpy.CONFIG.PLEX_ON_BUFFER,
'on_watched': plexpy.CONFIG.PLEX_ON_WATCHED
},
{'name': 'NotifyMyAndroid',
@ -95,6 +107,9 @@ def available_notification_agents():
'state': checked(plexpy.CONFIG.NMA_ENABLED),
'on_play': plexpy.CONFIG.NMA_ON_PLAY,
'on_stop': plexpy.CONFIG.NMA_ON_STOP,
'on_pause': plexpy.CONFIG.NMA_ON_PAUSE,
'on_resume': plexpy.CONFIG.NMA_ON_RESUME,
'on_buffer': plexpy.CONFIG.NMA_ON_BUFFER,
'on_watched': plexpy.CONFIG.NMA_ON_WATCHED
},
{'name': 'Pushalot',
@ -104,6 +119,9 @@ def available_notification_agents():
'state': checked(plexpy.CONFIG.PUSHALOT_ENABLED),
'on_play': plexpy.CONFIG.PUSHALOT_ON_PLAY,
'on_stop': plexpy.CONFIG.PUSHALOT_ON_STOP,
'on_pause': plexpy.CONFIG.PUSHALOT_ON_PAUSE,
'on_resume': plexpy.CONFIG.PUSHALOT_ON_RESUME,
'on_buffer': plexpy.CONFIG.PUSHALOT_ON_BUFFER,
'on_watched': plexpy.CONFIG.PUSHALOT_ON_WATCHED
},
{'name': 'Pushbullet',
@ -113,6 +131,9 @@ def available_notification_agents():
'state': checked(plexpy.CONFIG.PUSHBULLET_ENABLED),
'on_play': plexpy.CONFIG.PUSHBULLET_ON_PLAY,
'on_stop': plexpy.CONFIG.PUSHBULLET_ON_STOP,
'on_pause': plexpy.CONFIG.PUSHBULLET_ON_PAUSE,
'on_resume': plexpy.CONFIG.PUSHBULLET_ON_RESUME,
'on_buffer': plexpy.CONFIG.PUSHBULLET_ON_BUFFER,
'on_watched': plexpy.CONFIG.PUSHBULLET_ON_WATCHED
},
{'name': 'Pushover',
@ -122,6 +143,9 @@ def available_notification_agents():
'state': checked(plexpy.CONFIG.PUSHOVER_ENABLED),
'on_play': plexpy.CONFIG.PUSHOVER_ON_PLAY,
'on_stop': plexpy.CONFIG.PUSHOVER_ON_STOP,
'on_pause': plexpy.CONFIG.PUSHOVER_ON_PAUSE,
'on_resume': plexpy.CONFIG.PUSHOVER_ON_RESUME,
'on_buffer': plexpy.CONFIG.PUSHOVER_ON_BUFFER,
'on_watched': plexpy.CONFIG.PUSHOVER_ON_WATCHED
},
{'name': 'Boxcar2',
@ -131,6 +155,9 @@ def available_notification_agents():
'state': checked(plexpy.CONFIG.BOXCAR_ENABLED),
'on_play': plexpy.CONFIG.BOXCAR_ON_PLAY,
'on_stop': plexpy.CONFIG.BOXCAR_ON_STOP,
'on_pause': plexpy.CONFIG.BOXCAR_ON_PAUSE,
'on_resume': plexpy.CONFIG.BOXCAR_ON_RESUME,
'on_buffer': plexpy.CONFIG.BOXCAR_ON_BUFFER,
'on_watched': plexpy.CONFIG.BOXCAR_ON_WATCHED
},
{'name': 'E-mail',
@ -140,6 +167,9 @@ def available_notification_agents():
'state': checked(plexpy.CONFIG.EMAIL_ENABLED),
'on_play': plexpy.CONFIG.EMAIL_ON_PLAY,
'on_stop': plexpy.CONFIG.EMAIL_ON_STOP,
'on_pause': plexpy.CONFIG.EMAIL_ON_PAUSE,
'on_resume': plexpy.CONFIG.EMAIL_ON_RESUME,
'on_buffer': plexpy.CONFIG.EMAIL_ON_BUFFER,
'on_watched': plexpy.CONFIG.EMAIL_ON_WATCHED
}
]
@ -154,6 +184,9 @@ def available_notification_agents():
'state': checked(plexpy.CONFIG.OSX_NOTIFY_ENABLED),
'on_play': plexpy.CONFIG.OSX_NOTIFY_ON_PLAY,
'on_stop': plexpy.CONFIG.OSX_NOTIFY_ON_STOP,
'on_pause': plexpy.CONFIG.OSX_NOTIFY_ON_PAUSE,
'on_resume': plexpy.CONFIG.OSX_NOTIFY_ON_RESUME,
'on_buffer': plexpy.CONFIG.OSX_NOTIFY_ON_BUFFER,
'on_watched': plexpy.CONFIG.OSX_NOTIFY_ON_WATCHED
})

View file

@ -436,9 +436,17 @@ class WebInterface(object):
"notify_on_start_body_text": plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT,
"notify_on_stop_subject_text": plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT,
"notify_on_stop_body_text": plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT,
"notify_on_pause_subject_text": plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT,
"notify_on_pause_body_text": plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT,
"notify_on_resume_subject_text": plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT,
"notify_on_resume_body_text": plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT,
"notify_on_buffer_subject_text": plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT,
"notify_on_buffer_body_text": plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT,
"notify_on_watched_subject_text": plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT,
"notify_on_watched_body_text": plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT,
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
"buffer_threshold": plexpy.CONFIG.BUFFER_THRESHOLD,
"buffer_wait": plexpy.CONFIG.BUFFER_WAIT
}
return serve_template(templatename="settings.html", title="Settings", config=config)
@ -1226,3 +1234,19 @@ class WebInterface(object):
return serve_template(templatename="notification_config.html", title="Notification Configuration",
data=config, checkboxes=checkboxes)
@cherrypy.expose
def get_notification_agent_triggers(self, config_id, **kwargs):
if config_id.isdigit():
agents = notifiers.available_notification_agents()
for agent in agents:
if int(config_id) == agent['id']:
this_agent = agent
break
else:
this_agent = None
else:
return None
return serve_template(templatename="notification_triggers_modal.html", title="Notification Triggers",
data=this_agent)