From 30544dce05f54fffb95c5bc5d4abf33589b8d15f Mon Sep 17 00:00:00 2001 From: twentyOne2x Date: Tue, 23 Jun 2026 11:56:06 +0200 Subject: [PATCH] Route Telegram smart research commands (#16) --- telegram/bot.py | 8 ++++++++ telegram/http_chat_proxy.py | 16 ++++++++++++++++ tests/test_telegram_leo_x402_bridge.py | 14 ++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/telegram/bot.py b/telegram/bot.py index 09c8711..5fc7d09 100644 --- a/telegram/bot.py +++ b/telegram/bot.py @@ -56,6 +56,7 @@ from http_chat_proxy import ( build_smart_research_proxy_payload, extract_smart_research_goal, post_chat_proxy, + smart_research_command_names, ) # ─── Config ───────────────────────────────────────────────────────────── @@ -982,6 +983,11 @@ async def handle_reply_to_bot(update: Update, context: ContextTypes.DEFAULT_TYPE await handle_tagged(update, context) +async def handle_smart_research_command(update: Update, context: ContextTypes.DEFAULT_TYPE): + """Route configured slash commands into the smart-research proxy path.""" + await handle_tagged(update, context) + + async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE): """Handle ALL incoming group messages — buffer for triage.""" if not update.message or not update.message.text: @@ -2236,6 +2242,8 @@ def main(): # Command handlers app.add_handler(CommandHandler("start", start_command)) app.add_handler(CommandHandler("stats", stats_command)) + for command in smart_research_command_names(AGENT_SMART_RESEARCH_COMMAND_PREFIXES): + app.add_handler(CommandHandler(command, handle_smart_research_command)) # Tag handler — messages mentioning the bot # python-telegram-bot filters.Mention doesn't work for bot mentions in groups diff --git a/telegram/http_chat_proxy.py b/telegram/http_chat_proxy.py index 2d90d33..829da1a 100644 --- a/telegram/http_chat_proxy.py +++ b/telegram/http_chat_proxy.py @@ -6,6 +6,22 @@ import re from typing import Any DEFAULT_SMART_RESEARCH_COMMAND_PREFIXES = ("/smart_research", "/paid_research") +_TELEGRAM_COMMAND_NAME_RE = re.compile(r"^[A-Za-z0-9_]+$") + + +def smart_research_command_names( + command_prefixes: tuple[str, ...] | list[str] = DEFAULT_SMART_RESEARCH_COMMAND_PREFIXES, +) -> list[str]: + """Return Telegram command names registered for smart-research routing.""" + command_names: set[str] = set() + for prefix in command_prefixes: + command = str(prefix).strip() + if not command.startswith("/"): + continue + command = command[1:].split("@", 1)[0].strip() + if command and _TELEGRAM_COMMAND_NAME_RE.match(command): + command_names.add(command) + return sorted(command_names) def build_chat_proxy_payload( diff --git a/tests/test_telegram_leo_x402_bridge.py b/tests/test_telegram_leo_x402_bridge.py index 380f6ca..97e39d9 100644 --- a/tests/test_telegram_leo_x402_bridge.py +++ b/tests/test_telegram_leo_x402_bridge.py @@ -15,6 +15,7 @@ from http_chat_proxy import ( # noqa: E402 build_smart_research_proxy_payload, extract_chat_proxy_reply, extract_smart_research_goal, + smart_research_command_names, ) @@ -118,6 +119,19 @@ def test_extract_smart_research_goal(message, expected): assert extract_smart_research_goal(message) == expected +def test_smart_research_command_names_are_safe_for_telegram_handlers(): + assert smart_research_command_names( + [ + "/smart_research", + "/paid_research", + "/paid_research@lipleowallet0622183538bot", + "not_a_command", + "/bad-name", + "/", + ] + ) == ["paid_research", "smart_research"] + + @pytest.mark.parametrize( ("payload", "expected"), [