fix telegram streaming message boundaries

This commit is contained in:
Xubin Ren
2026-03-26 02:35:12 +00:00
parent 813de554c9
commit 33abe915e7
4 changed files with 106 additions and 6 deletions
+24 -3
View File
@@ -12,7 +12,7 @@ from typing import Any, Literal
from loguru import logger
from pydantic import Field
from telegram import BotCommand, ReactionTypeEmoji, ReplyParameters, Update
from telegram.error import TimedOut
from telegram.error import BadRequest, TimedOut
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
from telegram.request import HTTPXRequest
@@ -163,6 +163,7 @@ class _StreamBuf:
text: str = ""
message_id: int | None = None
last_edit: float = 0.0
stream_id: str | None = None
class TelegramConfig(Base):
@@ -478,17 +479,24 @@ class TelegramChannel(BaseChannel):
logger.error("Error sending Telegram message: {}", e2)
raise
@staticmethod
def _is_not_modified_error(exc: Exception) -> bool:
return isinstance(exc, BadRequest) and "message is not modified" in str(exc).lower()
async def send_delta(self, chat_id: str, delta: str, metadata: dict[str, Any] | None = None) -> None:
"""Progressive message editing: send on first delta, edit on subsequent ones."""
if not self._app:
return
meta = metadata or {}
int_chat_id = int(chat_id)
stream_id = meta.get("_stream_id")
if meta.get("_stream_end"):
buf = self._stream_bufs.get(chat_id)
if not buf or not buf.message_id or not buf.text:
return
if stream_id is not None and buf.stream_id is not None and buf.stream_id != stream_id:
return
self._stop_typing(chat_id)
try:
html = _markdown_to_telegram_html(buf.text)
@@ -498,6 +506,10 @@ class TelegramChannel(BaseChannel):
text=html, parse_mode="HTML",
)
except Exception as e:
if self._is_not_modified_error(e):
logger.debug("Final stream edit already applied for {}", chat_id)
self._stream_bufs.pop(chat_id, None)
return
logger.debug("Final stream edit failed (HTML), trying plain: {}", e)
try:
await self._call_with_retry(
@@ -506,15 +518,21 @@ class TelegramChannel(BaseChannel):
text=buf.text,
)
except Exception as e2:
if self._is_not_modified_error(e2):
logger.debug("Final stream plain edit already applied for {}", chat_id)
self._stream_bufs.pop(chat_id, None)
return
logger.warning("Final stream edit failed: {}", e2)
raise # Let ChannelManager handle retry
self._stream_bufs.pop(chat_id, None)
return
buf = self._stream_bufs.get(chat_id)
if buf is None:
buf = _StreamBuf()
if buf is None or (stream_id is not None and buf.stream_id is not None and buf.stream_id != stream_id):
buf = _StreamBuf(stream_id=stream_id)
self._stream_bufs[chat_id] = buf
elif buf.stream_id is None:
buf.stream_id = stream_id
buf.text += delta
if not buf.text.strip():
@@ -541,6 +559,9 @@ class TelegramChannel(BaseChannel):
)
buf.last_edit = now
except Exception as e:
if self._is_not_modified_error(e):
buf.last_edit = now
return
logger.warning("Stream edit failed: {}", e)
raise # Let ChannelManager handle retry