Skip to content

Commit

Permalink
Matrix HTML and Markdown Support
Browse files Browse the repository at this point in the history
  • Loading branch information
caronc committed Aug 21, 2021
1 parent bb7c771 commit 3f48318
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 16 deletions.
76 changes: 62 additions & 14 deletions apprise/plugins/NotifyMatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import re
import six
import requests
from markdown import markdown
from json import dumps
from json import loads
from time import time
Expand All @@ -41,6 +42,7 @@
from ..common import NotifyFormat
from ..utils import parse_bool
from ..utils import parse_list
from ..utils import apply_template
from ..utils import validate_regex
from ..AppriseLocale import gettext_lazy as _

Expand Down Expand Up @@ -415,20 +417,31 @@ def _matrix_webhook_payload(self, body, title='',
payload = {
'displayName':
self.user if self.user else self.app_id,
'format': 'html',
'format': 'plain' if self.notify_format == NotifyFormat.TEXT
else 'html',
'text': '',
}

if self.notify_format == NotifyFormat.HTML:
payload['text'] = '{}{}'.format('' if not title else title, body)
# Add additional information to our content; use {{app_title}}
# to apply the title to the html body
tokens = {
'app_title': NotifyMatrix.escape_html(
title, whitespace=False),
}
payload['text'] = apply_template(body, **tokens)

else: # TEXT or MARKDOWN
elif self.notify_format == NotifyFormat.MARKDOWN:
if title:
payload['text'] = \
'<h4>{}</h4>'.format(
NotifyMatrix.escape_html(title, whitespace=False))

# Ensure our content is escaped
title = NotifyMatrix.escape_html(title)
body = NotifyMatrix.escape_html(body)
payload['text'] += markdown(body)

else: # TEXT
payload['text'] = '{}{}'.format(
'' if not title else '<h4>{}</h4>'.format(title), body)
'' if not title else '{}\r\n'.format(title), body)

return payload

Expand Down Expand Up @@ -497,11 +510,6 @@ def _send_server_notification(self, body, title='',
has_error = True
continue

# We have our data cached at this point we can freely use it
msg = '{title}{body}'.format(
title='' if not title else '{}\r\n'.format(title),
body=body)

# Acquire our image url if we're configured to do so
image_url = None if not self.include_image else \
self.image_url(notify_type)
Expand All @@ -527,9 +535,37 @@ def _send_server_notification(self, body, title='',
# Define our payload
payload = {
'msgtype': 'm.text',
'body': msg,
'body': '{title}{body}'.format(
title='' if not title else '{}\r\n'.format(title),
body=body),
'format': 'org.matrix.custom.html',
'formatted_body': '',
}

# Update our payload advance formatting for the services that
# support them.
if self.notify_format == NotifyFormat.HTML:
# Add additional information to our content; use {{app_title}}
# to apply the title to the html body
tokens = {
'app_title': NotifyMatrix.escape_html(
title, whitespace=False),
}
payload['formatted_body'] = apply_template(body, **tokens)

else: # TEXT or MARKDOWN
if title:
payload['formatted_body'] = \
'<h4>{}</h4>'.format(
NotifyMatrix.escape_html(title, whitespace=False))

if self.notify_format == NotifyFormat.TEXT:
payload['formatted_body'] += \
NotifyMatrix.escape_html(body, whitespace=False)

else: # NotifyFormat.MARKDOWN
payload['formatted_body'] += markdown(body)

# Build our path
path = '/rooms/{}/send/m.room.message'.format(
NotifyMatrix.quote(room_id))
Expand Down Expand Up @@ -697,7 +733,7 @@ def _room_join(self, room):
# Prepare our Join Payload
payload = {}

# Not in cache, next step is to check if it's a room id...
# Check if it's a room id...
result = IS_ROOM_ID.match(room)
if result:
# We detected ourselves the home_server
Expand All @@ -710,11 +746,23 @@ def _room_join(self, room):
home_server,
)

# Check our cache for speed:
if room_id in self._room_cache:
# We're done as we've already joined the channel
return self._room_cache[room_id]['id']

# Build our URL
path = '/join/{}'.format(NotifyMatrix.quote(room_id))

# Make our query
postokay, _ = self._fetch(path, payload=payload)
if postokay:
# Cache our entry for fast access later
self._room_cache[room_id] = {
'id': room_id,
'home_server': home_server,
}

return room_id if postokay else None

# Try to see if it's an alias then...
Expand Down
46 changes: 45 additions & 1 deletion test/test_matrix_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import requests
from apprise import plugins
from apprise import AppriseAsset
# from apprise import Apprise
from json import dumps

# Disable logging for a cleaner testing output
Expand Down Expand Up @@ -86,6 +85,31 @@ def test_notify_matrix_plugin_general(mock_post, mock_get):
# Registration Successful
assert obj.send(body="test") is True

# Test sending other format types
kwargs = plugins.NotifyMatrix.parse_url(
'matrix://user:passwd@hostname/#abcd?format=html')
obj = plugins.NotifyMatrix(**kwargs)
assert isinstance(obj.url(), six.string_types) is True
assert isinstance(obj, plugins.NotifyMatrix) is True
obj.send(body="test") is True
obj.send(title="title", body="test") is True

kwargs = plugins.NotifyMatrix.parse_url(
'matrix://user:passwd@hostname/#abcd/#abcd:localhost?format=markdown')
obj = plugins.NotifyMatrix(**kwargs)
assert isinstance(obj.url(), six.string_types) is True
assert isinstance(obj, plugins.NotifyMatrix) is True
obj.send(body="test") is True
obj.send(title="title", body="test") is True

kwargs = plugins.NotifyMatrix.parse_url(
'matrix://user:passwd@hostname/#abcd/!abcd:localhost?format=text')
obj = plugins.NotifyMatrix(**kwargs)
assert isinstance(obj.url(), six.string_types) is True
assert isinstance(obj, plugins.NotifyMatrix) is True
obj.send(body="test") is True
obj.send(title="title", body="test") is True

# Force a failed login
ro = response_obj.copy()
del ro['access_token']
Expand Down Expand Up @@ -392,16 +416,36 @@ def test_notify_matrix_plugin_rooms(mock_post, mock_get):

assert obj._register() is True
assert obj.access_token is not None

assert obj._room_join('!abc123') == response_obj['room_id']
# Use cache to get same results
assert len(obj._room_cache) == 1
assert obj._room_join('!abc123') == response_obj['room_id']

obj._room_cache = {}
assert obj._room_join('!abc123:localhost') == response_obj['room_id']
# Use cache to get same results
assert len(obj._room_cache) == 1
assert obj._room_join('!abc123:localhost') == response_obj['room_id']

obj._room_cache = {}
assert obj._room_join('abc123') == response_obj['room_id']
# Use cache to get same results
assert len(obj._room_cache) == 1
assert obj._room_join('abc123') == response_obj['room_id']

obj._room_cache = {}
assert obj._room_join('abc123:localhost') == response_obj['room_id']
# Use cache to get same results
assert len(obj._room_cache) == 1
assert obj._room_join('abc123:localhost') == response_obj['room_id']

obj._room_cache = {}
assert obj._room_join('#abc123:localhost') == response_obj['room_id']
# Use cache to get same results
assert len(obj._room_cache) == 1
assert obj._room_join('#abc123:localhost') == response_obj['room_id']

obj._room_cache = {}
assert obj._room_join('%') is None
assert obj._room_join(None) is None
Expand Down
2 changes: 1 addition & 1 deletion test/test_rest_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -1948,7 +1948,7 @@
.format('a' * 64), {
# user and token specified; image set to True
'instance': plugins.NotifyMatrix}),
('matrix://user@{}?mode=t2bot&format=markdown&image=False'
('matrix://user@{}?mode=t2bot&format=html&image=False'
.format('z' * 64), {
# user and token specified; image set to True
'instance': plugins.NotifyMatrix}),
Expand Down

0 comments on commit 3f48318

Please sign in to comment.