Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions slack_bolt/listener_matcher/builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ def func(body: Dict[str, Any]) -> bool:
if expected_subtype is None:
# "subtype" in constraints is intentionally None for this pattern
return "subtype" not in event
elif isinstance(expected_subtype, (str, Pattern)):
return "subtype" in event and _matches(
expected_subtype, event["subtype"]
)
elif isinstance(expected_subtype, Sequence):
subtypes: Sequence[
Optional[Union[str, Pattern]]
Expand Down
157 changes: 157 additions & 0 deletions tests/scenario_tests/test_events.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import re
from time import time, sleep

from slack_sdk.signature import SignatureVerifier
Expand Down Expand Up @@ -396,3 +397,159 @@ def handler2(say: Say):
assert self.mock_received_requests["/auth.test"] == 1
sleep(1) # wait a bit after auto ack()
assert self.mock_received_requests["/chat.postMessage"] == 2

message_file_share_body = {
"token": "verification-token",
"team_id": "T111",
"api_app_id": "A111",
"event": {
"type": "message",
"text": "Here is your file!",
"files": [
{
"id": "F111",
"created": 1610493713,
"timestamp": 1610493713,
"name": "test.png",
"title": "test.png",
"mimetype": "image/png",
"filetype": "png",
"pretty_type": "PNG",
"user": "U111",
"editable": False,
"size": 42706,
"mode": "hosted",
"is_external": False,
"external_type": "",
"is_public": False,
"public_url_shared": False,
"display_as_bot": False,
"username": "",
"url_private": "https://files.slack.com/files-pri/T111-F111/test.png",
"url_private_download": "https://files.slack.com/files-pri/T111-F111/download/test.png",
"thumb_64": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_64.png",
"thumb_80": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_80.png",
"thumb_360": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_360.png",
"thumb_360_w": 358,
"thumb_360_h": 360,
"thumb_480": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_480.png",
"thumb_480_w": 477,
"thumb_480_h": 480,
"thumb_160": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_160.png",
"thumb_720": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_720.png",
"thumb_720_w": 716,
"thumb_720_h": 720,
"original_w": 736,
"original_h": 740,
"thumb_tiny": "xxx",
"permalink": "https://xxx.slack.com/files/U111/F111/test.png",
"permalink_public": "https://slack-files.com/T111-F111-3e534ef8ca",
"has_rich_preview": False,
}
],
"upload": False,
"blocks": [
{
"type": "rich_text",
"block_id": "gvM",
"elements": [
{
"type": "rich_text_section",
"elements": [
{"type": "text", "text": "Here is your file!"}
],
}
],
}
],
"user": "U111",
"display_as_bot": False,
"ts": "1610493715.001000",
"channel": "G111",
"subtype": "file_share",
"event_ts": "1610493715.001000",
"channel_type": "group",
},
"type": "event_callback",
"event_id": "Ev111",
"event_time": 1610493715,
"authorizations": [
{
"enterprise_id": None,
"team_id": "T111",
"user_id": "U111",
"is_bot": True,
"is_enterprise_install": False,
}
],
"is_ext_shared_channel": False,
"event_context": "1-message-T111-G111",
}

def test_message_subtypes_0(self):
app = App(client=self.web_client, signing_secret=self.signing_secret)
app._client = WebClient(
token="uninstalled-revoked", base_url=self.mock_api_server_base_url
)

@app.event({"type": "message", "subtype": "file_share"})
def handler1(event):
assert event["subtype"] == "file_share"

timestamp, body = str(int(time())), json.dumps(self.message_file_share_body)
request: BoltRequest = BoltRequest(
body=body, headers=self.build_headers(timestamp, body)
)
response = app.dispatch(request)
assert response.status == 200

def test_message_subtypes_1(self):
app = App(client=self.web_client, signing_secret=self.signing_secret)
app._client = WebClient(
token="uninstalled-revoked", base_url=self.mock_api_server_base_url
)

@app.event({"type": "message", "subtype": re.compile("file_.+")})
def handler1(event):
assert event["subtype"] == "file_share"

timestamp, body = str(int(time())), json.dumps(self.message_file_share_body)
request: BoltRequest = BoltRequest(
body=body, headers=self.build_headers(timestamp, body)
)
response = app.dispatch(request)
assert response.status == 200

def test_message_subtypes_2(self):
app = App(client=self.web_client, signing_secret=self.signing_secret)
app._client = WebClient(
token="uninstalled-revoked", base_url=self.mock_api_server_base_url
)

@app.event({"type": "message", "subtype": ["file_share"]})
def handler1(event):
assert event["subtype"] == "file_share"

timestamp, body = str(int(time())), json.dumps(self.message_file_share_body)
request: BoltRequest = BoltRequest(
body=body, headers=self.build_headers(timestamp, body)
)
response = app.dispatch(request)
assert response.status == 200

def test_message_subtypes_3(self):
app = App(client=self.web_client, signing_secret=self.signing_secret)
app._client = WebClient(
token="uninstalled-revoked", base_url=self.mock_api_server_base_url
)

@app.event("message")
def handler1(event):
assert event["subtype"] == "file_share"

timestamp, body = str(int(time())), json.dumps(self.message_file_share_body)
request: BoltRequest = BoltRequest(
body=body, headers=self.build_headers(timestamp, body)
)
response = app.dispatch(request)
assert response.status == 200
161 changes: 161 additions & 0 deletions tests/scenario_tests_async/test_events.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import json
import re
from random import random
from time import time

Expand Down Expand Up @@ -400,6 +401,166 @@ async def handler2(say: AsyncSay):
await asyncio.sleep(1) # wait a bit after auto ack()
assert self.mock_received_requests["/chat.postMessage"] == 2

message_file_share_body = {
"token": "verification-token",
"team_id": "T111",
"api_app_id": "A111",
"event": {
"type": "message",
"text": "Here is your file!",
"files": [
{
"id": "F111",
"created": 1610493713,
"timestamp": 1610493713,
"name": "test.png",
"title": "test.png",
"mimetype": "image/png",
"filetype": "png",
"pretty_type": "PNG",
"user": "U111",
"editable": False,
"size": 42706,
"mode": "hosted",
"is_external": False,
"external_type": "",
"is_public": False,
"public_url_shared": False,
"display_as_bot": False,
"username": "",
"url_private": "https://files.slack.com/files-pri/T111-F111/test.png",
"url_private_download": "https://files.slack.com/files-pri/T111-F111/download/test.png",
"thumb_64": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_64.png",
"thumb_80": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_80.png",
"thumb_360": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_360.png",
"thumb_360_w": 358,
"thumb_360_h": 360,
"thumb_480": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_480.png",
"thumb_480_w": 477,
"thumb_480_h": 480,
"thumb_160": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_160.png",
"thumb_720": "https://files.slack.com/files-tmb/T111-F111-8d3f9a6d4b/test_720.png",
"thumb_720_w": 716,
"thumb_720_h": 720,
"original_w": 736,
"original_h": 740,
"thumb_tiny": "xxx",
"permalink": "https://xxx.slack.com/files/U111/F111/test.png",
"permalink_public": "https://slack-files.com/T111-F111-3e534ef8ca",
"has_rich_preview": False,
}
],
"upload": False,
"blocks": [
{
"type": "rich_text",
"block_id": "gvM",
"elements": [
{
"type": "rich_text_section",
"elements": [
{"type": "text", "text": "Here is your file!"}
],
}
],
}
],
"user": "U111",
"display_as_bot": False,
"ts": "1610493715.001000",
"channel": "G111",
"subtype": "file_share",
"event_ts": "1610493715.001000",
"channel_type": "group",
},
"type": "event_callback",
"event_id": "Ev111",
"event_time": 1610493715,
"authorizations": [
{
"enterprise_id": None,
"team_id": "T111",
"user_id": "U111",
"is_bot": True,
"is_enterprise_install": False,
}
],
"is_ext_shared_channel": False,
"event_context": "1-message-T111-G111",
}

@pytest.mark.asyncio
async def test_message_subtypes_0(self):
app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret)
app._client = AsyncWebClient(
token="uninstalled-revoked", base_url=self.mock_api_server_base_url
)

@app.event({"type": "message", "subtype": "file_share"})
async def handler1(event):
assert event["subtype"] == "file_share"

timestamp, body = str(int(time())), json.dumps(self.message_file_share_body)
request: AsyncBoltRequest = AsyncBoltRequest(
body=body, headers=self.build_headers(timestamp, body)
)
response = await app.async_dispatch(request)
assert response.status == 200

@pytest.mark.asyncio
async def test_message_subtypes_1(self):
app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret)
app._client = AsyncWebClient(
token="uninstalled-revoked", base_url=self.mock_api_server_base_url
)

@app.event({"type": "message", "subtype": re.compile("file_.+")})
async def handler1(event):
assert event["subtype"] == "file_share"

timestamp, body = str(int(time())), json.dumps(self.message_file_share_body)
request: AsyncBoltRequest = AsyncBoltRequest(
body=body, headers=self.build_headers(timestamp, body)
)
response = await app.async_dispatch(request)
assert response.status == 200

@pytest.mark.asyncio
async def test_message_subtypes_2(self):
app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret)
app._client = AsyncWebClient(
token="uninstalled-revoked", base_url=self.mock_api_server_base_url
)

@app.event({"type": "message", "subtype": ["file_share"]})
async def handler1(event):
assert event["subtype"] == "file_share"

timestamp, body = str(int(time())), json.dumps(self.message_file_share_body)
request: AsyncBoltRequest = AsyncBoltRequest(
body=body, headers=self.build_headers(timestamp, body)
)
response = await app.async_dispatch(request)
assert response.status == 200

@pytest.mark.asyncio
async def test_message_subtypes_3(self):
app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret)
app._client = AsyncWebClient(
token="uninstalled-revoked", base_url=self.mock_api_server_base_url
)

@app.event("message")
async def handler1(event):
assert event["subtype"] == "file_share"

timestamp, body = str(int(time())), json.dumps(self.message_file_share_body)
request: AsyncBoltRequest = AsyncBoltRequest(
body=body, headers=self.build_headers(timestamp, body)
)
response = await app.async_dispatch(request)
assert response.status == 200


app_mention_body = {
"token": "verification_token",
Expand Down