diff --git a/apprise/Apprise.py b/apprise/Apprise.py
index 1c0f1922..30c93653 100644
--- a/apprise/Apprise.py
+++ b/apprise/Apprise.py
@@ -43,6 +43,7 @@ from .AppriseLocale import AppriseLocale
from .config.ConfigBase import ConfigBase
from .plugins.NotifyBase import NotifyBase
+
from . import plugins
from . import __version__
@@ -542,11 +543,23 @@ class Apprise(object):
# determined we need to notify the service it's associated with
if server.notify_format not in conversion_body_map:
# Perform Conversion
- (conversion_title_map[server.notify_format],
- conversion_body_map[server.notify_format]) = \
+ conversion_body_map[server.notify_format] = \
convert_between(
- body_format, server.notify_format, body=body,
- title=title, title_format=server.title_format)
+ body_format, server.notify_format, content=body)
+
+ # Prepare our title
+ conversion_title_map[server.notify_format] = \
+ '' if not title else title
+
+ # Tidy Title IF required (hence it will become part of the
+ # body)
+ if server.title_maxlen <= 0 and \
+ conversion_title_map[server.notify_format]:
+
+ conversion_title_map[server.notify_format] = \
+ convert_between(
+ body_format, server.notify_format,
+ content=conversion_title_map[server.notify_format])
if interpret_escapes:
#
@@ -587,14 +600,6 @@ class Apprise(object):
if six.PY2:
# Python 2.7 strings must be encoded as utf-8 for
# consistency across all platforms
- if conversion_title_map[server.notify_format] and \
- isinstance(
- conversion_title_map[server.notify_format],
- unicode): # noqa: F821
- conversion_title_map[server.notify_format] = \
- conversion_title_map[server.notify_format]\
- .encode('utf-8')
-
if conversion_body_map[server.notify_format] and \
isinstance(
conversion_body_map[server.notify_format],
@@ -603,12 +608,21 @@ class Apprise(object):
conversion_body_map[server.notify_format]\
.encode('utf-8')
+ if conversion_title_map[server.notify_format] and \
+ isinstance(
+ conversion_title_map[server.notify_format],
+ unicode): # noqa: F821
+ conversion_title_map[server.notify_format] = \
+ conversion_title_map[server.notify_format]\
+ .encode('utf-8')
+
yield handler(
server,
body=conversion_body_map[server.notify_format],
title=conversion_title_map[server.notify_format],
notify_type=notify_type,
- attach=attach
+ attach=attach,
+ body_format=body_format,
)
def details(self, lang=None, show_requirements=False, show_disabled=False):
diff --git a/apprise/conversion.py b/apprise/conversion.py
index 827b65a7..bfd9a644 100644
--- a/apprise/conversion.py
+++ b/apprise/conversion.py
@@ -28,6 +28,7 @@ import re
import six
from markdown import markdown
from .common import NotifyFormat
+from .URLBase import URLBase
if six.PY2:
from HTMLParser import HTMLParser
@@ -36,13 +37,12 @@ else:
from html.parser import HTMLParser
-def convert_between(from_format, to_format, body, title=None,
- title_format=NotifyFormat.TEXT):
+def convert_between(from_format, to_format, content):
"""
- Converts between different notification formats. If no conversion exists,
+ Converts between different suported formats. If no conversion exists,
or the selected one fails, the original text will be returned.
- This function returns a tuple as (title, body)
+ This function returns the content translated (if required)
"""
converters = {
@@ -53,106 +53,39 @@ def convert_between(from_format, to_format, body, title=None,
(NotifyFormat.HTML, NotifyFormat.MARKDOWN): html_to_text,
}
- if NotifyFormat.MARKDOWN in (from_format, to_format):
- # Tidy any exising pre-formating configuration
- title = '' if not title else title.lstrip('\r\n \t\v\b*#-')
-
- else:
- title = '' if not title else title
-
convert = converters.get((from_format, to_format))
- title, body = convert(title=title, body=body, title_format=title_format) \
- if convert is not None else (title, body)
-
- return (title, body)
+ return convert(content) if convert else content
-def markdown_to_html(body, title=None, title_format=None):
+def markdown_to_html(content):
"""
- Handle Markdown conversions
+ Converts specified content from markdown to HTML.
"""
- if title_format == NotifyFormat.HTML and title:
- # perform conversion if otherwise told to do so
- title = markdown(title)
-
- return (
- # Title
- '' if not title else title,
-
- # Body
- markdown(body),
- )
+ return markdown(content)
-def text_to_html(body, title=None, title_format=None):
+def text_to_html(content):
"""
- Converts a notification body from plain text to HTML.
+ Converts specified content from plain text to HTML.
"""
- # Basic TEXT to HTML format map; supports keys only
- re_map = {
- # Support Ampersand
- r'&': '&',
-
- # Spaces to for formatting purposes since
- # multiple spaces are treated as one an this may
- # not be the callers intention
- r' ': ' ',
-
- # Tab support
- r'\t': ' ',
-
- # Greater than and Less than Characters
- r'>': '>',
- r'<': '<',
- }
-
- # Compile our map
- re_table = re.compile(
- r'(' + '|'.join(
- map(re.escape, re_map.keys())) + r')',
- re.IGNORECASE,
- )
-
- # Execute our map against our body in addition to
- # swapping out new lines and replacing them with
- return (
- # Title; swap whitespace with space
- '' if not title else re.sub(
- r'[\r\n]+', ' ', re_table.sub(
- lambda x: re_map[x.group()], title)),
-
- # Body Formatting
- re.sub(
- r'\r*\n', '
\n', re_table.sub(
- lambda x: re_map[x.group()], body)))
+ return URLBase.escape_html(content)
-def html_to_text(body, title=None, title_format=None):
+def html_to_text(content):
"""
- Converts a notification body from HTML to plain text.
+ Converts a content from HTML to plain text.
"""
parser = HTMLConverter()
if six.PY2:
# Python 2.7 requires an additional parsing to un-escape characters
- body = parser.unescape(body)
+ content = parser.unescape(content)
- if title:
- if six.PY2:
- # Python 2.7 requires an additional parsing to un-escape characters
- title = parser.unescape(title)
-
- parser.feed(title)
- parser.close()
- title = parser.converted
-
- parser.feed(body)
+ parser.feed(content)
parser.close()
- body = parser.converted
-
- return ('' if not title else title, body)
+ return parser.converted
class HTMLConverter(HTMLParser, object):
diff --git a/apprise/plugins/NotifyBase.py b/apprise/plugins/NotifyBase.py
index ea5b7c56..54e89790 100644
--- a/apprise/plugins/NotifyBase.py
+++ b/apprise/plugins/NotifyBase.py
@@ -121,13 +121,6 @@ class NotifyBase(BASE_OBJECT):
# automatically placed into the body
title_maxlen = 250
- # Set this to HTML for services that support the conversion of HTML in
- # the title. For example; services like Telegram support HTML in the
- # title, however services like Email (where this goes in the Subject line)
- # do not (but the body does). By default we do not convert titles but
- # allow those who wish to over-ride this to do so.
- title_format = NotifyFormat.TEXT
-
# Set the maximum line count; if this is set to anything larger then zero
# the message (prior to it being sent) will be truncated to this number
# of lines. Setting this to zero disables this feature.
@@ -272,7 +265,7 @@ class NotifyBase(BASE_OBJECT):
)
def notify(self, body, title=None, notify_type=NotifyType.INFO,
- overflow=None, attach=None, **kwargs):
+ overflow=None, attach=None, body_format=None, **kwargs):
"""
Performs notification
@@ -298,18 +291,22 @@ class NotifyBase(BASE_OBJECT):
title = '' if not title else title
# Apply our overflow (if defined)
- for chunk in self._apply_overflow(body=body, title=title,
- overflow=overflow):
+ for chunk in self._apply_overflow(
+ body=body, title=title, overflow=overflow,
+ body_format=body_format):
+
# Send notification
if not self.send(body=chunk['body'], title=chunk['title'],
- notify_type=notify_type, attach=attach):
+ notify_type=notify_type, attach=attach,
+ body_format=body_format):
# Toggle our return status flag
return False
return True
- def _apply_overflow(self, body, title=None, overflow=None):
+ def _apply_overflow(self, body, title=None, overflow=None,
+ body_format=None):
"""
Takes the message body and title as input. This function then
applies any defined overflow restrictions associated with the
@@ -341,18 +338,24 @@ class NotifyBase(BASE_OBJECT):
overflow = self.overflow_mode
if self.title_maxlen <= 0 and len(title) > 0:
- if self.notify_format == NotifyFormat.MARKDOWN:
- # Content is appended to body as markdown
- body = '**{}**\r\n{}'.format(title, body)
- elif self.notify_format == NotifyFormat.HTML:
+ if self.notify_format == NotifyFormat.HTML:
# Content is appended to body as html
body = '<{open_tag}>{title}{close_tag}>' \
'
\r\n{body}'.format(
open_tag=self.default_html_tag_id,
- title=self.escape_html(title),
+ title=title,
close_tag=self.default_html_tag_id,
body=body)
+
+ elif self.notify_format == NotifyFormat.MARKDOWN and \
+ body_format == NotifyFormat.TEXT:
+ # Content is appended to body as markdown
+ title = title.lstrip('\r\n \t\v\f#-')
+ if title:
+ # Content is appended to body as text
+ body = '# {}\r\n{}'.format(title, body)
+
else:
# Content is appended to body as text
body = '{}\r\n{}'.format(title, body)
diff --git a/apprise/plugins/NotifyTelegram.py b/apprise/plugins/NotifyTelegram.py
index fea3180f..23552eb6 100644
--- a/apprise/plugins/NotifyTelegram.py
+++ b/apprise/plugins/NotifyTelegram.py
@@ -105,8 +105,8 @@ class NotifyTelegram(NotifyBase):
# The maximum allowable characters allowed in the body per message
body_maxlen = 4096
- # Allow the title to support HTML character sets
- title_format = NotifyFormat.HTML
+ # Title is to be part of body
+ title_maxlen = 0
# Telegram is limited to sending a maximum of 100 requests per second.
request_rate_per_sec = 0.001
@@ -173,6 +173,49 @@ class NotifyTelegram(NotifyBase):
},
)
+ # Telegram's HTML support doesn't like having HTML escaped
+ # characters passed into it. to handle this situation, we need to
+ # search the body for these sequences and convert them to the
+ # output the user expected
+ __telegram_escape_html_dict = {
+ # New Lines
+ re.compile(r'<\s*/?br\s*/?>\r*\n?', re.I): '\r\n',
+ re.compile(r'<\s*/(br|p|div|li)[^>]*>\r*\n?', re.I): '\r\n',
+
+ # The following characters can be altered to become supported
+ re.compile(r'<\s*pre[^>]*>', re.I): '',
+ re.compile(r'<\s*/pre[^>]*>', re.I): '
',
+
+ # the following tags are not supported
+ re.compile(
+ r'<\s*(br|p|div|span|body|script|meta|html|font'
+ r'|label|iframe|li|ol|ul|source|script)[^>]*>', re.I): '',
+
+ re.compile(
+ r'<\s*/(span|body|script|meta|html|font'
+ r'|label|iframe|ol|ul|source|script)[^>]*>', re.I): '',
+
+ # Italic
+ re.compile(r'<\s*(caption|em)[^>]*>', re.I): '',
+ re.compile(r'<\s*/(caption|em)[^>]*>', re.I): '',
+
+ # Bold
+ re.compile(r'<\s*(h[1-6]|title|strong)[^>]*>', re.I): '',
+ re.compile(r'<\s*/(h[1-6]|title|strong)[^>]*>', re.I): '',
+
+ # HTML Spaces ( ) and tabs ( ) aren't supported
+ # See https://core.telegram.org/bots/api#html-style
+ re.compile(r'\ ?', re.I): ' ',
+
+ # Tabs become 3 spaces
+ re.compile(r'\ ?', re.I): ' ',
+
+ # Some characters get re-escaped by the Telegram upstream
+ # service so we need to convert these back,
+ re.compile(r'\'?', re.I): '\'',
+ re.compile(r'\"?', re.I): '"',
+ }
+
# Define our template tokens
template_tokens = dict(NotifyBase.template_tokens, **{
'bot_token': {
@@ -505,7 +548,7 @@ class NotifyTelegram(NotifyBase):
return 0
def send(self, body, title='', notify_type=NotifyType.INFO, attach=None,
- **kwargs):
+ body_format=None, **kwargs):
"""
Perform Telegram Notification
"""
@@ -548,93 +591,43 @@ class NotifyTelegram(NotifyBase):
if self.notify_format == NotifyFormat.MARKDOWN:
payload['parse_mode'] = 'MARKDOWN'
- payload['text'] = '{}{}'.format(
- '# {}\r\n'.format(title) if title else '',
- body,
- )
+ payload['text'] = body
+
+ else: # HTML
- elif self.notify_format == NotifyFormat.HTML:
# Use Telegram's HTML mode
payload['parse_mode'] = 'HTML'
+ for r, v in self.__telegram_escape_html_dict.items():
+ body = r.sub(v, body, re.I)
- # Telegram's HTML support doesn't like having HTML escaped
- # characters passed into it. to handle this situation, we need to
- # search the body for these sequences and convert them to the
- # output the user expected
- telegram_escape_html_dict = {
- # HTML Spaces ( ) and tabs ( ) aren't supported
- # See https://core.telegram.org/bots/api#html-style
- r'\ ?': ' ',
+ # Prepare our payload based on HTML or TEXT
+ payload['text'] = body
- # Tabs become 3 spaces
- r'\ ?': ' ',
+ # else: # self.notify_format == NotifyFormat.TEXT:
+ # # Use Telegram's HTML mode
+ # payload['parse_mode'] = 'HTML'
- # Some characters get re-escaped by the Telegram upstream
- # service so we need to convert these back,
- r'\'?': '\'',
- r'\"?': '"',
+ # # Further html escaping required...
+ # telegram_escape_text_dict = {
+ # # We need to escape characters that conflict with html
+ # # entity blocks (< and >) when displaying text
+ # r'>': '>',
+ # r'<': '<',
+ # r'\&': '&',
+ # }
- # the following tags are not supported
- r'<[ \t]*/?(br|p|div|span|body|script|meta|html|font'
- r'|label|iframe|li|ol|ul)[^>]*>': '',
+ # # Create a regular expression from the dictionary keys
+ # text_regex = re.compile("(%s)" % "|".join(
+ # map(re.escape, telegram_escape_text_dict.keys())).lower(),
+ # re.I)
- # The following characters can be altered to become supported
- r'<[ \t]*pre[^>]*>': '',
- r'<[ \t]*/pre[^>]*>': '
',
+ # # For each match, look-up corresponding value in dictionary
+ # body = text_regex.sub( # pragma: no branch
+ # lambda mo: telegram_escape_text_dict[
+ # mo.string[mo.start():mo.end()]], body)
- # Bold
- r'<[ \t]*(h[0-9]+|title|strong)[^>]*>': '',
- r'<[ \t]*/(h[0-9]+|title|strong)[^>]*>': '',
-
- # Italic
- r'<[ \t]*(caption|em)[^>]*>': '',
- r'<[ \t]*/(caption|em)[^>]*>': '',
- }
-
- for k, v in telegram_escape_html_dict.items():
- body = re.sub(k, v, body, re.I)
- if title:
- title = re.sub(k, v, title, re.I)
-
- # prepare our payload based on HTML or TEXT
- payload['text'] = '{}{}'.format(
- '{}\r\n'.format(title) if title else '',
- body,
- )
-
- else: # self.notify_format == NotifyFormat.TEXT:
- # Use Telegram's HTML mode
- payload['parse_mode'] = 'HTML'
-
- # Further html escaping required...
- telegram_escape_text_dict = {
- # We need to escape characters that conflict with html
- # entity blocks (< and >) when displaying text
- r'>': '>',
- r'<': '<',
- }
-
- # Create a regular expression from the dictionary keys
- text_regex = re.compile("(%s)" % "|".join(
- map(re.escape, telegram_escape_text_dict.keys())).lower(),
- re.I)
-
- # For each match, look-up corresponding value in dictionary
- body = text_regex.sub( # pragma: no branch
- lambda mo: telegram_escape_text_dict[
- mo.string[mo.start():mo.end()]], body)
-
- if title:
- # For each match, look-up corresponding value in dictionary
- title = text_regex.sub( # pragma: no branch
- lambda mo: telegram_escape_text_dict[
- mo.string[mo.start():mo.end()]], title)
-
- # prepare our payload based on HTML or TEXT
- payload['text'] = '{}{}'.format(
- '{}\r\n'.format(title) if title else '',
- body,
- )
+ # # prepare our payload based on HTML or TEXT
+ # payload['text'] = body
# Create a copy of the chat_ids list
targets = list(self.targets)
diff --git a/apprise/utils.py b/apprise/utils.py
index e7847f6e..6bf6df23 100644
--- a/apprise/utils.py
+++ b/apprise/utils.py
@@ -702,7 +702,7 @@ def parse_url(url, default_schema='http', verify_host=True, strict_port=False):
# Port Parsing
pmatch = re.search(
- r'^(?P([[0-9a-f:]+]|[^:]+)):(?P[^:]*)$',
+ r'^(?P(\[[0-9a-f:]+\]|[^:]+)):(?P[^:]*)$',
result['host'])
if pmatch:
diff --git a/test/test_conversion.py b/test/test_conversion.py
index a67de5b1..c6ab6d8a 100644
--- a/test/test_conversion.py
+++ b/test/test_conversion.py
@@ -32,7 +32,7 @@ import logging
logging.disable(logging.CRITICAL)
-def test_html_to_text():
+def test_conversion_html_to_text():
"""conversion: Test HTML to plain text
"""
@@ -40,7 +40,7 @@ def test_html_to_text():
"""
A function to simply html conversion tests
"""
- return convert_between(NotifyFormat.HTML, NotifyFormat.TEXT, body)[1]
+ return convert_between(NotifyFormat.HTML, NotifyFormat.TEXT, body)
assert to_html("No HTML code here.") == "No HTML code here."
@@ -134,3 +134,16 @@ def test_html_to_text():
with pytest.raises(TypeError):
# Invalid input
assert to_html(object)
+
+
+def test_conversion_text_to():
+ """conversion: Test Text to all types
+ """
+
+ response = convert_between(
+ NotifyFormat.TEXT, NotifyFormat.HTML,
+ "Test MessageBody")
+
+ assert response == \
+ '<title>Test Message</title><body>Body<'\
+ '/body>'
diff --git a/test/test_plugin_telegram.py b/test/test_plugin_telegram.py
index b65cffc4..a9f191b6 100644
--- a/test/test_plugin_telegram.py
+++ b/test/test_plugin_telegram.py
@@ -311,10 +311,6 @@ def test_plugin_telegram_general(mock_post):
# ensures our plugin inheritance is working properly
assert obj.body_maxlen == plugins.NotifyTelegram.body_maxlen
- # We don't override the title maxlen so we should be set to the same
- # as our parent class in this case
- assert obj.title_maxlen == plugins.NotifyBase.title_maxlen
-
# This tests erroneous messages involving multiple chat ids
assert obj.notify(
body='body', title='title', notify_type=NotifyType.INFO) is False
@@ -407,7 +403,7 @@ def test_plugin_telegram_general(mock_post):
# Test our payload
assert payload['text'] == \
- 'special characters\r\n\'"This can\'t\t\r\nfail us"\''
+ 'special characters\r\n\'"This can\'t\t\r\nfail us"\'\r\n'
# Test sending attachments
attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, 'apprise-test.gif'))
@@ -629,10 +625,11 @@ def test_plugin_telegram_formating_py3(mock_post):
# Test that everything is escaped properly in a TEXT mode
assert payload['text'] == \
- '🚨 Change detected for <i>Apprise Test' \
- ' Title</i>\r\n<a href="http://localhost">' \
- '<i>Apprise Body Title</i></a> had' \
- ' <a href="http://127.0.0.1">a change</a>'
+ '🚨 Change detected for <i>Apprise ' \
+ 'Test Title</i>\r\n<a href=' \
+ '"http://localhost"><i>Apprise Body Title<' \
+ '/i></a> had <a href="http://' \
+ '127.0.0.1">a change</a>'
# Reset our values
mock_post.reset_mock()
@@ -699,7 +696,12 @@ def test_plugin_telegram_formating_py3(mock_post):
aobj.add('tgram://987654321:abcdefg_hijklmnop/?format=html')
assert len(aobj) == 1
- # HTML forced by the command line, but MARKDOWN spacified as
+ # Now test our MARKDOWN Handling
+ title = '# 🚨 Another Change detected for _Apprise Test Title_'
+ body = '_[Apprise Body Title](http://localhost)_' \
+ ' had [a change](http://127.0.0.2)'
+
+ # HTML forced by the command line, but MARKDOWN specified as
# upstream mode
assert aobj.notify(
title=title, body=body, body_format=NotifyFormat.MARKDOWN)
@@ -716,9 +718,79 @@ def test_plugin_telegram_formating_py3(mock_post):
# Test that everything is escaped properly in a HTML mode
assert payload['text'] == \
- '🚨 Change detected for Apprise Test Title\r\n' \
- 'Apprise Body Title ' \
- 'had a change'
+ '🚨 Another Change detected for Apprise Test Title' \
+ '\r\nApprise Body Title' \
+ ' had a change\r\n'
+
+ # Now we'll test an edge case where a title was defined, but after
+ # processing it, it was determiend there really wasn't anything there
+ # at all at the end of the day.
+
+ # Reset our values
+ mock_post.reset_mock()
+
+ # Upstream to use HTML but input specified as Markdown
+ aobj = Apprise()
+ aobj.add('tgram://987654321:abcdefg_hijklmnop/?format=markdown')
+ assert len(aobj) == 1
+
+ # Now test our MARKDOWN Handling (no title defined... not really anyway)
+ title = '# '
+ body = '_[Apprise Body Title](http://localhost)_' \
+ ' had [a change](http://127.0.0.2)'
+
+ # MARKDOWN forced by the command line, but TEXT specified as
+ # upstream mode
+ assert aobj.notify(
+ title=title, body=body, body_format=NotifyFormat.TEXT)
+
+ # Test our calls
+ assert mock_post.call_count == 2
+
+ assert mock_post.call_args_list[0][0][0] == \
+ 'https://api.telegram.org/bot987654321:abcdefg_hijklmnop/getUpdates'
+ assert mock_post.call_args_list[1][0][0] == \
+ 'https://api.telegram.org/bot987654321:abcdefg_hijklmnop/sendMessage'
+
+ payload = loads(mock_post.call_args_list[1][1]['data'])
+
+ # Test that everything is escaped properly in a HTML mode
+ assert payload['text'] == \
+ '_[Apprise Body Title](http://localhost)_ had ' \
+ '[a change](http://127.0.0.2)'
+
+ # Reset our values
+ mock_post.reset_mock()
+
+ # Upstream to use HTML but input specified as Markdown
+ aobj = Apprise()
+ aobj.add('tgram://987654321:abcdefg_hijklmnop/?format=markdown')
+ assert len(aobj) == 1
+
+ # Set an actual title this time
+ title = '# A Great Title'
+ body = '_[Apprise Body Title](http://localhost)_' \
+ ' had [a change](http://127.0.0.2)'
+
+ # MARKDOWN forced by the command line, but TEXT specified as
+ # upstream mode
+ assert aobj.notify(
+ title=title, body=body, body_format=NotifyFormat.TEXT)
+
+ # Test our calls
+ assert mock_post.call_count == 2
+
+ assert mock_post.call_args_list[0][0][0] == \
+ 'https://api.telegram.org/bot987654321:abcdefg_hijklmnop/getUpdates'
+ assert mock_post.call_args_list[1][0][0] == \
+ 'https://api.telegram.org/bot987654321:abcdefg_hijklmnop/sendMessage'
+
+ payload = loads(mock_post.call_args_list[1][1]['data'])
+
+ # Test that everything is escaped properly in a HTML mode
+ assert payload['text'] == \
+ '# A Great Title\r\n_[Apprise Body Title](http://localhost)_ had ' \
+ '[a change](http://127.0.0.2)'
@pytest.mark.skipif(sys.version_info.major >= 3, reason="Requires Python 2.x+")
@@ -809,11 +881,11 @@ def test_plugin_telegram_formating_py2(mock_post):
# Test that everything is escaped properly in a TEXT mode
assert payload['text'].encode('utf-8') == \
- '\xf0\x9f\x9a\xa8 Change detected for ' \
- '<i>Apprise Test Title</i>\r\n' \
- '<a href="http://localhost"><i>Apprise Body ' \
- 'Title</i></a> had <a ' \
- 'href="http://127.0.0.1">a change</a>'
+ '\xf0\x9f\x9a\xa8 Change detected for <i>' \
+ 'Apprise Test Title</i>\r\n<a ' \
+ 'href="http://localhost"><i>Apprise Body ' \
+ 'Title</i></a> had <a href="' \
+ 'http://127.0.0.1">a change</a>'
# Reset our values
mock_post.reset_mock()
@@ -880,7 +952,7 @@ def test_plugin_telegram_formating_py2(mock_post):
aobj.add('tgram://987654321:abcdefg_hijklmnop/?format=html')
assert len(aobj) == 1
- # HTML forced by the command line, but MARKDOWN spacified as
+ # HTML forced by the command line, but MARKDOWN specified as
# upstream mode
assert aobj.notify(
title=title, body=body, body_format=NotifyFormat.MARKDOWN)
@@ -897,9 +969,10 @@ def test_plugin_telegram_formating_py2(mock_post):
# Test that everything is escaped properly in a HTML mode
assert payload['text'].encode('utf-8') == \
- '\xf0\x9f\x9a\xa8 Change detected for Apprise Test Title' \
- '\r\nApprise Body Title ' \
- 'had a change'
+ '\xf0\x9f\x9a\xa8 Change detected for ' \
+ 'Apprise Test Title\r\n' \
+ 'Apprise Body Title'\
+ ' had a change\r\n'
# Reset our values
mock_post.reset_mock()
@@ -951,6 +1024,76 @@ def test_plugin_telegram_formating_py2(mock_post):
'\xd7\xa0\xd7\xa4\xd7\x9c\xd7\x90\xd7\x94\r\n[_[\xd7\x96\xd7\x95 '\
'\xd7\x94\xd7\x95\xd7\x93\xd7\xa2\xd7\x94](http://localhost)_'
+ # Now we'll test an edge case where a title was defined, but after
+ # processing it, it was determiend there really wasn't anything there
+ # at all at the end of the day.
+
+ # Reset our values
+ mock_post.reset_mock()
+
+ # Upstream to use HTML but input specified as Markdown
+ aobj = Apprise()
+ aobj.add('tgram://987654321:abcdefg_hijklmnop/?format=markdown')
+ assert len(aobj) == 1
+
+ # Now test our MARKDOWN Handling (no title defined... not really anyway)
+ title = '# '
+ body = '_[Apprise Body Title](http://localhost)_' \
+ ' had [a change](http://127.0.0.2)'
+
+ # MARKDOWN forced by the command line, but TEXT specified as
+ # upstream mode
+ assert aobj.notify(
+ title=title, body=body, body_format=NotifyFormat.TEXT)
+
+ # Test our calls
+ assert mock_post.call_count == 2
+
+ assert mock_post.call_args_list[0][0][0] == \
+ 'https://api.telegram.org/bot987654321:abcdefg_hijklmnop/getUpdates'
+ assert mock_post.call_args_list[1][0][0] == \
+ 'https://api.telegram.org/bot987654321:abcdefg_hijklmnop/sendMessage'
+
+ payload = loads(mock_post.call_args_list[1][1]['data'])
+
+ # Test that everything is escaped properly in a HTML mode
+ assert payload['text'] == \
+ '_[Apprise Body Title](http://localhost)_ had ' \
+ '[a change](http://127.0.0.2)'
+
+ # Reset our values
+ mock_post.reset_mock()
+
+ # Upstream to use HTML but input specified as Markdown
+ aobj = Apprise()
+ aobj.add('tgram://987654321:abcdefg_hijklmnop/?format=markdown')
+ assert len(aobj) == 1
+
+ # Set an actual title this time
+ title = '# A Great Title'
+ body = '_[Apprise Body Title](http://localhost)_' \
+ ' had [a change](http://127.0.0.2)'
+
+ # MARKDOWN forced by the command line, but TEXT specified as
+ # upstream mode
+ assert aobj.notify(
+ title=title, body=body, body_format=NotifyFormat.TEXT)
+
+ # Test our calls
+ assert mock_post.call_count == 2
+
+ assert mock_post.call_args_list[0][0][0] == \
+ 'https://api.telegram.org/bot987654321:abcdefg_hijklmnop/getUpdates'
+ assert mock_post.call_args_list[1][0][0] == \
+ 'https://api.telegram.org/bot987654321:abcdefg_hijklmnop/sendMessage'
+
+ payload = loads(mock_post.call_args_list[1][1]['data'])
+
+ # Test that everything is escaped properly in a HTML mode
+ assert payload['text'] == \
+ '# A Great Title\r\n_[Apprise Body Title](http://localhost)_ had ' \
+ '[a change](http://127.0.0.2)'
+
@mock.patch('requests.post')
def test_plugin_telegram_html_formatting(mock_post):
@@ -1020,8 +1163,8 @@ def test_plugin_telegram_html_formatting(mock_post):
# Test that everything is escaped properly in a HTML mode
assert payload['text'] == \
- '\'information\'\r\n"This is in Italic"' \
- ' Headings are dropped and converted to bold'
+ '\'information\'\r\n"This is in Italic"' \
+ '\r\n Headings are dropped and converted to bold'
mock_post.reset_mock()
@@ -1034,6 +1177,7 @@ def test_plugin_telegram_html_formatting(mock_post):
assert payload['text'] == \
'<title>'information&apos</title>' \
- '\r\n<em>"This is in Italic"</em>' \
- '<br/><h5> &emspHeadings are' \
- ' dropped and converted to bold</h5>'
+ '\r\n<em>"This is in Italic"</em' \
+ '><br/><h5> &emspHeadings ' \
+ 'are dropped and converted to bold<' \
+ '/h5>'
diff --git a/test/test_rest_plugins.py b/test/test_rest_plugins.py
index f6a52dfe..c709c2dc 100644
--- a/test/test_rest_plugins.py
+++ b/test/test_rest_plugins.py
@@ -386,3 +386,57 @@ def test_notify_overflow_split():
_body = chunk.get('body')
assert bulk[offset: len(_body) + offset] == _body
offset += len(_body)
+
+
+def test_notify_overflow_general():
+ """
+ API: Overflow General Testing
+
+ """
+
+ #
+ # A little preparation
+ #
+
+ # Disable Throttling to speed testing
+ plugins.NotifyBase.request_rate_per_sec = 0
+
+ #
+ # First Test: Truncated Title
+ #
+ class TestMarkdownNotification(NotifyBase):
+
+ # Force our title to wrap
+ title_maxlen = 0
+
+ # Default Notify Format
+ notify_format = NotifyFormat.MARKDOWN
+
+ def __init__(self, *args, **kwargs):
+ super(TestMarkdownNotification, self).__init__(**kwargs)
+
+ def notify(self, *args, **kwargs):
+ # Pretend everything is okay
+ return True
+
+ # Load our object
+ obj = TestMarkdownNotification()
+ assert obj is not None
+
+ # A bad header
+ title = " # "
+ body = "**Test Body**"
+
+ chunks = obj._apply_overflow(body=body, title=title)
+ assert len(chunks) == 1
+ # whitspace is trimmed
+ assert '#\r\n**Test Body**' == chunks[0].get('body')
+ assert chunks[0].get('title') == ""
+
+ # If we know our input is text however, we perform manipulation
+ chunks = obj._apply_overflow(
+ body=body, title=title, body_format=NotifyFormat.TEXT)
+ assert len(chunks) == 1
+ # Our title get's stripped off since it's not of valid markdown
+ assert body == chunks[0].get('body')
+ assert chunks[0].get('title') == ""