Merge pull request #418 from richipargo/slack-agent

Add slack as a notification agent
This commit is contained in:
JonnyWong16 2015-12-31 19:58:57 -08:00
commit 0d2666f7d3
4 changed files with 158 additions and 12 deletions

View file

@ -132,12 +132,17 @@ from plexpy import helpers
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#testSlack').click(function() {
$.get("/test_slack", function(data) { $('#ajaxMsg').html("<i class='fa fa-check'></i>" + data); });
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#pushbullet_apikey').on('change', function () {
doAjaxCall('set_notification_config', $(this), 'tabs', true);
reloadModal();
return false;
});
// Never send checkbox values directly, always substitute value in hidden input.
$('.checkboxes').click(function () {
var configToggle = $(this).data('id');

View file

@ -281,6 +281,22 @@ _CONFIG_DEFINITIONS = {
'PUSHOVER_ON_INTUP': (int, 'Pushover', 0),
'REFRESH_USERS_INTERVAL': (int, 'Monitoring', 12),
'REFRESH_USERS_ON_STARTUP': (int, 'Monitoring', 1),
'SLACK_ENABLED': (int, 'Slack', 0),
'SLACK_HOOK': (str, 'Slack', ''),
'SLACK_CHANNEL': (str, 'Slack', ''),
'SLACK_ICON_EMOJI': (str, 'Slack', ''),
'SLACK_USERNAME': (str, 'Slack', ''),
'SLACK_ON_PLAY': (int, 'Slack', 0),
'SLACK_ON_STOP': (int, 'Slack', 0),
'SLACK_ON_PAUSE': (int, 'Slack', 0),
'SLACK_ON_RESUME': (int, 'Slack', 0),
'SLACK_ON_BUFFER': (int, 'Slack', 0),
'SLACK_ON_WATCHED': (int, 'Slack', 0),
'SLACK_ON_CREATED': (int, 'Slack', 0),
'SLACK_ON_EXTDOWN': (int, 'Slack', 0),
'SLACK_ON_INTDOWN': (int, 'Slack', 0),
'SLACK_ON_EXTUP': (int, 'Slack', 0),
'SLACK_ON_INTUP': (int, 'Slack', 0),
'TELEGRAM_BOT_TOKEN': (str, 'Telegram', ''),
'TELEGRAM_ENABLED': (int, 'Telegram', 0),
'TELEGRAM_CHAT_ID': (str, 'Telegram', ''),
@ -448,4 +464,4 @@ class Config(object):
if self.VIDEO_LOGGING_ENABLE == 0:
self.MOVIE_LOGGING_ENABLE = 0
self.TV_LOGGING_ENABLE = 0
self.CONFIG_VERSION = '1'
self.CONFIG_VERSION = '1'

View file

@ -19,6 +19,7 @@ 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 urllib import urlencode
from pynma import pynma
@ -52,7 +53,8 @@ AGENT_IDS = {"Growl": 0,
"Email": 10,
"Twitter": 11,
"IFTTT": 12,
"Telegram": 13}
"Telegram": 13,
"Slack":14}
def available_notification_agents():
agents = [{'name': 'Growl',
@ -275,6 +277,23 @@ def available_notification_agents():
'on_intdown': plexpy.CONFIG.TELEGRAM_ON_INTDOWN,
'on_extup': plexpy.CONFIG.TELEGRAM_ON_EXTUP,
'on_intup': plexpy.CONFIG.TELEGRAM_ON_INTUP
},
{'name': 'Slack',
'id': AGENT_IDS['Slack'],
'config_prefix': 'slack',
'has_config': True,
'state': checked(plexpy.CONFIG.SLACK_ENABLED),
'on_play': plexpy.CONFIG.SLACK_ON_PLAY,
'on_stop': plexpy.CONFIG.SLACK_ON_STOP,
'on_resume': plexpy.CONFIG.SLACK_ON_RESUME,
'on_pause': plexpy.CONFIG.SLACK_ON_PAUSE,
'on_buffer': plexpy.CONFIG.SLACK_ON_BUFFER,
'on_watched': plexpy.CONFIG.SLACK_ON_WATCHED,
'on_created': plexpy.CONFIG.SLACK_ON_CREATED,
'on_extdown': plexpy.CONFIG.SLACK_ON_EXTDOWN,
'on_intdown': plexpy.CONFIG.SLACK_ON_INTDOWN,
'on_extup': plexpy.CONFIG.SLACK_ON_EXTUP,
'on_intup': plexpy.CONFIG.SLACK_ON_INTUP
}
]
@ -347,6 +366,9 @@ def get_notification_agent_config(config_id):
elif config_id == 13:
telegramClient = TELEGRAM()
return telegramClient.return_config_options()
elif config_id == 14:
slackClient = SLACK()
return slackClient.return_config_options()
else:
return []
else:
@ -398,12 +420,14 @@ def send_notification(config_id, subject, body):
elif config_id == 13:
telegramClient = TELEGRAM()
telegramClient.notify(message=body, event=subject)
elif config_id == 14:
slackClient = SLACK()
slackClient.notify(message=body, event=subject)
else:
logger.debug(u"PlexPy Notifier :: Unknown agent id received.")
else:
logger.debug(u"PlexPy Notifier :: Notification requested but no agent id received.")
class GROWL(object):
"""
Growl notifications, for OS X.
@ -860,7 +884,7 @@ class PUSHBULLET(object):
'Authorization': 'Basic %s' % base64.b64encode(plexpy.CONFIG.PUSHBULLET_APIKEY + ":")})
response = http_handler.getresponse()
request_status = response.status
if request_status == 200:
data = json.loads(response.read())
devices = data.get('devices', [])
@ -1021,7 +1045,7 @@ class PUSHOVER(object):
http_handler.request("GET", "/1/sounds.json?token=" + self.application_token)
response = http_handler.getresponse()
request_status = response.status
if request_status == 200:
data = json.loads(response.read())
sounds = data.get('sounds', {})
@ -1445,7 +1469,6 @@ class Email(object):
return config_option
class IFTTT(object):
def __init__(self):
@ -1574,3 +1597,94 @@ class TELEGRAM(object):
]
return config_option
class SLACK(object):
"""
Slack Notifications
"""
def __init__(self):
self.enabled = plexpy.CONFIG.SLACK_ENABLED
self.slack_hook = plexpy.CONFIG.SLACK_HOOK
self.channel = plexpy.CONFIG.SLACK_CHANNEL
self.username = plexpy.CONFIG.SLACK_USERNAME
self.icon_emoji = plexpy.CONFIG.SLACK_ICON_EMOJI
def conf(self, options):
return cherrypy.config['config'].get('Slack', options)
def notify(self, message, event):
if not message or not event:
return
http_handler = HTTPSConnection("hooks.slack.com")
data = {'text': event.encode('utf-8') + ': ' + message.encode("utf-8")}
if self.channel != '': data['channel'] = self.channel
if self.username != '': data['username'] = self.username
if self.icon_emoji != '':
if urlparse(self.icon_emoji).scheme == '':
data['icon_emoji'] = self.icon_emoji
else:
data['icon_url'] = self.icon_url
url = urlparse(self.slack_hook).path
http_handler.request("POST",
url,
headers={'Content-type': "application/x-www-form-urlencoded"},
body=json.dumps(data))
response = http_handler.getresponse()
request_status = response.status
if request_status == 200:
logger.info(u"Slack notifications sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.info(u"Slack request failed: %s" % response.reason)
return False
else:
logger.info(u"Slack notification failed serverside.")
return False
def updateLibrary(self):
#For uniformity reasons not removed
return
def test(self):
self.enabled = True
return self.notify('Main Screen Activate', 'Test Message')
def return_config_options(self):
config_option = [{'label': 'Slack Hook',
'value': self.slack_hook,
'name': 'slack_hook',
'description': 'Your Slack incoming webhook.',
'input_type': 'text'
},
{'label': 'Slack Channel',
'value': self.channel,
'name': 'slack_channel',
'description': 'Your slack channel name. (Begin with \'#\')',
'input_type': 'text'
},
{'label': 'Slack Username',
'value': self.username,
'name': 'slack_username',
'description': 'Slack username which will be shown',
'input_type': 'text'
},
{'label': 'Slack Icon',
'value': self.icon_emoji,
'description': 'Your icon you wish to show, use Slack emoji or image url',
'name': 'slack_icon_emoji',
'input_type': 'text'
},
{'label': 'Test Event',
'value': 'Test Event',
'name': 'testSlack',
'description': 'Test if Slack notifications are working. See logs for troubleshooting.',
'input_type': 'button'
}
]
return config_option

View file

@ -499,8 +499,8 @@ class WebInterface(object):
"tv_notify_on_start", "movie_notify_on_start", "music_notify_on_start",
"tv_notify_on_stop", "movie_notify_on_stop", "music_notify_on_stop",
"tv_notify_on_pause", "movie_notify_on_pause", "music_notify_on_pause", "refresh_users_on_startup",
"ip_logging_enable", "movie_logging_enable", "tv_logging_enable", "music_logging_enable",
"pms_is_remote", "home_stats_type", "group_history_tables", "notify_consecutive",
"ip_logging_enable", "movie_logging_enable", "tv_logging_enable", "music_logging_enable",
"pms_is_remote", "home_stats_type", "group_history_tables", "notify_consecutive",
"notify_recently_added", "notify_recently_added_grandparent", "monitor_remote_access"
]
for checked_config in checked_configs:
@ -526,7 +526,7 @@ class WebInterface(object):
if (kwargs['monitoring_interval'] != str(plexpy.CONFIG.MONITORING_INTERVAL)) or \
(kwargs['refresh_users_interval'] != str(plexpy.CONFIG.REFRESH_USERS_INTERVAL)):
reschedule = True
if 'notify_recently_added' in kwargs and \
(kwargs['notify_recently_added'] != plexpy.CONFIG.NOTIFY_RECENTLY_ADDED):
reschedule = True
@ -554,7 +554,7 @@ class WebInterface(object):
# Get new server URLs for SSL communications.
plextv.get_real_pms_url()
# Get new server friendly name
pmsconnect.get_server_friendly_name()
@ -696,6 +696,17 @@ class WebInterface(object):
else:
return "Error sending event."
@cherrypy.expose
def test_slack(self):
cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
event = notifiers.SLACK()
result = event.test()
if result:
return "Notification successful."
else:
return "Error sending event."
@cherrypy.expose
def osxnotifyregister(self, app):
cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
@ -1457,7 +1468,7 @@ class WebInterface(object):
@cherrypy.expose
def undelete_user(self, user_id=None, username=None, **kwargs):
data_factory = datafactory.DataFactory()
if user_id:
delete_row = data_factory.undelete_user(user_id=user_id)