diff --git a/apprise/plugins/slack.py b/apprise/plugins/slack.py index 50a872ee..bf69d564 100644 --- a/apprise/plugins/slack.py +++ b/apprise/plugins/slack.py @@ -280,6 +280,40 @@ class NotifySlack(NotifyBase): }, }) + # Formatting requirements are defined here: + # https://api.slack.com/docs/message-formatting + _re_formatting_map = { + # New lines must become the string version + r'\r\*\n': '\\n', + # Escape other special characters + r'&': '&', + r'<': '<', + r'>': '>', + } + + # To notify a channel, one uses + _re_channel_support = re.compile( + r'(?P(?:<|\<)?[ \t]*' + r'!(?P[^| \n]+)' + r'(?:[ \t]*\|[ \t]*(?:(?P[^\n]+?)[ \t]*)?(?:>|\>)' + r'|(?:>|\>)))', re.IGNORECASE) + + # To notify a user by their ID, one uses <@U6TTX1F9R> + _re_user_id_support = re.compile( + r'(?P(?:<|\<)?[ \t]*' + r'@(?P[^| \n]+)' + r'(?:[ \t]*\|[ \t]*(?:(?P[^\n]+?)[ \t]*)?(?:>|\>)' + r'|(?:>|\>)))', re.IGNORECASE) + + # The markdown in slack isn't [desc](url), it's + # + # To accomodate this, we need to ensure we don't escape URLs that match + _re_url_support = re.compile( + r'(?P(?:<|\<)?[ \t]*' + r'(?P(?:https?|mailto)://[^| \n]+)' + r'(?:[ \t]*\|[ \t]*(?:(?P[^\n]+?)[ \t]*)?(?:>|\>)' + r'|(?:>|\>)))', re.IGNORECASE) + def __init__(self, access_token=None, token_a=None, token_b=None, token_c=None, targets=None, include_image=True, include_footer=True, use_blocks=None, **kwargs): @@ -344,39 +378,11 @@ class NotifySlack(NotifyBase): None if self.mode is SlackMode.WEBHOOK else self.default_notification_channel) - # Formatting requirements are defined here: - # https://api.slack.com/docs/message-formatting - self._re_formatting_map = { - # New lines must become the string version - r'\r\*\n': '\\n', - # Escape other special characters - r'&': '&', - r'<': '<', - r'>': '>', - } - - # To notify a channel, one uses - self._re_channel_support = re.compile( - r'(?P(?:<|\<)?[ \t]*' - r'!(?P[^| \n]+)' - r'(?:[ \t]*\|[ \t]*(?:(?P[^\n]+?)[ \t]*)?(?:>|\>)' - r'|(?:>|\>)))', re.IGNORECASE) - - # 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')', re.IGNORECASE, ) - # Place a thumbnail image inline with the message body self.include_image = include_image @@ -478,6 +484,20 @@ class NotifySlack(NotifyBase): body, re.IGNORECASE) + # Support <@userid|desc>, <@channel> entries + for match in self._re_user_id_support.findall(body): + # Swap back any ampersands previously updaated + user = match[1].strip() + desc = match[2].strip() + + # Update our string + body = re.sub( + re.escape(match[0]), + '<@{user}|{desc}>'.format(user=user, desc=desc) + if desc else '<@{user}>'.format(user=user), + body, + re.IGNORECASE) + # Support , entries for match in self._re_url_support.findall(body): # Swap back any ampersands previously updaated diff --git a/test/test_plugin_slack.py b/test/test_plugin_slack.py index eaff0aff..02387d4d 100644 --- a/test/test_plugin_slack.py +++ b/test/test_plugin_slack.py @@ -731,6 +731,10 @@ def test_plugin_slack_markdown(mock_get, mock_request): Channel Testing + + User ID Testing + <@U1ZQL9N3Y> + <@U1ZQL9N3Y|heheh> """) # Send our notification @@ -752,7 +756,8 @@ def test_plugin_slack_markdown(mock_get, mock_request): "\n .\n"\ "We also want to be able to support "\ "links without the\ndescription."\ - "\n\nChannel Testing\n\n" + "\n\nChannel Testing\n\n\n\n"\ + "User ID Testing\n<@U1ZQL9N3Y>\n<@U1ZQL9N3Y|heheh>" @mock.patch('requests.request')