Skip to content

Commit 2d67290

Browse files
committed
Fix #232 Unmatched message listener middleware can be called
1 parent 2fd8674 commit 2d67290

File tree

4 files changed

+116
-8
lines changed

4 files changed

+116
-8
lines changed

slack_bolt/app/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ def __call__(*args, **kwargs):
517517
# By contrast, messages posted using class app's bot token still have the subtype.
518518
constraints = {"type": "message", "subtype": (None, "bot_message")}
519519
primary_matcher = builtin_matchers.event(constraints=constraints)
520-
middleware.append(MessageListenerMatches(keyword))
520+
middleware.insert(0, MessageListenerMatches(keyword))
521521
return self._register_listener(
522522
list(functions), primary_matcher, matchers, middleware, True
523523
)

slack_bolt/app/async_app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ def __call__(*args, **kwargs):
567567
primary_matcher = builtin_matchers.event(
568568
constraints=constraints, asyncio=True
569569
)
570-
middleware.append(AsyncMessageListenerMatches(keyword))
570+
middleware.insert(0, AsyncMessageListenerMatches(keyword))
571571
return self._register_listener(
572572
list(functions), primary_matcher, matchers, middleware, True
573573
)

tests/scenario_tests/test_message.py

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from slack_sdk.signature import SignatureVerifier
66
from slack_sdk.web import WebClient
77

8+
from slack_bolt import BoltResponse
89
from slack_bolt.app import App
910
from slack_bolt.request import BoltRequest
1011
from tests.mock_web_api_server import (
@@ -46,13 +47,15 @@ def build_headers(self, timestamp: str, body: str):
4647
"x-slack-request-timestamp": [timestamp],
4748
}
4849

49-
def build_request(self) -> BoltRequest:
50+
def build_request_from_body(self, message_body: dict) -> BoltRequest:
5051
timestamp, body = str(int(time.time())), json.dumps(message_body)
5152
return BoltRequest(body=body, headers=self.build_headers(timestamp, body))
5253

54+
def build_request(self) -> BoltRequest:
55+
return self.build_request_from_body(message_body)
56+
5357
def build_request2(self) -> BoltRequest:
54-
timestamp, body = str(int(time.time())), json.dumps(message_body2)
55-
return BoltRequest(body=body, headers=self.build_headers(timestamp, body))
58+
return self.build_request_from_body(message_body2)
5659

5760
def test_string_keyword(self):
5861
app = App(
@@ -136,6 +139,55 @@ def test_regexp_keyword_unmatched(self):
136139
assert response.status == 404
137140
assert_auth_test_count(self, 1)
138141

142+
# https://github.com/slackapi/bolt-python/issues/232
143+
def test_issue_232_message_listener_middleware(self):
144+
app = App(
145+
client=self.web_client,
146+
signing_secret=self.signing_secret,
147+
)
148+
called = {
149+
"first": False,
150+
"second": False,
151+
}
152+
153+
def this_should_be_skipped():
154+
return BoltResponse(status=500, body="failed")
155+
156+
@app.message("first", middleware=[this_should_be_skipped])
157+
def first():
158+
called["first"] = True
159+
160+
@app.message("second", middleware=[])
161+
def second():
162+
called["second"] = True
163+
164+
request = self.build_request_from_body(
165+
{
166+
"token": "verification_token",
167+
"team_id": "T111",
168+
"enterprise_id": "E111",
169+
"api_app_id": "A111",
170+
"event": {
171+
"client_msg_id": "a8744611-0210-4f85-9f15-5faf7fb225c8",
172+
"type": "message",
173+
"text": "This message should match the second listener only",
174+
"user": "W111",
175+
"ts": "1596183880.004200",
176+
"team": "T111",
177+
"channel": "C111",
178+
"event_ts": "1596183880.004200",
179+
"channel_type": "channel",
180+
},
181+
"type": "event_callback",
182+
"event_id": "Ev111",
183+
"event_time": 1596183880,
184+
}
185+
)
186+
response = app.dispatch(request)
187+
assert response.status == 200
188+
assert called["first"] == False
189+
assert called["second"] == True
190+
139191

140192
message_body = {
141193
"token": "verification_token",

tests/scenario_tests_async/test_message.py

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from slack_sdk.signature import SignatureVerifier
88
from slack_sdk.web.async_client import AsyncWebClient
99

10+
from slack_bolt import BoltResponse
1011
from slack_bolt.app.async_app import AsyncApp
1112
from slack_bolt.request.async_request import AsyncBoltRequest
1213
from tests.mock_web_api_server import (
@@ -52,13 +53,15 @@ def build_headers(self, timestamp: str, body: str):
5253
"x-slack-request-timestamp": [timestamp],
5354
}
5455

55-
def build_request(self) -> AsyncBoltRequest:
56+
def build_request_from_body(self, message_body: dict) -> AsyncBoltRequest:
5657
timestamp, body = str(int(time())), json.dumps(message_body)
5758
return AsyncBoltRequest(body=body, headers=self.build_headers(timestamp, body))
5859

60+
def build_request(self) -> AsyncBoltRequest:
61+
return self.build_request_from_body(message_body)
62+
5963
def build_request2(self) -> AsyncBoltRequest:
60-
timestamp, body = str(int(time())), json.dumps(message_body2)
61-
return AsyncBoltRequest(body=body, headers=self.build_headers(timestamp, body))
64+
return self.build_request_from_body(message_body2)
6265

6366
@pytest.mark.asyncio
6467
async def test_string_keyword(self):
@@ -148,6 +151,59 @@ async def test_regexp_keyword_unmatched(self):
148151
assert response.status == 404
149152
await assert_auth_test_count_async(self, 1)
150153

154+
# https://github.com/slackapi/bolt-python/issues/232
155+
@pytest.mark.asyncio
156+
async def test_issue_232_message_listener_middleware(self):
157+
app = AsyncApp(
158+
client=self.web_client,
159+
signing_secret=self.signing_secret,
160+
)
161+
162+
called = {
163+
"first": False,
164+
"second": False,
165+
}
166+
167+
async def this_should_be_skipped():
168+
return BoltResponse(status=500, body="failed")
169+
170+
@app.message("first", middleware=[this_should_be_skipped])
171+
async def first():
172+
called["first"] = True
173+
174+
@app.message("second", middleware=[])
175+
async def second():
176+
called["second"] = True
177+
178+
request = self.build_request_from_body(
179+
{
180+
"token": "verification_token",
181+
"team_id": "T111",
182+
"enterprise_id": "E111",
183+
"api_app_id": "A111",
184+
"event": {
185+
"client_msg_id": "a8744611-0210-4f85-9f15-5faf7fb225c8",
186+
"type": "message",
187+
"text": "This message should match the second listener only",
188+
"user": "W111",
189+
"ts": "1596183880.004200",
190+
"team": "T111",
191+
"channel": "C111",
192+
"event_ts": "1596183880.004200",
193+
"channel_type": "channel",
194+
},
195+
"type": "event_callback",
196+
"event_id": "Ev111",
197+
"event_time": 1596183880,
198+
}
199+
)
200+
response = await app.async_dispatch(request)
201+
assert response.status == 200
202+
203+
await asyncio.sleep(0.3)
204+
assert called["first"] == False
205+
assert called["second"] == True
206+
151207

152208
message_body = {
153209
"token": "verification_token",

0 commit comments

Comments
 (0)