diff options
Diffstat (limited to 'slack/slack_message.py')
-rw-r--r-- | slack/slack_message.py | 94 |
1 files changed, 63 insertions, 31 deletions
diff --git a/slack/slack_message.py b/slack/slack_message.py index 4301560..ade737c 100644 --- a/slack/slack_message.py +++ b/slack/slack_message.py @@ -4,7 +4,7 @@ import re from collections import OrderedDict from datetime import date, datetime, timedelta from enum import Enum -from typing import TYPE_CHECKING, Generator, List, Match, Optional, Union +from typing import TYPE_CHECKING, Generator, Iterable, List, Match, Optional, Union import weechat @@ -19,7 +19,7 @@ from slack.python_compatibility import removeprefix, removesuffix from slack.shared import shared from slack.slack_user import SlackBot, SlackUser, format_bot_nick, nick_color from slack.task import gather -from slack.util import intersperse, unhtmlescape, with_color +from slack.util import htmlescape, intersperse, unhtmlescape, with_color if TYPE_CHECKING: from slack_api.slack_conversations_history import SlackMessage as SlackMessageDict @@ -662,7 +662,9 @@ class SlackMessage: uncaught_error = UncaughtError(e) print_error(store_and_format_uncaught_error(uncaught_error)) text = f"<Error rendering message {self.ts}, error id: {uncaught_error.id}>" - self._rendered_message = with_color(shared.config.color.render_error.value, text) + self._rendered_message = with_color( + shared.config.color.render_error.value, text + ) return self._rendered_message @@ -716,6 +718,19 @@ class SlackMessage: if i < len(message): yield message[i:] + def _unfurl_and_unescape( + self, items: Iterable[Union[str, PendingMessageItem]] + ) -> Generator[Union[str, PendingMessageItem], None, None]: + for item in items: + if isinstance(item, str): + for sub_item in self._unfurl_refs(item): + if isinstance(sub_item, str): + yield unhtmlescape(sub_item) + else: + yield sub_item + else: + yield item + def _get_emoji(self, emoji_name: str, skin_tone: Optional[int] = None) -> str: emoji_name_with_colons = f":{emoji_name}:" if shared.config.look.render_emoji_as.value == "name": @@ -1077,7 +1092,10 @@ class SlackMessage: if "attachments" not in self._message_json: return [] - attachments_texts: List[Union[str, PendingMessageItem]] = [] + attachments: List[List[Union[str, PendingMessageItem]]] = [] + if any(items_before): + attachments.append([]) + for attachment in self._message_json["attachments"]: # Attachments should be rendered roughly like: # @@ -1088,16 +1106,16 @@ class SlackMessage: if ( attachment.get("is_app_unfurl") - and shared.config.look.display_link_previews + and not shared.config.look.display_link_previews.value ): continue - items: List[Union[str, PendingMessageItem]] = [] + lines: List[List[Union[str, PendingMessageItem]]] = [] prepend_title_text = "" if "author_name" in attachment: prepend_title_text = attachment["author_name"] + ": " if "pretext" in attachment: - items.append(attachment["pretext"]) + lines.append([attachment["pretext"]]) link_shown = False title = attachment.get("title") title_link = attachment.get("title_link", "") @@ -1107,10 +1125,12 @@ class SlackMessage: title_link = "" link_shown = True if title and title_link: - items.append(f"{prepend_title_text}{title} ({title_link})") + lines.append( + [f"{prepend_title_text}{title} ({htmlescape(title_link)})"] + ) prepend_title_text = "" elif title and not title_link: - items.append(f"{prepend_title_text}{title}") + lines.append([f"{prepend_title_text}{title}"]) prepend_title_text = "" from_url = attachment.get("from_url", "") if ( @@ -1119,20 +1139,16 @@ class SlackMessage: ) and from_url != title_link ): - items.append(from_url) + lines.append([htmlescape(from_url)]) elif from_url: link_shown = True atext = attachment.get("text") if atext: tx = re.sub(r" *\n[\n ]+", "\n", atext) - items.append(prepend_title_text + tx) + lines.append([prepend_title_text + tx]) prepend_title_text = "" - # TODO: Don't render both text and blocks - blocks_items = self._render_blocks(attachment.get("blocks", [])) - items.extend(blocks_items) - image_url = attachment.get("image_url", "") if ( not any( @@ -1141,30 +1157,41 @@ class SlackMessage: and image_url != from_url and image_url != title_link ): - items.append(image_url) + lines.append([htmlescape(image_url)]) elif image_url: link_shown = True for field in attachment.get("fields", []): if field.get("title"): - items.append(f"{field['title']}: {field['value']}") + lines.append([f"{field['title']}: {field['value']}"]) else: - items.append(field["value"]) + lines.append([field["value"]]) + + lines = [ + [item for item in self._unfurl_and_unescape(line)] for line in lines + ] files = self._render_files(attachment.get("files", [])) if files: - items.append(files) + lines.append([files]) - if attachment.get("is_msg_unfurl"): + # TODO: Don't render both text and blocks + blocks_items = self._render_blocks(attachment.get("blocks", [])) + if blocks_items: + lines.append(blocks_items) + + if "is_msg_unfurl" in attachment and attachment["is_msg_unfurl"]: channel_name = PendingMessageItem( - self, "conversation", self.conversation.id + self, "conversation", attachment["channel_id"], "chat" ) if attachment.get("is_reply_unfurl"): footer = ["From a thread in ", channel_name] else: footer = ["Posted in ", channel_name] elif attachment.get("footer"): - footer = [attachment.get("footer")] + footer: List[Union[str, PendingMessageItem]] = [ + attachment.get("footer") + ] else: footer = [] @@ -1181,20 +1208,23 @@ class SlackMessage: if date.today() - date.fromtimestamp(ts_int) <= timedelta(days=1): time_string = " at {time}" timestamp_formatted = format_date( - ts_int, "date_short_pretty" + time_string + ts_int, "{date_short_pretty}" + time_string ) footer.append(f" | {timestamp_formatted.capitalize()}") - items.extend(footer) + + lines.append([item for item in self._unfurl_and_unescape(footer)]) fallback = attachment.get("fallback") - if items == [] and fallback and not link_shown: - items.append(fallback) + if not any(lines) and fallback and not link_shown: + lines.append([fallback]) + + items = [item for items in intersperse(lines, ["\n"]) for item in items] texts_separate_newlines = [ item_separate_newline for item in items for item_separate_newline in ( - intersperse(item.strip().split("\n"), "\n") + intersperse(item.split("\n"), "\n") if isinstance(item, str) else [item] ) @@ -1221,10 +1251,12 @@ class SlackMessage: for item in texts_separate_newlines ] + attachment_texts: List[Union[str, PendingMessageItem]] = [] if line_color: - attachments_texts.append(weechat.color(line_color)) - attachments_texts.extend(texts_with_prefix) + attachment_texts.append(weechat.color(line_color)) + attachment_texts.extend(texts_with_prefix) if line_color: - attachments_texts.append(weechat.color("reset")) + attachment_texts.append(weechat.color("reset")) + attachments.append(attachment_texts) - return attachments_texts + return [item for items in intersperse(attachments, ["\n"]) for item in items] |