Browse Source

Add Telegram notifier.

pull/1289/head
JackDandy 5 years ago
parent
commit
8d20a7976d
  1. 1
      CHANGES.md
  2. BIN
      gui/slick/images/notifiers/telegram.png
  3. 85
      gui/slick/interfaces/default/config_notifications.tmpl
  4. 43
      gui/slick/js/configNotifications.js
  5. 6
      lib/apprise/URLBase.py
  6. 15
      lib/apprise/plugins/NotifyTelegram.py
  7. 26
      sickbeard/__init__.py
  8. 3
      sickbeard/notifiers/__init__.py
  9. 61
      sickbeard/notifiers/telegram.py
  10. 18
      sickbeard/webserve.py

1
CHANGES.md

@ -16,6 +16,7 @@
* Update Six compatibility library 1.13.0 (ec58185) to 1.14.0 (3a3db75)
* Update Tornado_py3 Web Server 6.0.3 (ff985fe) to 6.0.xx (18b653c)
* Update urllib3 release 1.25.6 (4a6c288) to 1.25.7 (37ba61a)
* Add Telegram notifier
[develop changelog]

BIN
gui/slick/images/notifiers/telegram.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

85
gui/slick/interfaces/default/config_notifications.tmpl

@ -1425,6 +1425,7 @@
<div class="item"><a href="#slack" rel="noreferrer"><img height="16px" src="$sbRoot/images/notifiers/slack.png">Slack</a></div>
<div class="item"><a href="#discordapp" rel="noreferrer"><img height="16px" src="$sbRoot/images/notifiers/discordapp.png">Discordapp</a></div>
<div class="item"><a href="#gitter" rel="noreferrer"><img height="16px" src="$sbRoot/images/notifiers/gitter.png">Gitter</a></div>
<div class="item"><a href="#telegram" rel="noreferrer"><img height="16px" src="$sbRoot/images/notifiers/telegram.png">Telegram</a></div>
<div class="item"><a href="#email" rel="noreferrer"><img height="16px" src="$sbRoot/images/notifiers/email.png">Email</a></div>
</span>
</div>
@ -1814,7 +1815,7 @@
<div class="component-group">
<div class="component-group-desc">
<img class="notifier-icon" src="$sbRoot/images/notifiers/gitter.png" alt="" title="Gitter">
<h3><a name="gitter" href="<%= anon_url('https://gitter.com/') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">Gitter</a></h3>
<h3><a name="gitter" href="<%= anon_url('https://gitter.im/') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">Gitter</a></h3>
<p>Gitter chat and networking platform.</p>
</div>
<fieldset class="component-group-list">
@ -1883,6 +1884,88 @@
<div class="component-group">
<div class="component-group-desc">
<img class="notifier-icon" src="$sbRoot/images/notifiers/telegram.png" alt="" title="Telegram">
<h3><a name="telegram" href="<%= anon_url('https://telegram.org/') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">Telegram</a></h3>
<p>Mobile and desktop messaging with a focus on security and speed.</p>
</div>
<fieldset class="component-group-list">
<div class="field-pair">
<label for="use-telegram">
<span class="component-title">Enable</span>
<span class="component-desc">
<input type="checkbox" class="enabler" name="use_telegram" id="use-telegram" #if $sickbeard.USE_TELEGRAM then 'checked="checked"' else ''#>
<p>should SickGear send Telegram notifications ?</p>
</span>
</label>
</div>
<div id="content_use-telegram">
<div class="field-pair">
<label for="telegram-notify-onsnatch">
<span class="component-title">Notify on snatch</span>
<span class="component-desc">
<input type="checkbox" name="telegram_notify_onsnatch" id="telegram-notify-onsnatch" #if $sickbeard.TELEGRAM_NOTIFY_ONSNATCH then 'checked="checked"' else ''#>
<p>send a notification when a download starts ?</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="telegram-notify-ondownload">
<span class="component-title">Notify on download</span>
<span class="component-desc">
<input type="checkbox" name="telegram_notify_ondownload" id="telegram-notify-ondownload" #if $sickbeard.TELEGRAM_NOTIFY_ONDOWNLOAD then 'checked="checked"' else ''#>
<p>send a notification when a download finishes ?</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="telegram-notify-onsubtitledownload">
<span class="component-title">Notify on subtitle download</span>
<span class="component-desc">
<input type="checkbox" name="telegram_notify_onsubtitledownload" id="telegram-notify-onsubtitledownload" #if $sickbeard.TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD then 'checked="checked"' else ''#>
<p>send a notification when subtitles are downloaded ?</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="telegram-send-icon">
<span class="component-title">Send icon image</span>
<span class="component-desc">
<input type="checkbox" name="telegram_send_icon" id="telegram-send-icon"#if $sg_var('TELEGRAM_SEND_ICON') then 'checked="checked"' else ''#>
<p>send icon image before the notification</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="telegram-access-token">
<span class="component-title">Telegram bot access token</span>
<span class="component-desc">
<input type="text" name="telegram_access_token" id="telegram-access-token" value="$sickbeard.TELEGRAM_ACCESS_TOKEN" class="form-control input-sm input350">
<div class="clear-left"><p>msg BotFather with <code>/newbot</code> for a token. (tip: enter <code>tg://resolve?domain=BotFather</code> in a browser to make a running desktop client connect to BotFather)</p></div>
</span>
</label>
</div>
<div class="field-pair">
<label for="telegram-chatid">
<span class="component-title">Telegram chat id</span>
<span class="component-desc">
<input type="text" name="telegram_chatid" id="telegram-chatid" value="$sickbeard.TELEGRAM_CHATID" class="form-control input-sm input250">
<span style="float:left">where to send notifications</span>
<div class="clear-left"><p>if a private msg has already been sent to the bot, the "Test..." button<br>
will auto-fill the chat id. Otherwise, find and enter a chat id manually</p></div>
</span>
</label>
</div>
<div class="test-notification" id="test-telegram-result">Click below to test</div>
<input type="button" class="btn" value="Test Telegram" id="test-telegram">
<input type="submit" class="btn config_submitter" value="Save Changes">
</div><!-- /content_use-telegram //-->
</fieldset>
</div><!-- /telegram component-group //-->
<div class="component-group">
<div class="component-group-desc">
<img class="notifier-icon" src="$sbRoot/images/notifiers/email.png" alt="" title="Email">
<h3><a name="email" href="<%= anon_url('http://en.wikipedia.org/wiki/Comparison_of_webmail_providers') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">Email</a></h3>
<p>Email notification settings.</p>

43
gui/slick/js/configNotifications.js

@ -2,6 +2,7 @@
/** @namespace JSONData.account_name */
/** @namespace JSONData.error_message */
/** @namespace JSONData.num_accounts */
/** @namespace JSONData.chatid */
$(document).ready(function(){
var loading = '<img src="' + sbRoot + '/images/loading16' + themeSpinner + '.gif" height="16" width="16" />';
@ -509,6 +510,48 @@ $(document).ready(function(){
}
});
$('#test-telegram').click(function () {
var telegramSendIcon = $('#telegram-send-icon').prop('checked'),
accessToken = '#telegram-access-token', telegramAccessToken = $(accessToken).val().replace(/\s/g, ''),
chatid = '#telegram-chatid', telegramChatid = $(chatid).val().replace(/\s/g, '');
$(accessToken + ', ' + chatid).removeClass('warning');
if (!telegramAccessToken) {
$('#test-telegram-result').html('Please fill out the necessary fields above.');
$(accessToken).addClass('warning');
} else {
$(this).prop('disabled', !0);
$('#test-telegram-result').html(loading);
$.getJSON(sbRoot + '/home/test-telegram',
{send_icon: telegramSendIcon, access_token: telegramAccessToken, chatid: telegramChatid})
.done(function (JSONdata) {
$('#test-telegram-result').html(JSONdata.result);
if ('' === telegramChatid) {
if ('' === JSONdata.chatid) {
$(chatid).addClass('warning');
} else {
$(chatid).val(JSONdata.chatid);
}
}
$('#test-telegram').prop('disabled', !1);
});
}
});
$('.config_submitter').click(function (e) {
if ($('#use-telegram').prop('checked')){
var chatid$ = $('#telegram-chatid');
if ('' === chatid$.val().replace(/\s/g, '')){
chatid$.addClass('warning');
alert('Cannot save, Telegram is enabled and the chat id field needs attention');
e.preventDefault();
return !1;
} else {
chatid$.removeClass('warning');
}
}
});
function getPushbulletDevices (msg) {
var pushbulletAccessToken = $.trim($('#pushbullet-access-token').val());
if (!pushbulletAccessToken) {

6
lib/apprise/URLBase.py

@ -47,6 +47,8 @@ from .utils import parse_url
from .utils import parse_bool
from .utils import parse_list
from six import iteritems
# Used to break a path list into parts
PATHSPLIT_LIST_DELIM = re.compile(r'[ \t\r\n,\\/]+')
@ -378,7 +380,7 @@ class URLBase(object):
pass in an empty variable, set it to an empty string.
Args:
query (str): The dictionary to encode
query (dict): The dictionary to encode
doseq (:obj:`bool`, optional): Handle sequences
safe (:obj:`str`): non-ascii characters and URI specific ones that
you do not wish to escape (if detected). Setting this string
@ -391,7 +393,7 @@ class URLBase(object):
str: The escaped parameters returned as a string
"""
# Tidy query by eliminating any records set to None
_query = {k: v for (k, v) in query.items() if v is not None}
_query = {k: v for (k, v) in iteritems(query) if v is not None}
try:
# Python v3.x
return _urlencode(

15
lib/apprise/plugins/NotifyTelegram.py

@ -87,6 +87,8 @@ class NotifyTelegram(NotifyBase):
# The services URL
service_url = 'https://telegram.org/'
icon_path = None
# The default secure protocol
secure_protocol = 'tgram'
@ -182,7 +184,6 @@ class NotifyTelegram(NotifyBase):
'name': _('Target Chat ID'),
'type': 'string',
'map_to': 'targets',
'map_to': 'targets',
'regex': (r'^((-?[0-9]{1,32})|([a-z_-][a-z0-9_-]+))$', 'i'),
},
'targets': {
@ -264,7 +265,6 @@ class NotifyTelegram(NotifyBase):
# Our function name and payload are determined on the path
function_name = 'SendPhoto'
key = 'photo'
path = None
if isinstance(attach, AttachBase):
if not attach:
@ -295,7 +295,8 @@ class NotifyTelegram(NotifyBase):
return True
# Take on specified attachent as path
path = attach
# hack in self.icon_path to use alt icon as nothing on homepage docs shows how)
path = self.icon_path or attach
file_name = os.path.basename(path)
url = '%s%s/%s' % (
@ -385,9 +386,6 @@ class NotifyTelegram(NotifyBase):
'Telegram User Detection POST URL: %s (cert_verify=%r)' % (
url, self.verify_certificate))
# Track our response object
response = None
try:
r = requests.post(
url,
@ -427,6 +425,7 @@ class NotifyTelegram(NotifyBase):
return 0
# Track our response object
# Load our response and attempt to fetch our userid
response = loads(r.content)
@ -577,7 +576,7 @@ class NotifyTelegram(NotifyBase):
# Define our path
if not self.send_media(payload['chat_id'], notify_type):
# We failed to send the image associated with our
notify_type
# notify_type
self.logger.warning(
'Failed to send Telegram type image to {}.',
payload['chat_id'])
@ -683,7 +682,7 @@ class NotifyTelegram(NotifyBase):
args=NotifyTelegram.urlencode(args))
@staticmethod
def parse_url(url):
def parse_url(url, **kwargs):
"""
Parses the URL and returns enough arguments that can allow
us to substantiate this object.

26
sickbeard/__init__.py

@ -453,6 +453,14 @@ GITTER_NOTIFY_ONSUBTITLEDOWNLOAD = False
GITTER_ROOM = None
GITTER_ACCESS_TOKEN = None
USE_TELEGRAM = False
TELEGRAM_NOTIFY_ONSNATCH = False
TELEGRAM_NOTIFY_ONDOWNLOAD = False
TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD = False
TELEGRAM_SEND_ICON = True
TELEGRAM_ACCESS_TOKEN = None
TELEGRAM_CHATID = None
USE_EMAIL = False
EMAIL_OLD_SUBJECTS = False
EMAIL_NOTIFY_ONSNATCH = False
@ -701,6 +709,8 @@ def init_stage_1(console_logging):
DISCORDAPP_AS_AUTHED, DISCORDAPP_USERNAME, DISCORDAPP_ICON_URL, DISCORDAPP_AS_TTS, DISCORDAPP_ACCESS_TOKEN,\
USE_GITTER, GITTER_NOTIFY_ONSNATCH, GITTER_NOTIFY_ONDOWNLOAD, GITTER_NOTIFY_ONSUBTITLEDOWNLOAD,\
GITTER_ROOM, GITTER_ACCESS_TOKEN, \
USE_TELEGRAM, TELEGRAM_NOTIFY_ONSNATCH, TELEGRAM_NOTIFY_ONDOWNLOAD, TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD, \
TELEGRAM_SEND_ICON, TELEGRAM_ACCESS_TOKEN, TELEGRAM_CHATID, \
USE_EMAIL, EMAIL_NOTIFY_ONSNATCH, EMAIL_NOTIFY_ONDOWNLOAD, EMAIL_NOTIFY_ONSUBTITLEDOWNLOAD, EMAIL_FROM, \
EMAIL_HOST, EMAIL_PORT, EMAIL_TLS, EMAIL_USER, EMAIL_PASSWORD, EMAIL_LIST, EMAIL_OLD_SUBJECTS
# Anime Settings
@ -1154,6 +1164,15 @@ def init_stage_1(console_logging):
GITTER_ROOM = check_setting_str(CFG, 'Gitter', 'gitter_room', '')
GITTER_ACCESS_TOKEN = check_setting_str(CFG, 'Gitter', 'gitter_access_token', '')
USE_TELEGRAM = bool(check_setting_int(CFG, 'Telegram', 'use_telegram', 0))
TELEGRAM_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Telegram', 'telegram_notify_onsnatch', 0))
TELEGRAM_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Telegram', 'telegram_notify_ondownload', 0))
TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD = bool(check_setting_int(
CFG, 'Telegram', 'telegram_notify_onsubtitledownload', 0))
TELEGRAM_SEND_ICON = bool(check_setting_int(CFG, 'Telegram', 'telegram_send_icon', 1))
TELEGRAM_ACCESS_TOKEN = check_setting_str(CFG, 'Telegram', 'telegram_access_token', '')
TELEGRAM_CHATID = check_setting_str(CFG, 'Telegram', 'telegram_chatid', '')
USE_EMAIL = bool(check_setting_int(CFG, 'Email', 'use_email', 0))
EMAIL_OLD_SUBJECTS = bool(check_setting_int(CFG, 'Email', 'email_old_subjects',
None is not EMAIL_HOST and any(EMAIL_HOST)))
@ -2022,6 +2041,12 @@ def save_config():
('room', GITTER_ROOM),
('access_token', GITTER_ACCESS_TOKEN),
]),
('Telegram', [
('use_%s', int(USE_TELEGRAM)),
('send_icon', int(TELEGRAM_SEND_ICON)),
('access_token', TELEGRAM_ACCESS_TOKEN),
('chatid', TELEGRAM_CHATID),
]),
('Email', [
('use_%s', int(USE_EMAIL)),
('old_subjects', int(EMAIL_OLD_SUBJECTS)),
@ -2063,6 +2088,7 @@ def save_config():
('Slack', SLACK_NOTIFY_ONSNATCH, SLACK_NOTIFY_ONDOWNLOAD, SLACK_NOTIFY_ONSUBTITLEDOWNLOAD),
('Discordapp', DISCORDAPP_NOTIFY_ONSNATCH, DISCORDAPP_NOTIFY_ONDOWNLOAD, DISCORDAPP_NOTIFY_ONSUBTITLEDOWNLOAD),
('Gitter', GITTER_NOTIFY_ONSNATCH, GITTER_NOTIFY_ONDOWNLOAD, GITTER_NOTIFY_ONSUBTITLEDOWNLOAD),
('Telegram', TELEGRAM_NOTIFY_ONSNATCH, TELEGRAM_NOTIFY_ONDOWNLOAD, TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD),
('Email', EMAIL_NOTIFY_ONSNATCH, EMAIL_NOTIFY_ONDOWNLOAD, EMAIL_NOTIFY_ONSUBTITLEDOWNLOAD),
]:
if any([onsnatch, ondownload, onsubtitledownload]):

3
sickbeard/notifiers/__init__.py

@ -23,7 +23,7 @@ import re
# from lib import libtrakt
from . import emby, kodi, plex, xbmc, \
boxcar2, nmj, nmjv2, pushbullet, pushover, pytivo, synoindex, synologynotifier, \
discordapp, emailnotify, gitter, libnotify, growl, prowl, slack, trakt
discordapp, emailnotify, gitter, libnotify, growl, prowl, slack, telegram, trakt
import sickbeard
# noinspection PyPep8Naming
@ -61,6 +61,7 @@ class NotifierFactory(object):
SLACK=slack.SlackNotifier,
DISCORDAPP=discordapp.DiscordappNotifier,
GITTER=gitter.GitterNotifier,
TELEGRAM=telegram.TelegramNotifier,
EMAIL=emailnotify.EmailNotifier,
)

61
sickbeard/notifiers/telegram.py

@ -0,0 +1,61 @@
# coding=utf-8
#
# This file is part of SickGear.
#
# SickGear 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.
#
# SickGear 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 SickGear. If not, see <http://www.gnu.org/licenses/>.
import os
from .generic import Notifier
import sickbeard
# noinspection PyPep8Naming
import encodingKludge as ek
from exceptions_helper import ex
from lib.apprise.plugins.NotifyTelegram import NotifyTelegram
class TelegramNotifier(Notifier):
def __init__(self):
super(TelegramNotifier, self).__init__()
def _notify(self, title, body, send_icon='', access_token='', chatid='', **kwargs):
result = None
cid = ''
use_icon = bool(self._choose(send_icon, sickbeard.TELEGRAM_SEND_ICON))
try:
tg = NotifyTelegram(
bot_token=self._choose(access_token, sickbeard.TELEGRAM_ACCESS_TOKEN),
targets=self._choose(chatid, sickbeard.TELEGRAM_CHATID),
include_image=use_icon
)
cid = chatid or isinstance(tg.targets, list) and 1 == len(tg.targets) and tg.targets[0] or ''
if use_icon:
tg.icon_path = ek.ek(os.path.join, sickbeard.PROG_DIR, 'gui', 'slick',
'images', 'ico', 'apple-touch-icon-76x76.png')
tg.image_size = '72x72'
result = tg.send(body, title=title)
except (BaseException, Exception) as e:
if 'No chat_id' in ex(e):
result = 'a chat id is not set, and a msg has not been sent to the bot to auto detect one.'
if True is not result:
self._log_error('Failed to send message, %s' % result)
return dict(chatid=cid,
result=self._choose(('Successful test notice sent.',
'Error sending notification, %s' % result)[True is not result], result))
notifier = TelegramNotifier

18
sickbeard/webserve.py

@ -1772,6 +1772,13 @@ class Home(MainHandler):
return notifiers.NotifierFactory().get('GITTER').test_notify(
room_name=room_name, access_token=access_token)
def test_telegram(self, send_icon=False, access_token=None, chatid=None):
self.set_header('Cache-Control', 'max-age=0,no-cache,no-store')
r = notifiers.NotifierFactory().get('TELEGRAM').test_notify(
send_icon=bool(config.checkbox_to_value(send_icon)), access_token=access_token, chatid=chatid)
return json.dumps(r)
def test_email(self, host=None, port=None, smtp_from=None, use_tls=None, user=None, pwd=None, to=None):
self.set_header('Cache-Control', 'max-age=0,no-cache,no-store')
@ -7255,6 +7262,9 @@ class ConfigNotifications(Config):
discordapp_as_tts=None,
use_gitter=None, gitter_notify_onsnatch=None, gitter_notify_ondownload=None,
gitter_notify_onsubtitledownload=None, gitter_access_token=None, gitter_room=None,
use_telegram=None, telegram_notify_onsnatch=None, telegram_notify_ondownload=None,
telegram_notify_onsubtitledownload=None, telegram_access_token=None, telegram_chatid=None,
telegram_send_icon=None,
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,
@ -7410,6 +7420,14 @@ class ConfigNotifications(Config):
sickbeard.GITTER_ACCESS_TOKEN = gitter_access_token
sickbeard.GITTER_ROOM = gitter_room
sickbeard.USE_TELEGRAM = config.checkbox_to_value(use_telegram)
sickbeard.TELEGRAM_NOTIFY_ONSNATCH = config.checkbox_to_value(telegram_notify_onsnatch)
sickbeard.TELEGRAM_NOTIFY_ONDOWNLOAD = config.checkbox_to_value(telegram_notify_ondownload)
sickbeard.TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD = config.checkbox_to_value(telegram_notify_onsubtitledownload)
sickbeard.TELEGRAM_ACCESS_TOKEN = telegram_access_token
sickbeard.TELEGRAM_CHATID = telegram_chatid
sickbeard.TELEGRAM_SEND_ICON = config.checkbox_to_value(telegram_send_icon)
sickbeard.USE_EMAIL = config.checkbox_to_value(use_email)
sickbeard.EMAIL_NOTIFY_ONSNATCH = config.checkbox_to_value(email_notify_onsnatch)
sickbeard.EMAIL_NOTIFY_ONDOWNLOAD = config.checkbox_to_value(email_notify_ondownload)

Loading…
Cancel
Save