diff options
author | Trygve Aaberge <trygveaa@gmail.com> | 2023-08-21 19:25:03 +0200 |
---|---|---|
committer | Trygve Aaberge <trygveaa@gmail.com> | 2024-02-18 11:32:54 +0100 |
commit | fed3a064a788b94f1c0b420bf276c158f8197ddf (patch) | |
tree | e2da384f076e579185e1dfb1c640b2e768bcc7b3 /slack | |
parent | 9453d1771232882ca111ff53ca3bf343fccbb62a (diff) | |
download | wee-slack-fed3a064a788b94f1c0b420bf276c158f8197ddf.tar.gz |
Support rendering emoji unicode characters
Diffstat (limited to 'slack')
-rw-r--r-- | slack/config.py | 17 | ||||
-rw-r--r-- | slack/register.py | 2 | ||||
-rw-r--r-- | slack/shared.py | 2 | ||||
-rw-r--r-- | slack/slack_emoji.py | 64 | ||||
-rw-r--r-- | slack/slack_message.py | 19 | ||||
-rw-r--r-- | slack/weechat_config.py | 4 |
6 files changed, 103 insertions, 5 deletions
diff --git a/slack/config.py b/slack/config.py index a3b01ce..864ac18 100644 --- a/slack/config.py +++ b/slack/config.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Optional +from typing import TYPE_CHECKING, Optional import weechat @@ -17,6 +17,9 @@ from slack.weechat_config import ( WeeChatSection, ) +if TYPE_CHECKING: + from typing_extensions import Literal + class SlackConfigSectionColor: def __init__(self, weechat_config: WeeChatConfig): @@ -136,6 +139,16 @@ class SlackConfigSectionLook: "*", ) + self.render_emoji_as: WeeChatOption[ + Literal["emoji", "name", "both"] + ] = WeeChatOption( + self._section, + "render_emoji_as", + "show emojis as: emoji = the emoji unicode character, name = the emoji name, both = both the emoji name and the emoji character", + "emoji", + string_values=["emoji", "name", "both"], + ) + self.typing_status_nicks = WeeChatOption( self._section, "typing_status_nicks", @@ -221,7 +234,7 @@ class SlackConfigSectionWorkspace: default_value: WeeChatOptionType, min_value: Optional[int] = None, max_value: Optional[int] = None, - string_values: Optional[str] = None, + string_values: Optional[list[WeeChatOptionType]] = None, ) -> WeeChatOption[WeeChatOptionType]: if self._workspace_name: option_name = f"{self._workspace_name}.{name}" diff --git a/slack/register.py b/slack/register.py index 7eab789..d77163b 100644 --- a/slack/register.py +++ b/slack/register.py @@ -6,6 +6,7 @@ from slack.commands import register_commands from slack.config import SlackConfig from slack.shared import shared from slack.slack_conversation import get_conversation_from_buffer_pointer +from slack.slack_emoji import load_standard_emojis from slack.task import run_async, sleep from slack.util import get_callback_name, with_color @@ -105,6 +106,7 @@ def register(): "", ): shared.weechat_version = int(weechat.info_get("version_number", "") or 0) + shared.standard_emojis = load_standard_emojis() shared.workspaces = {} shared.config = SlackConfig() shared.config.config_read() diff --git a/slack/shared.py b/slack/shared.py index 8dbac1a..600723b 100644 --- a/slack/shared.py +++ b/slack/shared.py @@ -6,6 +6,7 @@ from typing import TYPE_CHECKING, Callable, Dict, List, Union if TYPE_CHECKING: from slack.config import SlackConfig from slack.error import UncaughtError + from slack.slack_emoji import Emoji from slack.slack_workspace import SlackWorkspace from slack.task import Future, Task @@ -24,6 +25,7 @@ class Shared: self.workspaces: Dict[str, SlackWorkspace] = {} self.config: SlackConfig self.uncaught_errors: List[UncaughtError] = [] + self.standard_emojis: Dict[str, Emoji] shared = Shared() diff --git a/slack/slack_emoji.py b/slack/slack_emoji.py new file mode 100644 index 0000000..e2b9b11 --- /dev/null +++ b/slack/slack_emoji.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +import json +import os +from typing import TYPE_CHECKING, Any, Dict + +import weechat + +from slack.error import store_and_format_exception +from slack.log import print_error + +if TYPE_CHECKING: + from typing_extensions import NotRequired, TypedDict +else: + TypedDict = Any + + +class EmojiSkinVariation(TypedDict): + name: str + unicode: str + + +class Emoji(TypedDict): + aliasOf: NotRequired[str] + name: str + skinVariations: NotRequired[Dict[str, EmojiSkinVariation]] + unicode: str + + +def load_standard_emojis() -> Dict[str, Emoji]: + weechat_dir = weechat.info_get("weechat_data_dir", "") or weechat.info_get( + "weechat_dir", "" + ) + weechat_sharedir = weechat.info_get("weechat_sharedir", "") + local_weemoji, global_weemoji = ( + f"{path}/weemoji.json" for path in (weechat_dir, weechat_sharedir) + ) + path = ( + global_weemoji + if os.path.exists(global_weemoji) and not os.path.exists(local_weemoji) + else local_weemoji + ) + if not os.path.exists(path): + return {} + + try: + with open(path) as f: + emojis: Dict[str, Emoji] = json.loads(f.read()) + + emojis_skin_tones: Dict[str, Emoji] = { + skin_tone["name"]: { + "name": skin_tone["name"], + "unicode": skin_tone["unicode"], + } + for emoji in emojis.values() + if "skinVariations" in emoji + for skin_tone in emoji["skinVariations"].values() + } + + emojis.update(emojis_skin_tones) + return emojis + except Exception as e: + print_error(f"couldn't read weemoji.json: {store_and_format_exception(e)}") + return {} diff --git a/slack/slack_message.py b/slack/slack_message.py index d1d29fe..ab72582 100644 --- a/slack/slack_message.py +++ b/slack/slack_message.py @@ -16,6 +16,7 @@ from slack.util import with_color if TYPE_CHECKING: from slack_api.slack_conversations_history import SlackMessage as SlackMessageDict from slack_api.slack_conversations_history import SlackMessageReaction + from typing_extensions import assert_never from slack.slack_conversation import SlackConversation from slack.slack_workspace import SlackWorkspace @@ -321,6 +322,22 @@ class SlackMessage: return re_mention.sub(unfurl_ref, message) + def _get_emoji(self, emoji_name: str) -> str: + emoji_name_with_colons = f":{emoji_name}:" + if shared.config.look.render_emoji_as.value == "name": + return emoji_name_with_colons + + emoji_item = shared.standard_emojis.get(emoji_name) + if emoji_item is None: + return emoji_name_with_colons + + if shared.config.look.render_emoji_as.value == "emoji": + return emoji_item["unicode"] + elif shared.config.look.render_emoji_as.value == "both": + return f"{emoji_item['unicode']}({emoji_name_with_colons})" + else: + assert_never(shared.config.look.render_emoji_as.value) + async def _create_reaction_string(self, reaction: SlackMessageReaction) -> str: if shared.config.look.display_reaction_nicks.value: # TODO: initialize_items? @@ -332,7 +349,7 @@ class SlackMessage: else: users_str = len(reaction["users"]) - reaction_string = f":{reaction['name']}:{users_str}" + reaction_string = f"{self._get_emoji(reaction['name'])}{users_str}" if self.workspace.my_user.id in reaction["users"]: return with_color( diff --git a/slack/weechat_config.py b/slack/weechat_config.py index 78b36a1..6eab089 100644 --- a/slack/weechat_config.py +++ b/slack/weechat_config.py @@ -77,7 +77,7 @@ class WeeChatOption(Generic[WeeChatOptionType]): default_value: WeeChatOptionType min_value: Optional[int] = None max_value: Optional[int] = None - string_values: Optional[str] = None + string_values: Optional[list[WeeChatOptionType]] = None parent_option: Union[WeeChatOption[WeeChatOptionType], str, None] = None callback_change: Optional[ Callable[[WeeChatOption[WeeChatOptionType], bool], None] @@ -174,7 +174,7 @@ class WeeChatOption(Generic[WeeChatOptionType]): name, self.weechat_type, self.description, - self.string_values or "", + "|".join(str(x) for x in self.string_values or []), self.min_value or -(2**31), self.max_value or 2**31 - 1, default_value, |