mirror of https://github.com/caronc/apprise
Merge pull request #57 from caronc/52-telegram-code-block-support
telegram markdown support added; refs #52pull/58/head
commit
042c5ed2da
|
@ -159,9 +159,9 @@ class NotifyBase(object):
|
||||||
self.user = kwargs.get('user')
|
self.user = kwargs.get('user')
|
||||||
self.password = kwargs.get('password')
|
self.password = kwargs.get('password')
|
||||||
|
|
||||||
if 'notify_format' in kwargs:
|
if 'format' in kwargs:
|
||||||
# Store the specified notify_format if specified
|
# Store the specified format if specified
|
||||||
notify_format = kwargs.get('notify_format')
|
notify_format = kwargs.get('format', '')
|
||||||
if notify_format.lower() not in NOTIFY_FORMATS:
|
if notify_format.lower() not in NOTIFY_FORMATS:
|
||||||
self.logger.error(
|
self.logger.error(
|
||||||
'Invalid notification format %s' % notify_format,
|
'Invalid notification format %s' % notify_format,
|
||||||
|
|
|
@ -227,6 +227,9 @@ class NotifyEmail(NotifyBase):
|
||||||
# A URL that takes you to the setup/help of the specific protocol
|
# A URL that takes you to the setup/help of the specific protocol
|
||||||
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_email'
|
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_email'
|
||||||
|
|
||||||
|
# Default Notify Format
|
||||||
|
notify_format = NotifyFormat.HTML
|
||||||
|
|
||||||
# Default Non-Encryption Port
|
# Default Non-Encryption Port
|
||||||
default_port = 25
|
default_port = 25
|
||||||
|
|
||||||
|
@ -433,20 +436,10 @@ class NotifyEmail(NotifyBase):
|
||||||
|
|
||||||
# Apply our settings now
|
# Apply our settings now
|
||||||
|
|
||||||
# Default Format is HTML
|
|
||||||
results['notify_format'] = NotifyFormat.HTML
|
|
||||||
results['secure_mode'] = NotifyEmail.default_secure_mode
|
|
||||||
|
|
||||||
to_addr = ''
|
to_addr = ''
|
||||||
from_addr = ''
|
from_addr = ''
|
||||||
smtp_host = ''
|
smtp_host = ''
|
||||||
|
|
||||||
if 'format' in results['qsd'] and len(results['qsd']['format']):
|
|
||||||
# Extract email format (Text/Html)
|
|
||||||
format = NotifyBase.unquote(results['qsd']['format']).lower()
|
|
||||||
if len(format) > 0 and format[0] == 't':
|
|
||||||
results['notify_format'] = NotifyFormat.TEXT
|
|
||||||
|
|
||||||
# Attempt to detect 'from' email address
|
# Attempt to detect 'from' email address
|
||||||
if 'from' in results['qsd'] and len(results['qsd']['from']):
|
if 'from' in results['qsd'] and len(results['qsd']['from']):
|
||||||
from_addr = NotifyBase.unquote(results['qsd']['from'])
|
from_addr = NotifyBase.unquote(results['qsd']['from'])
|
||||||
|
|
|
@ -62,6 +62,7 @@ from .NotifyBase import HTTP_ERROR_MAP
|
||||||
from ..common import NotifyImageSize
|
from ..common import NotifyImageSize
|
||||||
from ..utils import compat_is_basestring
|
from ..utils import compat_is_basestring
|
||||||
from ..utils import parse_bool
|
from ..utils import parse_bool
|
||||||
|
from ..common import NotifyFormat
|
||||||
|
|
||||||
TELEGRAM_IMAGE_XY = NotifyImageSize.XY_256
|
TELEGRAM_IMAGE_XY = NotifyImageSize.XY_256
|
||||||
|
|
||||||
|
@ -262,7 +263,7 @@ class NotifyTelegram(NotifyBase):
|
||||||
# Try to get the error message if we can:
|
# Try to get the error message if we can:
|
||||||
error_msg = loads(r.content)['description']
|
error_msg = loads(r.content)['description']
|
||||||
|
|
||||||
except:
|
except Exception:
|
||||||
error_msg = None
|
error_msg = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -356,25 +357,51 @@ class NotifyTelegram(NotifyBase):
|
||||||
|
|
||||||
payload = {}
|
payload = {}
|
||||||
|
|
||||||
|
# Prepare Email Message
|
||||||
|
if self.notify_format == NotifyFormat.MARKDOWN:
|
||||||
|
payload['parse_mode'] = 'MARKDOWN'
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Either TEXT or HTML; if TEXT we'll make it HTML
|
||||||
|
payload['parse_mode'] = 'HTML'
|
||||||
|
|
||||||
|
# HTML Spaces ( ) and tabs ( ) aren't supported
|
||||||
|
# See https://core.telegram.org/bots/api#html-style
|
||||||
|
body = re.sub(' ?', ' ', body, re.I)
|
||||||
|
|
||||||
|
# Tabs become 3 spaces
|
||||||
|
body = re.sub(' ?', ' ', body, re.I)
|
||||||
|
|
||||||
|
if title:
|
||||||
# HTML Spaces ( ) and tabs ( ) aren't supported
|
# HTML Spaces ( ) and tabs ( ) aren't supported
|
||||||
# See https://core.telegram.org/bots/api#html-style
|
# See https://core.telegram.org/bots/api#html-style
|
||||||
title = re.sub(' ?', ' ', title, re.I)
|
title = re.sub(' ?', ' ', title, re.I)
|
||||||
body = re.sub(' ?', ' ', body, re.I)
|
|
||||||
# Tabs become 3 spaces
|
# Tabs become 3 spaces
|
||||||
title = re.sub(' ?', ' ', title, re.I)
|
title = re.sub(' ?', ' ', title, re.I)
|
||||||
body = re.sub(' ?', ' ', body, re.I)
|
|
||||||
|
|
||||||
# HTML
|
# HTML
|
||||||
title = NotifyBase.escape_html(title, whitespace=False)
|
title = NotifyBase.escape_html(title, whitespace=False)
|
||||||
body = NotifyBase.escape_html(body, whitespace=False)
|
body = NotifyBase.escape_html(body, whitespace=False)
|
||||||
|
|
||||||
payload['parse_mode'] = 'HTML'
|
# Assign the body
|
||||||
|
payload['text'] = body
|
||||||
|
|
||||||
|
if title and self.notify_format == NotifyFormat.TEXT:
|
||||||
|
# Text HTML Formatting
|
||||||
payload['text'] = '<b>%s</b>\r\n%s' % (
|
payload['text'] = '<b>%s</b>\r\n%s' % (
|
||||||
title,
|
title,
|
||||||
body,
|
body,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
elif title:
|
||||||
|
# Already HTML; trust developer has wrapped
|
||||||
|
# the title appropriately
|
||||||
|
payload['text'] = '%s\r\n%s' % (
|
||||||
|
title,
|
||||||
|
body,
|
||||||
|
)
|
||||||
|
|
||||||
# Create a copy of the chat_ids list
|
# Create a copy of the chat_ids list
|
||||||
chat_ids = list(self.chat_ids)
|
chat_ids = list(self.chat_ids)
|
||||||
while len(chat_ids):
|
while len(chat_ids):
|
||||||
|
@ -426,7 +453,7 @@ class NotifyTelegram(NotifyBase):
|
||||||
# Try to get the error message if we can:
|
# Try to get the error message if we can:
|
||||||
error_msg = loads(r.content)['description']
|
error_msg = loads(r.content)['description']
|
||||||
|
|
||||||
except:
|
except Exception:
|
||||||
error_msg = None
|
error_msg = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -35,7 +35,6 @@ from apprise import NotifyBase
|
||||||
from apprise import NotifyType
|
from apprise import NotifyType
|
||||||
from apprise import NotifyFormat
|
from apprise import NotifyFormat
|
||||||
from apprise import NotifyImageSize
|
from apprise import NotifyImageSize
|
||||||
from apprise import plugins
|
|
||||||
from apprise import __version__
|
from apprise import __version__
|
||||||
from apprise.Apprise import __load_matrix
|
from apprise.Apprise import __load_matrix
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -243,27 +242,35 @@ def test_apprise_notify_formats(tmpdir):
|
||||||
assert(len(a) == 0)
|
assert(len(a) == 0)
|
||||||
|
|
||||||
class TextNotification(NotifyBase):
|
class TextNotification(NotifyBase):
|
||||||
|
# set our default notification format
|
||||||
|
notify_format = NotifyFormat.TEXT
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(TextNotification, self).__init__(
|
super(TextNotification, self).__init__()
|
||||||
notify_format=NotifyFormat.TEXT)
|
|
||||||
|
|
||||||
def notify(self, **kwargs):
|
def notify(self, **kwargs):
|
||||||
# Pretend everything is okay
|
# Pretend everything is okay
|
||||||
return True
|
return True
|
||||||
|
|
||||||
class HtmlNotification(NotifyBase):
|
class HtmlNotification(NotifyBase):
|
||||||
|
|
||||||
|
# set our default notification format
|
||||||
|
notify_format = NotifyFormat.HTML
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(HtmlNotification, self).__init__(
|
super(HtmlNotification, self).__init__()
|
||||||
notify_format=NotifyFormat.HTML)
|
|
||||||
|
|
||||||
def notify(self, **kwargs):
|
def notify(self, **kwargs):
|
||||||
# Pretend everything is okay
|
# Pretend everything is okay
|
||||||
return True
|
return True
|
||||||
|
|
||||||
class MarkDownNotification(NotifyBase):
|
class MarkDownNotification(NotifyBase):
|
||||||
|
|
||||||
|
# set our default notification format
|
||||||
|
notify_format = NotifyFormat.MARKDOWN
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(MarkDownNotification, self).__init__(
|
super(MarkDownNotification, self).__init__()
|
||||||
notify_format=NotifyFormat.MARKDOWN)
|
|
||||||
|
|
||||||
def notify(self, **kwargs):
|
def notify(self, **kwargs):
|
||||||
# Pretend everything is okay
|
# Pretend everything is okay
|
||||||
|
@ -339,7 +346,7 @@ def test_apprise_asset(tmpdir):
|
||||||
# The exception we expect since dict is not supported
|
# The exception we expect since dict is not supported
|
||||||
assert(True)
|
assert(True)
|
||||||
|
|
||||||
except:
|
except Exception:
|
||||||
# Any other exception is not good
|
# Any other exception is not good
|
||||||
assert(False)
|
assert(False)
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
from apprise import plugins
|
from apprise import plugins
|
||||||
from apprise import NotifyType
|
from apprise import NotifyType
|
||||||
from apprise import Apprise
|
from apprise import Apprise
|
||||||
|
from apprise.plugins import NotifyEmailBase
|
||||||
|
|
||||||
import smtplib
|
import smtplib
|
||||||
import mock
|
import mock
|
||||||
import re
|
import re
|
||||||
|
@ -287,8 +289,6 @@ def test_webbase_lookup(mock_smtp, mock_smtpssl):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from apprise.plugins import NotifyEmailBase
|
|
||||||
|
|
||||||
# Insert a test email at the head of our table
|
# Insert a test email at the head of our table
|
||||||
NotifyEmailBase.WEBBASE_LOOKUP_TABLE = (
|
NotifyEmailBase.WEBBASE_LOOKUP_TABLE = (
|
||||||
(
|
(
|
||||||
|
@ -324,8 +324,6 @@ def test_smtplib_init_fail(mock_smtplib):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from apprise.plugins import NotifyEmailBase
|
|
||||||
|
|
||||||
obj = Apprise.instantiate(
|
obj = Apprise.instantiate(
|
||||||
'mailto://user:pass@gmail.com', suppress_exceptions=False)
|
'mailto://user:pass@gmail.com', suppress_exceptions=False)
|
||||||
assert(isinstance(obj, plugins.NotifyEmail))
|
assert(isinstance(obj, plugins.NotifyEmail))
|
||||||
|
@ -362,8 +360,7 @@ def test_smtplib_send_okay(mock_smtplib):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from apprise.plugins import NotifyEmailBase
|
# Defaults to HTML
|
||||||
|
|
||||||
obj = Apprise.instantiate(
|
obj = Apprise.instantiate(
|
||||||
'mailto://user:pass@gmail.com', suppress_exceptions=False)
|
'mailto://user:pass@gmail.com', suppress_exceptions=False)
|
||||||
assert(isinstance(obj, plugins.NotifyEmail))
|
assert(isinstance(obj, plugins.NotifyEmail))
|
||||||
|
@ -374,4 +371,13 @@ def test_smtplib_send_okay(mock_smtplib):
|
||||||
mock_smtplib.sendmail.return_value = True
|
mock_smtplib.sendmail.return_value = True
|
||||||
mock_smtplib.quit.return_value = True
|
mock_smtplib.quit.return_value = True
|
||||||
|
|
||||||
obj.notify(title='test', body='body', notify_type=NotifyType.INFO)
|
assert(obj.notify(
|
||||||
|
title='test', body='body', notify_type=NotifyType.INFO) is True)
|
||||||
|
|
||||||
|
# Set Text
|
||||||
|
obj = Apprise.instantiate(
|
||||||
|
'mailto://user:pass@gmail.com?format=text', suppress_exceptions=False)
|
||||||
|
assert(isinstance(obj, plugins.NotifyEmail))
|
||||||
|
|
||||||
|
assert(obj.notify(
|
||||||
|
title='test', body='body', notify_type=NotifyType.INFO) is True)
|
||||||
|
|
|
@ -38,7 +38,7 @@ def test_notify_base():
|
||||||
|
|
||||||
# invalid types throw exceptions
|
# invalid types throw exceptions
|
||||||
try:
|
try:
|
||||||
nb = NotifyBase(notify_format='invalid')
|
nb = NotifyBase(**{'format': 'invalid'})
|
||||||
# We should never reach here as an exception should be thrown
|
# We should never reach here as an exception should be thrown
|
||||||
assert(False)
|
assert(False)
|
||||||
|
|
||||||
|
|
|
@ -140,6 +140,15 @@ TEST_URLS = (
|
||||||
'instance': plugins.NotifyDiscord,
|
'instance': plugins.NotifyDiscord,
|
||||||
'requests_response_code': requests.codes.no_content,
|
'requests_response_code': requests.codes.no_content,
|
||||||
}),
|
}),
|
||||||
|
# different format support
|
||||||
|
('discord://%s/%s?format=markdown' % ('i' * 24, 't' * 64), {
|
||||||
|
'instance': plugins.NotifyDiscord,
|
||||||
|
'requests_response_code': requests.codes.no_content,
|
||||||
|
}),
|
||||||
|
('discord://%s/%s?format=text' % ('i' * 24, 't' * 64), {
|
||||||
|
'instance': plugins.NotifyDiscord,
|
||||||
|
'requests_response_code': requests.codes.no_content,
|
||||||
|
}),
|
||||||
# Test without image set
|
# Test without image set
|
||||||
('discord://%s/%s' % ('i' * 24, 't' * 64), {
|
('discord://%s/%s' % ('i' * 24, 't' * 64), {
|
||||||
'instance': plugins.NotifyDiscord,
|
'instance': plugins.NotifyDiscord,
|
||||||
|
@ -1155,6 +1164,16 @@ TEST_URLS = (
|
||||||
('tgram://123456789:abcdefg_hijklmnop/lead2gold/?format=', {
|
('tgram://123456789:abcdefg_hijklmnop/lead2gold/?format=', {
|
||||||
'instance': plugins.NotifyTelegram,
|
'instance': plugins.NotifyTelegram,
|
||||||
}),
|
}),
|
||||||
|
# Testing valid formats
|
||||||
|
('tgram://123456789:abcdefg_hijklmnop/lead2gold/?format=markdown', {
|
||||||
|
'instance': plugins.NotifyTelegram,
|
||||||
|
}),
|
||||||
|
('tgram://123456789:abcdefg_hijklmnop/lead2gold/?format=html', {
|
||||||
|
'instance': plugins.NotifyTelegram,
|
||||||
|
}),
|
||||||
|
('tgram://123456789:abcdefg_hijklmnop/lead2gold/?format=text', {
|
||||||
|
'instance': plugins.NotifyTelegram,
|
||||||
|
}),
|
||||||
# Simple Message without image
|
# Simple Message without image
|
||||||
('tgram://123456789:abcdefg_hijklmnop/lead2gold/', {
|
('tgram://123456789:abcdefg_hijklmnop/lead2gold/', {
|
||||||
'instance': plugins.NotifyTelegram,
|
'instance': plugins.NotifyTelegram,
|
||||||
|
@ -1486,6 +1505,9 @@ def test_rest_plugins(mock_post, mock_get):
|
||||||
assert(hasattr(key, obj))
|
assert(hasattr(key, obj))
|
||||||
assert(getattr(key, obj) == val)
|
assert(getattr(key, obj) == val)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Stage 1: with title defined
|
||||||
|
#
|
||||||
try:
|
try:
|
||||||
if test_requests_exceptions is False:
|
if test_requests_exceptions is False:
|
||||||
# check that we're as expected
|
# check that we're as expected
|
||||||
|
@ -1521,6 +1543,44 @@ def test_rest_plugins(mock_post, mock_get):
|
||||||
# Check that we were expecting this exception to happen
|
# Check that we were expecting this exception to happen
|
||||||
assert isinstance(e, response)
|
assert isinstance(e, response)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Stage 1: without title defined
|
||||||
|
#
|
||||||
|
try:
|
||||||
|
if test_requests_exceptions is False:
|
||||||
|
# check that we're as expected
|
||||||
|
assert obj.notify(
|
||||||
|
title='', body='body',
|
||||||
|
notify_type=notify_type) == response
|
||||||
|
|
||||||
|
else:
|
||||||
|
for _exception in REQUEST_EXCEPTIONS:
|
||||||
|
mock_post.side_effect = _exception
|
||||||
|
mock_get.side_effect = _exception
|
||||||
|
|
||||||
|
try:
|
||||||
|
assert obj.notify(
|
||||||
|
title='', body='body',
|
||||||
|
notify_type=NotifyType.INFO) is False
|
||||||
|
|
||||||
|
except AssertionError:
|
||||||
|
# Don't mess with these entries
|
||||||
|
raise
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# We can't handle this exception type
|
||||||
|
print('%s / %s' % (url, str(e)))
|
||||||
|
assert False
|
||||||
|
|
||||||
|
except AssertionError:
|
||||||
|
# Don't mess with these entries
|
||||||
|
print('%s AssertionError' % url)
|
||||||
|
raise
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# Check that we were expecting this exception to happen
|
||||||
|
assert isinstance(e, response)
|
||||||
|
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
# Don't mess with these entries
|
# Don't mess with these entries
|
||||||
print('%s AssertionError' % url)
|
print('%s AssertionError' % url)
|
||||||
|
|
Loading…
Reference in New Issue