Browse Source

enhanced Discord formatting with markdown; refs #10

pull/12/head
Chris Caron 7 years ago
parent
commit
b040e232ae
  1. 41
      apprise/plugins/NotifyDiscord.py
  2. 35
      test/test_rest_plugins.py

41
apprise/plugins/NotifyDiscord.py

@ -33,12 +33,14 @@
# API Documentation on Webhooks: # API Documentation on Webhooks:
# - https://discordapp.com/developers/docs/resources/webhook # - https://discordapp.com/developers/docs/resources/webhook
# #
import re
import requests import requests
from json import dumps from json import dumps
from .NotifyBase import NotifyBase from .NotifyBase import NotifyBase
from .NotifyBase import HTTP_ERROR_MAP from .NotifyBase import HTTP_ERROR_MAP
from ..common import NotifyImageSize from ..common import NotifyImageSize
from ..common import NotifyFormat
from ..utils import parse_bool from ..utils import parse_bool
# Image Support (256x256) # Image Support (256x256)
@ -58,13 +60,15 @@ class NotifyDiscord(NotifyBase):
notify_url = 'https://discordapp.com/api/webhooks' notify_url = 'https://discordapp.com/api/webhooks'
def __init__(self, webhook_id, webhook_token, tts=False, avatar=True, def __init__(self, webhook_id, webhook_token, tts=False, avatar=True,
footer=False, thumbnail=True, **kwargs): footer=False, thumbnail=True,
notify_format=NotifyFormat.MARKDOWN, **kwargs):
""" """
Initialize Discord Object Initialize Discord Object
""" """
super(NotifyDiscord, self).__init__( super(NotifyDiscord, self).__init__(
title_maxlen=250, body_maxlen=2000, title_maxlen=250, body_maxlen=2000,
notify_format=notify_format,
image_size=DISCORD_IMAGE_XY, **kwargs) image_size=DISCORD_IMAGE_XY, **kwargs)
if not webhook_id: if not webhook_id:
@ -128,6 +132,17 @@ class NotifyDiscord(NotifyBase):
}] }]
} }
if self.notify_format == NotifyFormat.MARKDOWN:
fields = self.extract_markdown_sections(body)
if len(fields) > 0:
# Apply our additional parsing for a better presentation
# Swap first entry for description
payload['embeds'][0]['description'] = \
fields[0].get('name') + fields[0].get('value')
payload['embeds'][0]['fields'] = fields[1:]
if self.footer: if self.footer:
logo_url = self.image_url(notify_type, logo=True) logo_url = self.image_url(notify_type, logo=True)
payload['embeds'][0]['footer'] = { payload['embeds'][0]['footer'] = {
@ -249,3 +264,27 @@ class NotifyDiscord(NotifyBase):
parse_bool(results['qsd'].get('thumbnail', True)) parse_bool(results['qsd'].get('thumbnail', True))
return results return results
@staticmethod
def extract_markdown_sections(markdown):
"""
Takes a string in a markdown type format and extracts
the headers and their corresponding sections into individual
fields that get passed as an embed entry to Discord.
"""
regex = re.compile(
r'\s*#+\s*(?P<name>[^#\n]+)([ \r\t\v#]*)'
r'(?P<value>(.+?)(\n(?!\s#))|\s*$)', flags=re.S)
common = regex.finditer(markdown)
fields = list()
for el in common:
d = el.groupdict()
fields.append({
'name': d.get('name', '').strip(),
'value': '```md\n' + d.get('value', '').strip() + '\n```'
})
return fields

35
test/test_rest_plugins.py

@ -21,6 +21,8 @@ from apprise import NotifyType
from apprise import Apprise from apprise import Apprise
from apprise import AppriseAsset from apprise import AppriseAsset
from apprise.utils import compat_is_basestring from apprise.utils import compat_is_basestring
from apprise.common import NotifyFormat
from json import dumps from json import dumps
import uuid import uuid
import requests import requests
@ -1656,6 +1658,39 @@ def test_notify_discord_plugin(mock_post, mock_get):
assert obj.notify(title='title', body='body', assert obj.notify(title='title', body='body',
notify_type=NotifyType.INFO) is True notify_type=NotifyType.INFO) is True
# Test our header parsing
test_markdown = "## Heading one\nbody body\n\n" + \
"# Heading 2 ##\n\nTest\n\n" + \
"more content\n" + \
"even more content \t\r\n\n\n" + \
"# Heading 3 ##\n\n\n" + \
"normal content\n" + \
"# heading 4\n" + \
"#### Heading 5"
results = obj.extract_markdown_sections(test_markdown)
assert(isinstance(results, list))
# We should have 5 sections (since there are 5 headers identified above)
assert(len(results) == 5)
# Use our test markdown string during a notification
assert obj.notify(title='title', body=test_markdown,
notify_type=NotifyType.INFO) is True
# Our processing is slightly different when we aren't using markdown
# as we do not pre-parse content during our notifications
obj = plugins.NotifyDiscord(
webhook_id=webhook_id,
webhook_token=webhook_token,
notify_format=NotifyFormat.TEXT)
# Disable throttling to speed up unit tests
obj.throttle_attempt = 0
# This call includes an image with it's payload:
assert obj.notify(title='title', body='body',
notify_type=NotifyType.INFO) is True
@mock.patch('requests.get') @mock.patch('requests.get')
@mock.patch('requests.post') @mock.patch('requests.post')

Loading…
Cancel
Save