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

如何识别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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:40:43