Matrix HTML and Markdown Support (#431)

pull/436/head
Chris Caron 2021-08-29 11:29:30 -04:00 committed by GitHub
parent bb7c77105e
commit a888b85f8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 18 deletions

View File

@ -30,6 +30,7 @@
import re import re
import six import six
import requests import requests
from markdown import markdown
from json import dumps from json import dumps
from json import loads from json import loads
from time import time from time import time
@ -41,6 +42,7 @@ from ..common import NotifyImageSize
from ..common import NotifyFormat from ..common import NotifyFormat
from ..utils import parse_bool from ..utils import parse_bool
from ..utils import parse_list from ..utils import parse_list
from ..utils import apply_template
from ..utils import validate_regex from ..utils import validate_regex
from ..AppriseLocale import gettext_lazy as _ from ..AppriseLocale import gettext_lazy as _
@ -415,20 +417,31 @@ class NotifyMatrix(NotifyBase):
payload = { payload = {
'displayName': 'displayName':
self.user if self.user else self.app_id, 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: 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:
# Add additional information to our content; use {{app_title}}
# to apply the title to the html body
tokens = {
'app_title': title,
}
payload['text'] = markdown(apply_template(body, **tokens))
# Ensure our content is escaped else: # NotifyFormat.TEXT
title = NotifyMatrix.escape_html(title) payload['text'] = \
body = NotifyMatrix.escape_html(body) body if not title else '{}\r\n{}'.format(title, body)
payload['text'] = '{}{}'.format(
'' if not title else '<h4>{}</h4>'.format(title), body)
return payload return payload
@ -497,11 +510,6 @@ class NotifyMatrix(NotifyBase):
has_error = True has_error = True
continue 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 # Acquire our image url if we're configured to do so
image_url = None if not self.include_image else \ image_url = None if not self.include_image else \
self.image_url(notify_type) self.image_url(notify_type)
@ -527,9 +535,35 @@ class NotifyMatrix(NotifyBase):
# Define our payload # Define our payload
payload = { payload = {
'msgtype': 'm.text', 'msgtype': 'm.text',
'body': msg, 'body': '{title}{body}'.format(
title='' if not title else '{}\r\n'.format(title),
body=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.update({
'format': 'org.matrix.custom.html',
'formatted_body': apply_template(body, **tokens),
})
elif self.notify_format == NotifyFormat.MARKDOWN:
tokens = {
'app_title': title,
}
payload.update({
'format': 'org.matrix.custom.html',
'formatted_body': markdown(apply_template(body, **tokens))
})
# Build our path # Build our path
path = '/rooms/{}/send/m.room.message'.format( path = '/rooms/{}/send/m.room.message'.format(
NotifyMatrix.quote(room_id)) NotifyMatrix.quote(room_id))
@ -697,7 +731,7 @@ class NotifyMatrix(NotifyBase):
# Prepare our Join Payload # Prepare our Join Payload
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) result = IS_ROOM_ID.match(room)
if result: if result:
# We detected ourselves the home_server # We detected ourselves the home_server
@ -710,11 +744,23 @@ class NotifyMatrix(NotifyBase):
home_server, 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 # Build our URL
path = '/join/{}'.format(NotifyMatrix.quote(room_id)) path = '/join/{}'.format(NotifyMatrix.quote(room_id))
# Make our query # Make our query
postokay, _ = self._fetch(path, payload=payload) 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 return room_id if postokay else None
# Try to see if it's an alias then... # Try to see if it's an alias then...

View File

@ -28,7 +28,6 @@ import mock
import requests import requests
from apprise import plugins from apprise import plugins
from apprise import AppriseAsset from apprise import AppriseAsset
# from apprise import Apprise
from json import dumps from json import dumps
# Disable logging for a cleaner testing output # Disable logging for a cleaner testing output
@ -86,6 +85,31 @@ def test_notify_matrix_plugin_general(mock_post, mock_get):
# Registration Successful # Registration Successful
assert obj.send(body="test") is True 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 # Force a failed login
ro = response_obj.copy() ro = response_obj.copy()
del ro['access_token'] del ro['access_token']
@ -392,16 +416,36 @@ def test_notify_matrix_plugin_rooms(mock_post, mock_get):
assert obj._register() is True assert obj._register() is True
assert obj.access_token is not None 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'] assert obj._room_join('!abc123') == response_obj['room_id']
obj._room_cache = {} obj._room_cache = {}
assert obj._room_join('!abc123:localhost') == response_obj['room_id'] 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 = {} obj._room_cache = {}
assert obj._room_join('abc123') == response_obj['room_id'] 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 = {} obj._room_cache = {}
assert obj._room_join('abc123:localhost') == response_obj['room_id'] 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 = {} obj._room_cache = {}
assert obj._room_join('#abc123:localhost') == response_obj['room_id'] 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 = {} obj._room_cache = {}
assert obj._room_join('%') is None assert obj._room_join('%') is None
assert obj._room_join(None) is None assert obj._room_join(None) is None

View File

@ -1948,7 +1948,7 @@ TEST_URLS = (
.format('a' * 64), { .format('a' * 64), {
# user and token specified; image set to True # user and token specified; image set to True
'instance': plugins.NotifyMatrix}), 'instance': plugins.NotifyMatrix}),
('matrix://user@{}?mode=t2bot&format=markdown&image=False' ('matrix://user@{}?mode=t2bot&format=html&image=False'
.format('z' * 64), { .format('z' * 64), {
# user and token specified; image set to True # user and token specified; image set to True
'instance': plugins.NotifyMatrix}), 'instance': plugins.NotifyMatrix}),