diff --git a/matrix_appservice_kakaotalk/formatter/from_kakaotalk.py b/matrix_appservice_kakaotalk/formatter/from_kakaotalk.py index 4ab4c8d..d1ed85e 100644 --- a/matrix_appservice_kakaotalk/formatter/from_kakaotalk.py +++ b/matrix_appservice_kakaotalk/formatter/from_kakaotalk.py @@ -16,11 +16,12 @@ from __future__ import annotations from typing import Match -from html import escape import re from mautrix.types import Format, MessageType, TextMessageEventContent +from ..kt.types.chat.attachment.mention import MentionStruct + from .. import puppet as pu, user as u _START = r"^|\s" @@ -79,92 +80,38 @@ def _handle_blockquote(output: list[str], blockquote: bool, line: str) -> tuple[ return blockquote, line -def _handle_codeblock_pre( - output: list[str], codeblock: bool, line: str -) -> tuple[bool, str, tuple[str | None, str | None, str | None]]: - cb = line.find("```") - cb_lang = None - cb_content = None - post_cb_content = None - if cb != -1: - if not codeblock: - cb_lang = line[cb + 3 :] - if "```" in cb_lang: - end = cb_lang.index("```") - cb_content = cb_lang[:end] - post_cb_content = cb_lang[end + 3 :] - cb_lang = "" - else: - codeblock = True - line = line[:cb] - else: - output.append("") - codeblock = False - line = line[cb + 3 :] - return codeblock, line, (cb_lang, cb_content, post_cb_content) - - -def _handle_codeblock_post( - output: list[str], cb_lang: str | None, cb_content: str | None, post_cb_content: str | None -) -> None: - if cb_lang is not None: - if cb_lang: - output.append(f'
')
-        else:
-            output.append("
")
-        if cb_content:
-            output.append(cb_content)
-            output.append("
") - output.append(_convert_formatting(post_cb_content)) - - -async def kakaotalk_to_matrix(msg: str) -> TextMessageEventContent: +async def kakaotalk_to_matrix(msg: str | None, mentions: list[MentionStruct] | None) -> TextMessageEventContent: + # TODO Shouts text = msg or "" - mentions = [] content = TextMessageEventContent(msgtype=MessageType.TEXT, body=text) - mention_user_ids = [] - for m in reversed(mentions): - original = text[m.offset : m.offset + m.length] - if len(original) > 0 and original[0] == "@": - original = original[1:] - mention_user_ids.append(int(m.user_id)) - text = f"{text[:m.offset]}@{m.user_id}\u2063{original}\u2063{text[m.offset + m.length:]}" - html = escape(text) - output = [] - if html: - codeblock = False - blockquote = False - line: str - lines = html.split("\n") - for i, line in enumerate(lines): - blockquote, line = _handle_blockquote(output, blockquote, line) - codeblock, line, post_args = _handle_codeblock_pre(output, codeblock, line) - output.append(_convert_formatting(line)) - if i != len(lines) - 1: - if codeblock: - output.append("\n") - else: - output.append("
") - _handle_codeblock_post(output, *post_args) - html = "".join(output) - mention_user_map = {} - for ktid in mention_user_ids: - user = await u.User.get_by_ktid(ktid) - if user: - mention_user_map[ktid] = user.mxid - else: - puppet = await pu.Puppet.get_by_ktid(ktid, create=False) - mention_user_map[ktid] = puppet.mxid if puppet else None + if mentions: + mention_user_ids = [] + at_chunks = text.split("@") + for m in mentions: + for idx in m.at: + chunk = at_chunks[idx] + original = chunk[:m.len] + mention_user_ids.append(int(m.user_id)) + at_chunks[idx] = f"{m.user_id}\u2063{original}\u2063{chunk[m.len:]}" + text = "@".join(at_chunks) - def _mention_replacer(match: Match) -> str: - mxid = mention_user_map[int(match.group(1))] - if not mxid: - return match.group(2) - return f'{match.group(2)}' + mention_user_map = {} + for ktid in mention_user_ids: + user = await u.User.get_by_ktid(ktid) + if user: + mention_user_map[ktid] = user.mxid + else: + puppet = await pu.Puppet.get_by_ktid(ktid, create=False) + mention_user_map[ktid] = puppet.mxid if puppet else None - html = MENTION_REGEX.sub(_mention_replacer, html) - if html != escape(content.body).replace("\n", "
\n"): - content.format = Format.HTML - content.formatted_body = html + if mention_user_map: + def _mention_replacer(match: Match) -> str: + mxid = mention_user_map[int(match.group(1))] + if not mxid: + return match.group(2) + return f'{match.group(2)}' + + content.format = Format.HTML + content.formatted_body = MENTION_REGEX.sub(_mention_replacer, text).replace("\n", "
\n") return content diff --git a/matrix_appservice_kakaotalk/portal.py b/matrix_appservice_kakaotalk/portal.py index b627eb7..c21b952 100644 --- a/matrix_appservice_kakaotalk/portal.py +++ b/matrix_appservice_kakaotalk/portal.py @@ -69,6 +69,7 @@ from .kt.types.channel.channel_info import ChannelInfo from .kt.types.channel.channel_type import KnownChannelType, ChannelType from .kt.types.chat import Chatlog, ChatType, KnownChatType from .kt.types.chat.attachment import ( + Attachment, AudioAttachment, #FileAttachment, MediaAttachment, @@ -1082,12 +1083,12 @@ class Portal(DBPortal, BasePortal): async def _handle_remote_text( self, intent: IntentAPI, + attachment: Attachment | None, timestamp: int, message_text: str | None, **_ ) -> list[EventID]: - # TODO Handle mentions properly - content = await kakaotalk_to_matrix(message_text) + content = await kakaotalk_to_matrix(message_text, attachment.mentions if attachment else None) return [await self._send_message(intent, content, timestamp=timestamp)] async def _handle_remote_reply(