diff options
Diffstat (limited to 'slack')
-rw-r--r-- | slack/slack_buffer.py | 8 | ||||
-rw-r--r-- | slack/slack_conversation.py | 85 | ||||
-rw-r--r-- | slack/slack_message.py | 2 | ||||
-rw-r--r-- | slack/slack_thread.py | 4 | ||||
-rw-r--r-- | slack/slack_workspace.py | 25 |
5 files changed, 73 insertions, 51 deletions
diff --git a/slack/slack_buffer.py b/slack/slack_buffer.py index addd2be..108221c 100644 --- a/slack/slack_buffer.py +++ b/slack/slack_buffer.py @@ -221,7 +221,7 @@ class SlackBuffer(ABC): raise NotImplementedError() @abstractmethod - async def get_name_and_buffer_props(self) -> Tuple[str, Dict[str, str]]: + def get_name_and_buffer_props(self) -> Tuple[str, Dict[str, str]]: raise NotImplementedError() async def buffer_switched_to(self) -> None: @@ -236,7 +236,7 @@ class SlackBuffer(ABC): weechat.buffer_set(self.buffer_pointer, "display", "1") return - name, buffer_props = await self.get_name_and_buffer_props() + name, buffer_props = self.get_name_and_buffer_props() full_name = self.get_full_name(name) buffer_props["highlight_tags"] = ( @@ -272,8 +272,8 @@ class SlackBuffer(ABC): if switch: await self.buffer_switched_to() - async def update_buffer_props(self) -> None: - name, buffer_props = await self.get_name_and_buffer_props() + def update_buffer_props(self) -> None: + name, buffer_props = self.get_name_and_buffer_props() buffer_props["name"] = self.get_full_name(name) for key, value in buffer_props.items(): weechat.buffer_set(self.buffer_pointer, key, value) diff --git a/slack/slack_conversation.py b/slack/slack_conversation.py index a7a6928..22dd8f8 100644 --- a/slack/slack_conversation.py +++ b/slack/slack_conversation.py @@ -50,7 +50,7 @@ if TYPE_CHECKING: def update_buffer_props(): for workspace in shared.workspaces.values(): for conversation in workspace.open_conversations.values(): - run_async(conversation.update_buffer_props()) + conversation.update_buffer_props() def invalidate_nicklists(): @@ -114,7 +114,7 @@ class SlackConversationMessageHashes(Dict[SlackTs, str]): if other_message: run_async(self._conversation.rerender_message(other_message)) if other_message.thread_buffer is not None: - run_async(other_message.thread_buffer.update_buffer_props()) + other_message.thread_buffer.update_buffer_props() for reply in other_message.replies.values(): run_async(self._conversation.rerender_message(reply)) @@ -128,15 +128,25 @@ class SlackConversationMessageHashes(Dict[SlackTs, str]): class SlackConversation(SlackBuffer): + __create_key = object() + def __init__( self, + create_key: object, workspace: SlackWorkspace, info: SlackConversationsInfo, ): + if create_key is not self.__create_key: + raise SlackError( + workspace, + "SlackConversation must be created with SlackConversation.create or SlackConversation.create_from_info", + ) super().__init__() self._workspace = workspace self._info = info self._members: Optional[List[str]] = None + self._im_user: Optional[SlackUser] = None + self._mpim_users: Optional[List[SlackUser]] = None self._messages: OrderedDict[SlackTs, SlackMessage] = OrderedDict() self._nicklist: Dict[Union[SlackUser, SlackBot], str] = {} self.nicklist_needs_refresh = True @@ -145,7 +155,27 @@ class SlackConversation(SlackBuffer): @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"]) + return await cls.create_from_info(workspace, info_response["channel"]) + + @classmethod + async def create_from_info( + cls, workspace: SlackWorkspace, info: SlackConversationsInfo + ): + conversation = cls(cls.__create_key, workspace, info) + + if info["is_im"] is True: + conversation._im_user = await workspace.users[info["user"]] + elif conversation.type == "mpim": + members = await conversation.load_members(load_all=True) + conversation._mpim_users = await gather( + *( + workspace.users[user_id] + for user_id in members + if user_id != workspace.my_user.id + ) + ) + + return conversation def __repr__(self): return f"{self.__class__.__name__}({self.workspace}, {self.id})" @@ -209,30 +239,22 @@ class SlackConversation(SlackBuffer): if self.type == "im": return self._info.get("user") - async def sort_key(self) -> str: + def sort_key(self) -> str: type_sort_key = { "channel": 0, "private": 1, "mpim": 2, "im": 3, }[self.type] - name = await self.name() - return f"{type_sort_key}{name}".lower() - - async def name(self) -> str: - if self._info["is_im"] is True: - im_user = await self.workspace.users[self._info["user"]] - return im_user.nick() - elif self._info["is_mpim"] is True: - members = await self.load_members(load_all=True) - member_users = await gather( - *( - self.workspace.users[user_id] - for user_id in members - if user_id != self.workspace.my_user.id - ) - ) - return ",".join(sorted(user.nick() for user in member_users)) + return f"{type_sort_key}{self.name()}".lower() + + def name(self) -> str: + if self._im_user is not None: + return self._im_user.nick() + elif self._info["is_im"] is True: + raise SlackError(self.workspace, "IM conversation without _im_user set") + elif self._mpim_users is not None: + return ",".join(sorted(user.nick() for user in self._mpim_users)) else: return self._info["name"] @@ -255,11 +277,11 @@ class SlackConversation(SlackBuffer): else: return "#" - async def name_with_prefix( + def name_with_prefix( self, name_type: Literal["full_name", "short_name", "short_name_without_padding"], ) -> str: - return f"{self.name_prefix(name_type)}{await self.name()}" + return f"{self.name_prefix(name_type)}{self.name()}" def should_open(self): if "is_open" in self._info: @@ -269,23 +291,22 @@ class SlackConversation(SlackBuffer): return True return False - async def buffer_title(self) -> str: + def buffer_title(self) -> str: # TODO: unfurl and apply styles topic = unhtmlescape(self._info.get("topic", {}).get("value", "")) - if self.im_user_id: - user = await self.workspace.users[self.im_user_id] - status = f"{user.status_emoji} {user.status_text}".strip() + if self._im_user: + status = f"{self._im_user.status_emoji} {self._im_user.status_text}".strip() return " | ".join(part for part in [status, topic] if part) return topic - async def set_topic(self, title: str): + def set_topic(self, title: str): if "topic" not in self._info: self._info["topic"] = {"value": "", "creator": "", "last_set": 0} self._info["topic"]["value"] = title - await self.update_buffer_props() + self.update_buffer_props() - async def get_name_and_buffer_props(self) -> Tuple[str, Dict[str, str]]: - name_without_prefix = await self.name() + def get_name_and_buffer_props(self) -> Tuple[str, Dict[str, str]]: + name_without_prefix = self.name() name = f"{self.name_prefix('full_name')}{name_without_prefix}" short_name = self.name_prefix("short_name") + name_without_prefix if self.muted: @@ -295,7 +316,7 @@ class SlackConversation(SlackBuffer): return name, { "short_name": short_name, - "title": await self.buffer_title(), + "title": self.buffer_title(), "input_multiline": "1", "nicklist": "0" if self.type == "im" else "1", "nicklist_display_groups": "0", diff --git a/slack/slack_message.py b/slack/slack_message.py index 6d5b39e..18d3d3a 100644 --- a/slack/slack_message.py +++ b/slack/slack_message.py @@ -187,7 +187,7 @@ class PendingMessageItem: if self.item_type == "conversation": try: conversation = await self.message.workspace.conversations[self.item_id] - name = await conversation.name_with_prefix("short_name_without_padding") + name = conversation.name_with_prefix("short_name_without_padding") except (SlackApiError, SlackError) as e: if ( isinstance(e, SlackApiError) diff --git a/slack/slack_thread.py b/slack/slack_thread.py index 3a96789..38f0ac2 100644 --- a/slack/slack_thread.py +++ b/slack/slack_thread.py @@ -47,8 +47,8 @@ class SlackThread(SlackBuffer): def last_read(self) -> Optional[SlackTs]: return self.parent.last_read - async def get_name_and_buffer_props(self) -> Tuple[str, Dict[str, str]]: - conversation_name = await self.parent.conversation.name_with_prefix("full_name") + def get_name_and_buffer_props(self) -> Tuple[str, Dict[str, str]]: + conversation_name = self.parent.conversation.name_with_prefix("full_name") name = f"{conversation_name}.${self.parent.hash}" short_name = f" ${self.parent.hash}" diff --git a/slack/slack_workspace.py b/slack/slack_workspace.py index fc3f65a..350a3ca 100644 --- a/slack/slack_workspace.py +++ b/slack/slack_workspace.py @@ -88,7 +88,7 @@ class SlackItem( item = items_info.get(item_id) if item is None: raise SlackError(self.workspace, "item_not_found") - return self._create_item_from_info(item) + return await self._create_item_from_info(item) else: return await self._item_class.create(self.workspace, item_id) @@ -99,7 +99,7 @@ class SlackItem( raise NotImplementedError() @abstractmethod - def _create_item_from_info(self, item_info: SlackItemInfo) -> SlackItemClass: + async def _create_item_from_info(self, item_info: SlackItemInfo) -> SlackItemClass: raise NotImplementedError() @@ -120,10 +120,10 @@ class SlackConversations(SlackItem[SlackConversation, SlackConversationsInfo]): response["channel"]["id"]: response["channel"] for response in responses } - def _create_item_from_info( + async def _create_item_from_info( self, item_info: SlackConversationsInfo ) -> SlackConversation: - return self._item_class(self.workspace, item_info) + return await self._item_class.create_from_info(self.workspace, item_info) class SlackUsers(SlackItem[SlackUser, SlackUserInfo]): @@ -136,7 +136,7 @@ class SlackUsers(SlackItem[SlackUser, SlackUserInfo]): response = await self.workspace.api.fetch_users_info(item_ids) return {info["id"]: info for info in response["users"]} - def _create_item_from_info(self, item_info: SlackUserInfo) -> SlackUser: + async def _create_item_from_info(self, item_info: SlackUserInfo) -> SlackUser: return self._item_class(self.workspace, item_info) @@ -150,7 +150,7 @@ class SlackBots(SlackItem[SlackBot, SlackBotInfo]): response = await self.workspace.api.fetch_bots_info(item_ids) return {info["id"]: info for info in response["bots"]} - def _create_item_from_info(self, item_info: SlackBotInfo) -> SlackBot: + async def _create_item_from_info(self, item_info: SlackBotInfo) -> SlackBot: return self._item_class(self.workspace, item_info) @@ -166,7 +166,9 @@ class SlackUsergroups(SlackItem[SlackUsergroup, SlackUsergroupInfo]): ) return {info["id"]: info for info in response["results"]} - def _create_item_from_info(self, item_info: SlackUsergroupInfo) -> SlackUsergroup: + async def _create_item_from_info( + self, item_info: SlackUsergroupInfo + ) -> SlackUsergroup: return self._item_class(self.workspace, item_info) @@ -283,8 +285,7 @@ class SlackWorkspace: if not history["messages"]: return - sort_key = await conversation.sort_key() - return sort_key, conversation + return conversation.sort_key(), conversation async def _connect_ws(self, url: str): proxy = Proxy() @@ -348,14 +349,14 @@ class SlackWorkspace: for channel_id in changed_channels: channel = self.open_conversations.get(channel_id) if channel: - await channel.update_buffer_props() + channel.update_buffer_props() return elif data["type"] == "user_status_changed": user = await self.users[data["user"]["id"]] user.update_info_json(data["user"]) for conversation in self.open_conversations.values(): if conversation.im_user_id == user.id: - await conversation.update_buffer_props() + conversation.update_buffer_props() return elif data["type"] == "channel_joined" or data["type"] == "group_joined": channel_id = data["channel"]["id"] @@ -413,7 +414,7 @@ class SlackWorkspace: await channel.change_message(data) else: if "subtype" in data and data["subtype"] == "channel_topic": - await channel.set_topic(data["topic"]) + channel.set_topic(data["topic"]) message = SlackMessage(channel, data) await channel.add_new_message(message) |