# ------------------------------------------------ # instead of slack_bolt in requirements.txt import sys sys.path.insert(1, "..") # ------------------------------------------------ import logging from typing import Callable from logging import Logger from slack_bolt import App, BoltResponse, Ack, Respond from slack_sdk import WebClient from slack_sdk.models.blocks import ( PlainTextObject, InputBlock, PlainTextInputElement, ExternalDataSelectElement, ExternalDataMultiSelectElement, Option, OptionGroup, SectionBlock, MarkdownTextObject, ButtonElement, ) from slack_sdk.models.views import View logging.basicConfig(level=logging.DEBUG) app = App() @app.middleware # or app.use(log_request) def log_request( logger: Logger, body: dict, next: Callable[[], BoltResponse] ) -> BoltResponse: logger.debug(body) return next() @app.command("/hello-bolt-python") def handle_command( body: dict, ack: Ack, respond: Respond, client: WebClient, logger: Logger ) -> None: logger.info(body) ack( text="Accepted!", blocks=[ SectionBlock( block_id="b", text=MarkdownTextObject(text=":white_check_mark: Accepted!"), ) ], ) respond( blocks=[ SectionBlock( block_id="b", text=MarkdownTextObject( text="You can add a button alongside text in your message. " ), accessory=ButtonElement( action_id="a", text=PlainTextObject(text="Button"), value="click_me_123", ), ), ] ) res = client.views_open( trigger_id=body["trigger_id"], view=View( type="modal", callback_id="view-id", title=PlainTextObject(text="My App"), submit=PlainTextObject(text="Submit"), close=PlainTextObject(text="Cancel"), blocks=[ InputBlock( element=PlainTextInputElement(action_id="text"), label=PlainTextObject(text="Label"), ), InputBlock( block_id="es_b", element=ExternalDataSelectElement( action_id="es_a", placeholder=PlainTextObject(text="Select an item"), min_query_length=0, ), label=PlainTextObject(text="Search"), ), InputBlock( block_id="mes_b", element=ExternalDataMultiSelectElement( action_id="mes_a", placeholder=PlainTextObject(text="Select an item"), min_query_length=0, ), label=PlainTextObject(text="Search (multi)"), ), ], ), ) logger.info(res) @app.options("es_a") def show_options(ack: Ack) -> None: ack(options=[Option(text=PlainTextObject(text="Maru"), value="maru")]) @app.options("mes_a") def show_multi_options(ack: Ack) -> None: ack( option_groups=[ OptionGroup( label=PlainTextObject(text="Group 1"), options=[ Option(text=PlainTextObject(text="Option 1"), value="1-1"), Option(text=PlainTextObject(text="Option 2"), value="1-2"), ], ), OptionGroup( label=PlainTextObject(text="Group 2"), options=[Option(text=PlainTextObject(text="Option 1"), value="2-1"),], ), ] ) @app.view("view-id") def view_submission(ack: Ack, body: dict, logger: Logger) -> None: ack() logger.info(body["view"]["state"]["values"]) @app.action("a") def button_click(ack: Ack, body: dict, respond: Respond) -> None: ack() user_id: str = body["user"]["id"] # in_channel / dict respond( response_type="in_channel", replace_original=False, text=f"<@{user_id}> clicked a button! (in_channel)", ) # ephemeral / kwargs respond( replace_original=False, text=":white_check_mark: Done!", ) if __name__ == "__main__": app.start(3000) # pip install slack_bolt # export SLACK_SIGNING_SECRET=*** # export SLACK_BOT_TOKEN=xoxb-*** # python modals_app_typed.py