Python开发Telegram Bot如何检测回复键盘按钮点击并收集后续消息
问题根因
原有逻辑仅做单次文本等值匹配,没有记录用户交互状态:程序识别到Add variants文本时,只会执行对应分支下的单次逻辑,无法感知用户点击按钮后进入了「持续收集后续消息」的模式,自然无法实现后续消息自动追加的需求。
另外不要使用全局单一的variants列表,多用户同时使用时会出现数据串扰,需要按用户维度隔离存储状态和数据。
可行实现方案
核心是为每个用户维护独立的状态标记和专属的变体列表,通过状态判断当前收到的消息该走哪条处理逻辑:
- 初始化一个字典作为用户数据存储,key为用户chat id,value存储用户当前状态、已收集的变体列表
- 当检测到用户点击
Add variants按钮时,将对应用户的状态切换为「收集变体中」,同时给用户发送操作提示 - 通用消息处理逻辑优先判断用户当前状态:如果处于收集变体状态,就把收到的普通文本追加到该用户的变体列表中;如果用户点击
Back🔙按钮,就把状态切回普通模式,终止收集流程
修改后完整代码
import telebot from telebot import types # 替换为你自己的bot token bot = telebot.TeleBot("YOUR_BOT_TOKEN") # 用户数据存储,结构示例:{chat_id: {"status": "normal/collect_variant", "variants": []}} user_data = {} @bot.message_handler(commands=['start', 'welcome']) def start(message): chat_id = message.chat.id # 初始化新用户数据 if chat_id not in user_data: user_data[chat_id] = {"status": "normal", "variants": []} markup = types.ReplyKeyboardMarkup(resize_keyboard=True) item_1 = types.KeyboardButton('Random🎲') item_2 = types.KeyboardButton('TradingView💸') item_3 = types.KeyboardButton('Weather🌤') item_4 = types.KeyboardButton('Other') item_5 = types.KeyboardButton('Back🔙') markup.add(item_1, item_2, item_3, item_4, item_5) bot.send_message(chat_id, 'Choose', reply_markup=markup) @bot.message_handler(content_types=['text']) def bot_message(message): chat_id = message.chat.id # 初始化未录入的用户数据 if chat_id not in user_data: user_data[chat_id] = {"status": "normal", "variants": []} if message.chat.type == 'private': # 优先判断是否处于收集变体的状态 if user_data[chat_id]["status"] == "collect_variant": # 点击返回按钮则退出收集模式 if message.text == 'Back🔙': user_data[chat_id]["status"] = "normal" # 此处可添加收集完成后的业务逻辑 collected = "\n".join(user_data[chat_id]["variants"]) bot.send_message(chat_id, f"已停止收集,当前收集到的变体:\n{collected}") # 切回Random功能菜单键盘 markup = types.ReplyKeyboardMarkup(resize_keyboard=True) item_1 = types.KeyboardButton('Add variants') item_2 = types.KeyboardButton('Back🔙') markup.add(item_1, item_2) bot.send_message(chat_id, 'Choose', reply_markup=markup) return # 普通消息直接追加到对应用户的变体列表 user_data[chat_id]["variants"].append(message.text) bot.send_message(chat_id, f"已添加变体:{message.text},继续发送可追加,点Back🔙结束收集") return # 普通模式下的菜单逻辑 if message.text == 'Random🎲': # 进入Random菜单时清空之前收集的变体 user_data[chat_id]["variants"] = [] markup = types.ReplyKeyboardMarkup(resize_keyboard=True) item_1 = types.KeyboardButton('Add variants') item_2 = types.KeyboardButton('Back🔙') markup.add(item_1, item_2) bot.send_message(chat_id, 'Choose', reply_markup=markup) elif message.text == 'Add variants': # 切换到收集变体状态 user_data[chat_id]["status"] = "collect_variant" bot.send_message(chat_id, "请依次发送需要添加的变体内容,发送的每条消息都会被自动收录,点Back🔙可结束收集") elif message.text == 'Back🔙': # 返回主菜单 user_data[chat_id]["status"] = "normal" markup = types.ReplyKeyboardMarkup(resize_keyboard=True) item_1 = types.KeyboardButton('Random🎲') item_2 = types.KeyboardButton('TradingView💸') item_3 = types.KeyboardButton('Weather🌤') item_4 = types.KeyboardButton('Other') item_5 = types.KeyboardButton('Back🔙') markup.add(item_1, item_2, item_3, item_4, item_5) bot.send_message(chat_id, 'Choose', reply_markup=markup) if __name__ == "__main__": bot.infinity_polling()
补充说明
- 上述实现为内存级存储,bot重启后所有用户的状态和收集的数据都会清空,如果需要持久化存储,可以把
user_data里的内容同步到数据库或者本地文件 - 如果需要实现更复杂的多步交互,可以基于这个状态判断的逻辑扩展更多状态值,无需依赖额外的第三方状态管理库
内容的提问来源于stack exchange,提问作者xogeh
相关产品推荐
相关产品推荐

