Add basic support for bridging custom emojis from Telegram

This commit is contained in:
Tulir Asokan
2022-08-12 21:35:50 +03:00
parent 473ab17fe7
commit 76eafbf48c
5 changed files with 113 additions and 21 deletions
+45 -8
View File
@@ -20,7 +20,7 @@ import logging
import re
from telethon.errors import RPCError
from telethon.helpers import add_surrogate, del_surrogate, within_surrogate
from telethon.helpers import add_surrogate, del_surrogate
from telethon.tl.custom import Message
from telethon.tl.types import (
MessageEntityBlockquote,
@@ -52,8 +52,9 @@ from telethon.tl.types import (
from mautrix.types import Format, MessageType, TextMessageEventContent
from .. import abstract_user as au, portal as po, puppet as pu, user as u
from ..db import Message as DBMessage
from ..db import Message as DBMessage, TelegramFile as DBTelegramFile
from ..types import TelegramID
from ..util.file_transfer import transfer_custom_emojis_to_matrix
log: logging.Logger = logging.getLogger("mau.fmt.tg")
@@ -125,6 +126,27 @@ async def _add_forward_header(
)
class ReuploadedCustomEmoji(MessageEntityCustomEmoji):
file: DBTelegramFile
def __init__(self, parent: MessageEntityCustomEmoji, file: DBTelegramFile) -> None:
super().__init__(parent.offset, parent.length, parent.document_id)
self.file = file
async def _convert_custom_emoji(
source: au.AbstractUser, entities: list[TypeMessageEntity]
) -> None:
emoji_ids = [
entity.document_id for entity in entities if isinstance(entity, MessageEntityCustomEmoji)
]
custom_emojis = await transfer_custom_emojis_to_matrix(source, emoji_ids)
if len(custom_emojis) > 0:
for i, entity in enumerate(entities):
if isinstance(entity, MessageEntityCustomEmoji):
entities[i] = ReuploadedCustomEmoji(entity, custom_emojis[entity.document_id])
async def telegram_to_matrix(
evt: Message | SponsoredMessage,
source: au.AbstractUser,
@@ -138,6 +160,7 @@ async def telegram_to_matrix(
)
entities = override_entities or evt.entities
if entities:
await _convert_custom_emoji(source, entities)
content.format = Format.HTML
html = await _telegram_entities_to_matrix_catch(add_surrogate(content.body), entities)
content.formatted_body = del_surrogate(html)
@@ -166,9 +189,20 @@ async def _telegram_entities_to_matrix_catch(text: str, entities: list[TypeMessa
return "[failed conversion in _telegram_entities_to_matrix]"
def within_surrogate(text, index):
"""
`True` if ``index`` is within a surrogate (before and after it, not at!).
"""
return (
1 < index < len(text) # in bounds
and "\ud800" <= text[index - 1] <= "\udbff" # current is low surrogate
and "\udc00" <= text[index] <= "\udfff" # previous is high surrogate
)
async def _telegram_entities_to_matrix(
text: str,
entities: list[TypeMessageEntity],
entities: list[TypeMessageEntity | ReuploadedCustomEmoji],
offset: int = 0,
length: int = None,
in_codeblock: bool = False,
@@ -197,10 +231,9 @@ async def _telegram_entities_to_matrix(
elif relative_offset < last_offset:
continue
# TODO this breaks when there are lots of emojis in a row (e.g. custom emojis)
# while within_surrogate(text, relative_offset, length=length):
# relative_offset += 1
while within_surrogate(text, relative_offset + entity.length, length=length):
while within_surrogate(text, relative_offset):
relative_offset += 1
while within_surrogate(text, relative_offset + entity.length):
entity.length += 1
skip_entity = False
@@ -244,8 +277,12 @@ async def _telegram_entities_to_matrix(
html, entity_text, entity.url if entity_type == MessageEntityTextUrl else None
)
elif entity_type == MessageEntityCustomEmoji:
# TODO support properly
html.append(entity_text)
elif entity_type == ReuploadedCustomEmoji:
html.append(
f'<img data-mx-emoticon src="{escape(entity.file.mxc)}" height="32" '
f'alt="{entity_text}" title="{entity_text}"/>'
)
elif entity_type in (
MessageEntityBotCommand,
MessageEntityHashtag,