From 55c70f3508c62e2a4cbe2092e5fbc0e6c7b116df Mon Sep 17 00:00:00 2001 From: teknium1 Date: Sat, 7 Mar 2026 01:23:18 -0800 Subject: [PATCH] fix: strip MarkdownV2 escapes from Telegram plaintext fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When Telegram's MarkdownV2 parser rejects a message, the send() fallback was sending the already-escaped text as plain text. This caused users to see raw backslashes before every special character (periods, dashes, parentheses, etc.) — e.g. 'sentence\.' or '\-\-auto\-approve'. Changes: - Add _strip_mdv2() to reverse MarkdownV2 escaping for clean plaintext - Use stripped text in the send() fallback path instead of raw escaped chunk - Add logging when the MDV2 fallback is triggered for diagnostics - Add logger to telegram.py (was missing) The edit_message() fallback already correctly used the original content; this brings send() in line with that behavior. --- gateway/platforms/telegram.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/gateway/platforms/telegram.py b/gateway/platforms/telegram.py index 757d9d38..9ed47a39 100644 --- a/gateway/platforms/telegram.py +++ b/gateway/platforms/telegram.py @@ -8,10 +8,13 @@ Uses python-telegram-bot library for: """ import asyncio +import logging import os import re from typing import Dict, List, Optional, Any +logger = logging.getLogger(__name__) + try: from telegram import Update, Bot, Message from telegram.ext import ( @@ -73,6 +76,19 @@ def _escape_mdv2(text: str) -> str: return _MDV2_ESCAPE_RE.sub(r'\\\1', text) +def _strip_mdv2(text: str) -> str: + """Strip MarkdownV2 escape backslashes to produce clean plain text. + + Also removes MarkdownV2 bold markers (*text* -> text) so the fallback + doesn't show stray asterisks from header/bold conversion. + """ + # Remove escape backslashes before special characters + cleaned = re.sub(r'\\([_*\[\]()~`>#\+\-=|{}.!\\])', r'\1', text) + # Remove MarkdownV2 bold markers that format_message converted from **bold** + cleaned = re.sub(r'\*([^*]+)\*', r'\1', cleaned) + return cleaned + + class TelegramAdapter(BasePlatformAdapter): """ Telegram bot adapter. @@ -199,9 +215,13 @@ class TelegramAdapter(BasePlatformAdapter): except Exception as md_error: # Markdown parsing failed, try plain text if "parse" in str(md_error).lower() or "markdown" in str(md_error).lower(): + logger.warning("[%s] MarkdownV2 parse failed, falling back to plain text: %s", self.name, md_error) + # Strip MDV2 escape backslashes so the user doesn't + # see raw backslashes littered through the message. + plain_chunk = _strip_mdv2(chunk) msg = await self._bot.send_message( chat_id=int(chat_id), - text=chunk, + text=plain_chunk, parse_mode=None, # Plain text reply_to_message_id=int(reply_to) if reply_to and i == 0 else None, message_thread_id=int(thread_id) if thread_id else None,