diff options
Diffstat (limited to 'slack')
-rw-r--r-- | slack/slack_api.py | 20 | ||||
-rw-r--r-- | slack/slack_conversation.py | 54 | ||||
-rw-r--r-- | slack/slack_message.py | 2 | ||||
-rw-r--r-- | slack/slack_workspace.py | 56 |
4 files changed, 103 insertions, 29 deletions
diff --git a/slack/slack_api.py b/slack/slack_api.py index eb04ce2..fd75277 100644 --- a/slack/slack_api.py +++ b/slack/slack_api.py @@ -12,6 +12,7 @@ if TYPE_CHECKING: from slack_api.slack_bots_info import SlackBotInfoResponse, SlackBotsInfoResponse from slack_api.slack_conversations_history import SlackConversationsHistoryResponse from slack_api.slack_conversations_info import SlackConversationsInfoResponse + from slack_api.slack_conversations_members import SlackConversationsMembersResponse from slack_api.slack_rtm_connect import SlackRtmConnectResponse from slack_api.slack_usergroups_info import SlackUsergroupsInfoResponse from slack_api.slack_users_conversations import SlackUsersConversationsResponse @@ -96,14 +97,29 @@ class SlackApi: raise SlackApiError(self.workspace, method, response, params) return response - async def fetch_conversations_info(self, conversation: SlackConversation): + async def fetch_conversations_info(self, conversation_id: str): method = "conversations.info" - params = {"channel": conversation.id} + params = {"channel": conversation_id} response: SlackConversationsInfoResponse = await self._fetch(method, params) if response["ok"] is False: raise SlackApiError(self.workspace, method, response, params) return response + async def fetch_conversations_members( + self, + conversation: SlackConversation, + limit: int = 1000, + pages: int = -1, + ): + method = "conversations.members" + params = {"channel": conversation.id, "limit": limit} + response: SlackConversationsMembersResponse = await self._fetch_list( + method, "members", params, pages + ) + if response["ok"] is False: + raise SlackApiError(self.workspace, method, response, params) + return response + async def fetch_users_conversations( self, types: str, diff --git a/slack/slack_conversation.py b/slack/slack_conversation.py index a23666e..fbf42bf 100644 --- a/slack/slack_conversation.py +++ b/slack/slack_conversation.py @@ -12,6 +12,7 @@ from slack.task import gather from slack.util import get_callback_name if TYPE_CHECKING: + from slack_api.slack_conversations_info import SlackConversationsInfo from typing_extensions import Literal from slack.slack_api import SlackApi @@ -22,16 +23,21 @@ def get_conversation_from_buffer_pointer( buffer_pointer: str, ) -> Optional[SlackConversation]: for workspace in shared.workspaces.values(): - for conversation in workspace.conversations.values(): + for conversation in workspace.open_conversations.values(): if conversation.buffer_pointer == buffer_pointer: return conversation return None class SlackConversation: - def __init__(self, workspace: SlackWorkspace, id: str): + def __init__( + self, + workspace: SlackWorkspace, + info: SlackConversationsInfo, + ): self.workspace = workspace - self.id = id + self._info = info + self._members: List[str] # TODO: buffer_pointer may be accessed by buffer_switch before it's initialized self.buffer_pointer: str = "" self.name: str @@ -48,10 +54,19 @@ class SlackConversation: self.completion_values: List[str] = [] self.completion_index = 0 + @classmethod + async def create(cls, workspace: SlackWorkspace, conversation_id: str): + info_response = await workspace.api.fetch_conversations_info(conversation_id) + return cls(workspace, info_response["channel"]) + @property def _api(self) -> SlackApi: return self.workspace.api + @property + def id(self) -> str: + return self._info["id"] + @contextmanager def loading(self): self.is_loading = True @@ -70,17 +85,28 @@ class SlackConversation: finally: self.completion_context = "ACTIVE_COMPLETION" - async def init(self): - with self.loading(): - info = await self._api.fetch_conversations_info(self) + async def open_if_open(self): + if "is_open" in self._info: + if self._info["is_open"]: + await self.open_buffer() + elif "is_member" in self._info and self._info["is_member"]: + await self.open_buffer() - info_channel = info["channel"] - if info_channel["is_im"] is True: - self.name = "IM" # TODO - elif info_channel["is_mpim"] is True: - self.name = "MPIM" # TODO - else: - self.name = info_channel["name"] + async def open_buffer(self): + with self.loading(): + if "is_im" in self._info and self._info["is_im"] is True: + im_user = await self.workspace.users[self._info["user"]] + self.name = im_user.nick() + elif self._info["is_mpim"] is True: + members_response = await self._api.fetch_conversations_members(self) + self._members = members_response["members"] + await self.workspace.users.initialize_items(self._members) + member_users = await gather( + *(self.workspace.users[user_id] for user_id in self._members) + ) + self.name = ",".join([user.nick() for user in member_users]) + else: + self.name = f"#{self._info['name']}" full_name = f"{shared.SCRIPT_NAME}.{self.workspace.name}.{self.name}" @@ -92,6 +118,8 @@ class SlackConversation: self.buffer_pointer, "localvar_set_nick", self.workspace.my_user.nick() ) + self.workspace.open_conversations[self.id] = self + async def fill_history(self): if self.history_filled or self.history_pending: return diff --git a/slack/slack_message.py b/slack/slack_message.py index f79cdc2..07b03f4 100644 --- a/slack/slack_message.py +++ b/slack/slack_message.py @@ -55,7 +55,7 @@ class SlackMessage: async def _lookup_item_id(self, item_id: str): if item_id.startswith("#"): - return self.workspace.conversations[removeprefix(item_id, "#")] + return await self.workspace.conversations[removeprefix(item_id, "#")] elif item_id.startswith("@"): return await self.workspace.users[removeprefix(item_id, "@")] elif item_id.startswith("!subteam^"): diff --git a/slack/slack_workspace.py b/slack/slack_workspace.py index c5c4732..176e031 100644 --- a/slack/slack_workspace.py +++ b/slack/slack_workspace.py @@ -15,21 +15,29 @@ from slack.shared import shared from slack.slack_api import SlackApi from slack.slack_conversation import SlackConversation from slack.slack_user import SlackBot, SlackUser, SlackUsergroup -from slack.task import Future, create_task +from slack.task import Future, create_task, gather from slack.util import get_callback_name if TYPE_CHECKING: from slack_api.slack_bots_info import SlackBotInfo + from slack_api.slack_conversations_info import SlackConversationsInfo from slack_api.slack_usergroups_info import SlackUsergroupInfo from slack_api.slack_users_info import SlackUserInfo else: SlackBotInfo = Any + SlackConversationsInfo = Any SlackUsergroupInfo = Any SlackUserInfo = Any -SlackItemClass = TypeVar("SlackItemClass", SlackUser, SlackBot, SlackUsergroup) +SlackItemClass = TypeVar( + "SlackItemClass", SlackConversation, SlackUser, SlackBot, SlackUsergroup +) SlackItemInfo = TypeVar( - "SlackItemInfo", SlackUserInfo, SlackBotInfo, SlackUsergroupInfo + "SlackItemInfo", + SlackConversationsInfo, + SlackUserInfo, + SlackBotInfo, + SlackUsergroupInfo, ) @@ -74,6 +82,29 @@ class SlackItem( raise NotImplementedError() +class SlackConversations(SlackItem[SlackConversation, SlackConversationsInfo]): + def __init__(self, workspace: SlackWorkspace): + super().__init__(workspace, SlackConversation) + + async def _fetch_items_info( + self, item_ids: Iterable[str] + ) -> Dict[str, SlackConversationsInfo]: + responses = await gather( + *( + self.workspace.api.fetch_conversations_info(item_id) + for item_id in item_ids + ) + ) + return { + response["channel"]["id"]: response["channel"] for response in responses + } + + def _create_item_from_info( + self, item_info: SlackConversationsInfo + ) -> SlackConversation: + return self._item_class(self.workspace, item_info) + + class SlackUsers(SlackItem[SlackUser, SlackUserInfo]): def __init__(self, workspace: SlackWorkspace): super().__init__(workspace, SlackUser) @@ -122,10 +153,11 @@ class SlackWorkspace: self.config = shared.config.create_workspace_config(self.name) self.api = SlackApi(self) self._is_connected = False + self.conversations = SlackConversations(self) + self.open_conversations: Dict[str, SlackConversation] = {} self.users = SlackUsers(self) self.bots = SlackBots(self) self.usergroups = SlackUsergroups(self) - self.conversations: Dict[str, SlackConversation] = {} def __repr__(self): return f"{self.__class__.__name__}('{self.name}')" @@ -147,16 +179,14 @@ class SlackWorkspace: await self.connect_ws(rtm_connect["url"]) - # "types": "public_channel,private_channel,im", - user_channels_response = await self.api.fetch_users_conversations( - "public_channel" + users_conversations_response = await self.api.fetch_users_conversations( + "public_channel,private_channel,mpim,im" ) - user_channels = user_channels_response["channels"] - - for channel in user_channels: - conversation = SlackConversation(self, channel["id"]) - self.conversations[channel["id"]] = conversation - create_task(conversation.init()) + channels = users_conversations_response["channels"] + await self.conversations.initialize_items(channel["id"] for channel in channels) + for channel in channels: + conversation = await self.conversations[channel["id"]] + create_task(conversation.open_if_open()) self.is_connected = True |