Incoming mentions

This commit is contained in:
Andrew Ferrazzutti 2022-04-05 18:21:35 -04:00
parent 2b9c59a2af
commit 6867e6b349
2 changed files with 34 additions and 86 deletions

View File

@ -16,11 +16,12 @@
from __future__ import annotations from __future__ import annotations
from typing import Match from typing import Match
from html import escape
import re import re
from mautrix.types import Format, MessageType, TextMessageEventContent from mautrix.types import Format, MessageType, TextMessageEventContent
from ..kt.types.chat.attachment.mention import MentionStruct
from .. import puppet as pu, user as u from .. import puppet as pu, user as u
_START = r"^|\s" _START = r"^|\s"
@ -79,92 +80,38 @@ def _handle_blockquote(output: list[str], blockquote: bool, line: str) -> tuple[
return blockquote, line return blockquote, line
def _handle_codeblock_pre( async def kakaotalk_to_matrix(msg: str | None, mentions: list[MentionStruct] | None) -> TextMessageEventContent:
output: list[str], codeblock: bool, line: str # TODO Shouts
) -> 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("</code></pre>")
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'<pre><code class="language-{cb_lang}">')
else:
output.append("<pre><code>")
if cb_content:
output.append(cb_content)
output.append("</code></pre>")
output.append(_convert_formatting(post_cb_content))
async def kakaotalk_to_matrix(msg: str) -> TextMessageEventContent:
text = msg or "" text = msg or ""
mentions = []
content = TextMessageEventContent(msgtype=MessageType.TEXT, body=text) 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("<br/>")
_handle_codeblock_post(output, *post_args)
html = "".join(output)
mention_user_map = {} if mentions:
for ktid in mention_user_ids: mention_user_ids = []
user = await u.User.get_by_ktid(ktid) at_chunks = text.split("@")
if user: for m in mentions:
mention_user_map[ktid] = user.mxid for idx in m.at:
else: chunk = at_chunks[idx]
puppet = await pu.Puppet.get_by_ktid(ktid, create=False) original = chunk[:m.len]
mention_user_map[ktid] = puppet.mxid if puppet else None 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: mention_user_map = {}
mxid = mention_user_map[int(match.group(1))] for ktid in mention_user_ids:
if not mxid: user = await u.User.get_by_ktid(ktid)
return match.group(2) if user:
return f'<a href="https://matrix.to/#/{mxid}">{match.group(2)}</a>' 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 mention_user_map:
if html != escape(content.body).replace("\n", "<br/>\n"): def _mention_replacer(match: Match) -> str:
content.format = Format.HTML mxid = mention_user_map[int(match.group(1))]
content.formatted_body = html if not mxid:
return match.group(2)
return f'<a href="https://matrix.to/#/{mxid}">{match.group(2)}</a>'
content.format = Format.HTML
content.formatted_body = MENTION_REGEX.sub(_mention_replacer, text).replace("\n", "<br/>\n")
return content return content

View File

@ -69,6 +69,7 @@ from .kt.types.channel.channel_info import ChannelInfo
from .kt.types.channel.channel_type import KnownChannelType, ChannelType from .kt.types.channel.channel_type import KnownChannelType, ChannelType
from .kt.types.chat import Chatlog, ChatType, KnownChatType from .kt.types.chat import Chatlog, ChatType, KnownChatType
from .kt.types.chat.attachment import ( from .kt.types.chat.attachment import (
Attachment,
AudioAttachment, AudioAttachment,
#FileAttachment, #FileAttachment,
MediaAttachment, MediaAttachment,
@ -1082,12 +1083,12 @@ class Portal(DBPortal, BasePortal):
async def _handle_remote_text( async def _handle_remote_text(
self, self,
intent: IntentAPI, intent: IntentAPI,
attachment: Attachment | None,
timestamp: int, timestamp: int,
message_text: str | None, message_text: str | None,
**_ **_
) -> list[EventID]: ) -> list[EventID]:
# TODO Handle mentions properly content = await kakaotalk_to_matrix(message_text, attachment.mentions if attachment else None)
content = await kakaotalk_to_matrix(message_text)
return [await self._send_message(intent, content, timestamp=timestamp)] return [await self._send_message(intent, content, timestamp=timestamp)]
async def _handle_remote_reply( async def _handle_remote_reply(