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}")