如何识别Telegram Bot中被点击的动态InlineKeyboardButton?
解决方案
问题出在你给所有日期按钮的callback_data都设成了同一个SET_DRAWDATE,导致回调函数无法区分具体点击的是哪个按钮。核心解决思路是给每个按钮的回调数据添加唯一标识,再在回调函数中解析出这个标识。
1. 修改动态键盘生成逻辑
把每个按钮对应的日期(或索引)拼接到callback_data中,用下划线做分隔符(避免和日期格式冲突):
def drawdate_keyboard(drawdates): keyboard = [] for idx, drawdate in enumerate(drawdates): # 将SET_DRAWDATE与日期拼接,生成唯一回调数据 callback_data = f"{SET_DRAWDATE}_{drawdate}" keyboard.append([InlineKeyboardButton(drawdate, callback_data=callback_data)]) keyboard.append([InlineKeyboardButton('Cancel', callback_data=str(CANCEL))]) return InlineKeyboardMarkup(keyboard)
如果担心日期中包含下划线,也可以用索引代替日期:
def drawdate_keyboard(drawdates): keyboard = [] for idx, drawdate in enumerate(drawdates): callback_data = f"{SET_DRAWDATE}_{idx}" keyboard.append([InlineKeyboardButton(drawdate, callback_data=callback_data)]) keyboard.append([InlineKeyboardButton('Cancel', callback_data=str(CANCEL))]) return InlineKeyboardMarkup(keyboard)
2. 更新对话处理器的匹配规则
调整CallbackQueryHandler的正则匹配规则,使其能识别带后缀的回调数据:
conv_handler = ConversationHandler( entry_points=[CommandHandler("start", start)], states={ # ... 其他状态保持不变 DRAWDATE: [ # 匹配以SET_DRAWDATE_开头的所有回调数据 CallbackQueryHandler(set_drawdate, pattern=r"^" + str(SET_DRAWDATE) + r"_.*$"), CallbackQueryHandler(start_over, pattern=r"^" + str(CANCEL) + r"$"), ], }, fallbacks=[CommandHandler("start", start)], )
3. 在回调函数中解析点击信息
根据拼接的回调数据,拆分出用户选择的日期或索引:
若用日期拼接:
def set_drawdate(update: Update, context) -> int: query = update.callback_query query.answer() # 拆分回调数据,获取日期部分(只拆一次,避免日期含下划线) callback_parts = query.data.split("_", 1) if len(callback_parts) == 2: selected_drawdate = callback_parts[1] # 这里可添加你的业务逻辑,比如保存选择的日期 print(f"用户选择的日期:{selected_drawdate}") return DRAWDATE # 或返回对应对话状态
若用索引拼接:
需要先把drawdates列表存入用户会话数据(比如在生成键盘的前置函数中):
def get_drawdates(update: Update, context) -> int: # 假设这里获取到drawdates列表 drawdates = ["2024-05-01", "2024-05-08", "2024-05-15"] # 存入用户会话,供后续回调使用 context.user_data["drawdates"] = drawdates keyboard = drawdate_keyboard(drawdates) update.callback_query.edit_message_text("请选择日期:", reply_markup=keyboard) return DRAWDATE
然后在回调函数中解析索引并获取日期:
def set_drawdate(update: Update, context) -> int: query = update.callback_query query.answer() callback_parts = query.data.split("_", 1) if len(callback_parts) == 2: try: selected_idx = int(callback_parts[1]) drawdates = context.user_data.get("drawdates", []) if 0 <= selected_idx < len(drawdates): selected_drawdate = drawdates[selected_idx] print(f"用户选择的日期:{selected_drawdate}") except ValueError: # 处理索引转换失败的异常 pass return DRAWDATE
内容的提问来源于stack exchange,提问作者Michael ten Den
相关产品推荐
相关产品推荐

