pull/1337/merge
John Torakis 2025-07-16 08:14:55 -05:00 committed by GitHub
commit 19b280231b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 78 additions and 10 deletions

View File

@ -76,6 +76,7 @@ import re
import requests import requests
from json import dumps from json import dumps
from json import loads from json import loads
from json import JSONDecodeError
from time import time from time import time
from .base import NotifyBase from .base import NotifyBase
@ -410,18 +411,30 @@ class NotifySlack(NotifyBase):
if self.notify_format == NotifyFormat.MARKDOWN \ if self.notify_format == NotifyFormat.MARKDOWN \
else 'plain_text' else 'plain_text'
payload = { # If we have to handle Blocks API serialized JSON
'username': self.user if self.user else self.app_id, if kwargs.get('body_format', None) == 'json':
'attachments': [{ try:
'blocks': [{ content = loads(body)
except JSONDecodeError:
self.logger.error(
"'body_format' is set as 'json',"
"but body is not valid JSON string"
)
return False
# Else, we continue as before
else:
content = {'blocks': [{
'type': 'section', 'type': 'section',
'text': { 'text': {
'type': _slack_format, 'type': _slack_format,
'text': body 'text': body
} }
}], }]}
'color': self.color(notify_type), content.update({'color': self.color(notify_type)})
}]
payload = {
'username': self.user if self.user else self.app_id,
'attachments': [content.copy()]
} }
# Slack only accepts non-empty header sections # Slack only accepts non-empty header sections
@ -463,6 +476,14 @@ class NotifySlack(NotifyBase):
payload['attachments'][0]['blocks'].append(_footer) payload['attachments'][0]['blocks'].append(_footer)
else: else:
# We do not support JSON body without the Blocks API
if kwargs.get('body_format', None) == 'json':
self.logger.error(
"'body_format' is set as 'json',"
"the 'blocks' URL parameter is not set"
)
return False
# #
# Legacy API Formatting # Legacy API Formatting
# #

View File

@ -759,6 +759,53 @@ def test_plugin_slack_markdown(mock_get, mock_request):
"\n\nChannel Testing\n<!channelA>\n<!channelA|Description>\n\n"\ "\n\nChannel Testing\n<!channelA>\n<!channelA|Description>\n\n"\
"User ID Testing\n<@U1ZQL9N3Y>\n<@U1ZQL9N3Y|heheh>" "User ID Testing\n<@U1ZQL9N3Y>\n<@U1ZQL9N3Y|heheh>"
@mock.patch('requests.request')
@mock.patch('requests.get')
def test_plugin_slack_body_format_blocks(mock_get, mock_request):
"""
NotifySlack() for using Blocks API directly
"""
request = mock.Mock()
request.content = b'ok'
request.status_code = requests.codes.ok
# Prepare Mock
mock_request.return_value = request
mock_get.return_value = request
# Variation Initializations
aobj = Apprise()
assert aobj.add(
'slack://T1JJ3T3L2/A1BRTD4JD/TIiajkdnlazkcOXrIdevi7FQ/?blocks=yes')
body_text = "Blocks API"
title_text = "title"
body = dumps({"blocks":[
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": body_text
}
},
]})
# Send our notification
assert aobj.notify(
body=body, title=title_text, notify_type=NotifyType.INFO,
body_format="json")
data = loads(mock_request.call_args_list[0][1]['data'])
# Our added block is not [0], as a title block
# has been injected by the plugin
title_block = data['attachments'][0]["blocks"][0]
added_block = data['attachments'][0]["blocks"][1]
assert title_block["text"]["text"] == title_text
assert added_block["text"]["text"] == body_text
@mock.patch('requests.request') @mock.patch('requests.request')
def test_plugin_slack_single_thread_reply(mock_request): def test_plugin_slack_single_thread_reply(mock_request):