diff --git a/slack_bolt/context/ack/ack.py b/slack_bolt/context/ack/ack.py index 69cf928cc..5ebc5f5ad 100644 --- a/slack_bolt/context/ack/ack.py +++ b/slack_bolt/context/ack/ack.py @@ -19,6 +19,8 @@ def __call__( text: Union[str, dict] = "", # text: str or whole_response: dict blocks: Optional[Sequence[Union[dict, Block]]] = None, attachments: Optional[Sequence[Union[dict, Attachment]]] = None, + unfurl_links: Optional[bool] = None, + unfurl_media: Optional[bool] = None, response_type: Optional[str] = None, # in_channel / ephemeral # block_suggestion / dialog_suggestion options: Optional[Sequence[Union[dict, Option]]] = None, @@ -33,6 +35,8 @@ def __call__( text_or_whole_response=text, blocks=blocks, attachments=attachments, + unfurl_links=unfurl_links, + unfurl_media=unfurl_media, response_type=response_type, options=options, option_groups=option_groups, diff --git a/slack_bolt/context/ack/async_ack.py b/slack_bolt/context/ack/async_ack.py index 3be06918a..c12e7b6d2 100644 --- a/slack_bolt/context/ack/async_ack.py +++ b/slack_bolt/context/ack/async_ack.py @@ -19,6 +19,8 @@ async def __call__( text: Union[str, dict] = "", # text: str or whole_response: dict blocks: Optional[Sequence[Union[dict, Block]]] = None, attachments: Optional[Sequence[Union[dict, Attachment]]] = None, + unfurl_links: Optional[bool] = None, + unfurl_media: Optional[bool] = None, response_type: Optional[str] = None, # in_channel / ephemeral # block_suggestion / dialog_suggestion options: Optional[Sequence[Union[dict, Option]]] = None, @@ -33,6 +35,8 @@ async def __call__( text_or_whole_response=text, blocks=blocks, attachments=attachments, + unfurl_links=unfurl_links, + unfurl_media=unfurl_media, response_type=response_type, options=options, option_groups=option_groups, diff --git a/slack_bolt/context/ack/internals.py b/slack_bolt/context/ack/internals.py index 8d21b6559..1985e26ca 100644 --- a/slack_bolt/context/ack/internals.py +++ b/slack_bolt/context/ack/internals.py @@ -14,6 +14,8 @@ def _set_response( text_or_whole_response: Union[str, dict] = "", blocks: Optional[Sequence[Union[dict, Block]]] = None, attachments: Optional[Sequence[Union[dict, Attachment]]] = None, + unfurl_links: Optional[bool] = None, + unfurl_media: Optional[bool] = None, response_type: Optional[str] = None, # in_channel / ephemeral # block_suggestion / dialog_suggestion options: Optional[Sequence[Union[dict, Option]]] = None, @@ -28,6 +30,10 @@ def _set_response( body = {"text": text} if response_type: body["response_type"] = response_type + if unfurl_links is not None: + body["unfurl_links"] = unfurl_links + if unfurl_media is not None: + body["unfurl_media"] = unfurl_media if attachments and len(attachments) > 0: body.update( {"text": text, "attachments": convert_to_dict_list(attachments)} diff --git a/slack_bolt/context/respond/async_respond.py b/slack_bolt/context/respond/async_respond.py index 77a4665ac..60e4fe473 100644 --- a/slack_bolt/context/respond/async_respond.py +++ b/slack_bolt/context/respond/async_respond.py @@ -21,6 +21,8 @@ async def __call__( response_type: Optional[str] = None, replace_original: Optional[bool] = None, delete_original: Optional[bool] = None, + unfurl_links: Optional[bool] = None, + unfurl_media: Optional[bool] = None, ) -> WebhookResponse: if self.response_url is not None: client = AsyncWebhookClient(self.response_url) @@ -33,6 +35,8 @@ async def __call__( response_type=response_type, replace_original=replace_original, delete_original=delete_original, + unfurl_links=unfurl_links, + unfurl_media=unfurl_media, ) return await client.send_dict(message) elif isinstance(text_or_whole_response, dict): diff --git a/slack_bolt/context/respond/internals.py b/slack_bolt/context/respond/internals.py index 28cbbbec4..21acfaf43 100644 --- a/slack_bolt/context/respond/internals.py +++ b/slack_bolt/context/respond/internals.py @@ -13,6 +13,8 @@ def _build_message( response_type: Optional[str] = None, replace_original: Optional[bool] = None, delete_original: Optional[bool] = None, + unfurl_links: Optional[bool] = None, + unfurl_media: Optional[bool] = None, ) -> Dict[str, Any]: message = {"text": text} if blocks is not None and len(blocks) > 0: @@ -25,4 +27,8 @@ def _build_message( message["replace_original"] = replace_original if delete_original is not None: message["delete_original"] = delete_original + if unfurl_links is not None: + message["unfurl_links"] = unfurl_links + if unfurl_media is not None: + message["unfurl_media"] = unfurl_media return message diff --git a/slack_bolt/context/respond/respond.py b/slack_bolt/context/respond/respond.py index 09e2727df..21de92263 100644 --- a/slack_bolt/context/respond/respond.py +++ b/slack_bolt/context/respond/respond.py @@ -21,6 +21,8 @@ def __call__( response_type: Optional[str] = None, replace_original: Optional[bool] = None, delete_original: Optional[bool] = None, + unfurl_links: Optional[bool] = None, + unfurl_media: Optional[bool] = None, ) -> WebhookResponse: if self.response_url is not None: client = WebhookClient(self.response_url) @@ -34,6 +36,8 @@ def __call__( response_type=response_type, replace_original=replace_original, delete_original=delete_original, + unfurl_links=unfurl_links, + unfurl_media=unfurl_media, ) return client.send_dict(message) elif isinstance(text_or_whole_response, dict): diff --git a/slack_bolt/context/say/async_say.py b/slack_bolt/context/say/async_say.py index a47838e1b..88afe2533 100644 --- a/slack_bolt/context/say/async_say.py +++ b/slack_bolt/context/say/async_say.py @@ -26,6 +26,8 @@ async def __call__( attachments: Optional[Sequence[Union[Dict, Attachment]]] = None, channel: Optional[str] = None, thread_ts: Optional[str] = None, + unfurl_links: Optional[bool] = None, + unfurl_media: Optional[bool] = None, **kwargs, ) -> AsyncSlackResponse: if _can_say(self, channel): @@ -38,6 +40,8 @@ async def __call__( blocks=blocks, attachments=attachments, thread_ts=thread_ts, + unfurl_links=unfurl_links, + unfurl_media=unfurl_media, **kwargs, ) elif isinstance(text_or_whole_response, dict): diff --git a/slack_bolt/context/say/say.py b/slack_bolt/context/say/say.py index ccf7d6d91..58535da90 100644 --- a/slack_bolt/context/say/say.py +++ b/slack_bolt/context/say/say.py @@ -27,6 +27,8 @@ def __call__( attachments: Optional[Sequence[Union[Dict, Attachment]]] = None, channel: Optional[str] = None, thread_ts: Optional[str] = None, + unfurl_links: Optional[bool] = None, + unfurl_media: Optional[bool] = None, **kwargs, ) -> SlackResponse: if _can_say(self, channel): @@ -39,6 +41,8 @@ def __call__( blocks=blocks, attachments=attachments, thread_ts=thread_ts, + unfurl_links=unfurl_links, + unfurl_media=unfurl_media, **kwargs, ) elif isinstance(text_or_whole_response, dict): diff --git a/tests/slack_bolt/context/test_ack.py b/tests/slack_bolt/context/test_ack.py index e7d7443e9..2ae0b1050 100644 --- a/tests/slack_bolt/context/test_ack.py +++ b/tests/slack_bolt/context/test_ack.py @@ -54,6 +54,19 @@ def test_blocks(self): '{"text": "foo", "blocks": [{"type": "divider"}]}', ) + def test_unfurl_options(self): + ack = Ack() + response: BoltResponse = ack( + text="foo", + blocks=[{"type": "divider"}], + unfurl_links=True, + unfurl_media=True, + ) + assert (response.status, response.body) == ( + 200, + '{"text": "foo", "unfurl_links": true, "unfurl_media": true, "blocks": [{"type": "divider"}]}', + ) + sample_options = [{"text": {"type": "plain_text", "text": "Maru"}, "value": "maru"}] def test_options(self): diff --git a/tests/slack_bolt/context/test_respond.py b/tests/slack_bolt/context/test_respond.py index 1a76e507d..f108664f3 100644 --- a/tests/slack_bolt/context/test_respond.py +++ b/tests/slack_bolt/context/test_respond.py @@ -23,3 +23,9 @@ def test_respond2(self): respond = Respond(response_url=response_url) response = respond({"text": "Hi there!"}) assert response.status_code == 200 + + def test_unfurl_options(self): + response_url = "http://localhost:8888" + respond = Respond(response_url=response_url) + response = respond(text="Hi there!", unfurl_media=True, unfurl_links=True) + assert response.status_code == 200 diff --git a/tests/slack_bolt/context/test_respond_internals.py b/tests/slack_bolt/context/test_respond_internals.py index 173fdf003..facb293da 100644 --- a/tests/slack_bolt/context/test_respond_internals.py +++ b/tests/slack_bolt/context/test_respond_internals.py @@ -43,3 +43,9 @@ def test_build_message_replace_original(self): def test_build_message_delete_original(self): message = _build_message(delete_original=True) assert message is not None + + def test_build_message_unfurl_options(self): + message = _build_message(text="Hi there!", unfurl_links=True, unfurl_media=True) + assert message is not None + assert message.get("unfurl_links") is True + assert message.get("unfurl_media") is True diff --git a/tests/slack_bolt/context/test_say.py b/tests/slack_bolt/context/test_say.py index a28fbbd9d..fae42d1f0 100644 --- a/tests/slack_bolt/context/test_say.py +++ b/tests/slack_bolt/context/test_say.py @@ -26,6 +26,13 @@ def test_say(self): response: SlackResponse = say(text="Hi there!") assert response.status_code == 200 + def test_say_unfurl_options(self): + say = Say(client=self.web_client, channel="C111") + response: SlackResponse = say( + text="Hi there!", unfurl_media=True, unfurl_links=True + ) + assert response.status_code == 200 + def test_say_dict(self): say = Say(client=self.web_client, channel="C111") response: SlackResponse = say({"text": "Hi!"}) diff --git a/tests/slack_bolt_async/context/test_async_ack.py b/tests/slack_bolt_async/context/test_async_ack.py index 6004002dd..e4f498842 100644 --- a/tests/slack_bolt_async/context/test_async_ack.py +++ b/tests/slack_bolt_async/context/test_async_ack.py @@ -22,6 +22,20 @@ async def test_blocks(self): '{"text": "foo", "blocks": [{"type": "divider"}]}', ) + @pytest.mark.asyncio + async def test_unfurl_options(self): + ack = AsyncAck() + response: BoltResponse = await ack( + text="foo", + blocks=[{"type": "divider"}], + unfurl_links=True, + unfurl_media=True, + ) + assert (response.status, response.body) == ( + 200, + '{"text": "foo", "unfurl_links": true, "unfurl_media": true, "blocks": [{"type": "divider"}]}', + ) + sample_attachments = [ { "fallback": "Plain-text summary of the attachment.", diff --git a/tests/slack_bolt_async/context/test_async_respond.py b/tests/slack_bolt_async/context/test_async_respond.py index fb3083132..18ae114e8 100644 --- a/tests/slack_bolt_async/context/test_async_respond.py +++ b/tests/slack_bolt_async/context/test_async_respond.py @@ -31,3 +31,10 @@ async def test_respond2(self): respond = AsyncRespond(response_url=response_url) response = await respond({"text": "Hi there!"}) assert response.status_code == 200 + + @pytest.mark.asyncio + async def test_respond_unfurl_options(self): + response_url = "http://localhost:8888" + respond = AsyncRespond(response_url=response_url) + response = await respond(text="Hi there!", unfurl_media=True, unfurl_links=True) + assert response.status_code == 200 diff --git a/tests/slack_bolt_async/context/test_async_say.py b/tests/slack_bolt_async/context/test_async_say.py index 03a2978ec..77f846154 100644 --- a/tests/slack_bolt_async/context/test_async_say.py +++ b/tests/slack_bolt_async/context/test_async_say.py @@ -32,6 +32,14 @@ async def test_say(self): response: AsyncSlackResponse = await say(text="Hi there!") assert response.status_code == 200 + @pytest.mark.asyncio + async def test_say_unfurl_options(self): + say = AsyncSay(client=self.web_client, channel="C111") + response: AsyncSlackResponse = await say( + text="Hi there!", unfurl_links=True, unfurl_media=True + ) + assert response.status_code == 200 + @pytest.mark.asyncio async def test_say_dict(self): say = AsyncSay(client=self.web_client, channel="C111")