如何在Python Telegram Bot中提取内联键盘点击信息并完成问卷流程?
问题解决方案
核心问题分析
你的代码存在两个关键问题:
- 回调处理器注册方式错误:未正确使用
@dp.callback_query_handler()装饰器,导致按钮点击事件无法被正常捕获处理。 - 状态流转逻辑错误:点击按钮后仅设置了
activity状态,但未将选择的活动信息存入状态存储,也未直接跳转到下一阶段,而是等待用户发送额外消息,不符合预期流程。
关键修复步骤
- 修正回调处理器注册:直接用
@dp.callback_query_handler()装饰处理器函数,而非将函数作为参数传入。 - 在回调中完成状态更新与流转:点击按钮后立即将选择的活动信息存入状态,直接切换到
full_name状态并发送全名输入提示,无需等待用户额外输入。 - 移除冗余的
activity状态消息处理器:活动信息已通过按钮回调获取,不再需要等待用户发送消息收集该信息。
修正后的完整代码
from aiogram import Bot, Dispatcher, types, executor from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton from aiogram.dispatcher.filters import Command from aiogram.dispatcher.filters.state import StatesGroup, State from aiogram.dispatcher import FSMContext from aiogram.contrib.fsm_storage.memory import MemoryStorage from API_KEY_1196494 import API_KEY # 状态类定义 class reg_state(StatesGroup): full_name = State() phone = State() # 按钮文本与实例 button1_text = 'Activity 1' button2_text = 'Activity 2' button1 = InlineKeyboardButton(text=button1_text, callback_data='activity1') button2 = InlineKeyboardButton(text=button2_text, callback_data='activity2') # 内联键盘 keyboard_inline = InlineKeyboardMarkup().add(button1).add(button2) # 提示文本 enter_your_name_details = 'Enter your full name' enter_your_phone = "Enter your phone number" bot = Bot(API_KEY) storage = MemoryStorage() dp = Dispatcher(bot, storage=storage) # 启动命令:发送活动选择键盘 @dp.message_handler(commands=['start']) async def activity_reg(message: types.Message): user_name_greeting = message.from_user.first_name await message.answer( text=f"{user_name_greeting}, Which activity do you want to choose?", reply_markup=keyboard_inline ) # 内联按钮回调处理器:处理活动选择并流转状态 @dp.callback_query_handler() async def inline_buttons_handler(call: types.CallbackQuery, state: FSMContext): activity_choice = "" match call.data: case 'activity1': activity_choice = button1_text await call.message.answer(f"You chose {button1_text}") case 'activity2': activity_choice = button2_text await call.message.answer(f"You chose {button2_text}") # 将活动选择存入状态 await state.update_data(activity=activity_choice) # 回复回调查询,消除按钮加载状态 await call.answer() # 切换到全名输入状态并发送提示 await reg_state.full_name.set() await call.message.answer(enter_your_name_details) # 收集全名并流转到手机号输入 @dp.message_handler(state=reg_state.full_name) async def grab_full_name(message: types.Message, state: FSMContext): await state.update_data(full_name=message.text) await message.answer(enter_your_phone) await reg_state.phone.set() # 收集手机号并展示汇总信息 @dp.message_handler(state=reg_state.phone) async def grab_phone(message: types.Message, state: FSMContext): await state.update_data(phone=message.text) data_full = await state.get_data() await message.answer( f"Activity: {data_full['activity']}\n" f"Full name: {data_full['full_name']}\n" f"Phone: {data_full['phone']}" ) await state.finish() if __name__ == '__main__': executor.start_polling(dp)
修复说明
- 移除了
reg_state中的activity状态,该信息已通过按钮回调直接获取,无需单独的等待状态。 - 回调处理器添加
state: FSMContext参数,用于将活动选择存入状态存储。 - 点击按钮后直接切换到
full_name状态并发送输入提示,实现自动流转。 - 修正了回调处理器的注册方式,确保按钮点击事件能被正确捕获。
内容的提问来源于stack exchange,提问作者Arthur
相关产品推荐
相关产品推荐

