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

Python-Telegram-Bot点击InlineKeyboardButton后如何等待用户输入

解决方案

问题根因

  • 会话处理器(ConversationHandler)的入口配置错误,未覆盖Inline按钮触发的场景,且原有回调处理函数吞掉了jkpMenu返回的状态值,导致状态跳转失败
  • jokenpo函数误用while循环,python-telegram-bot是事件驱动框架,每一次用户输入只会触发一次函数调用,死循环会导致程序直接跑完逻辑不会等待用户输入
  • 获取用户输入的对象错误:后续用户发送的是普通文本消息,不再是回调请求,不能从update.callback_query拿内容
  • 全局变量存储游戏数据会导致多用户使用时数据冲突,建议改用上下文存储

修正步骤

1. 修改回调处理函数,透传状态返回值

原有comQuery返回类型为None,会吞掉jkpMenu返回的状态,需要修改为返回状态值:

def comQuery(update: Update, context: CallbackContext) -> int:
    query = update.callback_query
    query.answer()
    if query.data == 'clog':        
        changelog(update, context)
        return ConversationHandler.END # 其他非游戏功能直接结束会话
    if query.data == 'info':        
        myInfo(update, context)
        return ConversationHandler.END
    if query.data == 'jokenpo':     
        return jkpMenu(update, context) # 透传游戏菜单返回的状态值

2. 修正jokenpo函数逻辑,适配事件驱动模式

删掉while循环,每次处理完用户输入后返回JKP状态等待下一次输入,同时调整用户输入获取方式,改用上下文存储游戏数据:

# Jokenpo 1: 问候与规则说明
def jkpMenu(update: Update, context: CallbackContext) -> int:
    # 初始化游戏数据存入user_data,避免多用户冲突
    context.user_data['varScore'] = 0
    context.user_data['varLives'] = 5
    context.user_data['varTie'] = 0
    update.callback_query.message.reply_text('Jokenpo mode. Please type "rock", "paper" or "scissors" to continue')
    return JKP

# Jokenpo 2: 游戏逻辑处理
def jokenpo(update: Update, context: CallbackContext) -> int:
    msgUser = update.message.text.lower() # 普通消息从update.message拿内容
    game_data = context.user_data
    computer = random.choice(("rock", "paper", "scissors"))
    
    if (msgUser== "rock" and computer == "paper") or (msgUser== "paper" and computer == "scissors") or (msgUser=="scissors" and computer == "rock"):
        update.message.reply_text(f"Computer chooses <i>{computer}</i>. <b>You lose!</b>", parse_mode ='HTML')
        game_data['varLives'] -= 1
    elif (msgUser== "rock" and computer == "scissors") or (msgUser == "paper" and computer == "rock") or (msgUser == "scissors" and computer == "paper"):
        update.message.reply_text(f"Computer chooses <i>{computer}</i>. <b>You win!</b>", parse_mode ='HTML')
        game_data['varScore'] +=1
    elif (msgUser== computer):
        update.message.reply_text(f"We both chose <i>{computer}</i>. <b>It's a tie!</b>", parse_mode ='HTML')
        game_data['varTie'] +=1
    elif (msgUser== "status"):
        update.message.reply_text(f"Your current score: {game_data['varScore']} points.\nYou have {game_data['varLives']} lives left.\nWe tied {game_data['varTie']} times.")
        return JKP # 查询状态后继续等待用户输入
    
    # 结束判断
    if (msgUser== "sair") or (game_data['varLives'] == 0):
        update.message.reply_text(f"Game finished. You made <b>{game_data['varScore']}</b> points.\nWe tied {game_data['varTie']} times.\n", parse_mode ='HTML')
        # 清空用户数据
        context.user_data.clear()
        return ConversationHandler.END
    
    update.message.reply_text('Please choose: paper, rock or scissors? ')
    return JKP # 返回状态继续等待下一次输入

3. 修正ConversationHandler配置

把入口调整为包含Inline回调触发的路径:

def main():
    # 其他处理器注册...
    convHandler = ConversationHandler(
        entry_points=[
            CommandHandler('jokenpo', jkpMenu), # 保留原命令触发入口
            CallbackQueryHandler(comQuery) # 新增Inline按钮回调作为入口
        ],
        fallbacks=[],
        states = {
            JKP: [MessageHandler(Filters.text & ~Filters.command, jokenpo)] # 过滤掉命令,只处理普通文本
        })
    dp.add_handler(convHandler)
    # 其他启动逻辑...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 20:18:03