slackapi / bolt-python

A framework to build Slack apps using Python
https://slack.dev/bolt-python/
MIT License
1.06k stars 245 forks source link

How to listen, respond and close connection? #1034

Closed BS-98 closed 7 months ago

BS-98 commented 7 months ago

Hi! I want to listen for message "hello" (like in yours tutorial), respond with "Hi!" and close the connection. I need to use a WebSocket. I have a program:

def run():
    from slack_bolt import App
    from slack_bolt.adapter.socket_mode import SocketModeHandler

    app = App(token="bot_token")
    handler = SocketModeHandler(app, "app_token")

    @app.message("hello")
    def message_hello(message, say):
        say(f"Hey there <@{message['user']}>!")
        #handler.disconnect()
        #handler.close()

    handler.start()
    #handler.close()

run()

Then, I execute with python3 my_program.py. I would like to execute function run() elsewhere in my system.

zimeg commented 7 months ago

Hey @BS-98 👋 The start() method is a blocking one so changing this to connect() should leave the program control flow to you! There's a bit more detail on this in #558 but I found that the following snippet works alright:

import threading
import time

from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler

def run():
    app = App(token="bot_token")
    handler = SocketModeHandler(app, "app_token")
    disconnect_event = threading.Event()

    @app.message("hello")
    def message_hello(message, say):
        say(f"Hey there <@{message['user']}>!")
        time.sleep(1)
        handler.disconnect()
        disconnect_event.set()

    handler.connect()
    disconnect_event.wait()

run()

I'm not sure if there's a way to accomplish this without the time.sleep, but I found that the message event from say is only partially received when the disconnect event happens and would raise a JSONDecodeError error :thinking:

More details on the error are here ``` INFO:slack_bolt.App:The connection has been closed (session id: 4eeafc1c-d57f-4ae1-a9ff-4f291871bc90) DEBUG:slack_bolt.App:The connection seems to be already closed. DEBUG:slack_bolt.App:on_message invoked: (message: {"envelope_id":"9974af45-6302-43e5-b11c-eeb522ed5895","payload":{"token":"0123456789ABCDEFG","team_id":"T02A074M3U3","context_team_id":"T02A074M3U3","context_enterprise_id":null,"api_app_id":"A05FURW3A6R","event":{"user":"U05FURYLBT7","type":"message","ts":"1709343171.845879","bot_id":"B05FH7YQGEB","app_id":"A05FURW3A6R","text":"Hey there <@U04051AF9NJ>!","team":"T02A074M3U3","bot_profile":{"id":"B05FH7YQGEB","deleted":false,"name":"gibra","updated":1688778364,"app_id":"A05FURW3A6R","icons":{"image_36":"https:\/\/avatars.slack-edge.com\/2023-07-07\/5547349776131_f361d1dc106545934fba_36.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2023-07-07\/5547349776131_f361d1dc106545934fba_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2023-07-07\/5547349776131_f361d1dc106545934fba_72.jpg"},"team_id":"T02A074M3U3"},"blocks":[{"type":"rich_text","block_id":"ct7","elements":[{"type":"rich_text_section","elements":[{"type":"text","text":"Hey there "},{"type":"user","user_id":"U04051AF9NJ"},{"type":"tex) DEBUG:slack_bolt.App:A new message enqueued (current queue size: 1) DEBUG:slack_bolt.App:A message dequeued (current queue size: 0) ERROR:slack_bolt.App:Failed to process a message: Unterminated string starting at: line 1 column 1017 (char 1016) Traceback (most recent call last): File "/Users/me/programming/triage/py.sdk.sdkai/.venv/lib/python3.12/site-packages/slack_sdk/socket_mode/client.py", line 155, in process_messages self.process_message() File "/Users/me/programming/triage/py.sdk.sdkai/.venv/lib/python3.12/site-packages/slack_sdk/socket_mode/client.py", line 110, in process_message message = json.loads(raw_message) ^^^^^^^^^^^^^^^^^^^^^^^ File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/json/__init__.py", line 346, in loads return _default_decoder.decode(s) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/json/decoder.py", line 337, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/json/decoder.py", line 353, in raw_decode obj, end = self.scan_once(s, idx) ^^^^^^^^^^^^^^^^^^^^^^ json.decoder.JSONDecodeError: Unterminated string starting at: line 1 column 1017 (char 1016) ```

Hopefully this fits into your app alright, but please let me know if any problems arise!

BS-98 commented 7 months ago

It works! Thank you!

Indeed, without time.sleep I get an error:

raise SlackClientNotConnectedError(
slack_sdk.errors.SlackClientNotConnectedError: Failed to send a message as the connection is no longer active (session_id: <session_id>, error: 'NoneType' object has no attribute 'send')

So I assume that the solutions you gave, is correct and after disconnect_event.set() all connections are close and resources are free and everything is clear, am I right?

seratch commented 7 months ago

Yeah, you're right on it. Glad to know @zimeg's suggestion was helpful! Let me close this issue now.