Example #1
0
class SlackHelper:
    def __init__(self, bot_token, app_token, channel):
        self.bot_token = bot_token
        self.app_token = app_token
        self.channel = channel
        self.message_queue = Queue()
        self.last_connect_try: Optional[float] = None

        print("Initializing SlackHelper")
        self.socket_client = SocketModeClient(
            app_token=self.app_token,
            web_client=WebClient(token=self.bot_token))
        self.socket_client.socket_mode_request_listeners.append(
            lambda client, req: self._process_event(client, req))
        self.check_connected()
        print("Finished initializing SlackHelper")

    def __del__(self):
        self.socket_client.close()

    def check_connected(self):
        if not self.socket_client.is_connected():
            now = time.time()
            if self.last_connect_try is not None and self.last_connect_try + 10 > now:
                return  # We've tried in the last 10 seconds
            print("Going to try to connect")
            try:
                self.socket_client.connect()
                print("Connected")
            except URLError:
                print("Could not connect")
            self.last_connect_try = now

    def _process_event(self, client: SocketModeClient, req: SocketModeRequest):
        if req.type == "events_api":
            # Acknowledge the request anyway
            response = SocketModeResponse(envelope_id=req.envelope_id)
            client.send_socket_mode_response(response)

            # Add a reaction to the message if it's a new message
            message = req.payload["event"]
            if message["type"] == "message" and message.get("subtype") is None:
                self.message_queue.put(message)
                # This doesn't work for some reason
                # print(client.web_client.reactions_add(
                #     name="eyes",
                #     channel=message["channel"],
                #     timestamp=message["ts"],
                # ))

    def new_messages(self) -> list:
        self.check_connected()  # We don't really care if this blocks
        messages = []
        while not self.message_queue.empty():
            messages.append(self.message_queue.get())
        return messages
 def test_init_close(self):
     on_message_listeners = [lambda message: None]
     client = SocketModeClient(app_token="xapp-A111-222-xyz",
                               on_message_listeners=on_message_listeners)
     try:
         self.assertIsNotNone(client)
         self.assertFalse(client.is_connected())
         self.assertIsNone(client.session_id())  # not yet connected
     finally:
         client.close()
    def test_send_message_while_disconnection(self):
        if is_ci_unstable_test_skip_enabled():
            return
        t = Thread(target=start_socket_mode_server(self, 3011))
        t.daemon = True
        t.start()
        time.sleep(2)  # wait for the server

        try:
            self.reset_sever_state()
            client = SocketModeClient(
                app_token="xapp-A111-222-xyz",
                web_client=self.web_client,
                auto_reconnect_enabled=False,
                trace_enabled=True,
            )
            client.wss_uri = "ws://0.0.0.0:3011/link"
            client.connect()
            time.sleep(1)  # wait for the connection
            client.send_message("foo")

            client.disconnect()
            time.sleep(1)  # wait for the connection
            try:
                client.send_message("foo")
                self.fail("SlackClientNotConnectedError is expected here")
            except SlackClientNotConnectedError as _:
                pass

            client.connect()
            time.sleep(1)  # wait for the connection
            client.send_message("foo")
        finally:
            client.close()
            self.server.stop()
            self.server.close()
    def test_interactions(self):
        if is_ci_unstable_test_skip_enabled():
            return
        t = Thread(target=start_socket_mode_server(self, 3011))
        t.daemon = True
        t.start()
        time.sleep(2)  # wait for the server

        try:
            buffer_size_list = [1024, 9000, 35, 49] + list(
                [randint(16, 128) for _ in range(10)])
            for buffer_size in buffer_size_list:
                self.reset_sever_state()

                received_messages = []
                received_socket_mode_requests = []

                def message_handler(message):
                    self.logger.info(f"Raw Message: {message}")
                    time.sleep(randint(50, 200) / 1000)
                    received_messages.append(message)

                def socket_mode_request_handler(client: BaseSocketModeClient,
                                                request: SocketModeRequest):
                    self.logger.info(f"Socket Mode Request: {request}")
                    time.sleep(randint(50, 200) / 1000)
                    received_socket_mode_requests.append(request)

                self.logger.info(
                    f"Started testing with buffer size: {buffer_size}")
                client = SocketModeClient(
                    app_token="xapp-A111-222-xyz",
                    web_client=self.web_client,
                    on_message_listeners=[message_handler],
                    receive_buffer_size=buffer_size,
                    auto_reconnect_enabled=False,
                    trace_enabled=True,
                )
                try:
                    client.socket_mode_request_listeners.append(
                        socket_mode_request_handler)
                    client.wss_uri = "ws://0.0.0.0:3011/link"
                    client.connect()
                    self.assertTrue(client.is_connected())
                    time.sleep(2)  # wait for the message receiver

                    repeat = 2
                    for _ in range(repeat):
                        client.send_message("foo")
                        client.send_message("bar")
                        client.send_message("baz")
                    self.assertTrue(client.is_connected())

                    expected = (socket_mode_envelopes +
                                [socket_mode_hello_message] +
                                ["foo", "bar", "baz"] * repeat)
                    expected.sort()

                    count = 0
                    while count < 5 and len(received_messages) < len(expected):
                        time.sleep(0.1)
                        self.logger.debug(
                            f"Received messages: {len(received_messages)}")
                        count += 0.1

                    received_messages.sort()
                    self.assertEqual(len(received_messages), len(expected))
                    self.assertEqual(received_messages, expected)

                    self.assertEqual(len(socket_mode_envelopes),
                                     len(received_socket_mode_requests))
                finally:
                    pass
                    # client.close()
                self.logger.info(f"Passed with buffer size: {buffer_size}")

        finally:
            client.close()
            self.server.stop()
            self.server.close()

        self.logger.info(f"Passed with buffer size: {buffer_size_list}")