diff options
-rw-r--r-- | slack/config.py | 30 | ||||
-rw-r--r-- | slack/register.py | 2 | ||||
-rw-r--r-- | slack/slack_conversation.py | 47 | ||||
-rw-r--r-- | slack/slack_user.py | 7 | ||||
-rw-r--r-- | slack/weechat_config.py | 66 |
5 files changed, 125 insertions, 27 deletions
diff --git a/slack/config.py b/slack/config.py index 8b60ac1..e7dbbaf 100644 --- a/slack/config.py +++ b/slack/config.py @@ -6,6 +6,7 @@ import weechat from slack.log import print_error from slack.shared import shared +from slack.slack_conversation import invalidate_nicklists from slack.slack_workspace import SlackWorkspace from slack.util import get_callback_name from slack.weechat_config import ( @@ -76,6 +77,15 @@ class SlackConfigSectionLook: " :]", ) + self.color_nicks_in_nicklist = WeeChatOption( + self._section, + "color_nicks_in_nicklist", + "use nick color in nicklist", + False, + parent_option="irc.look.color_nicks_in_nicklist", + callback_change=self.config_change_color_nicks_in_nicklist_cb, + ) + self.external_user_suffix = WeeChatOption( self._section, "external_user_suffix", @@ -83,6 +93,26 @@ class SlackConfigSectionLook: "*", ) + weechat.hook_config( + "weechat.look.nick_color_*", + get_callback_name(self.config_change_nick_colors_cb), + "", + ) + weechat.hook_config( + "weechat.color.chat_nick_colors", + get_callback_name(self.config_change_nick_colors_cb), + "", + ) + + def config_change_color_nicks_in_nicklist_cb( + self, option: WeeChatOption[WeeChatOptionType], parent_changed: bool + ): + invalidate_nicklists() + + def config_change_nick_colors_cb(self, data: str, option: str, value: str): + invalidate_nicklists() + return weechat.WEECHAT_RC_OK + class SlackConfigSectionWorkspace: def __init__( diff --git a/slack/register.py b/slack/register.py index 5e40c6a..e7628e0 100644 --- a/slack/register.py +++ b/slack/register.py @@ -22,7 +22,7 @@ def shutdown_cb(): def signal_buffer_switch_cb(data: str, signal: str, buffer_pointer: str) -> int: conversation = get_conversation_from_buffer_pointer(buffer_pointer) if conversation: - run_async(conversation.fill_history()) + run_async(conversation.buffer_switched_to()) return weechat.WEECHAT_RC_OK diff --git a/slack/slack_conversation.py b/slack/slack_conversation.py index 00052af..fc53979 100644 --- a/slack/slack_conversation.py +++ b/slack/slack_conversation.py @@ -30,6 +30,12 @@ def get_conversation_from_buffer_pointer( return None +def invalidate_nicklists(): + for workspace in shared.workspaces.values(): + for conversation in workspace.open_conversations.values(): + conversation.nicklist_needs_refresh = True + + class SlackConversation: def __init__( self, @@ -45,6 +51,7 @@ class SlackConversation: self.is_loading = False self.history_filled = False self.history_pending = False + self.nicklist_needs_refresh = True self.completion_context: Literal[ "NO_COMPLETION", @@ -84,12 +91,9 @@ class SlackConversation: im_user = await self.workspace.users[self._info["user"]] return im_user.nick() elif self._info["is_mpim"] is True: - if self._members is None: - members_response = await self._api.fetch_conversations_members(self) - self._members = members_response["members"] - await self.workspace.users.initialize_items(self._members) + members = await self.load_members(load_all=True) member_users = await gather( - *(self.workspace.users[user_id] for user_id in self._members) + *(self.workspace.users[user_id] for user_id in members) ) return ",".join([user.nick() for user in member_users]) else: @@ -147,6 +151,8 @@ class SlackConversation: "short_name": short_name, "title": "topic", "input_multiline": "1", + "nicklist": "0" if self.type == "im" else "1", + "nicklist_display_groups": "0", "localvar_set_type": ( "private" if self.type in ("im", "mpim") else "channel" ), @@ -178,6 +184,18 @@ class SlackConversation: self.workspace.open_conversations[self.id] = self + async def buffer_switched_to(self): + await gather(self.nicklist_update(), self.fill_history()) + + async def load_members(self, load_all: bool = False): + if self._members is None: + members_response = await self._api.fetch_conversations_members( + self, pages=-1 if load_all else 1 + ) + self._members = members_response["members"] + await self.workspace.users.initialize_items(self._members) + return self._members + async def fill_history(self): if self.history_filled or self.history_pending: return @@ -204,6 +222,25 @@ class SlackConversation: self.history_filled = True self.history_pending = False + async def nicklist_update(self): + if self.nicklist_needs_refresh: + self.nicklist_needs_refresh = False + members = await self.load_members() + weechat.nicklist_remove_all(self.buffer_pointer) + await gather(*(self.nicklist_add_user(user_id) for user_id in members)) + + async def nicklist_add_user(self, user_id: str): + user = await self.workspace.users[user_id] + # TODO: weechat.color.nicklist_away + color = ( + user.nick_color() + if shared.config.look.color_nicks_in_nicklist.value + else "" + ) + weechat.nicklist_add_nick( + self.buffer_pointer, "", user.nick(), color, "", "", 1 + ) + async def add_message(self, message: SlackMessage): self._messages[message.ts] = message if self.history_filled: diff --git a/slack/slack_user.py b/slack/slack_user.py index 2356eaf..9a5989d 100644 --- a/slack/slack_user.py +++ b/slack/slack_user.py @@ -58,7 +58,7 @@ class SlackUser: nick = self._name_without_spaces() if colorize: - nick = with_color(self._nick_color(), nick) + nick = with_color(self.nick_color(), nick) if self._info["profile"]["team"] != self.workspace.id: nick += shared.config.look.external_user_suffix.value @@ -68,7 +68,7 @@ class SlackUser: def _name_without_spaces(self) -> str: return name_from_user_info_without_spaces(self.workspace, self._info) - def _nick_color(self) -> str: + def nick_color(self) -> str: if self._info["id"] == self.workspace.my_user._info["id"]: return weechat.config_string( weechat.config_get("weechat.color.chat_nick_self") @@ -90,6 +90,9 @@ class SlackBot: def nick(self, colorize: bool = False) -> str: return format_bot_nick(self._info["name"], colorize) + def nick_color(self): + return nick_color(self._info["name"].replace(" ", "")) + class SlackUsergroup: def __init__(self, workspace: SlackWorkspace, info: SlackUsergroupInfo): diff --git a/slack/weechat_config.py b/slack/weechat_config.py index 7fc2742..c2f5b16 100644 --- a/slack/weechat_config.py +++ b/slack/weechat_config.py @@ -1,11 +1,12 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Generic, Optional, TypeVar, Union, cast +from typing import Callable, Generic, Optional, TypeVar, Union, cast import weechat from slack.shared import shared +from slack.util import get_callback_name class WeeChatColor(str): @@ -52,6 +53,19 @@ WeeChatOptionTypes = Union[int, str] WeeChatOptionType = TypeVar("WeeChatOptionType", bound=WeeChatOptionTypes) +def option_get_value( + option_pointer: str, option_type: WeeChatOptionType +) -> WeeChatOptionType: + if isinstance(option_type, bool): + return cast(WeeChatOptionType, weechat.config_boolean(option_pointer) == 1) + if isinstance(option_type, int): + return cast(WeeChatOptionType, weechat.config_integer(option_pointer)) + if isinstance(option_type, WeeChatColor): + color = weechat.config_color(option_pointer) + return cast(WeeChatOptionType, WeeChatColor(color)) + return cast(WeeChatOptionType, weechat.config_string(option_pointer)) + + @dataclass class WeeChatOption(Generic[WeeChatOptionType]): section: WeeChatSection @@ -61,7 +75,10 @@ class WeeChatOption(Generic[WeeChatOptionType]): min_value: Optional[int] = None max_value: Optional[int] = None string_values: Optional[str] = None - parent_option: Optional[WeeChatOption[WeeChatOptionType]] = None + parent_option: Union[WeeChatOption[WeeChatOptionType], str, None] = None + callback_change: Optional[ + Callable[[WeeChatOption[WeeChatOptionType], bool], None] + ] = None def __post_init__(self): self._pointer = self._create_weechat_option() @@ -69,18 +86,13 @@ class WeeChatOption(Generic[WeeChatOptionType]): @property def value(self) -> WeeChatOptionType: if weechat.config_option_is_null(self._pointer): - if self.parent_option: + if isinstance(self.parent_option, str): + parent_option_pointer = weechat.config_get(self.parent_option) + return option_get_value(parent_option_pointer, self.default_value) + elif self.parent_option: return self.parent_option.value return self.default_value - - if isinstance(self.default_value, bool): - return cast(WeeChatOptionType, weechat.config_boolean(self._pointer) == 1) - if isinstance(self.default_value, int): - return cast(WeeChatOptionType, weechat.config_integer(self._pointer)) - if isinstance(self.default_value, WeeChatColor): - color = weechat.config_color(self._pointer) - return cast(WeeChatOptionType, WeeChatColor(color)) - return cast(WeeChatOptionType, weechat.config_string(self._pointer)) + return option_get_value(self._pointer, self.default_value) @value.setter def value(self, value: WeeChatOptionType): @@ -110,16 +122,32 @@ class WeeChatOption(Generic[WeeChatOptionType]): return "color" return "string" + def _changed_cb(self, data: str, option: str, value: Optional[str] = None): + if self.callback_change: + parent_changed = data == "parent_changed" + if not parent_changed or weechat.config_option_is_null(self._pointer): + self.callback_change(self, parent_changed) + return weechat.WEECHAT_RC_OK + def _create_weechat_option(self) -> str: if self.parent_option: - parent_option_name = ( - f"{self.parent_option.section.weechat_config.name}" - f".{self.parent_option.section.name}" - f".{self.parent_option.name}" - ) - name = f"{self.name} << {parent_option_name}" + if isinstance(self.parent_option, str): + parent_option_name = self.parent_option + name = f"{self.name} << {parent_option_name}" + else: + parent_option_name = ( + f"{self.parent_option.section.weechat_config.name}" + f".{self.parent_option.section.name}" + f".{self.parent_option.name}" + ) + name = f"{self.name} << {parent_option_name}" default_value = None null_value_allowed = True + weechat.hook_config( + parent_option_name, + get_callback_name(self._changed_cb), + "parent_changed", + ) else: name = self.name default_value = str(self.default_value) @@ -145,7 +173,7 @@ class WeeChatOption(Generic[WeeChatOptionType]): null_value_allowed, "", "", - "", + get_callback_name(self._changed_cb), "", "", "", |