diff --git a/gui/slick/images/notifiers/telegram.png b/gui/slick/images/notifiers/telegram.png new file mode 100644 index 0000000000000000000000000000000000000000..427d6cc567cd3c5888721c57552cbe664038193d Binary files /dev/null and b/gui/slick/images/notifiers/telegram.png differ diff --git a/gui/slick/js/core.js b/gui/slick/js/core.js index a709733b677120187e5fbfcbfac66ce050c05b9a..4784e58767dd08beb118a43263ba9d3875683342 100644 --- a/gui/slick/js/core.js +++ b/gui/slick/js/core.js @@ -700,6 +700,36 @@ var SICKRAGE = { }); }); + $('#testTelegram').on('click', function () { + var telegram = {}; + telegram.id = $.trim($('#telegram_id').val()); + telegram.apikey = $.trim($('#telegram_apikey').val()); + if (!telegram.id || !telegram.apikey) { + $('#testTelegram-result').html('Please fill out the necessary fields above.'); + if (!telegram.id) { + $('#telegram_id').addClass('warning'); + } else { + $('#telegram_id').removeClass('warning'); + } + if (!telegram.apikey) { + $('#telegram_apikey').addClass('warning'); + } else { + $('#telegram_apikey').removeClass('warning'); + } + return; + } + $('#telegram_id,#telegram_apikey').removeClass('warning'); + $(this).prop('disabled', true); + $('#testTelegram-result').html(loading); + $.get(srRoot + '/home/testTelegram', { + 'telegram_id': telegram.id, + 'telegram_apikey': telegram.apikey + }).done(function (data) { + $('#testTelegram-result').html(data); + $('#testTelegram').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').removeClass('hide'); diff --git a/gui/slick/js/core.min.js b/gui/slick/js/core.min.js index b686b374013131b21bb08e46f6b17fb3ccbf8387..0e5d8c3ab3dba6c9fa22f35b013eba434e9be19c 100644 Binary files a/gui/slick/js/core.min.js and b/gui/slick/js/core.min.js differ diff --git a/gui/slick/views/config_notifications.mako b/gui/slick/views/config_notifications.mako index ac84c8e66d8d1bcbdfc9221543b7605f294b9c42..3da70fb383bd40ba6c229a47d38e41a3bbb2189f 100644 --- a/gui/slick/views/config_notifications.mako +++ b/gui/slick/views/config_notifications.mako @@ -1388,6 +1388,79 @@ </fieldset> </div><!-- /freemobile component-group //--> + <div class="component-group"> + <div class="component-group-desc"> + <img class="notifier-icon" src="${srRoot}/images/notifiers/telegram.png" alt="" title="Telegram" /> + <h3><a href="${anon_url('https://telegram.org/')}" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">Telegram</a></h3> + <p>Telegram is a cloud-based instant messaging service.</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" ${('', 'checked="checked"')[bool(sickbeard.USE_TELEGRAM)]}/> + <p>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" ${('', 'checked="checked"')[bool(sickbeard.TELEGRAM_NOTIFY_ONSNATCH)]}/> + <p>Send a Telegram message 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" ${('', 'checked="checked"')[bool(sickbeard.TELEGRAM_NOTIFY_ONDOWNLOAD)]}/> + <p>Send a Telegram message when a download finishes?</p> + </span> + </label> + </div> + </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" ${('', 'checked="checked"')[bool(sickbeard.TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD)]}/> + <p>Send a Telegram message when subtitles are downloaded?</p> + </span> + </label> + </div> + <div class="field-pair"> + <label for="telegram_id"> + <span class="component-title">Telegram user/group ID</span> + <input type="text" name="telegram_id" id="telegram_id" value="${sickbeard.TELEGRAM_ID}" class="form-control input-sm input250" autocapitalize="off" /> + </label> + <label> + <span class="component-title"> </span> + <span class="component-desc">Contact @myidbot on Telegram to get an ID</span> + </label> + </div> + <div class="field-pair"> + <label for="telegram_password"> + <span class="component-title">Telegram bot API token</span> + <input type="text" name="telegram_apikey" id="telegram_apikey" value="${sickbeard.TELEGRAM_APIKEY}" class="form-control input-sm input250" autocapitalize="off" /> + </label> + <label> + <span class="component-title"> </span> + <span class="component-desc">Contact @BotFather on Telegram to set up one</span> + </label> + </div> + <div class="testNotification" id="testTelegram-result">Click below to test your settings.</div> + <input class="btn" type="button" value="Test Telegram" id="testTelegram" /> + <input type="submit" class="config_submitter btn" value="Save Changes" /> + </div><!-- /content_use_telegram //--> + + </fieldset> + </div><!-- /telegram component-group //--> </div> diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 5975c78669b8395ac70c0083a60c8e8c3c4dc556..db363953754def0519369ba68aca1de42a50bd80 100644 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -374,6 +374,13 @@ FREEMOBILE_NOTIFY_ONSUBTITLEDOWNLOAD = False FREEMOBILE_ID = '' FREEMOBILE_APIKEY = '' +USE_TELEGRAM = False +TELEGRAM_NOTIFY_ONSNATCH = False +TELEGRAM_NOTIFY_ONDOWNLOAD = False +TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD = False +TELEGRAM_ID = '' +TELEGRAM_APIKEY = '' + USE_PROWL = False PROWL_NOTIFY_ONSNATCH = False PROWL_NOTIFY_ONDOWNLOAD = False @@ -593,6 +600,7 @@ def initialize(consoleLogging=True): NEWZNAB_DATA, NZBS, NZBS_UID, NZBS_HASH, INDEXER_DEFAULT, INDEXER_TIMEOUT, USENET_RETENTION, TORRENT_DIR, \ QUALITY_DEFAULT, FLATTEN_FOLDERS_DEFAULT, SUBTITLES_DEFAULT, STATUS_DEFAULT, STATUS_DEFAULT_AFTER, \ GROWL_NOTIFY_ONSNATCH, GROWL_NOTIFY_ONDOWNLOAD, GROWL_NOTIFY_ONSUBTITLEDOWNLOAD, TWITTER_NOTIFY_ONSNATCH, TWITTER_NOTIFY_ONDOWNLOAD, TWITTER_NOTIFY_ONSUBTITLEDOWNLOAD, USE_FREEMOBILE, FREEMOBILE_ID, FREEMOBILE_APIKEY, FREEMOBILE_NOTIFY_ONSNATCH, FREEMOBILE_NOTIFY_ONDOWNLOAD, FREEMOBILE_NOTIFY_ONSUBTITLEDOWNLOAD, \ + USE_TELEGRAM, TELEGRAM_ID, TELEGRAM_APIKEY, TELEGRAM_NOTIFY_ONSNATCH, TELEGRAM_NOTIFY_ONDOWNLOAD, TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD, \ USE_GROWL, GROWL_HOST, GROWL_PASSWORD, USE_PROWL, PROWL_NOTIFY_ONSNATCH, PROWL_NOTIFY_ONDOWNLOAD, PROWL_NOTIFY_ONSUBTITLEDOWNLOAD, PROWL_API, PROWL_PRIORITY, PROWL_MESSAGE_TITLE, \ USE_PYTIVO, PYTIVO_NOTIFY_ONSNATCH, PYTIVO_NOTIFY_ONDOWNLOAD, PYTIVO_NOTIFY_ONSUBTITLEDOWNLOAD, PYTIVO_UPDATE_LIBRARY, PYTIVO_HOST, PYTIVO_SHARE_NAME, PYTIVO_TIVO_NAME, \ USE_NMA, NMA_NOTIFY_ONSNATCH, NMA_NOTIFY_ONDOWNLOAD, NMA_NOTIFY_ONSUBTITLEDOWNLOAD, NMA_API, NMA_PRIORITY, \ @@ -1021,6 +1029,13 @@ def initialize(consoleLogging=True): FREEMOBILE_ID = check_setting_str(CFG, 'FreeMobile', 'freemobile_id', '') FREEMOBILE_APIKEY = check_setting_str(CFG, 'FreeMobile', 'freemobile_apikey', '') + 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_ID = check_setting_str(CFG, 'Telegram', 'telegram_id', '') + TELEGRAM_APIKEY = check_setting_str(CFG, 'Telegram', 'telegram_apikey', '') + USE_PROWL = bool(check_setting_int(CFG, 'Prowl', 'use_prowl', 0)) PROWL_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Prowl', 'prowl_notify_onsnatch', 0)) PROWL_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Prowl', 'prowl_notify_ondownload', 0)) @@ -1930,6 +1945,14 @@ def save_config(): new_config['FreeMobile']['freemobile_id'] = FREEMOBILE_ID new_config['FreeMobile']['freemobile_apikey'] = FREEMOBILE_APIKEY + new_config['Telegram'] = {} + new_config['Telegram']['use_telegram'] = int(USE_TELEGRAM) + new_config['Telegram']['telegram_notify_onsnatch'] = int(TELEGRAM_NOTIFY_ONSNATCH) + new_config['Telegram']['telegram_notify_ondownload'] = int(TELEGRAM_NOTIFY_ONDOWNLOAD) + new_config['Telegram']['telegram_notify_onsubtitledownload'] = int(TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD) + new_config['Telegram']['telegram_id'] = TELEGRAM_ID + new_config['Telegram']['telegram_apikey'] = TELEGRAM_APIKEY + new_config['Prowl'] = {} new_config['Prowl']['use_prowl'] = int(USE_PROWL) new_config['Prowl']['prowl_notify_onsnatch'] = int(PROWL_NOTIFY_ONSNATCH) diff --git a/sickbeard/notifiers/__init__.py b/sickbeard/notifiers/__init__.py index ab4472ec4acc4b3d791af006584f468f8dbb7867..6609343a229eeeca00bfb2ba2fa4e341a8986064 100644 --- a/sickbeard/notifiers/__init__.py +++ b/sickbeard/notifiers/__init__.py @@ -37,6 +37,8 @@ import nma import pushalot import pushbullet import freemobile +import telegram + import tweet import trakt @@ -61,6 +63,7 @@ nma_notifier = nma.NMA_Notifier() pushalot_notifier = pushalot.PushalotNotifier() pushbullet_notifier = pushbullet.PushbulletNotifier() freemobile_notifier = freemobile.FreeMobileNotifier() +telegram_notifier = telegram.TelegramNotifier() # social twitter_notifier = tweet.TwitterNotifier() trakt_notifier = trakt.TraktNotifier() @@ -77,6 +80,7 @@ notifiers = [ pytivo_notifier, growl_notifier, freemobile_notifier, + telegram_notifier, prowl_notifier, pushover_notifier, boxcar2_notifier, diff --git a/sickbeard/notifiers/telegram.py b/sickbeard/notifiers/telegram.py new file mode 100644 index 0000000000000000000000000000000000000000..d3559c0b186b9e592e382f96f2cf9b61cd90e61e --- /dev/null +++ b/sickbeard/notifiers/telegram.py @@ -0,0 +1,133 @@ +# coding=utf-8 + +# Author: Marvin Pinto <me@marvinp.ca> +# Author: Dennis Lutter <lad1337@gmail.com> +# Author: Aaron Bieber <deftly@gmail.com> +# URL: http://code.google.com/p/sickbeard/ +# +# This file is part of SickRage. +# +# SickRage 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. +# +# SickRage 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 SickRage. If not, see <http://www.gnu.org/licenses/>. +import urllib +import urllib2 + +import sickbeard +from sickbeard import logger +from sickbeard.common import notifyStrings, NOTIFY_SNATCH, NOTIFY_DOWNLOAD, NOTIFY_SUBTITLE_DOWNLOAD, NOTIFY_GIT_UPDATE, NOTIFY_GIT_UPDATE_TEXT, NOTIFY_GIT_UPDATE_TEXT + + +class TelegramNotifier(object): + + def test_notify(self, id=None, apiKey=None): + return self._notifyTelegram('Test', "This is a test notification from SickRage", id, apiKey, force=True) + + def _sendTelegramMsg(self, title, msg, id=None, apiKey=None): + """ + Sends a Telegram notification + + title: The title of the notification to send + msg: The message string to send + id: The Telegram user/group id to send the message to + apikey: Your Telegram bot API token + + returns: True if the message succeeded, False otherwise + """ + + if id is None: + id = sickbeard.TELEGRAM_ID + if apiKey is None: + apiKey = sickbeard.TELEGRAM_APIKEY + + logger.log(u"Telegram in use with API KEY: " + apiKey, logger.DEBUG) + + message = title.encode('utf-8') + ": " + msg.encode('utf-8') + payload = urllib.urlencode({'chat_id': id, 'text': message}) + TELEGRAM_API = "https://api.telegram.org/bot%s/%s" + + req = urllib2.Request(TELEGRAM_API % (apiKey, "sendMessage"), payload) + + try: + urllib2.urlopen(req) + except IOError as e: + if hasattr(e, 'code'): + if e.code == 400: + message = "Missing parameter(s)." + logger.log(message, logger.ERROR) + return False, message + if e.code == 401: + message = "Authentication failed." + logger.log(message, logger.ERROR) + return False, message + if e.code == 420: + message = "Too many messages." + logger.log(message, logger.ERROR) + return False, message + if e.code == 500: + message = "Server error. Please retry in few moment." + logger.log(message, logger.ERROR) + return False, message + except Exception as e: + message = u"Error while sending Telegram message: {0}".format(e) + logger.log(message, logger.ERROR) + return False, message + + message = "Telegram message sent successfully." + logger.log(message, logger.INFO) + return True, message + + def notify_snatch(self, ep_name, title=notifyStrings[NOTIFY_SNATCH]): + if sickbeard.TELEGRAM_NOTIFY_ONSNATCH: + self._notifyTelegram(title, ep_name) + + def notify_download(self, ep_name, title=notifyStrings[NOTIFY_DOWNLOAD]): + if sickbeard.TELEGRAM_NOTIFY_ONDOWNLOAD: + self._notifyTelegram(title, ep_name) + + def notify_subtitle_download(self, ep_name, lang, title=notifyStrings[NOTIFY_SUBTITLE_DOWNLOAD]): + if sickbeard.TELEGRAM_NOTIFY_ONSUBTITLEDOWNLOAD: + self._notifyTelegram(title, ep_name + ": " + lang) + + def notify_git_update(self, new_version="??"): + if sickbeard.USE_TELEGRAM: + update_text = notifyStrings[NOTIFY_GIT_UPDATE_TEXT] + title = notifyStrings[NOTIFY_GIT_UPDATE] + self._notifyTelegram(title, update_text + new_version) + + def notify_login(self, ipaddress=""): + if sickbeard.USE_TELEGRAM: + update_text = common.notifyStrings[common.NOTIFY_LOGIN_TEXT] + title = common.notifyStrings[common.NOTIFY_LOGIN] + self._notifyTelegram(title, update_text.format(ipaddress)) + + def _notifyTelegram(self, title, message, id=None, apiKey=None, force=False): + """ + Sends a Telegram notification + + title: The title of the notification to send + message: The message string to send + id: The Telegram user/group id to send the message to + apikey: Your Telegram bot API token + force: Enforce sending, for instance for testing + """ + + if not sickbeard.USE_TELEGRAM and not force: + logger.log("Notification for Telegram not enabled, skipping this notification", logger.DEBUG) + return False, "Disabled" + + logger.log("Sending a Telegram message for " + message, logger.DEBUG) + + return self._sendTelegramMsg(title, message, id, apiKey) + + +notifier = TelegramNotifier diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index e18889e7f68afb9bd162b04cf45538d9cf2d040c..82d3fa3bece64e0667dd1acc0d5f979008881a33 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -802,6 +802,15 @@ class Home(WebRoot): else: return "Problem sending SMS: " + message + @staticmethod + def testTelegram(telegram_id=None, telegram_apikey=None): + + result, message = notifiers.telegram_notifier.test_notify(telegram_id, telegram_apikey) + if result: + return "Telegram notification succeeded. Check your Telegram clients to make sure it worked" + else: + return "Error sending Telegram notification: " + message + @staticmethod def testGrowl(host=None, password=None): # self.set_header('Cache-Control', 'max-age=0,no-cache,no-store') @@ -4752,6 +4761,8 @@ class ConfigNotifications(Config): growl_notify_onsubtitledownload=None, growl_host=None, growl_password=None, use_freemobile=None, freemobile_notify_onsnatch=None, freemobile_notify_ondownload=None, freemobile_notify_onsubtitledownload=None, freemobile_id=None, freemobile_apikey=None, + use_telegram=None, telegram_notify_onsnatch=None, telegram_notify_ondownload=None, + telegram_notify_onsubtitledownload=None, telegram_id=None, telegram_apikey=None, use_prowl=None, prowl_notify_onsnatch=None, prowl_notify_ondownload=None, prowl_notify_onsubtitledownload=None, prowl_api=None, prowl_priority=0, prowl_show_list=None, prowl_show=None, prowl_message_title=None, @@ -4833,6 +4844,13 @@ class ConfigNotifications(Config): sickbeard.FREEMOBILE_ID = freemobile_id sickbeard.FREEMOBILE_APIKEY = freemobile_apikey + 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_ID = telegram_id + sickbeard.TELEGRAM_APIKEY = telegram_apikey + sickbeard.USE_PROWL = config.checkbox_to_value(use_prowl) sickbeard.PROWL_NOTIFY_ONSNATCH = config.checkbox_to_value(prowl_notify_onsnatch) sickbeard.PROWL_NOTIFY_ONDOWNLOAD = config.checkbox_to_value(prowl_notify_ondownload)