Skip to content

Commit

Permalink
Add slack notifier (#3002)
Browse files Browse the repository at this point in the history
* Add slack notifier.
* Added the slack icon to the sprite.
* Added slack icon to css.
* Added padding to create some space between the icon and the h3/a.
* Added padding to create some space between the .component-group-desc.
* Added docstrings, and brushed up the string templates.
  • Loading branch information
p0psicles committed Aug 12, 2017
1 parent a24f84c commit 38e6cbf
Show file tree
Hide file tree
Showing 11 changed files with 258 additions and 15 deletions.
15 changes: 14 additions & 1 deletion medusa/__main__.py
Expand Up @@ -379,7 +379,7 @@ def initialize(self, console_logging=True):

sections = [
'General', 'Blackhole', 'Newzbin', 'SABnzbd', 'NZBget', 'KODI', 'PLEX', 'Emby', 'Growl', 'Prowl', 'Twitter',
'Boxcar2', 'NMJ', 'NMJv2', 'Synology', 'SynologyNotifier', 'pyTivo', 'NMA', 'Pushalot', 'Pushbullet',
'Boxcar2', 'NMJ', 'NMJv2', 'Synology', 'Slack', 'SynologyNotifier', 'pyTivo', 'NMA', 'Pushalot', 'Pushbullet',
'Subtitles', 'pyTivo',
]

Expand Down Expand Up @@ -759,6 +759,12 @@ def initialize(self, console_logging=True):
app.SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD = bool(
check_setting_int(app.CFG, 'SynologyNotifier', 'synologynotifier_notify_onsubtitledownload', 0))

app.USE_SLACK = bool(check_setting_bool(app.CFG, 'Slack', 'use_slack', 0))
app.SLACK_NOTIFY_SNATCH = bool(check_setting_bool(app.CFG, 'Slack', 'slack_notify_snatch', 0))
app.SLACK_NOTIFY_DOWNLOAD = bool(check_setting_bool(app.CFG, 'Slack', 'slack_notify_download', 0))
app.SLACK_NOTIFY_SUBTITLEDOWNLOAD = bool(check_setting_bool(app.CFG, 'Slack', 'slack_notify_onsubtitledownload', 0))
app.SLACK_WEBHOOK = check_setting_str(app.CFG, 'Slack', 'slack_webhook', '', censor_log='normal')

app.USE_TRAKT = bool(check_setting_int(app.CFG, 'Trakt', 'use_trakt', 0))
app.TRAKT_USERNAME = check_setting_str(app.CFG, 'Trakt', 'trakt_username', '', censor_log='normal')
app.TRAKT_ACCESS_TOKEN = check_setting_str(app.CFG, 'Trakt', 'trakt_access_token', '', censor_log='low')
Expand Down Expand Up @@ -1706,6 +1712,13 @@ def save_config():
new_config['SynologyNotifier']['synologynotifier_notify_onsubtitledownload'] = int(
app.SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD)

new_config['Slack'] = {}
new_config['Slack']['use_slack'] = int(app.USE_SLACK)
new_config['Slack']['slack_notify_snatch'] = int(app.SLACK_NOTIFY_SNATCH)
new_config['Slack']['slack_notify_download'] = int(app.SLACK_NOTIFY_DOWNLOAD)
new_config['Slack']['slack_notify_onsubtitledownload'] = int(app.SLACK_NOTIFY_SUBTITLEDOWNLOAD)
new_config['Slack']['slack_webhook'] = app.SLACK_WEBHOOK

new_config['Trakt'] = {}
new_config['Trakt']['use_trakt'] = int(app.USE_TRAKT)
new_config['Trakt']['trakt_username'] = app.TRAKT_USERNAME
Expand Down
6 changes: 6 additions & 0 deletions medusa/app.py
Expand Up @@ -437,6 +437,12 @@
SYNOLOGYNOTIFIER_NOTIFY_ONDOWNLOAD = False
SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD = False

USE_SLACK = False
SLACK_NOTIFY_SNATCH = None
SLACK_NOTIFY_DOWNLOAD = None
SLACK_NOTIFY_SUBTITLEDOWNLOAD = None
SLACK_WEBHOOK = None

USE_TRAKT = False
TRAKT_USERNAME = None
TRAKT_ACCESS_TOKEN = None
Expand Down
3 changes: 3 additions & 0 deletions medusa/notifiers/__init__.py
Expand Up @@ -22,6 +22,7 @@
pushbullet,
pushover,
pytivo,
slack,
synoindex,
synology_notifier,
telegram,
Expand Down Expand Up @@ -59,6 +60,7 @@
twitter_notifier = tweet.Notifier()
trakt_notifier = trakt.Notifier()
email_notifier = emailnotify.Notifier()
slack_notifier = slack.Notifier()

notifiers = [
libnotify_notifier, # Libnotify notifier goes first because it doesn't involve blocking on network activity.
Expand All @@ -81,6 +83,7 @@
twitter_notifier,
trakt_notifier,
email_notifier,
slack_notifier
]


Expand Down
111 changes: 111 additions & 0 deletions medusa/notifiers/slack.py
@@ -0,0 +1,111 @@
"""Slack notifier."""
# coding=utf-8

from __future__ import unicode_literals

import json
import logging
from medusa import app, common
from medusa.logger.adapters.style import BraceAdapter
import requests
import six

log = BraceAdapter(logging.getLogger(__name__))
log.logger.addHandler(logging.NullHandler())


class Notifier(object):
"""Slack notifier class."""

SLACK_WEBHOOK_URL = 'https://hooks.slack.com/services/'

def notify_snatch(self, ep_name, is_proper):
"""
Send a notification to a Slack channel when an episode is snatched.
:param ep_name: The name of the episode snatched
:param is_proper: Boolean. If snatch is proper or not
"""
if app.SLACK_NOTIFY_SNATCH:
message = common.notifyStrings[(common.NOTIFY_SNATCH, common.NOTIFY_SNATCH_PROPER)[is_proper]]
self._notify_slack('{message} : {ep_name}'.format(message=message, ep_name=ep_name))

def notify_download(self, ep_name):
"""
Send a notification to a slack channel when an episode is downloaded.
:param ep_name: The name of the episode downloaded
"""
if app.SLACK_NOTIFY_DOWNLOAD:
message = common.notifyStrings[common.NOTIFY_DOWNLOAD]
self._notify_slack('{message} : {ep_name}'.format(message=message, ep_name=ep_name))

def notify_subtitle_download(self, ep_name, lang):
"""
Send a notification to a Slack channel when subtitles for an episode are downloaded.
:param ep_name: The name of the episode subtitles were downloaded for
:param lang: The language of the downloaded subtitles
"""
if app.SLACK_NOTIFY_SUBTITLEDOWNLOAD:
message = common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD]
self._notify_slack('{message} {ep_name}: {lang}'.format(message=message, ep_name=ep_name, lang=lang))

def notify_git_update(self, new_version='??'):
"""
Send a notification to a Slack channel for git updates.
:param new_version: The new version available from git
"""
if app.USE_SLACK:
message = common.notifyStrings[common.NOTIFY_GIT_UPDATE_TEXT]
title = common.notifyStrings[common.NOTIFY_GIT_UPDATE]
self._notify_slack('{title} - {message} {version}'.format(title=title, message=message, version=new_version))

def notify_login(self, ipaddress=''):
"""
Send a notification to a Slack channel on login.
:param ipaddress: The ip address the login is originating from
"""
if app.USE_SLACK:
message = common.notifyStrings[common.NOTIFY_LOGIN_TEXT]
title = common.notifyStrings[common.NOTIFY_LOGIN]
self._notify_slack(title + '{title} - {message}'.format(title=title, message=message.format(ipaddress)))

def test_notify(self, slack_webhook):
"""
Send a test notification.
:param slack_webhook: The slack webhook to send the message to
:returns: the notification
"""
return self._notify_slack('This is a test notification from Medusa', force=True, webhook=slack_webhook)

def _send_slack(self, message=None, webhook=None):
"""Send the http request using the Slack webhook."""
app.SLACK_WEBHOOK = webhook or app.SLACK_WEBHOOK
slack_webhook = self.SLACK_WEBHOOK_URL + app.SLACK_WEBHOOK.replace(self.SLACK_WEBHOOK_URL, '')

log.info('Sending slack message: {message}', {'message': message})
log.info('Sending slack message to url: {url}', {'url': slack_webhook})

if isinstance(message, six.text_type):
message = message.encode('utf-8')

headers = {b'Content-Type': b'application/json'}
try:
r = requests.post(slack_webhook, data=json.dumps(dict(text=message, username='MedusaBot')), headers=headers)
r.raise_for_status()
except Exception:
log.exception('Error Sending Slack message')
return False

return True

def _notify_slack(self, message='', force=False, webhook=None):
"""Send the Slack notification."""
if not app.USE_SLACK and not force:
return False

return self._send_slack(message, webhook)
2 changes: 1 addition & 1 deletion medusa/notifiers/telegram.py
Expand Up @@ -94,7 +94,7 @@ def notify_snatch(self, ep_name, is_proper):
:param ep_name: The name of the episode snatched
:param is_proper: Boolean. If snatch is proper or not
"""
title=notifyStrings[(NOTIFY_SNATCH, NOTIFY_SNATCH_PROPER)[is_proper]]
title = notifyStrings[(NOTIFY_SNATCH, NOTIFY_SNATCH_PROPER)[is_proper]]
if app.TELEGRAM_NOTIFY_ONSNATCH:
self._notify_telegram(title, ep_name)

Expand Down
10 changes: 9 additions & 1 deletion medusa/server/web/config/notifications.py
Expand Up @@ -79,7 +79,9 @@ def saveNotifications(self, use_kodi=None, kodi_always_on=None, kodi_notify_onsn
use_email=None, email_notify_onsnatch=None, email_notify_ondownload=None,
email_notify_onsubtitledownload=None, email_host=None, email_port=25, email_from=None,
email_tls=None, email_user=None, email_password=None, email_list=None, email_subject=None, email_show_list=None,
email_show=None):
email_show=None,
use_slack=None, slack_notify_onsnatch=None, slack_notify_ondownload=None, slack_notify_onsubtitledownload=None,
slack_webhook=None):
"""
Save notification related settings
"""
Expand Down Expand Up @@ -195,6 +197,12 @@ def saveNotifications(self, use_kodi=None, kodi_always_on=None, kodi_notify_onsn
app.SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD = config.checkbox_to_value(
synologynotifier_notify_onsubtitledownload)

app.USE_SLACK = config.checkbox_to_value(use_slack)
app.SLACK_NOTIFY_DOWNLOAD = config.checkbox_to_value(slack_notify_ondownload)
app.SLACK_NOTIFY_SNATCH = config.checkbox_to_value(slack_notify_onsnatch)
app.SLACK_NOTIFY_SUBTITLEDOWNLOAD = config.checkbox_to_value(slack_notify_onsubtitledownload)
app.SLACK_WEBHOOK = slack_webhook

config.change_USE_TRAKT(use_trakt)
app.TRAKT_USERNAME = trakt_username
app.TRAKT_REMOVE_WATCHLIST = config.checkbox_to_value(trakt_remove_watchlist)
Expand Down
8 changes: 8 additions & 0 deletions medusa/server/web/home/handler.py
Expand Up @@ -328,6 +328,14 @@ def testTelegram(telegram_id=None, telegram_apikey=None):
else:
return 'Error sending Telegram notification: {msg}'.format(msg=message)

@staticmethod
def testslack(slack_webhook=None):
result = notifiers.slack_notifier.test_notify(slack_webhook)
if result:
return 'Slack notification succeeded. Check your Slack channel to make sure it worked'
else:
return 'Error sending Slack notification'

@staticmethod
def testGrowl(host=None, password=None):
success = 'Registered and Tested growl successfully'
Expand Down
12 changes: 10 additions & 2 deletions static/css/style.css
Expand Up @@ -1994,6 +1994,7 @@ config*.mako
}

.component-group-desc {
margin-top: 5px;
float: left;
width: 250px;
}
Expand Down Expand Up @@ -2470,13 +2471,12 @@ div.metadataDiv .disabled {
.icon-notifiers-telegram {
background-position: -587px 0;
}

.icon-notifiers-twitter {
background-position: -624px 0;
}

.icon-notifiers-trakt {
background-position: -659px 0;
background-position: -660px 0;
}

.icon-notifiers-email {
Expand All @@ -2491,6 +2491,14 @@ div.metadataDiv .disabled {
background-position: -769px 0;
}

.icon-notifiers-slack {
background-position: -804px 0;
}

div#config-components h3 > a {
padding-left: 5px;
}

/* =======================================================================
manage*.mako
========================================================================== */
Expand Down
Binary file modified static/images/32x_sprite_colored_notifiers.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions static/js/config/notifications.js
Expand Up @@ -378,6 +378,26 @@ MEDUSA.config.notifications = function() { // eslint-disable-line max-lines
});
});

$('#testSlack').on('click', function() {
var slack = {};
slack.webhook = $.trim($('#slack_webhook').val());

if (!slack.webhook) {
$('#testSlack-result').html('Please fill out the necessary fields above.');
$('#slack_webhook').addRemoveWarningClass(slack.webhook);
return;
}
$('#slack_webhook').removeClass('warning');
$(this).prop('disabled', true);
$('#testSlack-result').html(MEDUSA.config.loading);
$.get('home/testslack', {
slack_webhook: slack.webhook // eslint-disable-line camelcase
}).done(function(data) {
$('#testSlack-result').html(data);
$('#testSlack').prop('disabled', false);
});
});

$('#TraktGetPin').on('click', function() {
window.open($('#trakt_pin_url').val(), 'popUp', 'toolbar=no, scrollbars=no, resizable=no, top=200, left=200, width=650, height=550');
$('#trakt_pin').prop('disabled', false);
Expand Down

0 comments on commit 38e6cbf

Please sign in to comment.