Skip to content

Commit e8136c0

Browse files
authored
Fix #683 IgnoringSelfEvents middleware does not filter out Message sent via response_url (#684)
1 parent 398c900 commit e8136c0

File tree

4 files changed

+156
-6
lines changed

4 files changed

+156
-6
lines changed

slack_bolt/middleware/ignoring_self_events/async_ignoring_self_events.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ async def async_process(
1515
next: Callable[[], Awaitable[BoltResponse]],
1616
) -> BoltResponse:
1717
auth_result = req.context.authorize_result
18-
if self._is_self_event(auth_result, req.context.user_id, req.body):
18+
# message events can have $.event.bot_id while it does not have its user_id
19+
bot_id = req.body.get("event", {}).get("bot_id")
20+
if self._is_self_event(auth_result, req.context.user_id, bot_id, req.body):
1921
self._debug_log(req.body)
2022
return await req.context.ack()
2123
else:

slack_bolt/middleware/ignoring_self_events/ignoring_self_events.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,35 @@ def process(
2121
next: Callable[[], BoltResponse],
2222
) -> BoltResponse:
2323
auth_result = req.context.authorize_result
24-
if self._is_self_event(auth_result, req.context.user_id, req.body):
24+
# message events can have $.event.bot_id while it does not have its user_id
25+
bot_id = req.body.get("event", {}).get("bot_id")
26+
if self._is_self_event(auth_result, req.context.user_id, bot_id, req.body):
2527
self._debug_log(req.body)
2628
return req.context.ack()
2729
else:
2830
return next()
2931

3032
# -----------------------------------------
3133

32-
# Its an Events API event that isn't of type message,
34+
# It's an Events API event that isn't of type message,
3335
# but the user ID might match our own app. Filter these out.
3436
# However, some events still must be fired, because they can make sense.
3537
events_that_should_be_kept = ["member_joined_channel", "member_left_channel"]
3638

3739
@classmethod
38-
def _is_self_event(cls, auth_result: AuthorizeResult, user_id: str, body: Dict[str, Any]):
40+
def _is_self_event(
41+
cls,
42+
auth_result: AuthorizeResult,
43+
user_id: Optional[str],
44+
bot_id: Optional[str],
45+
body: Dict[str, Any],
46+
):
3947
return (
4048
auth_result is not None
41-
and user_id is not None
42-
and user_id == auth_result.bot_user_id
49+
and (
50+
(user_id is not None and user_id == auth_result.bot_user_id)
51+
or (bot_id is not None and bot_id == auth_result.bot_id) # for bot_message events
52+
)
4353
and body.get("event") is not None
4454
and body.get("event", {}).get("type") not in cls.events_that_should_be_kept
4555
)

tests/scenario_tests/test_events_ignore_self.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,35 @@ def handle_app_mention(say):
4242
# The listener should not be executed
4343
assert self.mock_received_requests.get("/chat.postMessage") is None
4444

45+
def test_self_events_response_url(self):
46+
app = App(client=self.web_client)
47+
48+
@app.event("message")
49+
def handle_app_mention(say):
50+
say("What's up?")
51+
52+
request: BoltRequest = BoltRequest(body=response_url_message_event, mode="socket_mode")
53+
response = app.dispatch(request)
54+
assert response.status == 200
55+
assert_auth_test_count(self, 1)
56+
sleep(1) # wait a bit after auto ack()
57+
# The listener should not be executed
58+
assert self.mock_received_requests.get("/chat.postMessage") is None
59+
60+
def test_not_self_events_response_url(self):
61+
app = App(client=self.web_client)
62+
63+
@app.event("message")
64+
def handle_app_mention(say):
65+
say("What's up?")
66+
67+
request: BoltRequest = BoltRequest(body=different_app_response_url_message_event, mode="socket_mode")
68+
response = app.dispatch(request)
69+
assert response.status == 200
70+
assert_auth_test_count(self, 1)
71+
sleep(1) # wait a bit after auto ack()
72+
assert self.mock_received_requests.get("/chat.postMessage") == 1
73+
4574
def test_self_events_disabled(self):
4675
app = App(
4776
client=self.web_client,
@@ -83,3 +112,45 @@ def handle_app_mention(say):
83112
"event_time": 1599616881,
84113
"authed_users": ["W111"],
85114
}
115+
116+
response_url_message_event = {
117+
"token": "verification_token",
118+
"team_id": "T111",
119+
"enterprise_id": "E111",
120+
"api_app_id": "A111",
121+
"event": {
122+
"type": "message",
123+
"subtype": "bot_message",
124+
"text": "Hi there! This is a reply using response_url.",
125+
"ts": "1658282075.825129",
126+
"bot_id": "BZYBOTHED",
127+
"channel": "C111",
128+
"event_ts": "1658282075.825129",
129+
"channel_type": "channel",
130+
},
131+
"type": "event_callback",
132+
"event_id": "Ev111",
133+
"event_time": 1599616881,
134+
"authed_users": ["W111"],
135+
}
136+
137+
different_app_response_url_message_event = {
138+
"token": "verification_token",
139+
"team_id": "T111",
140+
"enterprise_id": "E111",
141+
"api_app_id": "A111",
142+
"event": {
143+
"type": "message",
144+
"subtype": "bot_message",
145+
"text": "Hi there! This is a reply using response_url.",
146+
"ts": "1658282075.825129",
147+
"bot_id": "B_DIFFERENT_ONE",
148+
"channel": "C111",
149+
"event_ts": "1658282075.825129",
150+
"channel_type": "channel",
151+
},
152+
"type": "event_callback",
153+
"event_id": "Ev111",
154+
"event_time": 1599616881,
155+
"authed_users": ["W111"],
156+
}

tests/scenario_tests_async/test_events_ignore_self.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,29 @@ async def test_self_events(self):
4545
# The listener should not be executed
4646
assert self.mock_received_requests.get("/chat.postMessage") is None
4747

48+
@pytest.mark.asyncio
49+
async def test_self_events_response_url(self):
50+
app = AsyncApp(client=self.web_client)
51+
app.event("message")(whats_up)
52+
request = AsyncBoltRequest(body=response_url_message_event, mode="socket_mode")
53+
response = await app.async_dispatch(request)
54+
assert response.status == 200
55+
await assert_auth_test_count_async(self, 1)
56+
await asyncio.sleep(1) # wait a bit after auto ack()
57+
# The listener should not be executed
58+
assert self.mock_received_requests.get("/chat.postMessage") is None
59+
60+
@pytest.mark.asyncio
61+
async def test_not_self_events_response_url(self):
62+
app = AsyncApp(client=self.web_client)
63+
app.event("message")(whats_up)
64+
request = AsyncBoltRequest(body=different_app_response_url_message_event, mode="socket_mode")
65+
response = await app.async_dispatch(request)
66+
assert response.status == 200
67+
await assert_auth_test_count_async(self, 1)
68+
await asyncio.sleep(1) # wait a bit after auto ack()
69+
assert self.mock_received_requests.get("/chat.postMessage") == 1
70+
4871
@pytest.mark.asyncio
4972
async def test_self_events_disabled(self):
5073
app = AsyncApp(client=self.web_client, ignoring_self_events_enabled=False)
@@ -82,6 +105,50 @@ async def test_self_events_disabled(self):
82105
}
83106

84107

108+
response_url_message_event = {
109+
"token": "verification_token",
110+
"team_id": "T111",
111+
"enterprise_id": "E111",
112+
"api_app_id": "A111",
113+
"event": {
114+
"type": "message",
115+
"subtype": "bot_message",
116+
"text": "Hi there! This is a reply using response_url.",
117+
"ts": "1658282075.825129",
118+
"bot_id": "BZYBOTHED",
119+
"channel": "C111",
120+
"event_ts": "1658282075.825129",
121+
"channel_type": "channel",
122+
},
123+
"type": "event_callback",
124+
"event_id": "Ev111",
125+
"event_time": 1599616881,
126+
"authed_users": ["W111"],
127+
}
128+
129+
130+
different_app_response_url_message_event = {
131+
"token": "verification_token",
132+
"team_id": "T111",
133+
"enterprise_id": "E111",
134+
"api_app_id": "A111",
135+
"event": {
136+
"type": "message",
137+
"subtype": "bot_message",
138+
"text": "Hi there! This is a reply using response_url.",
139+
"ts": "1658282075.825129",
140+
"bot_id": "B_DIFFERENT_ONE",
141+
"channel": "C111",
142+
"event_ts": "1658282075.825129",
143+
"channel_type": "channel",
144+
},
145+
"type": "event_callback",
146+
"event_id": "Ev111",
147+
"event_time": 1599616881,
148+
"authed_users": ["W111"],
149+
}
150+
151+
85152
async def whats_up(body, say, payload, event):
86153
assert body["event"] == payload
87154
assert payload == event

0 commit comments

Comments
 (0)