diff --git a/slack_bolt/listener_matcher/builtins.py b/slack_bolt/listener_matcher/builtins.py index ae1d52dc2..cffcf95c1 100644 --- a/slack_bolt/listener_matcher/builtins.py +++ b/slack_bolt/listener_matcher/builtins.py @@ -21,6 +21,7 @@ to_action, is_workflow_step_save, ) +from ..logger.messages import error_message_event_type if sys.version_info.major == 3 and sys.version_info.minor <= 6: from re import _pattern_type as Pattern @@ -82,6 +83,7 @@ def event( ) -> Union[ListenerMatcher, "AsyncListenerMatcher"]: if isinstance(constraints, (str, Pattern)): event_type: Union[str, Pattern] = constraints + _verify_message_event_type(event_type) def func(body: Dict[str, Any]) -> bool: return is_event(body) and _matches(event_type, body["event"]["type"]) @@ -89,6 +91,7 @@ def func(body: Dict[str, Any]) -> bool: return build_listener_matcher(func, asyncio) elif "type" in constraints: + _verify_message_event_type(constraints["type"]) def func(body: Dict[str, Any]) -> bool: if is_event(body): @@ -132,6 +135,13 @@ def func(body: Dict[str, Any]) -> bool: ) +def _verify_message_event_type(event_type: str) -> None: + if isinstance(event_type, str) and event_type.startswith("message."): + raise ValueError(error_message_event_type(event_type)) + if isinstance(event_type, Pattern) and "message\\." in event_type.pattern: + raise ValueError(error_message_event_type(event_type)) + + def workflow_step_execute( callback_id: Union[str, Pattern], asyncio: bool = False, diff --git a/slack_bolt/logger/messages.py b/slack_bolt/logger/messages.py index 9be35c486..f7bc8af7e 100644 --- a/slack_bolt/logger/messages.py +++ b/slack_bolt/logger/messages.py @@ -50,6 +50,14 @@ def error_authorize_conflicts() -> str: return "`authorize` in the top-level arguments is not allowed when you pass either `oauth_settings` or `oauth_flow`" +def error_message_event_type(event_type: str) -> str: + return ( + f'Although the document mentions "{event_type}", ' + 'it is not a valid event type. Use "message" instead. ' + "If you want to filter message events, you can use `event.channel_type` for it." + ) + + # ------------------------------- # Warning # ------------------------------- diff --git a/tests/scenario_tests/test_events.py b/tests/scenario_tests/test_events.py index 0ce15d255..c80a23bff 100644 --- a/tests/scenario_tests/test_events.py +++ b/tests/scenario_tests/test_events.py @@ -2,6 +2,7 @@ import re from time import time, sleep +import pytest from slack_sdk.signature import SignatureVerifier from slack_sdk.web import WebClient @@ -553,3 +554,30 @@ def handler1(event): ) response = app.dispatch(request) assert response.status == 200 + + # https://github.com/slackapi/bolt-python/issues/199 + def test_invalid_message_events(self): + app = App(client=self.web_client, signing_secret=self.signing_secret) + + def handle(): + pass + + # valid + app.event("message")(handle) + + with pytest.raises(ValueError): + app.event("message.channels")(handle) + with pytest.raises(ValueError): + app.event("message.groups")(handle) + with pytest.raises(ValueError): + app.event("message.im")(handle) + with pytest.raises(ValueError): + app.event("message.mpim")(handle) + + with pytest.raises(ValueError): + app.event(re.compile("message\\..*"))(handle) + + with pytest.raises(ValueError): + app.event({"type": "message.channels"})(handle) + with pytest.raises(ValueError): + app.event({"type": re.compile("message\\..*")})(handle) diff --git a/tests/scenario_tests_async/test_events.py b/tests/scenario_tests_async/test_events.py index 9dda0b052..16fb92ef3 100644 --- a/tests/scenario_tests_async/test_events.py +++ b/tests/scenario_tests_async/test_events.py @@ -561,6 +561,37 @@ async def handler1(event): response = await app.async_dispatch(request) assert response.status == 200 + # https://github.com/slackapi/bolt-python/issues/199 + @pytest.mark.asyncio + async def test_invalid_message_events(self): + app = AsyncApp( + client=self.web_client, + signing_secret=self.signing_secret, + ) + + async def handle(): + pass + + # valid + app.event("message")(handle) + + with pytest.raises(ValueError): + app.event("message.channels")(handle) + with pytest.raises(ValueError): + app.event("message.groups")(handle) + with pytest.raises(ValueError): + app.event("message.im")(handle) + with pytest.raises(ValueError): + app.event("message.mpim")(handle) + + with pytest.raises(ValueError): + app.event(re.compile("message\\..*"))(handle) + + with pytest.raises(ValueError): + app.event({"type": "message.channels"})(handle) + with pytest.raises(ValueError): + app.event({"type": re.compile("message\\..*")})(handle) + app_mention_body = { "token": "verification_token",