Added Slack URL Markdown Support (#737)

This commit is contained in:
Chris Caron 2022-11-02 22:07:41 -04:00 committed by GitHub
parent 28f424b5aa
commit b64e1b7ce0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 2 deletions

View File

@ -347,6 +347,15 @@ class NotifySlack(NotifyBase):
r'>': '>',
}
# The markdown in slack isn't [desc](url), it's <url|desc>
#
# To accomodate this, we need to ensure we don't escape URLs that match
self._re_url_support = re.compile(
r'(?P<match>(?:<|\&lt;)?[ \t]*'
r'(?P<url>(?:https?|mailto)://[^| \n]+)'
r'(?:[ \t]*\|[ \t]*(?:(?P<val>[^\n]+?)[ \t]*)?(?:>|\&gt;)'
r'|(?:>|\&gt;)))', re.IGNORECASE)
# Iterate over above list and store content accordingly
self._re_formatting_rules = re.compile(
r'(' + '|'.join(self._re_formatting_map.keys()) + r')',
@ -439,6 +448,20 @@ class NotifySlack(NotifyBase):
lambda x: self._re_formatting_map[x.group()], body,
)
# Support <url|desc>, <url> entries
for match in self._re_url_support.findall(body):
# Swap back any ampersands previously updaated
url = match[1].replace('&amp;', '&')
desc = match[2].strip()
# Update our string
body = re.sub(
re.escape(match[0]),
'<{url}|{desc}>'.format(url=url, desc=desc)
if desc else '<{url}>'.format(url=url),
body,
re.IGNORECASE)
# Perform Formatting on title here; this is not needed for block
# mode above
title = self._re_formatting_rules.sub( # pragma: no branch
@ -803,7 +826,7 @@ class NotifySlack(NotifyBase):
# The text 'ok' is returned if this is a Webhook request
# So the below captures that as well.
status_okay = (response and response.get('ok', False)) \
if self.mode is SlackMode.BOT else r.text == 'ok'
if self.mode is SlackMode.BOT else r.content == 'ok'
if r.status_code != requests.codes.ok or not status_okay:
# We had a problem

View File

@ -25,15 +25,17 @@
import os
from unittest import mock
from inspect import cleandoc
import pytest
import requests
from apprise import Apprise
from apprise import NotifyType
from apprise import AppriseAttachment
from apprise.plugins.NotifySlack import NotifySlack
from helpers import AppriseURLTester
from json import dumps
from json import loads, dumps
# Disable logging for a cleaner testing output
import logging
@ -640,3 +642,55 @@ def test_plugin_slack_send_by_email(mock_get, mock_post):
assert mock_post.call_count == 0
assert mock_get.call_args_list[0][0][0] == \
'https://slack.com/api/users.lookupByEmail'
@mock.patch('requests.post')
@mock.patch('requests.get')
def test_plugin_slack_markdown(mock_get, mock_post):
"""
NotifySlack() Markdown tests
"""
request = mock.Mock()
request.content = 'ok'
request.status_code = requests.codes.ok
# Prepare Mock
mock_post.return_value = request
mock_get.return_value = request
# Variation Initializations
aobj = Apprise()
assert aobj.add(
'slack://T1JJ3T3L2/A1BRTD4JD/TIiajkdnlazkcOXrIdevi7FQ/#channel')
body = cleandoc("""
Here is a <https://slack.com|Slack Link> we want to support as part of it's
markdown.
This one has arguments we want to preserve:
<https://slack.com?arg=val&arg2=val2|Slack Link>.
We also want to be able to support <https://slack.com> links without the
description.
""")
# Send our notification
assert aobj.notify(
body=body, title='title', notify_type=NotifyType.INFO)
# We would have failed to look up the email, therefore we wouldn't have
# even bothered to attempt to send the notification
assert mock_get.call_count == 0
assert mock_post.call_count == 1
assert mock_post.call_args_list[0][0][0] == \
'https://hooks.slack.com/services/T1JJ3T3L2/A1BRTD4JD/' \
'TIiajkdnlazkcOXrIdevi7FQ'
data = loads(mock_post.call_args_list[0][1]['data'])
assert data['attachments'][0]['text'] == \
"Here is a <https://slack.com|Slack Link> we want to support as part "\
"of it's\nmarkdown.\n\nThis one has arguments we want to preserve:"\
"\n <https://slack.com?arg=val&arg2=val2|Slack Link>.\n"\
"We also want to be able to support <https://slack.com> "\
"links without the\ndescription."