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(