Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make WebhookClient (sync/async) #send method accept link unfurl params #1047

Merged
merged 18 commits into from Jun 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
78 changes: 62 additions & 16 deletions integration_tests/webhook/test_async_webhook.py
@@ -1,12 +1,13 @@
import os
from tests.helpers import async_test
import unittest
import time

from integration_tests.env_variable_names import (
SLACK_SDK_TEST_INCOMING_WEBHOOK_URL,
SLACK_SDK_TEST_INCOMING_WEBHOOK_CHANNEL_NAME,
SLACK_SDK_TEST_BOT_TOKEN,
)
from integration_tests.helpers import async_test
from slack_sdk.web.async_client import AsyncWebClient
from slack_sdk.webhook.async_client import AsyncWebhookClient
from slack_sdk.models.attachments import Attachment, AttachmentField
Expand All @@ -16,8 +17,22 @@


class TestAsyncWebhook(unittest.TestCase):
def setUp(self):
pass
@async_test
async def setUp(self):
if not hasattr(self, "channel_id"):
token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
channel_name = os.environ[
SLACK_SDK_TEST_INCOMING_WEBHOOK_CHANNEL_NAME
].replace("#", "")
client = AsyncWebClient(token=token)
self.channel_id = None
async for resp in await client.conversations_list(limit=10):
for c in resp["channels"]:
if c["name"] == channel_name:
self.channel_id = c["id"]
break
if self.channel_id is not None:
break

def tearDown(self):
pass
Expand All @@ -31,24 +46,55 @@ async def test_webhook(self):
self.assertEqual("ok", response.body)

token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
channel_name = os.environ[SLACK_SDK_TEST_INCOMING_WEBHOOK_CHANNEL_NAME].replace(
"#", ""
)
client = AsyncWebClient(token=token)
channel_id = None
async for resp in await client.conversations_list(limit=10):
for c in resp["channels"]:
if c["name"] == channel_name:
channel_id = c["id"]
break
if channel_id is not None:
break

history = await client.conversations_history(channel=channel_id, limit=1)
history = await client.conversations_history(channel=self.channel_id, limit=1)
self.assertIsNotNone(history)
actual_text = history["messages"][0]["text"]
self.assertEqual("Hello!", actual_text)

@async_test
async def test_with_unfurls_off(self):
url = os.environ[SLACK_SDK_TEST_INCOMING_WEBHOOK_URL]
token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
webhook = AsyncWebhookClient(url)
client = AsyncWebClient(token=token)
# send message that does not unfurl
response = await webhook.send(
text="<https://imgs.xkcd.com/comics/desert_golfing_2x.png|Desert Golfing>",
unfurl_links=False,
unfurl_media=False,
)
self.assertEqual(200, response.status_code)
self.assertEqual("ok", response.body)
# wait to allow Slack API to edit message with attachments
time.sleep(2)
history = await client.conversations_history(channel=self.channel_id, limit=1)
self.assertIsNotNone(history)
self.assertTrue("attachments" not in history["messages"][0])

@async_test
async def test_with_unfurls_on(self):
# Slack API rate limits unfurls of unique links so test will
# fail when repeated. For testing, either use a different URL
# for text option or delete existing attachments in webhook channel.
url = os.environ[SLACK_SDK_TEST_INCOMING_WEBHOOK_URL]
token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
webhook = AsyncWebhookClient(url)
client = AsyncWebClient(token=token)
# send message that does unfurl
response = await webhook.send(
text="<https://imgs.xkcd.com/comics/red_spiders_small.jpg|Spiders>",
unfurl_links=True,
unfurl_media=True,
)
self.assertEqual(200, response.status_code)
self.assertEqual("ok", response.body)
# wait to allow Slack API to edit message with attachments
time.sleep(2)
history = await client.conversations_history(channel=self.channel_id, limit=1)
self.assertIsNotNone(history)
self.assertTrue("attachments" in history["messages"][0])

@async_test
async def test_with_blocks(self):
url = os.environ[SLACK_SDK_TEST_INCOMING_WEBHOOK_URL]
Expand Down
71 changes: 57 additions & 14 deletions integration_tests/webhook/test_webhook.py
@@ -1,5 +1,6 @@
import os
import unittest
import time

from integration_tests.env_variable_names import (
SLACK_SDK_TEST_INCOMING_WEBHOOK_URL,
Expand All @@ -16,7 +17,20 @@

class TestWebhook(unittest.TestCase):
def setUp(self):
pass
if not hasattr(self, "channel_id"):
token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
channel_name = os.environ[
SLACK_SDK_TEST_INCOMING_WEBHOOK_CHANNEL_NAME
].replace("#", "")
client = WebClient(token=token)
self.channel_id = None
for resp in client.conversations_list(limit=10):
for c in resp["channels"]:
if c["name"] == channel_name:
self.channel_id = c["id"]
break
if self.channel_id is not None:
break

def tearDown(self):
pass
Expand All @@ -29,24 +43,53 @@ def test_webhook(self):
self.assertEqual("ok", response.body)

token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
channel_name = os.environ[SLACK_SDK_TEST_INCOMING_WEBHOOK_CHANNEL_NAME].replace(
"#", ""
)
client = WebClient(token=token)
channel_id = None
for resp in client.conversations_list(limit=10):
for c in resp["channels"]:
if c["name"] == channel_name:
channel_id = c["id"]
break
if channel_id is not None:
break

history = client.conversations_history(channel=channel_id, limit=1)
history = client.conversations_history(channel=self.channel_id, limit=1)
self.assertIsNotNone(history)
actual_text = history["messages"][0]["text"]
self.assertEqual("Hello!", actual_text)

def test_with_unfurls_off(self):
url = os.environ[SLACK_SDK_TEST_INCOMING_WEBHOOK_URL]
token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
webhook = WebhookClient(url)
client = WebClient(token=token)
# send message that does not unfurl
response = webhook.send(
text="<https://imgs.xkcd.com/comics/desert_golfing_2x.png|Desert Golfing>",
unfurl_links=False,
unfurl_media=False,
)
self.assertEqual(200, response.status_code)
self.assertEqual("ok", response.body)
# wait to allow Slack API to edit message with attachments
time.sleep(2)
srajiang marked this conversation as resolved.
Show resolved Hide resolved
history = client.conversations_history(channel=self.channel_id, limit=1)
self.assertIsNotNone(history)
self.assertTrue("attachments" not in history["messages"][0])

def test_with_unfurls_on(self):
srajiang marked this conversation as resolved.
Show resolved Hide resolved
# Slack API rate limits unfurls of unique links so test will
# fail when repeated. For testing, either use a different URL
# for text option or delete existing attachments in webhook channel.
url = os.environ[SLACK_SDK_TEST_INCOMING_WEBHOOK_URL]
token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
webhook = WebhookClient(url)
client = WebClient(token=token)
# send message that does unfurl
response = webhook.send(
text="<https://imgs.xkcd.com/comics/red_spiders_small.jpg|Spiders>",
unfurl_links=True,
unfurl_media=True,
)
self.assertEqual(200, response.status_code)
self.assertEqual("ok", response.body)
# wait to allow Slack API to edit message with attachments
time.sleep(2)
srajiang marked this conversation as resolved.
Show resolved Hide resolved
history = client.conversations_history(channel=self.channel_id, limit=1)
self.assertIsNotNone(history)
self.assertTrue("attachments" in history["messages"][0])
srajiang marked this conversation as resolved.
Show resolved Hide resolved

def test_with_blocks(self):
url = os.environ[SLACK_SDK_TEST_INCOMING_WEBHOOK_URL]
webhook = WebhookClient(url)
Expand Down
6 changes: 6 additions & 0 deletions slack_sdk/webhook/async_client.py
Expand Up @@ -87,6 +87,8 @@ async def send(
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,
headers: Optional[Dict[str, str]] = None,
) -> WebhookResponse:
"""Performs a Slack API request and returns the result.
Expand All @@ -98,6 +100,8 @@ async def send(
response_type: The type of message (either 'in_channel' or 'ephemeral')
replace_original: True if you use this option for response_url requests
delete_original: True if you use this option for response_url requests
unfurl_links: Option to indicate whether text url should unfurl
unfurl_media: Option to indicate whether media url should unfurl
headers: Request headers to append only for this request

Returns:
Expand All @@ -113,6 +117,8 @@ async def send(
"response_type": response_type,
"replace_original": replace_original,
"delete_original": delete_original,
"unfurl_links": unfurl_links,
"unfurl_media": unfurl_media,
},
headers=headers,
)
Expand Down
6 changes: 6 additions & 0 deletions slack_sdk/webhook/client.py
Expand Up @@ -77,6 +77,8 @@ def send(
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,
headers: Optional[Dict[str, str]] = None,
) -> WebhookResponse:
"""Performs a Slack API request and returns the result.
Expand All @@ -89,6 +91,8 @@ def send(
response_type: The type of message (either 'in_channel' or 'ephemeral')
replace_original: True if you use this option for response_url requests
delete_original: True if you use this option for response_url requests
unfurl_links: Option to indicate whether text url should unfurl
unfurl_media: Option to indicate whether media url should unfurl
headers: Request headers to append only for this request

Returns:
Expand All @@ -104,6 +108,8 @@ def send(
"response_type": response_type,
"replace_original": replace_original,
"delete_original": delete_original,
"unfurl_links": unfurl_links,
"unfurl_media": unfurl_media,
},
headers=headers,
)
Expand Down
2 changes: 0 additions & 2 deletions slack_sdk/webhook/internal_utils.py
Expand Up @@ -4,15 +4,13 @@
from slack_sdk.web.internal_utils import (
_parse_web_class_objects,
get_user_agent,
convert_bool_to_0_or_1,
)
from .webhook_response import WebhookResponse


def _build_body(original_body: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
if original_body:
body = {k: v for k, v in original_body.items() if v is not None}
body = convert_bool_to_0_or_1(body)
_parse_web_class_objects(body)
return body
return None
Expand Down
16 changes: 12 additions & 4 deletions tests/webhook/test_async_webhook.py
@@ -1,12 +1,9 @@
import asyncio
from tests.helpers import async_test
import unittest

import aiohttp

from slack.web.classes.attachments import Attachment, AttachmentField
from slack.web.classes.blocks import SectionBlock, ImageBlock
from slack.webhook import AsyncWebhookClient, WebhookResponse
from tests.helpers import async_test
from tests.webhook.mock_web_api_server import (
cleanup_mock_web_api_server,
setup_mock_web_api_server,
Expand All @@ -31,6 +28,17 @@ async def test_send(self):
resp = await client.send(text="hello!", response_type="in_channel")
self.assertEqual("ok", resp.body)

@async_test
async def test_send_with_url_unfurl_opts_issue_1045(self):
client = AsyncWebhookClient("http://localhost:8888")
resp: WebhookResponse = await client.send(
text="<https://imgs.xkcd.com/comics/1991_and_2021_2x.png|XKCD>",
unfurl_links=False,
unfurl_media=False,
)
self.assertEqual(200, resp.status_code)
self.assertEqual("ok", resp.body)

@async_test
async def test_send_blocks(self):
client = AsyncWebhookClient("http://localhost:8888")
Expand Down
10 changes: 10 additions & 0 deletions tests/webhook/test_webhook.py
Expand Up @@ -28,6 +28,16 @@ def test_send(self):
resp = client.send(text="hello!", response_type="in_channel")
self.assertEqual("ok", resp.body)

def test_send_with_url_unfurl_opts_issue_1045(self):
client = WebhookClient("http://localhost:8888")
resp: WebhookResponse = client.send(
text="<https://imgs.xkcd.com/comics/1991_and_2021_2x.png|XKCD>",
unfurl_links=False,
unfurl_media=False,
)
self.assertEqual(200, resp.status_code)
self.assertEqual("ok", resp.body)

def test_send_blocks(self):
client = WebhookClient("http://localhost:8888")

Expand Down