From b64e1b7ce0ce58d81fe93893cf04b4e3333d96f5 Mon Sep 17 00:00:00 2001 From: Chris Caron Date: Wed, 2 Nov 2022 22:07:41 -0400 Subject: [PATCH] Added Slack URL Markdown Support (#737) --- apprise/plugins/NotifySlack.py | 25 ++++++++++++++- test/test_plugin_slack.py | 56 +++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/apprise/plugins/NotifySlack.py b/apprise/plugins/NotifySlack.py index 2c895f34..15c38f77 100644 --- a/apprise/plugins/NotifySlack.py +++ b/apprise/plugins/NotifySlack.py @@ -347,6 +347,15 @@ class NotifySlack(NotifyBase): r'>': '>', } + # The markdown in slack isn't [desc](url), it's + # + # To accomodate this, we need to ensure we don't escape URLs that match + self._re_url_support = re.compile( + r'(?P(?:<|\<)?[ \t]*' + r'(?P(?:https?|mailto)://[^| \n]+)' + r'(?:[ \t]*\|[ \t]*(?:(?P[^\n]+?)[ \t]*)?(?:>|\>)' + r'|(?:>|\>)))', 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 , entries + for match in self._re_url_support.findall(body): + # Swap back any ampersands previously updaated + url = match[1].replace('&', '&') + 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 diff --git a/test/test_plugin_slack.py b/test/test_plugin_slack.py index 3efd0579..cd46eeb5 100644 --- a/test/test_plugin_slack.py +++ b/test/test_plugin_slack.py @@ -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 we want to support as part of it's + markdown. + + This one has arguments we want to preserve: + . + We also want to be able to support 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 we want to support as part "\ + "of it's\nmarkdown.\n\nThis one has arguments we want to preserve:"\ + "\n .\n"\ + "We also want to be able to support "\ + "links without the\ndescription."