From 27e70b058bdbeb06096cf22a7e7ab293f24ed0df Mon Sep 17 00:00:00 2001 From: Ygal Blum Date: Wed, 10 Jul 2024 10:30:48 -0400 Subject: [PATCH] Implement conversations.list API Read the channels list from a file in the slack server Add a handler that returns the list from the slack server Register the handler Add a setting to set the location of the channels file Avoid circular import Signed-off-by: Ygal Blum --- slack_server_mock/servers/http/handler.py | 22 ++++++++++++++++ slack_server_mock/servers/http/server.py | 8 +++--- slack_server_mock/settings/settings.py | 5 ++++ .../slack_server/slack_server.py | 26 ++++++++++++++++++- 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/slack_server_mock/servers/http/handler.py b/slack_server_mock/servers/http/handler.py index 48b46e4..6ffc146 100644 --- a/slack_server_mock/servers/http/handler.py +++ b/slack_server_mock/servers/http/handler.py @@ -6,6 +6,7 @@ from slack_server_mock.actor.actor import Actor from slack_server_mock.injector.di import global_injector +from slack_server_mock.slack_server.slack_server import SlackServer from slack_server_mock.servers.base_http_handlers import load_json_from_body from slack_server_mock.settings.settings import Settings @@ -121,3 +122,24 @@ def post(self): } } ) + + +class ConversationsListHandler(BaseSlackHandler): # pylint: disable=W0223 + """ Handler for conversations.list endpoint """ + def _handle(self): + self.write( + { + "ok": True, + "channels": global_injector.get(SlackServer).channels + } + ) + + def get(self): + """ Handle GET request """ + self._handle() + + def post(self): + """ Handle POST request. + While the documentation states that this is a GET command, the SDK calls PUT + """ + self._handle() diff --git a/slack_server_mock/servers/http/server.py b/slack_server_mock/servers/http/server.py index 5273694..bd2be32 100644 --- a/slack_server_mock/servers/http/server.py +++ b/slack_server_mock/servers/http/server.py @@ -5,20 +5,22 @@ from slack_server_mock.settings.settings import Settings from slack_server_mock.servers.base_http_server import BaseHTTPServer -from slack_server_mock.servers.http import handler @singleton -class SlackHTTPServer(BaseHTTPServer): +class SlackHTTPServer(BaseHTTPServer): # pylint: disable=C0415 """ Mock Implementation of the Slack HTTP server """ @inject def __init__(self, settings: Settings) -> None: + from slack_server_mock.servers.http import handler + app = Application( [ (r"/auth.test", handler.AuthTestHandler), (r"/apps.connections.open", handler.AppsConnectionsOpenHandler), (r"/api.test", handler.ApiTestHandler), - (r"/chat.postMessage", handler.ChatPostMessageHandler) + (r"/chat.postMessage", handler.ChatPostMessageHandler), + (r"/conversations.list", handler.ConversationsListHandler), ] ) super().__init__(app, settings.slack_server.http_port) diff --git a/slack_server_mock/settings/settings.py b/slack_server_mock/settings/settings.py index 862f8ef..d299468 100644 --- a/slack_server_mock/settings/settings.py +++ b/slack_server_mock/settings/settings.py @@ -16,6 +16,11 @@ class SlackServer(BaseModel): description="HTTP Server Listening port" ) + channels_path: str = Field( + None, + description="Path to a file containing the list of conversations" + ) + class Actor(BaseModel): """ Settings for the Actor """ diff --git a/slack_server_mock/slack_server/slack_server.py b/slack_server_mock/slack_server/slack_server.py index 9d25432..8405aa9 100644 --- a/slack_server_mock/slack_server/slack_server.py +++ b/slack_server_mock/slack_server/slack_server.py @@ -1,7 +1,10 @@ """ Slack Mock Server """ +import json + from injector import inject, singleton from slack_server_mock.injector.di import global_injector +from slack_server_mock.settings.settings import Settings from slack_server_mock.servers.http.server import SlackHTTPServer from slack_server_mock.servers.websocket.server import SlackWebSocketServer @@ -10,9 +13,20 @@ class SlackServer(): """ Class to hold and manage all Slack server related objects and operations """ @inject - def __init__(self, http_server: SlackHTTPServer, websocket_server: SlackWebSocketServer) -> None: + def __init__( + self, + settings: Settings, + http_server: SlackHTTPServer, + websocket_server: SlackWebSocketServer + ) -> None: self._http_server = http_server self._websocket_server = websocket_server + self._channels = self._load_channels(settings.slack_server.channels_path) + + @property + def channels(self): + """ Return the channels list """ + return self._channels def start(self): """ Start the Slack server """ @@ -24,6 +38,16 @@ def stop(self): self._http_server.stop() self._websocket_server.stop() + @staticmethod + def _load_channels(path): + channels = [] + if path: + with open(path, "r", encoding="utf-8") as f: + channels = json.load(f) + if not isinstance(channels, list): + raise ValueError("The content of the channels file is not a JSON array") + return channels + def start_slack_server(): """ Start the Slack server """