diff options
author | Trygve Aaberge <trygveaa@gmail.com> | 2023-01-15 14:18:37 +0100 |
---|---|---|
committer | Trygve Aaberge <trygveaa@gmail.com> | 2024-02-18 11:32:53 +0100 |
commit | 988c7770e2c70e0cdf8268dabb4ef6f02ce2ca99 (patch) | |
tree | 9fd61b1bc60d614904a1d5c51c6c157c10850394 | |
parent | 7b9cf4d9278f584c4ce754e3dfbbcd245b1f9985 (diff) | |
download | wee-slack-988c7770e2c70e0cdf8268dabb4ef6f02ce2ca99.tar.gz |
Show nick suffix for bots
-rw-r--r-- | slack/config.py | 7 | ||||
-rw-r--r-- | slack/slack_api.py | 6 | ||||
-rw-r--r-- | slack/slack_message.py | 18 | ||||
-rw-r--r-- | slack/slack_user.py | 35 | ||||
-rw-r--r-- | slack/slack_workspace.py | 18 | ||||
-rw-r--r-- | typings/slack_api/slack_bots_info.pyi | 24 | ||||
-rw-r--r-- | typings/slack_api/slack_conversations_history.pyi | 24 |
7 files changed, 121 insertions, 11 deletions
diff --git a/slack/config.py b/slack/config.py index 56b828f..4533780 100644 --- a/slack/config.py +++ b/slack/config.py @@ -48,6 +48,13 @@ class SlackConfigSectionLook: def __init__(self, weechat_config: WeeChatConfig): self._section = WeeChatSection(weechat_config, "look") + self.bot_user_suffix = WeeChatOption( + self._section, + "bot_user_suffix", + "the suffix appended to nicks to indicate a bot", + " :]", + ) + self.external_user_suffix = WeeChatOption( self._section, "external_user_suffix", diff --git a/slack/slack_api.py b/slack/slack_api.py index 463dce9..081a2f4 100644 --- a/slack/slack_api.py +++ b/slack/slack_api.py @@ -8,6 +8,7 @@ from slack.http import http_request from slack.shared import shared if TYPE_CHECKING: + from slack_api.slack_bots_info import SlackBotInfoResponse from slack_api.slack_conversations_history import SlackConversationsHistoryResponse from slack_api.slack_conversations_info import SlackConversationsInfoResponse from slack_api.slack_rtm_connect import SlackRtmConnectResponse @@ -15,7 +16,7 @@ if TYPE_CHECKING: from slack_api.slack_users_info import SlackUsersInfoResponse from slack.slack_conversation import SlackConversation - from slack.slack_user import SlackUser + from slack.slack_user import SlackBot, SlackUser from slack.slack_workspace import SlackWorkspace @@ -88,3 +89,6 @@ class SlackApi: async def fetch_users_info(self, user: SlackUser) -> SlackUsersInfoResponse: return await self._fetch("users.info", {"user": user.id}) + + async def fetch_bots_info(self, bot: SlackBot) -> SlackBotInfoResponse: + return await self._fetch("bots.info", {"bot": bot.id}) diff --git a/slack/slack_message.py b/slack/slack_message.py index d6431d7..3c5383b 100644 --- a/slack/slack_message.py +++ b/slack/slack_message.py @@ -3,6 +3,7 @@ from __future__ import annotations import re from typing import TYPE_CHECKING, List +from slack.slack_user import format_bot_nick from slack.task import gather if TYPE_CHECKING: @@ -23,12 +24,21 @@ class SlackMessage: return self.conversation.workspace async def render_message(self): - message = await self._unfurl_refs(self._message_json["text"]) - if "user" in self._message_json: + if ( + "subtype" in self._message_json + and self._message_json["subtype"] == "bot_message" + ): + username = self._message_json.get("username") + if username: + prefix = format_bot_nick(username, colorize=True) + else: + bot = await self.workspace.bots[self._message_json["bot_id"]] + prefix = bot.nick(colorize=True) + else: user = await self.workspace.users[self._message_json["user"]] prefix = user.nick(colorize=True) - else: - prefix = "bot" + + message = await self._unfurl_refs(self._message_json["text"]) return f"{prefix}\t{message}" diff --git a/slack/slack_user.py b/slack/slack_user.py index 7b04605..4d2c29c 100644 --- a/slack/slack_user.py +++ b/slack/slack_user.py @@ -11,6 +11,19 @@ if TYPE_CHECKING: from slack.slack_workspace import SlackApi, SlackWorkspace +def nick_color(nick: str) -> str: + return weechat.info_get("nick_color_name", nick) + + +def format_bot_nick(nick: str, colorize: bool = False) -> str: + nick = nick.replace(" ", "") + + if colorize: + nick = with_color(nick_color(nick), nick) + + return nick + shared.config.look.bot_user_suffix.value + + class SlackUser: def __init__(self, workspace: SlackWorkspace, id: str): self.workspace = workspace @@ -58,4 +71,24 @@ class SlackUser: weechat.config_get("weechat.color.chat_nick_self") ) - return weechat.info_get("nick_color_name", self._name_without_spaces()) + return nick_color(self._name_without_spaces()) + + +class SlackBot: + def __init__(self, workspace: SlackWorkspace, id: str): + self.workspace = workspace + self.id = id + + @property + def _api(self) -> SlackApi: + return self.workspace.api + + async def init(self): + info = await self._api.fetch_bots_info(self) + if info["ok"] is False: + # TODO: Handle error + raise Exception("Failed fetching user info") + self._info = info["bot"] + + def nick(self, colorize: bool = False) -> str: + return format_bot_nick(self._info["name"], colorize) diff --git a/slack/slack_workspace.py b/slack/slack_workspace.py index 4e18634..ba79281 100644 --- a/slack/slack_workspace.py +++ b/slack/slack_workspace.py @@ -13,7 +13,7 @@ from slack.proxy import Proxy from slack.shared import shared from slack.slack_api import SlackApi from slack.slack_conversation import SlackConversation -from slack.slack_user import SlackUser +from slack.slack_user import SlackBot, SlackUser from slack.task import Future, create_task from slack.util import get_callback_name @@ -33,6 +33,21 @@ class SlackUsers(Dict[str, Future[SlackUser]]): return user +class SlackBots(Dict[str, Future[SlackBot]]): + def __init__(self, workspace: SlackWorkspace): + super().__init__() + self.workspace = workspace + + def __missing__(self, key: str): + self[key] = create_task(self._create_bot(key)) + return self[key] + + async def _create_bot(self, bot_id: str) -> SlackBot: + bot = SlackBot(self.workspace, bot_id) + await bot.init() + return bot + + class SlackWorkspace: def __init__(self, name: str): self.name = name @@ -40,6 +55,7 @@ class SlackWorkspace: self.api = SlackApi(self) self.is_connected = False self.users = SlackUsers(self) + self.bots = SlackBots(self) self.conversations: Dict[str, SlackConversation] = {} def __setattr__(self, __name: str, __value: Any) -> None: diff --git a/typings/slack_api/slack_bots_info.pyi b/typings/slack_api/slack_bots_info.pyi new file mode 100644 index 0000000..0fb296f --- /dev/null +++ b/typings/slack_api/slack_bots_info.pyi @@ -0,0 +1,24 @@ +from typing import Dict, Literal, TypedDict, final + +from typing_extensions import NotRequired + +class SlackBotInfo(TypedDict): + id: str + deleted: bool + name: str + updated: int + app_id: str + user_id: NotRequired[str] + icons: Dict[str, str] + +@final +class SlackBotsInfoErrorResponse(TypedDict): + ok: Literal[False] + error: str + +@final +class SlackBotsInfoSuccessResponse(TypedDict): + ok: Literal[True] + bot: SlackBotInfo + +SlackBotInfoResponse = SlackBotsInfoSuccessResponse | SlackBotsInfoErrorResponse diff --git a/typings/slack_api/slack_conversations_history.pyi b/typings/slack_api/slack_conversations_history.pyi index 479fe50..b0220e3 100644 --- a/typings/slack_api/slack_conversations_history.pyi +++ b/typings/slack_api/slack_conversations_history.pyi @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import List, Literal, TypedDict, final +from typing import Dict, List, Literal, TypedDict, final from typing_extensions import NotRequired @@ -81,17 +81,21 @@ class SlackMessageFile(TypedDict): class SlackMessageCommon(TypedDict): type: Literal["message"] text: str - user: str ts: str reactions: NotRequired[List[SlackMessageReaction]] -class SlackMessageStandard(SlackMessageCommon): +class SlackMessageStandardCommon(SlackMessageCommon): client_msg_id: NotRequired[str] + user: str blocks: List[SlackMessageBlock] attachments: NotRequired[List[SlackMessageAttachment]] team: str -class SlackMessageThreadParentCommon(SlackMessageStandard): +@final +class SlackMessageStandard(SlackMessageStandardCommon): + pass + +class SlackMessageThreadParentCommon(SlackMessageStandardCommon): thread_ts: str reply_count: int reply_users_count: int @@ -108,21 +112,32 @@ class SlackMessageThreadParentSubscribed(SlackMessageThreadParentCommon): subscribed: Literal[True] last_read: str +@final class SlackMessageWithFiles(SlackMessageCommon): + user: str files: List[SlackMessageFile] upload: bool display_as_bot: bool # TODO: Add other subtypes @final +class SlackMessageSubtypeBotMessage(SlackMessageCommon): + subtype: Literal["bot_message"] + bot_id: str + username: NotRequired[str] + icons: NotRequired[Dict[str, str]] + +@final class SlackMessageSubtypeBotRemove(SlackMessageCommon): subtype: Literal["bot_remove"] + user: str bot_id: str bot_link: str @final class SlackMessageSubtypeBotAdd(SlackMessageCommon): subtype: Literal["bot_add"] + user: str bot_id: str bot_link: str @@ -136,6 +151,7 @@ SlackMessage = ( | SlackMessageThreadParentNotSubscribed | SlackMessageThreadParentSubscribed | SlackMessageWithFiles + | SlackMessageSubtypeBotMessage | SlackMessageSubtypeBotRemove | SlackMessageSubtypeBotAdd ) |