如何正确实现同时处理按钮与消息的ConversationHandler?
解决Telegram机器人ConversationHandler警告及文本输入触发问题
问题根源
你遇到的警告是因为默认per_message=False时,ConversationHandler按聊天会话跟踪状态,而CallbackQuery属于与普通消息不同的更新类型,可能导致状态跟踪不一致。你错误地将处理文本输入的MessageHandler替换成CallbackQueryHandler,而后者仅响应按钮回调,无法处理用户的文本消息,因此username_entered和guest_conv无法触发。
正确解决方案
保留处理文本输入的MessageHandler,同时调整ConversationHandler的结构并设置per_message=True来消除警告,具体步骤如下:
- 将
start命令处理器加入ConversationHandler的entry_points,而非单独注册 - 在
states中添加GUEST_OR_USER状态,用于处理用户的按钮选择 - 设置
per_message=True解决状态跟踪的警告问题 - 保留
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
相关产品推荐
相关产品推荐

