From ea7139fdf652530ef3e61403761557fae0aee8b2 Mon Sep 17 00:00:00 2001 From: Michael Ansel Date: Fri, 14 Nov 2025 16:17:59 +0000 Subject: [PATCH] fix: escape markdown special characters in /ls command Filenames containing Telegram markdown special characters (_, *, [, ], etc.) were breaking message rendering with "Can't parse entities" errors. Changes: - Add _escape_markdown() helper function to escape special chars - Apply escaping to all filenames in both /ls command and callback handler - Ensures filenames display correctly regardless of special characters Fixes Telegram markdown parsing errors when listing files with special characters in their names. --- src/bot/handlers/callback.py | 18 +++++++++++++++--- src/bot/handlers/command.py | 18 +++++++++++++++--- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/bot/handlers/callback.py b/src/bot/handlers/callback.py index b82ad0a..e09bb5f 100644 --- a/src/bot/handlers/callback.py +++ b/src/bot/handlers/callback.py @@ -613,15 +613,18 @@ async def _handle_ls_action(query, context: ContextTypes.DEFAULT_TYPE) -> None: if item.name.startswith("."): continue + # Escape markdown special characters in filenames + safe_name = _escape_markdown(item.name) + if item.is_dir(): - directories.append(f"📁 {item.name}/") + directories.append(f"📁 {safe_name}/") else: try: size = item.stat().st_size size_str = _format_file_size(size) - files.append(f"📄 {item.name} ({size_str})") + files.append(f"📄 {safe_name} ({size_str})") except OSError: - files.append(f"📄 {item.name}") + files.append(f"📄 {safe_name}") items = directories + files relative_path = current_dir.relative_to(settings.approved_directory) @@ -1151,3 +1154,12 @@ def _format_file_size(size: int) -> str: return f"{size:.1f}{unit}" if unit != "B" else f"{size}B" size /= 1024 return f"{size:.1f}TB" + + +def _escape_markdown(text: str) -> str: + """Escape special markdown characters in text for Telegram.""" + # Escape characters that have special meaning in Telegram Markdown + special_chars = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'] + for char in special_chars: + text = text.replace(char, f'\\{char}') + return text diff --git a/src/bot/handlers/command.py b/src/bot/handlers/command.py index 0c0b48f..b52cbc1 100644 --- a/src/bot/handlers/command.py +++ b/src/bot/handlers/command.py @@ -314,16 +314,19 @@ async def list_files(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None if item.name.startswith("."): continue + # Escape markdown special characters in filenames + safe_name = _escape_markdown(item.name) + if item.is_dir(): - directories.append(f"📁 {item.name}/") + directories.append(f"📁 {safe_name}/") else: # Get file size try: size = item.stat().st_size size_str = _format_file_size(size) - files.append(f"📄 {item.name} ({size_str})") + files.append(f"📄 {safe_name} ({size_str})") except OSError: - files.append(f"📄 {item.name}") + files.append(f"📄 {safe_name}") # Combine directories first, then files items = directories + files @@ -927,3 +930,12 @@ def _format_file_size(size: int) -> str: return f"{size:.1f}{unit}" if unit != "B" else f"{size}B" size /= 1024 return f"{size:.1f}TB" + + +def _escape_markdown(text: str) -> str: + """Escape special markdown characters in text for Telegram.""" + # Escape characters that have special meaning in Telegram Markdown + special_chars = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'] + for char in special_chars: + text = text.replace(char, f'\\{char}') + return text