Skip to content

Commit

Permalink
Branch matrix notifications (#5377)
Browse files Browse the repository at this point in the history
* Matrix support

* UI Fix: Matrix logo CSS was wrong

* Wierd debugging

* Bugs squashed

* Bugs squashed

* Fixed whitespace issue

* Fix isort
  • Loading branch information
jmtsantos authored and miigotu committed May 20, 2019
1 parent 175df89 commit 294c180
Show file tree
Hide file tree
Showing 10 changed files with 317 additions and 18 deletions.
6 changes: 6 additions & 0 deletions gui/slick/css/style.css
Expand Up @@ -2032,6 +2032,12 @@ div.metadataDiv .disabled {
background-size: 32px;
}

.icon-notifiers-matrix {
background: url("../images/Matrix_Web.png");
background-size: 32px;
background-color: white;
}

.icon-notifiers-discord {
background: url("../images/32px_discord_notifier.png");
background-size: 32px;
Expand Down
Binary file added gui/slick/images/Matrix_Web.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions gui/slick/js/core.js
Expand Up @@ -726,6 +726,12 @@ var SICKCHILL = {
});
});

$('#testMatrix').on('click', function() {
$.post(srRoot + '/home/testMatrix', function(data) {
$('#testMatrix-result').html(data);
});
});

$('#testDiscord').on('click', function() {
$.get(srRoot + '/home/testDiscord', function(data) {
$('#testDiscord-result').html(data);
Expand Down
2 changes: 1 addition & 1 deletion gui/slick/js/core.min.js

Large diffs are not rendered by default.

121 changes: 121 additions & 0 deletions gui/slick/views/config_notifications.mako
Expand Up @@ -3121,6 +3121,127 @@
<div class="config-group-divider"></div>
<!-- /matrix component-group //-->
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-4 col-xs-12">
<div class="component-group-desc">
<span class="icon-notifiers-matrix" title="${_('Matrix')}"></span>
<h3><a href="${anon_url('http://www.matrix.org/')}" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">Matrix</a></h3>
<p>${_('Matrix is an open fabric for communication that anyone can participate in.')}</p>
</div>
</div>
<div class="col-lg-9 col-md-8 col-sm-8 col-xs-12">
<fieldset class="component-group-list">
<div class="field-pair row">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">${_('Enable')}</label>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<div class="row">
<div class="col-md-12">
<input type="checkbox" class="enabler" name="use_matrix" id="use_matrix" ${('', 'checked="checked"')[bool(sickbeard.USE_MATRIX)]}/>
<label for="use_matrix">${_('should SickChill post messages on Matrix?')}</label>
</div>
</div>
</div>
</div>
<div id="content_use_matrix">
<div class="field-pair row">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">${_('Notify on snatch')}</label>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<input type="checkbox" name="matrix_notify_snatch" id="matrix_notify_snatch" ${('', 'checked="checked"')[bool(sickbeard.MATRIX_NOTIFY_SNATCH)]}/>
<label for="matrix_notify_snatch">${_('send a notification when a download starts?')}</label>
</div>
</div>
<div class="field-pair row">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">${_('Notify on download')}</label>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<input type="checkbox" name="matrix_notify_download" id="matrix_notify_download" ${('', 'checked="checked"')[bool(sickbeard.MATRIX_NOTIFY_DOWNLOAD)]}/>
<label for="matrix_notify_download">${_('send a notification when a download finishes?')}</label>
</div>
</div>
<div class="field-pair row">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">${_('Notify on subtitle download')}</label>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<input type="checkbox" name="matrix_notify_subtitledownload" id="matrix_notify_subtitledownload" ${('', 'checked="checked"')[bool(sickbeard.MATRIX_NOTIFY_SUBTITLEDOWNLOAD)]}/>
<label for="matrix_notify_subtitledownload">${_('send a notification when subtitles are downloaded?')}</label>
</div>
</div>
<div class="field-pair row">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">${_('matrix User Auth Token')}</label>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<div class="row">
<div class="col-md-12">
<input type="text" name="matrix_api_token" id="matrix_api_token" value="${sickbeard.MATRIX_API_TOKEN}" class="form-control input-sm input350" autocapitalize="off" />
</div>
</div>
</div>
</div>
<div class="field-pair row">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">${_('matrix server address')}</label>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<div class="row">
<div class="col-md-12">
<input type="text" name="matrix_server" id="matrix_server" value="${sickbeard.MATRIX_SERVER}" class="form-control input-sm input350" autocapitalize="off" />
</div>
</div>
</div>
</div>
<div class="field-pair row">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">${_('matrix server room')}</label>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<div class="row">
<div class="col-md-12">
<input type="text" name="matrix_room" id="matrix_room" value="${sickbeard.MATRIX_ROOM}" class="form-control input-sm input350" autocapitalize="off" />
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="testNotification" id="testMatrix-result">${_('Click below to test.')}</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<input class="btn" type="button" value="Test Matrix" id="testMatrix" />
<input type="submit" class="config_submitter btn" value="${_('Save Changes')}" />
</div>
</div>
</div>
</fieldset>
</div>
</div>
<div class="config-group-divider"></div>
<!-- /Discord component-group //-->
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-4 col-xs-12">
Expand Down
51 changes: 39 additions & 12 deletions sickbeard/__init__.py
Expand Up @@ -35,16 +35,8 @@
from configobj import ConfigObj
from tornado.locale import load_gettext_translations

try:
import pytz # pylint: disable=unused-import
except ImportError:
pytz = None
from pkg_resources import require
require('pytz')


from sickbeard import (auto_postprocessor, dailysearcher, db, helpers, logger, metadata, naming, post_processing_queue, properFinder, providers, scheduler,
search_queue, searchBacklog, show_queue, showUpdater, subtitles, traktChecker, versionChecker)
from sickbeard import (auto_postprocessor, dailysearcher, db, helpers, logger, metadata, naming, post_processing_queue, properFinder, providers,
scene_exceptions, scheduler, search_queue, searchBacklog, show_queue, showUpdater, subtitles, traktChecker, versionChecker)
from sickbeard.common import ARCHIVED, IGNORED, MULTI_EP_STRINGS, SD, SKIPPED, WANTED
from sickbeard.config import check_section, check_setting_bool, check_setting_float, check_setting_int, check_setting_str, ConfigMigrator
from sickbeard.databases import cache_db, failed_db, mainDB
Expand All @@ -58,7 +50,15 @@
from sickchill.helper.exceptions import ex
from sickchill.system.Shutdown import Shutdown

from sickbeard import scene_exceptions
try:
import pytz # pylint: disable=unused-import
except ImportError:
pytz = None
from pkg_resources import require
require('pytz')




gettext.install('messages', unicode=1, codeset='UTF-8', names=["ngettext"])

Expand Down Expand Up @@ -500,6 +500,14 @@
SLACK_WEBHOOK = None
SLACK_ICON_EMOJI = None

USE_MATRIX = False
MATRIX_NOTIFY_SNATCH = None
MATRIX_NOTIFY_DOWNLOAD = None
MATRIX_NOTIFY_SUBTITLEDOWNLOAD = None
MATRIX_API_TOKEN = None
MATRIX_SERVER = None
MATRIX_ROOM = None

USE_DISCORD = False
DISCORD_NOTIFY_SNATCH = None
DISCORD_NOTIFY_DOWNLOAD = None
Expand Down Expand Up @@ -722,7 +730,8 @@ def initialize(consoleLogging=True): # pylint: disable=too-many-locals, too-man
DOWNLOAD_URL, BACKLOG_DAYS, GIT_AUTH_TYPE, GIT_USERNAME, GIT_PASSWORD, GIT_TOKEN, DEVELOPER, DISPLAY_ALL_SEASONS, SSL_VERIFY, NEWS_LAST_READ, \
NEWS_LATEST, SOCKET_TIMEOUT, SYNOLOGY_DSM_HOST, SYNOLOGY_DSM_USERNAME, SYNOLOGY_DSM_PASSWORD, SYNOLOGY_DSM_PATH, GUI_LANG, SICKCHILL_BACKGROUND, \
SICKCHILL_BACKGROUND_PATH, FANART_BACKGROUND, FANART_BACKGROUND_OPACITY, CUSTOM_CSS, CUSTOM_CSS_PATH, USE_SLACK, SLACK_NOTIFY_SNATCH, \
SLACK_NOTIFY_DOWNLOAD, SLACK_NOTIFY_SUBTITLEDOWNLOAD, SLACK_WEBHOOK, SLACK_ICON_EMOJI, USE_DISCORD, DISCORD_NOTIFY_SNATCH, DISCORD_NOTIFY_DOWNLOAD, DISCORD_WEBHOOK
SLACK_NOTIFY_DOWNLOAD, SLACK_NOTIFY_SUBTITLEDOWNLOAD, SLACK_WEBHOOK, SLACK_ICON_EMOJI, USE_DISCORD, DISCORD_NOTIFY_SNATCH, DISCORD_NOTIFY_DOWNLOAD, DISCORD_WEBHOOK,\
USE_MATRIX, MATRIX_NOTIFY_SNATCH, MATRIX_NOTIFY_DOWNLOAD, MATRIX_NOTIFY_SUBTITLEDOWNLOAD, MATRIX_API_TOKEN, MATRIX_SERVER, MATRIX_ROOM

if __INITIALIZED__:
return False
Expand Down Expand Up @@ -1241,6 +1250,14 @@ def path_leaf(path):
SLACK_WEBHOOK = check_setting_str(CFG, 'Slack', 'slack_webhook')
SLACK_ICON_EMOJI = check_setting_str(CFG, 'Slack', 'slack_icon_emoji')

USE_MATRIX = check_setting_bool(CFG, 'Matrix', 'use_matrix')
MATRIX_NOTIFY_SNATCH = check_setting_bool(CFG, 'Matrix', 'matrix_notify_snatch')
MATRIX_NOTIFY_DOWNLOAD = check_setting_bool(CFG, 'Matrix', 'matrix_notify_download')
MATRIX_NOTIFY_SUBTITLEDOWNLOAD = check_setting_bool(CFG, 'Matrix', 'matrix_notify_subtitledownload')
MATRIX_API_TOKEN = check_setting_str(CFG, 'Matrix', 'matrix_api_token')
MATRIX_SERVER = check_setting_str(CFG, 'Matrix', 'matrix_server')
MATRIX_ROOM = check_setting_str(CFG, 'Matrix', 'matrix_room')

USE_DISCORD = check_setting_bool(CFG, 'Discord', 'use_discord')
DISCORD_NOTIFY_SNATCH = check_setting_bool(CFG, 'Discord', 'discord_notify_snatch')
DISCORD_NOTIFY_DOWNLOAD = check_setting_bool(CFG, 'Discord', 'discord_notify_download')
Expand Down Expand Up @@ -2155,6 +2172,16 @@ def save_config(): # pylint: disable=too-many-statements, too-many-branches
'slack_icon_emoji': SLACK_ICON_EMOJI
},

'Matrix': {
'use_matrix': int(USE_MATRIX),
'matrix_notify_snatch': int(MATRIX_NOTIFY_SNATCH),
'matrix_notify_download': int(MATRIX_NOTIFY_DOWNLOAD),
'matrix_notify_subtitledownload': int(MATRIX_NOTIFY_SUBTITLEDOWNLOAD),
'matrix_api_token': MATRIX_API_TOKEN,
'matrix_server': MATRIX_SERVER,
'matrix_room': MATRIX_ROOM
},

'Discord': {
'use_discord': int(USE_DISCORD),
'discord_notify_snatch': int(DISCORD_NOTIFY_SNATCH),
Expand Down
6 changes: 4 additions & 2 deletions sickbeard/notifiers/__init__.py
Expand Up @@ -21,8 +21,8 @@
from __future__ import print_function, unicode_literals

import sickbeard
from sickbeard.notifiers import (boxcar2, discord, emailnotify, emby, freemobile, growl, join, kodi, libnotify, nmj, nmjv2, plex, prowl, pushalot, pushbullet,
pushover, pytivo, slack, synoindex, synologynotifier, telegram, trakt, tweet, twilio_notify)
from sickbeard.notifiers import (boxcar2, discord, emailnotify, emby, freemobile, growl, join, kodi, libnotify, matrix, nmj, nmjv2, plex, prowl, pushalot,
pushbullet, pushover, pytivo, slack, synoindex, synologynotifier, telegram, trakt, tweet, twilio_notify)

# home theater / nas
kodi_notifier = kodi.Notifier()
Expand Down Expand Up @@ -51,6 +51,7 @@
trakt_notifier = trakt.Notifier()
email_notifier = emailnotify.Notifier()
slack_notifier = slack.Notifier()
matrix_notifier = matrix.Notifier()
discord_notifier = discord.Notifier()

notifiers = [
Expand All @@ -75,6 +76,7 @@
trakt_notifier,
email_notifier,
slack_notifier,
matrix_notifier,
discord_notifier,
join_notifier,
]
Expand Down
120 changes: 120 additions & 0 deletions sickbeard/notifiers/matrix.py
@@ -0,0 +1,120 @@
# coding=utf-8

# Author: Joao Santos <jmigueltsantos@riseup.net>
#
# This file is part of SickChill.
#
# SickChill is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# SickChill is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with SickChill. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals

import json
import time

import requests
import six

import sickbeard
from sickbeard import common, logger
from sickchill.helper.encoding import ss
from sickchill.helper.exceptions import ex


class Notifier(object):

def notify_snatch(self, ep_name):
if sickbeard.MATRIX_NOTIFY_SNATCH:
show = self._parseEp(ep_name)
message = '''<body>
<h3>SickChill Notification - Snatched</h3>
<p>Show: <b>{0}</b></p><p>Episode Number: <b>{1}</b></p><p>Episode: <b>{2}</b></p><p>Quality: <b>{3}</b></p>
<h5>Powered by SickChill.</h5></body>'''.format(show[0], show[1], show[2], show[3])
self._notify_matrix(message)

def notify_download(self, ep_name):
if sickbeard.MATRIX_NOTIFY_DOWNLOAD:
show = self._parseEp(ep_name)
message = '''<body>
<h3>SickChill Notification - Downloaded</h3>
<p>Show: <b>{0}</b></p><p>Episode Number: <b>{1}</b></p><p>Episode: <b>{2}</b></p><p>Quality: <b>{3}</b></p>
<h5 style="margin-top: 2.5em; padding: .7em 0;
color: #777; border-top: #BBB solid 1px;">
Powered by SickChill.</h5></body>'''.format(show[0], show[1], show[2], show[3])
self._notify_matrix(message)

def notify_subtitle_download(self, ep_name, lang):
if sickbeard.MATRIX_NOTIFY_SUBTITLEDOWNLOAD:
show = self._parseEp(ep_name)
message = '''<body>
<h3>SickChill Notification - Subtitle Downloaded</h3>
<p>Show: <b>{0}</b></p><p>Episode Number: <b>{1}</b></p><p>Episode: <b>{2}</b></p></p>
<p>Language: <b>{3}</b></p>
<h5>Powered by SickChill.</h5></body>'''.format(show[0], show[1], show[2], lang)
self._notify_matrix(message)

def notify_git_update(self, new_version="??"):
if sickbeard.USE_MATRIX:
update_text = common.notifyStrings[common.NOTIFY_GIT_UPDATE_TEXT]
title = common.notifyStrings[common.NOTIFY_GIT_UPDATE]
self._notify_matrix(title + " - " + update_text + new_version)

def notify_login(self, ipaddress=""):
if sickbeard.USE_MATRIX:
update_text = common.notifyStrings[common.NOTIFY_LOGIN_TEXT]
title = common.notifyStrings[common.NOTIFY_LOGIN]
self._notify_matrix(title + " - " + update_text.format(ipaddress))

def test_notify(self):
return self._notify_matrix("This is a test notification from SickChill", force=True)

def _send_matrix(self, message=None):
url = 'https://{0}/_matrix/client/r0/rooms/{1}/send/m.room.message/{2}?access_token={3}'.format(sickbeard.MATRIX_SERVER, sickbeard.MATRIX_ROOM, time.time(), sickbeard.MATRIX_API_TOKEN)

logger.log("Sending matrix message: " + message, logger.INFO)
logger.log("Sending matrix message to url: " + url, logger.INFO)

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

jsonMessage={
"msgtype": "m.text",
"format": "org.matrix.custom.html",
"body": message,
"formatted_body": message,
}

headers = {b"Content-Type": b"application/json"}
try:
r = requests.put(url , data=json.dumps(jsonMessage), headers=headers)
r.raise_for_status()

except Exception as e:
logger.log("Error Sending Matrix message: " + ex(e), logger.ERROR)
return False

return True

def _notify_matrix(self, message='', force=False):
if not sickbeard.USE_MATRIX and not force:
return False

return self._send_matrix(message)

@staticmethod
def _parseEp(ep_name):
ep_name = ss(ep_name)

sep = ' - '
titles = ep_name.split(sep)
logger.log('TITLES: {0}'.format(titles), logger.DEBUG)
return titles

0 comments on commit 294c180

Please sign in to comment.