From e06b92e4d975ebec9c2f924c00baf24fa2feb5ec Mon Sep 17 00:00:00 2001 From: SyberiaK Date: Fri, 19 Apr 2024 17:10:30 +0500 Subject: [PATCH] Formatting conversion (fails on 3+ styles applied to the same text chunk but whatever) --- plugins/incs2chat.py | 63 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/plugins/incs2chat.py b/plugins/incs2chat.py index 4e30525..99c2613 100644 --- a/plugins/incs2chat.py +++ b/plugins/incs2chat.py @@ -4,7 +4,7 @@ import requests from pyrogram import Client, filters -from pyrogram.enums import ChatMembersFilter +from pyrogram.enums import ChatMembersFilter, MessageEntityType from pyrogram.types import Message, MessageEntity # noinspection PyUnresolvedReferences @@ -12,8 +12,8 @@ import config -def correct_message_entity(entities: list[MessageEntity] | None, - original_text: str, new_text: str) -> list[MessageEntity] | None: +def correct_message_entities(entities: list[MessageEntity] | None, + original_text: str, new_text: str) -> list[MessageEntity] | None: """Correct message entities (a.k.a. Markdown formatting) for edited text.""" if entities is None: @@ -34,6 +34,52 @@ def correct_message_entity(entities: list[MessageEntity] | None, return entities +def convert_message_to_markdown_text(message: Message) -> str: + """Convert Telegram formatting to Markdown (primarily for Discord).""" + + entity_type_to_markdown = { # only includes simple closing entities + MessageEntityType.BOLD: '**', + MessageEntityType.ITALIC: '*', + MessageEntityType.UNDERLINE: '__', + MessageEntityType.STRIKETHROUGH: '~~', + MessageEntityType.SPOILER: '||', + MessageEntityType.CODE: '`' + } + + text = message.text or message.caption or '' + + if message.entities is None: + return text + + text = list(text) + text_shift = 0 + for entity in message.entities: + # special cases first + if entity.type is MessageEntityType.TEXT_LINK: + text.insert(entity.offset + text_shift, '[') + text.insert(entity.offset + entity.length + text_shift + 1, f']({entity.url})') + text_shift += 2 + if entity.type is MessageEntityType.PRE: + text.insert(entity.offset + text_shift, f'```{entity.language}\n') + text.insert(entity.offset + entity.length + text_shift + 1, f'\n```') + text_shift += 2 + if entity.type is MessageEntityType.BLOCKQUOTE: + text.insert(entity.offset + text_shift, '> ') + text_shift += 1 + + symbol = entity_type_to_markdown.get(entity.type) + if symbol: + previous_symbol = text[entity.offset + text_shift - 2] + if previous_symbol in entity_type_to_markdown.values(): # todo: still fails on 3+ styles in the same chunk + text.insert(entity.offset + text_shift - 1, symbol) + text.insert(entity.offset + entity.length + text_shift, symbol) + else: + text.insert(entity.offset + text_shift, symbol) + text.insert(entity.offset + entity.length + text_shift + 1, symbol) + text_shift += 2 + return ''.join(text) + + def translate_text(text: str, source_lang: str = 'RU', target_lang: str = 'EN'): headers = {'Authorization': f'DeepL-Auth-Key {config.DEEPL_TOKEN}', 'Content-Type': 'application/json'} data = {'text': [text], 'source_lang': source_lang, 'target_lang': target_lang} @@ -47,7 +93,7 @@ def translate_text(text: str, source_lang: str = 'RU', target_lang: str = 'EN'): logging.error(f'{r.status_code=}, {r.reason=}') -def post_to_discord_webhook(url: str, text: str): +def post_to_discord_webhook(url: str, text: str): # todo: attachments support? headers = {'Content-Type': 'application/json'} payload = {'content': text} r = requests.post(url, json=payload, headers=headers) @@ -123,7 +169,7 @@ async def echo(client: Client, message: Message): if message.text: text = message.text.removeprefix('/echo').strip() - entities = correct_message_entity(message.entities, message.text, text) + entities = correct_message_entities(message.entities, message.text, text) if not text: msg = await message.reply('Пустой текст.', quote=False) @@ -134,7 +180,7 @@ async def echo(client: Client, message: Message): return await reply_to.reply(text, entities=entities, quote=should_reply, disable_web_page_preview=True) caption = message.caption.removeprefix('/echo').strip() - entities = correct_message_entity(message.entities, message.caption, caption) + entities = correct_message_entities(message.entities, message.caption, caption) if message.animation: animation = message.animation.file_id @@ -163,8 +209,9 @@ async def echo(client: Client, message: Message): @Client.on_message(filters.channel & filters.chat(config.INCS2CHANNEL)) async def forward_to_discord(_, message: Message): - text = message.text if message.text is not None else message.caption # todo: attachments support? - + text = convert_message_to_markdown_text(message) + logging.info(text) + if text: post_to_discord_webhook(config.DS_WEBHOOK_URL, text) post_to_discord_webhook(config.DS_WEBHOOK_URL_EN, translate_text(text, 'RU', 'EN'))