You need to enable JavaScript to run this app. 如何实现点击按钮不发消息的Telegram Bot两级菜单返回功能
优惠活动
大模型
产品
解决方案
定价
更多

如何实现点击按钮不发消息的Telegram Bot两级菜单返回功能

代码核心问题定位
  • 错误1:ReplyKeyboardMarkup下的KeyboardButton不支持callback_data参数,这是内联键盘InlineKeyboardButton的专属属性,你给Reply按钮加的回调参数完全不生效,点击按钮根本不会触发callback_query_handler,只会触发普通文本消息处理逻辑。
  • 错误2:Reply键盘的切换逻辑不需要走回调链路,要实现“点击不发额外消息”的效果,直接编辑初始带菜单那条消息的reply_markup即可,不需要新发消息。
修复方案
  1. 移除所有Reply按钮上的无效callback_data字段,通过匹配按钮文本作为触发条件处理点击逻辑。
  2. 存下初始启动时发送的固定消息ID,切换菜单时直接调用edit_message_reply_markup修改这条消息的键盘,全程不会产生新的聊天消息。
修复后可运行代码
from telegram import Bot, Dispatcher, types, ReplyKeyboardMarkup, KeyboardButton
from telegram.ext import MessageHandler, Filters
import yaml

async def telegram():
    with open("madata") as f3:
        info = yaml.safe_load(f3)
        token = mytoken
    bot = Bot(token=token)
    dp = Dispatcher(bot)

    # 定义两级Reply菜单,移除无效的callback_data
    small_menu = ReplyKeyboardMarkup(
        keyboard=[[KeyboardButton(text="show functions")]],
        resize_keyboard=True
    )
    full_menu = ReplyKeyboardMarkup(
        keyboard=[
            [KeyboardButton(text="function 1")],
            [KeyboardButton(text="function 2")],
            [KeyboardButton(text="back to menu")]
        ],
        resize_keyboard=True
    )

    # 启动命令处理
    @dp.message_handler(commands=['start'])
    async def greeting(message: types.Message):
        chat_id = message.chat.id
        # 发送初始带短菜单的固定消息,存下消息ID供后续编辑使用
        fixed_msg = await bot.send_message(
            chat_id=chat_id,
            text="hello friend",
            parse_mode="Markdown",
            reply_markup=small_menu
        )
        # 按用户ID存储固定消息ID,避免多用户干扰
        bot.bot_data.setdefault("msg_map", {})[chat_id] = fixed_msg.message_id

    # 统一处理Reply按钮的点击逻辑
    @dp.message_handler(Filters.text & ~Filters.command)
    async def handle_reply_click(message: types.Message):
        chat_id = message.chat.id
        target_msg_id = bot.bot_data["msg_map"][chat_id]
        click_text = message.text

        # 菜单切换逻辑:直接编辑原有消息的键盘,不发送新消息
        if click_text == "show functions":
            await bot.edit_message_reply_markup(
                chat_id=chat_id,
                message_id=target_msg_id,
                reply_markup=full_menu
            )
        elif click_text == "back to menu":
            await bot.edit_message_reply_markup(
                chat_id=chat_id,
                message_id=target_msg_id,
                reply_markup=small_menu
            )
        # 在此处补充各功能按钮的业务逻辑
        elif click_text == "function 1":
            pass
        elif click_text == "function 2":
            pass

    dp.run_polling()
注意事项
  • 不要混淆Reply键盘和内联键盘的属性规则,Reply键盘的点击行为本质是用户发送了对应文本的消息,必须通过文本匹配做逻辑处理。
  • edit_message_reply_markup只会修改原有消息的按钮样式/类型,不会产生新的消息气泡,完全满足“点击不发额外消息”的要求。
  • 固定消息ID要按用户维度存储,避免多用户同时使用时出现编辑错消息的问题。

注:上述代码兼容python-telegram-bot 20+异步版本,低版本同步SDK仅需移除async/await关键字,调整对应方法的调用方式即可。

内容的提问来源于stack exchange,提问作者Aleksey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.10 00:36:04