From af34cdd5d24ed4580135d12dc704659eaf91d995 Mon Sep 17 00:00:00 2001 From: Raven95676 Date: Tue, 27 May 2025 20:12:20 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix(telegram):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E9=95=BF=E6=B6=88=E6=81=AF=E5=88=86=E6=AE=B5=E5=8F=91=E9=80=81?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E6=B6=88=E6=81=AF=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../platform/sources/telegram/tg_event.py | 89 ++++++++++++++----- 1 file changed, 65 insertions(+), 24 deletions(-) diff --git a/astrbot/core/platform/sources/telegram/tg_event.py b/astrbot/core/platform/sources/telegram/tg_event.py index 4b9fd0ad..4573d902 100644 --- a/astrbot/core/platform/sources/telegram/tg_event.py +++ b/astrbot/core/platform/sources/telegram/tg_event.py @@ -1,4 +1,5 @@ import os +import re import asyncio import telegramify_markdown from astrbot.api.event import AstrMessageEvent, MessageChain @@ -18,6 +19,16 @@ from astrbot.core.utils.astrbot_path import get_astrbot_data_path class TelegramPlatformEvent(AstrMessageEvent): + # Telegram 的最大消息长度限制 + MAX_MESSAGE_LENGTH = 4096 + + SPLIT_PATTERNS = { + "paragraph": re.compile(r"\n\n"), + "line": re.compile(r"\n"), + "sentence": re.compile(r"[.!?。!?]"), + "word": re.compile(r"\s"), + } + def __init__( self, message_str: str, @@ -29,8 +40,34 @@ class TelegramPlatformEvent(AstrMessageEvent): super().__init__(message_str, message_obj, platform_meta, session_id) self.client = client - @staticmethod - async def send_with_client(client: ExtBot, message: MessageChain, user_name: str): + def _split_message(self, text: str) -> list[str]: + if len(text) <= self.MAX_MESSAGE_LENGTH: + return [text] + + chunks = [] + while text: + if len(text) <= self.MAX_MESSAGE_LENGTH: + chunks.append(text) + break + + split_point = self.MAX_MESSAGE_LENGTH + segment = text[: self.MAX_MESSAGE_LENGTH] + + for _, pattern in self.SPLIT_PATTERNS.items(): + matches = list(pattern.finditer(segment)) + if matches: + last_match = matches[-1] + split_point = last_match.end() + break + + chunks.append(text[:split_point]) + text = text[split_point:].lstrip() + + return chunks + + async def send_with_client( + self, client: ExtBot, message: MessageChain, user_name: str + ): image_path = None has_reply = False @@ -61,17 +98,20 @@ class TelegramPlatformEvent(AstrMessageEvent): if at_user_id and not at_flag: i.text = f"@{at_user_id} " + i.text at_flag = True - text = i.text - try: - text = telegramify_markdown.markdownify( - i.text, max_line_length=None, normalize_whitespace=False - ) - except Exception as e: - logger.warning( - f"MarkdownV2 conversion failed: {e}. Using plain text instead." - ) - return - await client.send_message(text=text, parse_mode="MarkdownV2", **payload) + chunks = self._split_message(i.text) + for chunk in chunks: + try: + md_text = telegramify_markdown.markdownify( + chunk, max_line_length=None, normalize_whitespace=False + ) + await client.send_message( + text=md_text, parse_mode="MarkdownV2", **payload + ) + except Exception as e: + logger.warning( + f"MarkdownV2 conversion failed: {e}. Using plain text instead." + ) + await client.send_message(text=chunk, **payload) elif isinstance(i, Image): image_path = await i.convert_to_file_path() await client.send_photo(photo=image_path, **payload) @@ -147,17 +187,7 @@ class TelegramPlatformEvent(AstrMessageEvent): continue # Plain - if not message_id: - try: - msg = await self.client.send_message(text=delta, **payload) - current_content = delta - except Exception as e: - logger.warning(f"发送消息失败(streaming): {e!s}") - message_id = msg.message_id - last_edit_time = ( - asyncio.get_event_loop().time() - ) # 记录初始消息发送时间 - else: + if message_id and len(delta) <= self.MAX_MESSAGE_LENGTH: current_time = asyncio.get_event_loop().time() time_since_last_edit = current_time - last_edit_time @@ -176,6 +206,17 @@ class TelegramPlatformEvent(AstrMessageEvent): last_edit_time = ( asyncio.get_event_loop().time() ) # 更新上次编辑的时间 + else: + try: + msg = await self.client.send_message(text=delta, **payload) + current_content = delta + delta = "" + except Exception as e: + logger.warning(f"发送消息失败(streaming): {e!s}") + message_id = msg.message_id + last_edit_time = ( + asyncio.get_event_loop().time() + ) # 记录初始消息发送时间 try: if delta and current_content != delta: From 3deb6d3ab3044a635f77494377008efe555c54bb Mon Sep 17 00:00:00 2001 From: Raven95676 Date: Tue, 27 May 2025 20:49:05 +0800 Subject: [PATCH 2/3] fix: clean code --- astrbot/core/platform/sources/telegram/tg_event.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/astrbot/core/platform/sources/telegram/tg_event.py b/astrbot/core/platform/sources/telegram/tg_event.py index 4573d902..550d8dd6 100644 --- a/astrbot/core/platform/sources/telegram/tg_event.py +++ b/astrbot/core/platform/sources/telegram/tg_event.py @@ -54,8 +54,7 @@ class TelegramPlatformEvent(AstrMessageEvent): segment = text[: self.MAX_MESSAGE_LENGTH] for _, pattern in self.SPLIT_PATTERNS.items(): - matches = list(pattern.finditer(segment)) - if matches: + if matches := list(pattern.finditer(segment)): last_match = matches[-1] split_point = last_match.end() break @@ -96,7 +95,7 @@ class TelegramPlatformEvent(AstrMessageEvent): if isinstance(i, Plain): if at_user_id and not at_flag: - i.text = f"@{at_user_id} " + i.text + i.text = f"@{at_user_id} {i.text}" at_flag = True chunks = self._split_message(i.text) for chunk in chunks: @@ -109,7 +108,7 @@ class TelegramPlatformEvent(AstrMessageEvent): ) except Exception as e: logger.warning( - f"MarkdownV2 conversion failed: {e}. Using plain text instead." + f"MarkdownV2 send failed: {e}. Using plain text instead." ) await client.send_message(text=chunk, **payload) elif isinstance(i, Image): From a1cd5c53a916a5091827b18edb7081defb738810 Mon Sep 17 00:00:00 2001 From: Soulter <37870767+Soulter@users.noreply.github.com> Date: Tue, 27 May 2025 23:38:35 +0800 Subject: [PATCH 3/3] chore: add comments --- astrbot/core/platform/sources/telegram/tg_event.py | 1 + 1 file changed, 1 insertion(+) diff --git a/astrbot/core/platform/sources/telegram/tg_event.py b/astrbot/core/platform/sources/telegram/tg_event.py index 550d8dd6..30be7d4f 100644 --- a/astrbot/core/platform/sources/telegram/tg_event.py +++ b/astrbot/core/platform/sources/telegram/tg_event.py @@ -206,6 +206,7 @@ class TelegramPlatformEvent(AstrMessageEvent): asyncio.get_event_loop().time() ) # 更新上次编辑的时间 else: + # delta 长度一般不会大于 4096,因此这里直接发送 try: msg = await self.client.send_message(text=delta, **payload) current_content = delta