You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确实现同时处理按钮与消息的ConversationHandler?

解决Telegram机器人ConversationHandler警告及文本输入触发问题

问题根源

你遇到的警告是因为默认per_message=False时,ConversationHandler按聊天会话跟踪状态,而CallbackQuery属于与普通消息不同的更新类型,可能导致状态跟踪不一致。你错误地将处理文本输入的MessageHandler替换成CallbackQueryHandler,而后者仅响应按钮回调,无法处理用户的文本消息,因此username_entered和guest_conv无法触发。

正确解决方案

保留处理文本输入的MessageHandler,同时调整ConversationHandler的结构并设置per_message=True来消除警告,具体步骤如下:

  1. 将start命令处理器加入ConversationHandler的entry_points,而非单独注册
  2. 在states中添加GUEST_OR_USER状态,用于处理用户的按钮选择
  3. 设置per_message=True解决状态跟踪的警告问题
  4. 保留USERNAME和GUEST状态下的MessageHandler,确保文本输入能被正确处理

修改后的完整代码

INTRO, GUEST_OR_USER, USERNAME, GUEST = range(4)


async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    keyboard = [
        [InlineKeyboardButton("YES SIR!", callback_data='user')],
        [InlineKeyboardButton("no", callback_data='guest')],
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    await update.message.reply_text("Are you a Stack Overflow user?", reply_markup=reply_markup)
    return GUEST_OR_USER


async def guest_or_user_choice(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    query = update.callback_query
    await query.answer()
    if query.data == 'user':
        await context.bot.send_message(chat_id=update.effective_chat.id,
                                       text="Cool! What's your username?")
        return USERNAME
    await context.bot.send_message(chat_id=update.effective_chat.id,
                                   text="Oh! Why not?")
    return GUEST


async def username_entered(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await update.message.reply_text("👍")
    return


async def guest_conv(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await update.message.reply_text("That's a shame!")
    return

if __name__ == '__main__':
    application = ApplicationBuilder().token(TOKEN).build()
    # 移除单独的start_handler,改为加入ConversationHandler的entry_points
    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('start', start)],
        states={
            GUEST_OR_USER: [CallbackQueryHandler(guest_or_user_choice)],
            USERNAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, username_entered)],
            GUEST: [MessageHandler(filters.TEXT & ~filters.COMMAND, guest_conv)]
        },
        fallbacks=[],
        allow_reentry=True,
        per_message=True
    )
    application.add_handler(conv_handler)
    application.run_polling()

关键说明

  • CallbackQueryHandler仅用于处理内联按钮的回调交互,不能处理用户的文本输入,文本输入必须使用MessageHandler并搭配filters.TEXT过滤规则
  • per_message=True让ConversationHandler按每条消息跟踪对话状态,避免了不同更新类型(消息/回调)的状态冲突,彻底消除警告

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 02:48:14