mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-14 09:12:58 -07:00
commit
e321479712
6 changed files with 595 additions and 130 deletions
|
@ -48,7 +48,7 @@ from plexpy import helpers
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="${item['name']}">${item['label']}</label>
|
<label for="${item['name']}">${item['label']}</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-5">
|
<div class="col-md-8">
|
||||||
<select class="form-control" id="${item['name']}" name="${item['name']}" >
|
<select class="form-control" id="${item['name']}" name="${item['name']}" >
|
||||||
% for key, value in sorted(item['select_options'].iteritems()):
|
% for key, value in sorted(item['select_options'].iteritems()):
|
||||||
% if key == item['value']:
|
% if key == item['value']:
|
||||||
|
@ -79,6 +79,41 @@ from plexpy import helpers
|
||||||
<input class="form-control" type="text" id="test_body" name="test_body" value="Test notification">
|
<input class="form-control" type="text" id="test_body" name="test_body" value="Test notification">
|
||||||
<p class="help-block">Set a custom body.</p>
|
<p class="help-block">Set a custom body.</p>
|
||||||
</div>
|
</div>
|
||||||
|
%if agent['name'] == 'Scripts':
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="test_script">Script path</label>
|
||||||
|
<select class="form-control" id="test_script" name="test_script" >
|
||||||
|
% for key, value in sorted(data[1]['select_options'].iteritems()):
|
||||||
|
<option value="${key}">${value}</option>
|
||||||
|
% endfor
|
||||||
|
</select>
|
||||||
|
<p class="help-block">Pick your script</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="test_script_action">Script action</label>
|
||||||
|
<select class="form-control" id="test_script_action" name="test_script_action">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="buffer">Buffer warning</option>
|
||||||
|
<option value="watched">Watched</option>
|
||||||
|
<option value="play">Playback start</option>
|
||||||
|
<option value="pause">Playback stopp</option>
|
||||||
|
<option value="resume">Playback resume</option>
|
||||||
|
<option value="stop">Playback stop</option>
|
||||||
|
<option value="extdown">Plex Server Remote Down</option>
|
||||||
|
<option value="extup">Plex Server Remote Up</option>
|
||||||
|
<option value="intdown">Plex Server Down</option>
|
||||||
|
<option value="intup">Plex Server Up</option>
|
||||||
|
<option value="created">Recently added</option>
|
||||||
|
</select>
|
||||||
|
<p class="help-block">Pick your action</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="test_script_args">Script args</label>
|
||||||
|
<input class="form-control" type="text" id="test_script_args" name="test_script_args" value="">
|
||||||
|
<p class="help-block">Set a custom script args: -zomg --x.</p>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
|
@ -148,7 +183,10 @@ from plexpy import helpers
|
||||||
url: 'test_notifier',
|
url: 'test_notifier',
|
||||||
data: { config_id: '${agent["id"]}',
|
data: { config_id: '${agent["id"]}',
|
||||||
subject: $('#test_subject').val(),
|
subject: $('#test_subject').val(),
|
||||||
body: $('#test_body').val() },
|
body: $('#test_body').val(),
|
||||||
|
notify_action: $('#test_script_action').val(),
|
||||||
|
script: $('#test_script').val(),
|
||||||
|
script_args: $('#test_script_args').val() },
|
||||||
cache: false,
|
cache: false,
|
||||||
async: true,
|
async: true,
|
||||||
complete: function (xhr, status) {
|
complete: function (xhr, status) {
|
||||||
|
@ -164,6 +202,12 @@ from plexpy import helpers
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#scripts_folder').on('change', function () {
|
||||||
|
doAjaxCall('set_notification_config', $(this), 'tabs', true);
|
||||||
|
reloadModal();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
// Never send checkbox values directly, always substitute value in hidden input.
|
// Never send checkbox values directly, always substitute value in hidden input.
|
||||||
$('.checkboxes').click(function () {
|
$('.checkboxes').click(function () {
|
||||||
var configToggle = $(this).data('id');
|
var configToggle = $(this).data('id');
|
||||||
|
|
|
@ -751,7 +751,22 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<ul id="accordion-scripts" class="accordion list-unstyled">
|
||||||
|
<li>
|
||||||
|
<div class="link"><i class="glyphicon glyphicon-console"></i> Script <i class="fa fa-chevron-down"></i></div>
|
||||||
|
<ul class="submenu">
|
||||||
|
<li>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="notify_scripts_args_text">Script arguments</label>
|
||||||
|
<input class="form-control" type="text" id="notify_scripts_args_text" name="notify_scripts_args_text" value="${config['notify_scripts_args_text']}" data-parsley-trigger="change">
|
||||||
|
<p class="help-block">Set arguments passed to the script</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
|
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
|
||||||
</div>
|
</div>
|
||||||
<div role="tabpanel" class="tab-pane" id="tabs-10">
|
<div role="tabpanel" class="tab-pane" id="tabs-10">
|
||||||
|
@ -1111,6 +1126,14 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
|
||||||
<td><strong>{transcode_audio_channels}</strong></td>
|
<td><strong>{transcode_audio_channels}</strong></td>
|
||||||
<td>The audio channels of the transcoded media.</td>
|
<td>The audio channels of the transcoded media.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{streams}</strong></td>
|
||||||
|
<td>The number of concurrent streams.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{action}</strong></td>
|
||||||
|
<td>The action that trigged the notification.</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<table class="notification-params">
|
<table class="notification-params">
|
||||||
|
@ -1575,6 +1598,7 @@ $(document).ready(function() {
|
||||||
|
|
||||||
var accordion_session = new Accordion($('#accordion-session'), false);
|
var accordion_session = new Accordion($('#accordion-session'), false);
|
||||||
var accordion_timeline = new Accordion($('#accordion-timeline'), false);
|
var accordion_timeline = new Accordion($('#accordion-timeline'), false);
|
||||||
|
var accordion_scripts = new Accordion($('#accordion-scripts'), false);
|
||||||
|
|
||||||
var cards = "${config['home_stats_cards']}".split(/[\s,]+/);
|
var cards = "${config['home_stats_cards']}".split(/[\s,]+/);
|
||||||
cards.forEach(function (item) {
|
cards.forEach(function (item) {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import plexpy.logger
|
import plexpy.logger
|
||||||
import itertools
|
|
||||||
import os
|
|
||||||
import re
|
import re
|
||||||
from configobj import ConfigObj
|
from configobj import ConfigObj
|
||||||
|
|
||||||
|
@ -14,8 +12,6 @@ def bool_int(value):
|
||||||
value = 0
|
value = 0
|
||||||
return int(bool(value))
|
return int(bool(value))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_CONFIG_DEFINITIONS = {
|
_CONFIG_DEFINITIONS = {
|
||||||
'DATE_FORMAT': (str, 'General', 'YYYY-MM-DD'),
|
'DATE_FORMAT': (str, 'General', 'YYYY-MM-DD'),
|
||||||
'GROUPING_GLOBAL_HISTORY': (int, 'PlexWatch', 0),
|
'GROUPING_GLOBAL_HISTORY': (int, 'PlexWatch', 0),
|
||||||
|
@ -194,6 +190,7 @@ _CONFIG_DEFINITIONS = {
|
||||||
'NOTIFY_ON_EXTUP_BODY_TEXT': (unicode, 'Monitoring', 'The Plex Media Server remote access is back up.'),
|
'NOTIFY_ON_EXTUP_BODY_TEXT': (unicode, 'Monitoring', 'The Plex Media Server remote access is back up.'),
|
||||||
'NOTIFY_ON_INTUP_SUBJECT_TEXT': (unicode, 'Monitoring', 'PlexPy ({server_name})'),
|
'NOTIFY_ON_INTUP_SUBJECT_TEXT': (unicode, 'Monitoring', 'PlexPy ({server_name})'),
|
||||||
'NOTIFY_ON_INTUP_BODY_TEXT': (unicode, 'Monitoring', 'The Plex Media Server is back up.'),
|
'NOTIFY_ON_INTUP_BODY_TEXT': (unicode, 'Monitoring', 'The Plex Media Server is back up.'),
|
||||||
|
'NOTIFY_SCRIPTS_ARGS_TEXT': (unicode, 'Monitoring', ''),
|
||||||
'OSX_NOTIFY_APP': (str, 'OSX_Notify', '/Applications/PlexPy'),
|
'OSX_NOTIFY_APP': (str, 'OSX_Notify', '/Applications/PlexPy'),
|
||||||
'OSX_NOTIFY_ENABLED': (int, 'OSX_Notify', 0),
|
'OSX_NOTIFY_ENABLED': (int, 'OSX_Notify', 0),
|
||||||
'OSX_NOTIFY_ON_PLAY': (int, 'OSX_Notify', 0),
|
'OSX_NOTIFY_ON_PLAY': (int, 'OSX_Notify', 0),
|
||||||
|
@ -298,6 +295,30 @@ _CONFIG_DEFINITIONS = {
|
||||||
'SLACK_ON_INTDOWN': (int, 'Slack', 0),
|
'SLACK_ON_INTDOWN': (int, 'Slack', 0),
|
||||||
'SLACK_ON_EXTUP': (int, 'Slack', 0),
|
'SLACK_ON_EXTUP': (int, 'Slack', 0),
|
||||||
'SLACK_ON_INTUP': (int, 'Slack', 0),
|
'SLACK_ON_INTUP': (int, 'Slack', 0),
|
||||||
|
'SCRIPTS_ENABLED': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_FOLDER': (unicode, 'Scripts', ''),
|
||||||
|
'SCRIPTS_ON_PLAY': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_ON_STOP': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_ON_PAUSE': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_ON_RESUME': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_ON_BUFFER': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_ON_WATCHED': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_ON_CREATED': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_ON_EXTDOWN': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_ON_EXTUP': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_ON_INTDOWN': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_ON_INTUP': (int, 'Scripts', 0),
|
||||||
|
'SCRIPTS_ON_PLAY_SCRIPT': (unicode, 'Scripts', ''),
|
||||||
|
'SCRIPTS_ON_STOP_SCRIPT': (unicode, 'Scripts', ''),
|
||||||
|
'SCRIPTS_ON_PAUSE_SCRIPT': (unicode, 'Scripts', ''),
|
||||||
|
'SCRIPTS_ON_RESUME_SCRIPT': (unicode, 'Scripts', ''),
|
||||||
|
'SCRIPTS_ON_BUFFER_SCRIPT': (unicode, 'Scripts', ''),
|
||||||
|
'SCRIPTS_ON_WATCHED_SCRIPT': (unicode, 'Scripts', ''),
|
||||||
|
'SCRIPTS_ON_CREATED_SCRIPT': (unicode, 'Scripts', ''),
|
||||||
|
'SCRIPTS_ON_EXTDOWN_SCRIPT': (unicode, 'Scripts', ''),
|
||||||
|
'SCRIPTS_ON_EXTUP_SCRIPT': (unicode, 'Scripts', ''),
|
||||||
|
'SCRIPTS_ON_INTDOWN_SCRIPT': (unicode, 'Scripts', ''),
|
||||||
|
'SCRIPTS_ON_INTUP_SCRIPT': (unicode, 'Scripts', ''),
|
||||||
'TELEGRAM_BOT_TOKEN': (str, 'Telegram', ''),
|
'TELEGRAM_BOT_TOKEN': (str, 'Telegram', ''),
|
||||||
'TELEGRAM_ENABLED': (int, 'Telegram', 0),
|
'TELEGRAM_ENABLED': (int, 'Telegram', 0),
|
||||||
'TELEGRAM_CHAT_ID': (str, 'Telegram', ''),
|
'TELEGRAM_CHAT_ID': (str, 'Telegram', ''),
|
||||||
|
@ -351,6 +372,8 @@ _CONFIG_DEFINITIONS = {
|
||||||
'XBMC_ON_EXTUP': (int, 'XBMC', 0),
|
'XBMC_ON_EXTUP': (int, 'XBMC', 0),
|
||||||
'XBMC_ON_INTUP': (int, 'XBMC', 0)
|
'XBMC_ON_INTUP': (int, 'XBMC', 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# pylint:disable=R0902
|
# pylint:disable=R0902
|
||||||
# it might be nice to refactor for fewer instance variables
|
# it might be nice to refactor for fewer instance variables
|
||||||
class Config(object):
|
class Config(object):
|
||||||
|
|
|
@ -13,11 +13,13 @@
|
||||||
# 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, config, notifiers, database, helpers, plextv, pmsconnect
|
|
||||||
|
|
||||||
import plexpy
|
import re
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from plexpy import logger, config, notifiers, database, helpers, plextv, pmsconnect
|
||||||
|
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
|
||||||
|
@ -41,7 +43,10 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
# Set the notification state in the db
|
# Set the notification state in the db
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -51,7 +56,9 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -61,7 +68,9 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -71,7 +80,9 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -80,7 +91,9 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -94,7 +107,10 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
# Set the notification state in the db
|
# Set the notification state in the db
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -106,7 +122,10 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
# Set the notification state in the db
|
# Set the notification state in the db
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -118,7 +137,10 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
# Set the notification state in the db
|
# Set the notification state in the db
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -127,7 +149,10 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
# Set the notification state in the db
|
# Set the notification state in the db
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -136,7 +161,10 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
# Set the notification state in the db
|
# Set the notification state in the db
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -145,7 +173,10 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
# Set the notification state in the db
|
# Set the notification state in the db
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -154,7 +185,10 @@ def notify(stream_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
notify_strings = build_notify_text(session=stream_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
|
|
||||||
# Set the notification state in the db
|
# Set the notification state in the db
|
||||||
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=stream_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -181,7 +215,9 @@ def notify_timeline(timeline_data=None, notify_action=None):
|
||||||
notify_strings = build_notify_text(timeline=timeline_data, state=notify_action)
|
notify_strings = build_notify_text(timeline=timeline_data, state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
# Set the notification state in the db
|
# Set the notification state in the db
|
||||||
set_notify_state(session=timeline_data, state=notify_action, agent_info=agent)
|
set_notify_state(session=timeline_data, state=notify_action, agent_info=agent)
|
||||||
|
|
||||||
|
@ -192,25 +228,33 @@ def notify_timeline(timeline_data=None, notify_action=None):
|
||||||
notify_strings = build_server_notify_text(state=notify_action)
|
notify_strings = build_server_notify_text(state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
if agent['on_intdown'] and notify_action == 'intdown':
|
if agent['on_intdown'] and notify_action == 'intdown':
|
||||||
# Build and send notification
|
# Build and send notification
|
||||||
notify_strings = build_server_notify_text(state=notify_action)
|
notify_strings = build_server_notify_text(state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
if agent['on_extup'] and notify_action == 'extup':
|
if agent['on_extup'] and notify_action == 'extup':
|
||||||
# Build and send notification
|
# Build and send notification
|
||||||
notify_strings = build_server_notify_text(state=notify_action)
|
notify_strings = build_server_notify_text(state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
if agent['on_intup'] and notify_action == 'intup':
|
if agent['on_intup'] and notify_action == 'intup':
|
||||||
# Build and send notification
|
# Build and send notification
|
||||||
notify_strings = build_server_notify_text(state=notify_action)
|
notify_strings = build_server_notify_text(state=notify_action)
|
||||||
notifiers.send_notification(config_id=agent['id'],
|
notifiers.send_notification(config_id=agent['id'],
|
||||||
subject=notify_strings[0],
|
subject=notify_strings[0],
|
||||||
body=notify_strings[1])
|
body=notify_strings[1],
|
||||||
|
notify_action=notify_action,
|
||||||
|
script_args=notify_strings[2])
|
||||||
else:
|
else:
|
||||||
logger.debug(u"PlexPy Notifier :: Notify timeline called but incomplete data received.")
|
logger.debug(u"PlexPy Notifier :: Notify timeline called but incomplete data received.")
|
||||||
|
|
||||||
|
@ -237,6 +281,7 @@ def get_notify_state(session):
|
||||||
|
|
||||||
return notify_states
|
return notify_states
|
||||||
|
|
||||||
|
|
||||||
def get_notify_state_timeline(timeline):
|
def get_notify_state_timeline(timeline):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
result = monitor_db.select('SELECT on_created, agent_id '
|
result = monitor_db.select('SELECT on_created, agent_id '
|
||||||
|
@ -293,7 +338,6 @@ def set_notify_state(session, state, agent_info):
|
||||||
|
|
||||||
|
|
||||||
def build_notify_text(session=None, timeline=None, state=None):
|
def build_notify_text(session=None, timeline=None, state=None):
|
||||||
import re
|
|
||||||
|
|
||||||
# Get the server name
|
# Get the server name
|
||||||
server_name = plexpy.CONFIG.PMS_NAME
|
server_name = plexpy.CONFIG.PMS_NAME
|
||||||
|
@ -318,6 +362,8 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
metadata_list = pms_connect.get_metadata_details(rating_key=rating_key)
|
metadata_list = pms_connect.get_metadata_details(rating_key=rating_key)
|
||||||
|
|
||||||
|
stream_count = pms_connect.get_current_activity().get('stream_count', '')
|
||||||
|
|
||||||
if metadata_list:
|
if metadata_list:
|
||||||
metadata = metadata_list['metadata']
|
metadata = metadata_list['metadata']
|
||||||
else:
|
else:
|
||||||
|
@ -327,13 +373,13 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
# Check for exclusion tags
|
# Check for exclusion tags
|
||||||
if metadata['media_type'] == 'movie':
|
if metadata['media_type'] == 'movie':
|
||||||
# Regex pattern to remove the text in the tags we don't want
|
# Regex pattern to remove the text in the tags we don't want
|
||||||
pattern = re.compile('\n*<tv>[^>]+.</tv>\n*|\n*<music>[^>]+.</music>\n*', re.IGNORECASE|re.DOTALL)
|
pattern = re.compile('\n*<tv>[^>]+.</tv>\n*|\n*<music>[^>]+.</music>\n*', re.IGNORECASE | re.DOTALL)
|
||||||
elif metadata['media_type'] == 'show' or metadata['media_type'] == 'episode':
|
elif metadata['media_type'] == 'show' or metadata['media_type'] == 'episode':
|
||||||
# Regex pattern to remove the text in the tags we don't want
|
# Regex pattern to remove the text in the tags we don't want
|
||||||
pattern = re.compile('\n*<movie>[^>]+.</movie>\n*|\n*?<music>[^>]+.</music>\n*', re.IGNORECASE|re.DOTALL)
|
pattern = re.compile('\n*<movie>[^>]+.</movie>\n*|\n*?<music>[^>]+.</music>\n*', re.IGNORECASE | re.DOTALL)
|
||||||
elif metadata['media_type'] == 'artist' or metadata['media_type'] == 'track':
|
elif metadata['media_type'] == 'artist' or metadata['media_type'] == 'track':
|
||||||
# Regex pattern to remove the text in the tags we don't want
|
# Regex pattern to remove the text in the tags we don't want
|
||||||
pattern = re.compile('\n*<tv>[^>]+.</tv>\n*|\n*<movie>[^>]+.</movie>\n*', re.IGNORECASE|re.DOTALL)
|
pattern = re.compile('\n*<tv>[^>]+.</tv>\n*|\n*<movie>[^>]+.</movie>\n*', re.IGNORECASE | re.DOTALL)
|
||||||
else:
|
else:
|
||||||
pattern = None
|
pattern = None
|
||||||
|
|
||||||
|
@ -356,6 +402,7 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
on_watched_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT))
|
on_watched_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT))
|
||||||
on_created_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT))
|
on_created_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT))
|
||||||
on_created_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT))
|
on_created_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT))
|
||||||
|
script_args_text = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_SCRIPTS_ARGS_TEXT))
|
||||||
else:
|
else:
|
||||||
on_start_subject = plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT
|
on_start_subject = plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT
|
||||||
on_start_body = plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT
|
on_start_body = plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT
|
||||||
|
@ -371,6 +418,7 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
on_watched_body = plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT
|
on_watched_body = plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT
|
||||||
on_created_subject = plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT
|
on_created_subject = plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT
|
||||||
on_created_body = plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT
|
on_created_body = plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT
|
||||||
|
script_args_text = plexpy.CONFIG.NOTIFY_SCRIPTS_ARGS_TEXT
|
||||||
|
|
||||||
# Create a title
|
# Create a title
|
||||||
if metadata['media_type'] == 'episode' or metadata['media_type'] == 'track':
|
if metadata['media_type'] == 'episode' or metadata['media_type'] == 'track':
|
||||||
|
@ -516,12 +564,29 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
'summary': metadata['summary'],
|
'summary': metadata['summary'],
|
||||||
'tagline': metadata['tagline'],
|
'tagline': metadata['tagline'],
|
||||||
'rating': metadata['rating'],
|
'rating': metadata['rating'],
|
||||||
'duration': duration
|
'duration': duration,
|
||||||
|
'action': state,
|
||||||
|
'streams': stream_count
|
||||||
}
|
}
|
||||||
|
|
||||||
# Default subject text
|
# Default subject text
|
||||||
subject_text = 'PlexPy (%s)' % server_name
|
subject_text = 'PlexPy (%s)' % server_name
|
||||||
|
|
||||||
|
# Default scripts args
|
||||||
|
script_args = []
|
||||||
|
|
||||||
|
# Regex to match {param} but not "{param}"
|
||||||
|
params_to_quote = re.compile(r'(?<!\")([\{][^}]+[\}])(?!\"\})')
|
||||||
|
script_args_text = re.sub(params_to_quote, r'"\g<0>"', script_args_text)
|
||||||
|
|
||||||
|
if script_args_text:
|
||||||
|
try:
|
||||||
|
script_args = [unicode(arg).format(**available_params) for arg in script_args_text.split()]
|
||||||
|
except LookupError as e:
|
||||||
|
logger.error(u"PlexPy Notifier :: Unable to parse field %s in script argument. Using fallback." % e)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(u"PlexPy Notifier :: Unable to parse custom script arguments %s. Using fallback." % e)
|
||||||
|
|
||||||
if state == 'play':
|
if state == 'play':
|
||||||
# Default body text
|
# Default body text
|
||||||
body_text = '%s (%s) is watching %s' % (session['friendly_name'],
|
body_text = '%s (%s) is watching %s' % (session['friendly_name'],
|
||||||
|
@ -543,9 +608,9 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
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.")
|
||||||
|
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
elif state == 'stop':
|
elif state == 'stop':
|
||||||
# Default body text
|
# Default body text
|
||||||
body_text = '%s (%s) has stopped %s' % (session['friendly_name'],
|
body_text = '%s (%s) has stopped %s' % (session['friendly_name'],
|
||||||
|
@ -567,9 +632,9 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
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.")
|
||||||
|
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
elif state == 'pause':
|
elif state == 'pause':
|
||||||
# Default body text
|
# Default body text
|
||||||
body_text = '%s (%s) has paused %s' % (session['friendly_name'],
|
body_text = '%s (%s) has paused %s' % (session['friendly_name'],
|
||||||
|
@ -591,9 +656,9 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
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.")
|
||||||
|
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
elif state == 'resume':
|
elif state == 'resume':
|
||||||
# Default body text
|
# Default body text
|
||||||
body_text = '%s (%s) has resumed %s' % (session['friendly_name'],
|
body_text = '%s (%s) has resumed %s' % (session['friendly_name'],
|
||||||
|
@ -615,9 +680,9 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
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.")
|
||||||
|
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
elif state == 'buffer':
|
elif state == 'buffer':
|
||||||
# Default body text
|
# Default body text
|
||||||
body_text = '%s (%s) is buffering %s' % (session['friendly_name'],
|
body_text = '%s (%s) is buffering %s' % (session['friendly_name'],
|
||||||
|
@ -639,9 +704,9 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
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.")
|
||||||
|
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
elif state == 'watched':
|
elif state == 'watched':
|
||||||
# Default body text
|
# Default body text
|
||||||
body_text = '%s (%s) has watched %s' % (session['friendly_name'],
|
body_text = '%s (%s) has watched %s' % (session['friendly_name'],
|
||||||
|
@ -663,9 +728,9 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
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.")
|
||||||
|
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
elif state == 'created':
|
elif state == 'created':
|
||||||
# Default body text
|
# Default body text
|
||||||
body_text = '%s was recently added to Plex.' % full_title
|
body_text = '%s was recently added to Plex.' % full_title
|
||||||
|
@ -685,12 +750,13 @@ def build_notify_text(session=None, timeline=None, state=None):
|
||||||
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.")
|
||||||
|
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def build_server_notify_text(state=None):
|
def build_server_notify_text(state=None):
|
||||||
# Get the server name
|
# Get the server name
|
||||||
server_name = plexpy.CONFIG.PMS_NAME
|
server_name = plexpy.CONFIG.PMS_NAME
|
||||||
|
@ -716,11 +782,28 @@ def build_server_notify_text(state=None):
|
||||||
on_intup_body = plexpy.CONFIG.NOTIFY_ON_INTUP_BODY_TEXT
|
on_intup_body = plexpy.CONFIG.NOTIFY_ON_INTUP_BODY_TEXT
|
||||||
|
|
||||||
available_params = {'server_name': server_name,
|
available_params = {'server_name': server_name,
|
||||||
'server_uptime': server_uptime}
|
'server_uptime': server_uptime,
|
||||||
|
'action': state}
|
||||||
|
|
||||||
# Default text
|
# Default text
|
||||||
subject_text = 'PlexPy (%s)' % server_name
|
subject_text = 'PlexPy (%s)' % server_name
|
||||||
|
|
||||||
|
# Default scripts args
|
||||||
|
script_args = []
|
||||||
|
script_args_text = plexpy.CONFIG.NOTIFY_SCRIPTS_ARGS_TEXT
|
||||||
|
|
||||||
|
# Regex to match {param} but not "{param}"
|
||||||
|
params_to_quote = re.compile(r'(?<!\")([\{][^}]+[\}])(?!\"\})')
|
||||||
|
script_args_text = re.sub(params_to_quote, r'"\g<0>"', script_args_text)
|
||||||
|
|
||||||
|
if script_args_text:
|
||||||
|
try:
|
||||||
|
script_args = [unicode(arg).format(**available_params) for arg in script_args_text.split()]
|
||||||
|
except LookupError as e:
|
||||||
|
logger.error(u"PlexPy Notifier :: Unable to parse field %s in script argument. Using fallback." % e)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(u"PlexPy Notifier :: Unable to parse custom script arguments %s. Using fallback." % e)
|
||||||
|
|
||||||
if state == 'extdown':
|
if state == 'extdown':
|
||||||
# Default body text
|
# Default body text
|
||||||
body_text = 'The Plex Media Server remote access is down.'
|
body_text = 'The Plex Media Server remote access is down.'
|
||||||
|
@ -740,9 +823,10 @@ def build_server_notify_text(state=None):
|
||||||
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.")
|
||||||
|
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
|
|
||||||
elif state == 'intdown':
|
elif state == 'intdown':
|
||||||
# Default body text
|
# Default body text
|
||||||
body_text = 'The Plex Media Server is down.'
|
body_text = 'The Plex Media Server is down.'
|
||||||
|
@ -762,9 +846,9 @@ def build_server_notify_text(state=None):
|
||||||
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.")
|
||||||
|
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
if state == 'extup':
|
if state == 'extup':
|
||||||
# Default body text
|
# Default body text
|
||||||
body_text = 'The Plex Media Server remote access is back up.'
|
body_text = 'The Plex Media Server remote access is back up.'
|
||||||
|
@ -784,9 +868,9 @@ def build_server_notify_text(state=None):
|
||||||
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.")
|
||||||
|
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
elif state == 'intup':
|
elif state == 'intup':
|
||||||
# Default body text
|
# Default body text
|
||||||
body_text = 'The Plex Media Server is back up.'
|
body_text = 'The Plex Media Server is back up.'
|
||||||
|
@ -806,12 +890,14 @@ def build_server_notify_text(state=None):
|
||||||
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.")
|
||||||
|
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
else:
|
else:
|
||||||
return [subject_text, body_text]
|
return [subject_text, body_text, script_args]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def strip_tag(data):
|
def strip_tag(data):
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
|
@ -13,32 +13,31 @@
|
||||||
# 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, common, request
|
|
||||||
from plexpy.helpers import checked, radio
|
|
||||||
|
|
||||||
from xml.dom import minidom
|
|
||||||
from httplib import HTTPSConnection
|
|
||||||
from urlparse import parse_qsl
|
|
||||||
from urlparse import urlparse
|
from urlparse import urlparse
|
||||||
from urllib import urlencode
|
|
||||||
from pynma import pynma
|
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
import json
|
||||||
import cherrypy
|
import cherrypy
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
import email.utils
|
||||||
|
from httplib import HTTPSConnection
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
import smtplib
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from urllib import urlencode
|
||||||
import urllib
|
import urllib
|
||||||
import urllib2
|
import urllib2
|
||||||
import plexpy
|
from urlparse import parse_qsl
|
||||||
import os.path
|
|
||||||
import subprocess
|
|
||||||
import gntp.notifier
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
from pynma import pynma
|
||||||
|
import gntp.notifier
|
||||||
import oauth2 as oauth
|
import oauth2 as oauth
|
||||||
import pythontwitter as twitter
|
import pythontwitter as twitter
|
||||||
|
|
||||||
from email.mime.text import MIMEText
|
import plexpy
|
||||||
import smtplib
|
from plexpy import logger, helpers, request
|
||||||
import email.utils
|
from plexpy.helpers import checked
|
||||||
|
|
||||||
AGENT_IDS = {"Growl": 0,
|
AGENT_IDS = {"Growl": 0,
|
||||||
"Prowl": 1,
|
"Prowl": 1,
|
||||||
|
@ -54,7 +53,9 @@ AGENT_IDS = {"Growl": 0,
|
||||||
"Twitter": 11,
|
"Twitter": 11,
|
||||||
"IFTTT": 12,
|
"IFTTT": 12,
|
||||||
"Telegram": 13,
|
"Telegram": 13,
|
||||||
"Slack":14}
|
"Slack": 14,
|
||||||
|
"Scripts": 15}
|
||||||
|
|
||||||
|
|
||||||
def available_notification_agents():
|
def available_notification_agents():
|
||||||
agents = [{'name': 'Growl',
|
agents = [{'name': 'Growl',
|
||||||
|
@ -294,7 +295,25 @@ def available_notification_agents():
|
||||||
'on_intdown': plexpy.CONFIG.SLACK_ON_INTDOWN,
|
'on_intdown': plexpy.CONFIG.SLACK_ON_INTDOWN,
|
||||||
'on_extup': plexpy.CONFIG.SLACK_ON_EXTUP,
|
'on_extup': plexpy.CONFIG.SLACK_ON_EXTUP,
|
||||||
'on_intup': plexpy.CONFIG.SLACK_ON_INTUP
|
'on_intup': plexpy.CONFIG.SLACK_ON_INTUP
|
||||||
|
},
|
||||||
|
{'name': 'Scripts',
|
||||||
|
'id': AGENT_IDS['Scripts'],
|
||||||
|
'config_prefix': 'scripts',
|
||||||
|
'has_config': True,
|
||||||
|
'state': checked(plexpy.CONFIG.SCRIPTS_ENABLED),
|
||||||
|
'on_play': plexpy.CONFIG.SCRIPTS_ON_PLAY,
|
||||||
|
'on_stop': plexpy.CONFIG.SCRIPTS_ON_STOP,
|
||||||
|
'on_pause': plexpy.CONFIG.SCRIPTS_ON_PAUSE,
|
||||||
|
'on_resume': plexpy.CONFIG.SCRIPTS_ON_RESUME,
|
||||||
|
'on_buffer': plexpy.CONFIG.SCRIPTS_ON_BUFFER,
|
||||||
|
'on_watched': plexpy.CONFIG.SCRIPTS_ON_WATCHED,
|
||||||
|
'on_created': plexpy.CONFIG.SCRIPTS_ON_CREATED,
|
||||||
|
'on_extdown': plexpy.CONFIG.SCRIPTS_ON_EXTDOWN,
|
||||||
|
'on_extup': plexpy.CONFIG.SCRIPTS_ON_EXTUP,
|
||||||
|
'on_intdown': plexpy.CONFIG.SCRIPTS_ON_INTDOWN,
|
||||||
|
'on_intup': plexpy.CONFIG.SCRIPTS_ON_INTUP
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# OSX Notifications should only be visible if it can be used
|
# OSX Notifications should only be visible if it can be used
|
||||||
|
@ -320,6 +339,7 @@ def available_notification_agents():
|
||||||
|
|
||||||
return agents
|
return agents
|
||||||
|
|
||||||
|
|
||||||
def get_notification_agent_config(config_id):
|
def get_notification_agent_config(config_id):
|
||||||
if config_id:
|
if config_id:
|
||||||
config_id = int(config_id)
|
config_id = int(config_id)
|
||||||
|
@ -369,12 +389,16 @@ def get_notification_agent_config(config_id):
|
||||||
elif config_id == 14:
|
elif config_id == 14:
|
||||||
slackClient = SLACK()
|
slackClient = SLACK()
|
||||||
return slackClient.return_config_options()
|
return slackClient.return_config_options()
|
||||||
|
elif config_id == 15:
|
||||||
|
script = Scripts()
|
||||||
|
return script.return_config_options()
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def send_notification(config_id, subject, body):
|
|
||||||
|
def send_notification(config_id, subject, body, **kwargs):
|
||||||
if str(config_id).isdigit():
|
if str(config_id).isdigit():
|
||||||
config_id = int(config_id)
|
config_id = int(config_id)
|
||||||
|
|
||||||
|
@ -423,6 +447,9 @@ def send_notification(config_id, subject, body):
|
||||||
elif config_id == 14:
|
elif config_id == 14:
|
||||||
slackClient = SLACK()
|
slackClient = SLACK()
|
||||||
slackClient.notify(message=body, event=subject)
|
slackClient.notify(message=body, event=subject)
|
||||||
|
elif config_id == 15:
|
||||||
|
scripts = Scripts()
|
||||||
|
scripts.notify(message=body, subject=subject, **kwargs)
|
||||||
else:
|
else:
|
||||||
logger.debug(u"PlexPy Notifier :: Unknown agent id received.")
|
logger.debug(u"PlexPy Notifier :: Unknown agent id received.")
|
||||||
else:
|
else:
|
||||||
|
@ -503,7 +530,7 @@ class GROWL(object):
|
||||||
logger.info(u"Growl notifications sent.")
|
logger.info(u"Growl notifications sent.")
|
||||||
|
|
||||||
def updateLibrary(self):
|
def updateLibrary(self):
|
||||||
#For uniformity reasons not removed
|
# For uniformity reasons not removed
|
||||||
return
|
return
|
||||||
|
|
||||||
def test(self, host, password):
|
def test(self, host, password):
|
||||||
|
@ -530,6 +557,7 @@ class GROWL(object):
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class PROWL(object):
|
class PROWL(object):
|
||||||
"""
|
"""
|
||||||
Prowl notifications.
|
Prowl notifications.
|
||||||
|
@ -559,6 +587,7 @@ class PROWL(object):
|
||||||
"/publicapi/add",
|
"/publicapi/add",
|
||||||
headers={'Content-type': "application/x-www-form-urlencoded"},
|
headers={'Content-type': "application/x-www-form-urlencoded"},
|
||||||
body=urlencode(data))
|
body=urlencode(data))
|
||||||
|
|
||||||
response = http_handler.getresponse()
|
response = http_handler.getresponse()
|
||||||
request_status = response.status
|
request_status = response.status
|
||||||
|
|
||||||
|
@ -573,7 +602,7 @@ class PROWL(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def updateLibrary(self):
|
def updateLibrary(self):
|
||||||
#For uniformity reasons not removed
|
# For uniformity reasons not removed
|
||||||
return
|
return
|
||||||
|
|
||||||
def test(self, keys, priority):
|
def test(self, keys, priority):
|
||||||
|
@ -601,6 +630,7 @@ class PROWL(object):
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class XBMC(object):
|
class XBMC(object):
|
||||||
"""
|
"""
|
||||||
XBMC notifications
|
XBMC notifications
|
||||||
|
@ -647,12 +677,12 @@ class XBMC(object):
|
||||||
try:
|
try:
|
||||||
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']
|
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']
|
||||||
|
|
||||||
if version < 12: #Eden
|
if version < 12: # Eden
|
||||||
notification = header + "," + message + "," + time
|
notification = header + "," + message + "," + time
|
||||||
notifycommand = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' + notification + ')'}
|
notifycommand = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' + notification + ')'}
|
||||||
request = self._sendhttp(host, notifycommand)
|
request = self._sendhttp(host, notifycommand)
|
||||||
|
|
||||||
else: #Frodo
|
else: # Frodo
|
||||||
params = {'title': header, 'message': message, 'displaytime': int(time)}
|
params = {'title': header, 'message': message, 'displaytime': int(time)}
|
||||||
request = self._sendjson(host, 'GUI.ShowNotification', params)
|
request = self._sendjson(host, 'GUI.ShowNotification', params)
|
||||||
|
|
||||||
|
@ -685,6 +715,7 @@ class XBMC(object):
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class Plex(object):
|
class Plex(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
|
@ -763,6 +794,7 @@ class Plex(object):
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class NMA(object):
|
class NMA(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -821,6 +853,7 @@ class NMA(object):
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class PUSHBULLET(object):
|
class PUSHBULLET(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -852,6 +885,7 @@ class PUSHBULLET(object):
|
||||||
headers={'Content-type': "application/json",
|
headers={'Content-type': "application/json",
|
||||||
'Authorization': 'Basic %s' % base64.b64encode(plexpy.CONFIG.PUSHBULLET_APIKEY + ":")},
|
'Authorization': 'Basic %s' % base64.b64encode(plexpy.CONFIG.PUSHBULLET_APIKEY + ":")},
|
||||||
body=json.dumps(data))
|
body=json.dumps(data))
|
||||||
|
|
||||||
response = http_handler.getresponse()
|
response = http_handler.getresponse()
|
||||||
request_status = response.status
|
request_status = response.status
|
||||||
# logger.debug(u"PushBullet response status: %r" % request_status)
|
# logger.debug(u"PushBullet response status: %r" % request_status)
|
||||||
|
@ -882,6 +916,7 @@ class PUSHBULLET(object):
|
||||||
http_handler.request("GET", "/v2/devices",
|
http_handler.request("GET", "/v2/devices",
|
||||||
headers={'Content-type': "application/json",
|
headers={'Content-type': "application/json",
|
||||||
'Authorization': 'Basic %s' % base64.b64encode(plexpy.CONFIG.PUSHBULLET_APIKEY + ":")})
|
'Authorization': 'Basic %s' % base64.b64encode(plexpy.CONFIG.PUSHBULLET_APIKEY + ":")})
|
||||||
|
|
||||||
response = http_handler.getresponse()
|
response = http_handler.getresponse()
|
||||||
request_status = response.status
|
request_status = response.status
|
||||||
|
|
||||||
|
@ -926,6 +961,7 @@ class PUSHBULLET(object):
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class PUSHALOT(object):
|
class PUSHALOT(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -937,9 +973,9 @@ class PUSHALOT(object):
|
||||||
|
|
||||||
pushalot_authorizationtoken = plexpy.CONFIG.PUSHALOT_APIKEY
|
pushalot_authorizationtoken = plexpy.CONFIG.PUSHALOT_APIKEY
|
||||||
|
|
||||||
#logger.debug(u"Pushalot event: " + event)
|
# logger.debug(u"Pushalot event: " + event)
|
||||||
#logger.debug(u"Pushalot message: " + message)
|
# logger.debug(u"Pushalot message: " + message)
|
||||||
#logger.debug(u"Pushalot api: " + pushalot_authorizationtoken)
|
# logger.debug(u"Pushalot api: " + pushalot_authorizationtoken)
|
||||||
|
|
||||||
http_handler = HTTPSConnection("pushalot.com")
|
http_handler = HTTPSConnection("pushalot.com")
|
||||||
|
|
||||||
|
@ -954,9 +990,9 @@ class PUSHALOT(object):
|
||||||
response = http_handler.getresponse()
|
response = http_handler.getresponse()
|
||||||
request_status = response.status
|
request_status = response.status
|
||||||
|
|
||||||
#logger.debug(u"Pushalot response status: %r" % request_status)
|
# logger.debug(u"Pushalot response status: %r" % request_status)
|
||||||
#logger.debug(u"Pushalot response headers: %r" % response.getheaders())
|
# logger.debug(u"Pushalot response headers: %r" % response.getheaders())
|
||||||
#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"Pushalot notifications sent.")
|
||||||
|
@ -979,6 +1015,7 @@ class PUSHALOT(object):
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class PUSHOVER(object):
|
class PUSHOVER(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -1025,7 +1062,7 @@ class PUSHOVER(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def updateLibrary(self):
|
def updateLibrary(self):
|
||||||
#For uniformity reasons not removed
|
# For uniformity reasons not removed
|
||||||
return
|
return
|
||||||
|
|
||||||
def test(self, keys, priority, sound):
|
def test(self, keys, priority, sound):
|
||||||
|
@ -1089,6 +1126,7 @@ class PUSHOVER(object):
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class TwitterNotifier(object):
|
class TwitterNotifier(object):
|
||||||
|
|
||||||
REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token'
|
REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token'
|
||||||
|
@ -1204,6 +1242,7 @@ class TwitterNotifier(object):
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class OSX_NOTIFY(object):
|
class OSX_NOTIFY(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -1211,7 +1250,7 @@ class OSX_NOTIFY(object):
|
||||||
self.objc = __import__("objc")
|
self.objc = __import__("objc")
|
||||||
self.AppKit = __import__("AppKit")
|
self.AppKit = __import__("AppKit")
|
||||||
except:
|
except:
|
||||||
#logger.error(u"PlexPy Notifier :: Cannot load OSX Notifications agent.")
|
# logger.error(u"PlexPy Notifier :: Cannot load OSX Notifications agent.")
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
@ -1258,7 +1297,7 @@ class OSX_NOTIFY(object):
|
||||||
if image:
|
if image:
|
||||||
source_img = self.AppKit.NSImage.alloc().initByReferencingFile_(image)
|
source_img = self.AppKit.NSImage.alloc().initByReferencingFile_(image)
|
||||||
notification.setContentImage_(source_img)
|
notification.setContentImage_(source_img)
|
||||||
#notification.set_identityImage_(source_img)
|
# notification.set_identityImage_(source_img)
|
||||||
notification.setHasActionButton_(False)
|
notification.setHasActionButton_(False)
|
||||||
|
|
||||||
notification_center = NSUserNotificationCenter.defaultUserNotificationCenter()
|
notification_center = NSUserNotificationCenter.defaultUserNotificationCenter()
|
||||||
|
@ -1287,6 +1326,7 @@ class OSX_NOTIFY(object):
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class BOXCAR(object):
|
class BOXCAR(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -1347,7 +1387,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)',
|
||||||
|
@ -1363,6 +1403,7 @@ class BOXCAR(object):
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class Email(object):
|
class Email(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -1523,10 +1564,12 @@ class IFTTT(object):
|
||||||
' as value1 and value2 respectively.',
|
' as value1 and value2 respectively.',
|
||||||
'input_type': 'text'
|
'input_type': 'text'
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
class TELEGRAM(object):
|
class TELEGRAM(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -1565,7 +1608,7 @@ class TELEGRAM(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def updateLibrary(self):
|
def updateLibrary(self):
|
||||||
#For uniformity reasons not removed
|
# For uniformity reasons not removed
|
||||||
return
|
return
|
||||||
|
|
||||||
def test(self, bot_token, chat_id):
|
def test(self, bot_token, chat_id):
|
||||||
|
@ -1676,3 +1719,240 @@ class SLACK(object):
|
||||||
]
|
]
|
||||||
|
|
||||||
return config_option
|
return config_option
|
||||||
|
|
||||||
|
|
||||||
|
class Scripts(object):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def conf(self, options):
|
||||||
|
return cherrypy.config['config'].get('Scripts', options)
|
||||||
|
|
||||||
|
def updateLibrary(self):
|
||||||
|
# For uniformity reasons not removed
|
||||||
|
return
|
||||||
|
|
||||||
|
def test(self, subject, message, *args, **kwargs):
|
||||||
|
self.notify(subject, message, *args, **kwargs)
|
||||||
|
return
|
||||||
|
|
||||||
|
def list_scripts(self):
|
||||||
|
scriptdir = plexpy.CONFIG.SCRIPTS_FOLDER
|
||||||
|
scripts = {'': ''}
|
||||||
|
|
||||||
|
if scriptdir and not os.path.exists(scriptdir):
|
||||||
|
os.makedirs(scriptdir)
|
||||||
|
|
||||||
|
for root, dirs, files in os.walk(scriptdir):
|
||||||
|
for f in files:
|
||||||
|
name, ext = os.path.splitext(f)
|
||||||
|
if ext in ('.rb', '.pl', '.bat', '.py', '.sh', '.cmd', '.php'):
|
||||||
|
rfp = os.path.join(os.path.relpath(root, scriptdir), f)
|
||||||
|
fp = os.path.join(root, f)
|
||||||
|
scripts[fp] = rfp
|
||||||
|
|
||||||
|
return scripts
|
||||||
|
|
||||||
|
def notify(self, subject='', message='', notify_action='', script_args='', *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Args:
|
||||||
|
subject(string, optional): Head text,
|
||||||
|
message(string, optional): Body text,
|
||||||
|
notify_action(string): 'play'
|
||||||
|
script_args(list): ["python2", '-p', '-zomg']
|
||||||
|
"""
|
||||||
|
logger.debug(u'Trying to run notify script subject: %s message: %s, action: %s script_args: %s' %
|
||||||
|
(subject, message, notify_action, script_args))
|
||||||
|
|
||||||
|
prefix = ''
|
||||||
|
script = kwargs.get('script', '') # for manual scripts
|
||||||
|
|
||||||
|
if not plexpy.CONFIG.SCRIPTS_FOLDER:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Make sure we use the correct script..
|
||||||
|
if notify_action == 'play':
|
||||||
|
script = plexpy.CONFIG.SCRIPTS_ON_PLAY_SCRIPT
|
||||||
|
|
||||||
|
elif notify_action == 'stop':
|
||||||
|
script = plexpy.CONFIG.SCRIPTS_ON_STOP_SCRIPT
|
||||||
|
|
||||||
|
elif notify_action == 'pause':
|
||||||
|
script = plexpy.CONFIG.SCRIPTS_ON_PAUSE_SCRIPT
|
||||||
|
|
||||||
|
elif notify_action == 'resume':
|
||||||
|
script = plexpy.CONFIG.SCRIPTS_ON_RESUME_SCRIPT
|
||||||
|
|
||||||
|
elif notify_action == 'buffer':
|
||||||
|
script = plexpy.CONFIG.SCRIPTS_ON_BUFFER_SCRIPT
|
||||||
|
|
||||||
|
elif notify_action == 'extdown':
|
||||||
|
script = plexpy.CONFIG.SCRIPTS_ON_EXTDOWN_SCRIPT
|
||||||
|
|
||||||
|
elif notify_action == 'extup':
|
||||||
|
script = plexpy.CONFIG.SCRIPTS_ON_EXTUP_SCRIPT
|
||||||
|
|
||||||
|
elif notify_action == 'intdown':
|
||||||
|
script = plexpy.CONFIG.SCRIPTS_ON_INTDOWN_SCRIPT
|
||||||
|
|
||||||
|
elif notify_action == 'intup':
|
||||||
|
script = plexpy.CONFIG.SCRIPTS_ON_INTUP_SCRIPT
|
||||||
|
|
||||||
|
elif notify_action == 'created':
|
||||||
|
script = plexpy.CONFIG.SCRIPTS_ON_CREATED_SCRIPT
|
||||||
|
|
||||||
|
elif notify_action == 'watched':
|
||||||
|
script = plexpy.CONFIG.SCRIPTS_ON_WATCHED_SCRIPT
|
||||||
|
|
||||||
|
# Dont try to run the script
|
||||||
|
# if the action does not have one
|
||||||
|
if not script:
|
||||||
|
logger.debug(u'%s has no script, exiting..' % notify_action)
|
||||||
|
return
|
||||||
|
|
||||||
|
name, ext = os.path.splitext(script)
|
||||||
|
|
||||||
|
if ext == '.py':
|
||||||
|
prefix = 'python'
|
||||||
|
elif ext == '.php':
|
||||||
|
prefix = 'php'
|
||||||
|
elif ext == '.pl':
|
||||||
|
prefix = 'perl'
|
||||||
|
elif ext == '.rb':
|
||||||
|
prefix = 'ruby'
|
||||||
|
|
||||||
|
if os.name == 'nt':
|
||||||
|
script = script.encode(plexpy.SYS_ENCODING, 'ignore')
|
||||||
|
script = [script]
|
||||||
|
|
||||||
|
if prefix:
|
||||||
|
script.insert(0, prefix)
|
||||||
|
|
||||||
|
# for manual notifications
|
||||||
|
if script_args and isinstance(script_args, basestring):
|
||||||
|
# attemps for format it for the user
|
||||||
|
script_args = shlex.split(script_args)
|
||||||
|
|
||||||
|
# Windows handles unicode very badly.
|
||||||
|
# https://bugs.python.org/issue19264
|
||||||
|
if script_args and os.name == 'nt':
|
||||||
|
script_args = [s.encode(plexpy.SYS_ENCODING, 'ignore') for s in script_args]
|
||||||
|
|
||||||
|
# Allow overrides for shitty systems
|
||||||
|
if prefix and script_args:
|
||||||
|
if script_args[0] in ['python2', 'python', 'php', 'ruby', 'perl']:
|
||||||
|
script[0] = script_args[0]
|
||||||
|
del script_args[0]
|
||||||
|
|
||||||
|
script.extend(script_args)
|
||||||
|
|
||||||
|
logger.debug(u'Full script is %s' % script)
|
||||||
|
|
||||||
|
try:
|
||||||
|
p = subprocess.Popen(script, stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
cwd=plexpy.CONFIG.SCRIPTS_FOLDER)
|
||||||
|
|
||||||
|
out, error = p.communicate()
|
||||||
|
status = p.returncode
|
||||||
|
|
||||||
|
if out and status:
|
||||||
|
out = out.strip()
|
||||||
|
logger.debug(u'%s returned %s' % (script, out))
|
||||||
|
|
||||||
|
if error:
|
||||||
|
error = error.strip()
|
||||||
|
logger.error(u'%s' % error)
|
||||||
|
|
||||||
|
except OSError as out:
|
||||||
|
logger.error(u'Failed to run %s error %s' % (script, out))
|
||||||
|
|
||||||
|
def return_config_options(self):
|
||||||
|
config_option = [{'label': 'Script folder',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_FOLDER,
|
||||||
|
'name': 'scripts_folder',
|
||||||
|
'description': 'Add your script folder.',
|
||||||
|
'input_type': 'text',
|
||||||
|
},
|
||||||
|
{'label': 'Playback Start',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_ON_PLAY_SCRIPT,
|
||||||
|
'name': 'scripts_on_play_script',
|
||||||
|
'description': 'Pick the script for on play.',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.list_scripts()
|
||||||
|
},
|
||||||
|
{'label': 'Playback Stop',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_ON_STOP_SCRIPT,
|
||||||
|
'name': 'scripts_on_stop_script',
|
||||||
|
'description': 'Pick the script for on stop.',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.list_scripts()
|
||||||
|
},
|
||||||
|
{'label': 'Playback Pause',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_ON_PAUSE_SCRIPT,
|
||||||
|
'name': 'scripts_on_pause_script',
|
||||||
|
'description': 'Pick the script for on pause.',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.list_scripts()
|
||||||
|
},
|
||||||
|
{'label': 'Playback Resume',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_ON_RESUME_SCRIPT,
|
||||||
|
'name': 'scripts_on_resume_script',
|
||||||
|
'description': 'Pick the script for on resume.',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.list_scripts()
|
||||||
|
},
|
||||||
|
{'label': 'Watched',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_ON_WATCHED_SCRIPT,
|
||||||
|
'name': 'scripts_on_watched_script',
|
||||||
|
'description': 'Pick the script for on watched.',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.list_scripts()
|
||||||
|
},
|
||||||
|
{'label': 'Buffer Warnings',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_ON_BUFFER_SCRIPT,
|
||||||
|
'name': 'scripts_on_buffer_script',
|
||||||
|
'description': 'Pick the script for buffer warnings.',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.list_scripts()
|
||||||
|
},
|
||||||
|
{'label': 'Recently Added',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_ON_CREATED_SCRIPT,
|
||||||
|
'name': 'scripts_on_created_script',
|
||||||
|
'description': 'Pick the script for recently added.',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.list_scripts()
|
||||||
|
},
|
||||||
|
{'label': 'Plex Remote Access Down',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_ON_EXTDOWN_SCRIPT,
|
||||||
|
'name': 'scripts_on_extdown_script',
|
||||||
|
'description': 'Pick the script for external connection down.',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.list_scripts()
|
||||||
|
},
|
||||||
|
{'label': 'Plex Remote Access Up',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_ON_EXTUP_SCRIPT,
|
||||||
|
'name': 'scripts_on_extup_script',
|
||||||
|
'description': 'Pick the script for external connection up.',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.list_scripts()
|
||||||
|
},
|
||||||
|
{'label': 'Plex Server Down',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_ON_INTDOWN_SCRIPT,
|
||||||
|
'name': 'scripts_on_intdown_script',
|
||||||
|
'description': 'Pick the script for pms down',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.list_scripts()
|
||||||
|
},
|
||||||
|
{'label': 'Plex Server Up',
|
||||||
|
'value': plexpy.CONFIG.SCRIPTS_ON_INTUP_SCRIPT,
|
||||||
|
'name': 'scripts_on_intup_script',
|
||||||
|
'description': 'Pick the script for pms up',
|
||||||
|
'input_type': 'select',
|
||||||
|
'select_options': self.list_scripts()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
return config_option
|
||||||
|
|
|
@ -476,6 +476,7 @@ class WebInterface(object):
|
||||||
"notify_on_extup_body_text": plexpy.CONFIG.NOTIFY_ON_EXTUP_BODY_TEXT,
|
"notify_on_extup_body_text": plexpy.CONFIG.NOTIFY_ON_EXTUP_BODY_TEXT,
|
||||||
"notify_on_intup_subject_text": plexpy.CONFIG.NOTIFY_ON_INTUP_SUBJECT_TEXT,
|
"notify_on_intup_subject_text": plexpy.CONFIG.NOTIFY_ON_INTUP_SUBJECT_TEXT,
|
||||||
"notify_on_intup_body_text": plexpy.CONFIG.NOTIFY_ON_INTUP_BODY_TEXT,
|
"notify_on_intup_body_text": plexpy.CONFIG.NOTIFY_ON_INTUP_BODY_TEXT,
|
||||||
|
"notify_scripts_args_text": plexpy.CONFIG.NOTIFY_SCRIPTS_ARGS_TEXT,
|
||||||
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
|
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
|
||||||
"home_stats_type": checked(plexpy.CONFIG.HOME_STATS_TYPE),
|
"home_stats_type": checked(plexpy.CONFIG.HOME_STATS_TYPE),
|
||||||
"home_stats_count": plexpy.CONFIG.HOME_STATS_COUNT,
|
"home_stats_count": plexpy.CONFIG.HOME_STATS_COUNT,
|
||||||
|
@ -662,6 +663,7 @@ class WebInterface(object):
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def test_notifier(self, config_id=None, subject='PlexPy', body='Test notification', **kwargs):
|
def test_notifier(self, config_id=None, subject='PlexPy', body='Test notification', **kwargs):
|
||||||
cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
|
cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
|
||||||
|
print kwargs
|
||||||
|
|
||||||
if config_id.isdigit():
|
if config_id.isdigit():
|
||||||
agents = notifiers.available_notification_agents()
|
agents = notifiers.available_notification_agents()
|
||||||
|
@ -674,7 +676,7 @@ class WebInterface(object):
|
||||||
|
|
||||||
if this_agent:
|
if this_agent:
|
||||||
logger.debug("Sending test %s notification." % this_agent['name'])
|
logger.debug("Sending test %s notification." % this_agent['name'])
|
||||||
notifiers.send_notification(this_agent['id'], subject, body)
|
notifiers.send_notification(this_agent['id'], subject, body, **kwargs)
|
||||||
return "Notification sent."
|
return "Notification sent."
|
||||||
else:
|
else:
|
||||||
logger.debug("Unable to send test notification, invalid notification agent ID %s." % config_id)
|
logger.debug("Unable to send test notification, invalid notification agent ID %s." % config_id)
|
||||||
|
@ -1420,6 +1422,12 @@ class WebInterface(object):
|
||||||
return serve_template(templatename="notification_triggers_modal.html", title="Notification Triggers",
|
return serve_template(templatename="notification_triggers_modal.html", title="Notification Triggers",
|
||||||
data=this_agent)
|
data=this_agent)
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
def testScripts(self, *args, **kwargs):
|
||||||
|
''' Used for manual testing for now cba with adding buttion '''
|
||||||
|
script = notifiers.Scripts()
|
||||||
|
return script.test(*args, **kwargs)
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def delete_history_rows(self, row_id, **kwargs):
|
def delete_history_rows(self, row_id, **kwargs):
|
||||||
data_factory = datafactory.DataFactory()
|
data_factory = datafactory.DataFactory()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue