Telegraf如何实现用户触发指定命令后等待并使用其回复内容
Telegraf 实现命令触发后等待用户后续消息的逻辑
Telegraf 是事件驱动的框架,无法在命令的回调函数内直接阻塞等待用户发送的下一条消息,两个独立的消息事件需要通过用户状态标记关联,才能实现「触发命令→等待回复→处理回复内容」的流程。
核心实现代码
const { Telegraf } = require('telegraf') const app = new Telegraf(process.env.BOT_TOKEN); // 单实例场景下用Map做临时状态缓存,多实例场景需替换为Redis等公共存储 const userStateMap = new Map(); app.command('request', async (ctx) => { // 给当前用户打标记,记录其处于request流程的等待输入阶段 userStateMap.set(ctx.from.id, 'waiting_request_input'); await ctx.reply("Hi user, what is your request?"); }); // 全局监听普通文本消息 app.on('text', async (ctx, next) => { const currentState = userStateMap.get(ctx.from.id); // 用户没有等待中的流程,直接走后续中间件 if (!currentState) return next(); if (currentState === 'waiting_request_input') { const user_answer = ctx.message.text; // 处理完后清除状态,避免后续消息被误判 userStateMap.delete(ctx.from.id); // 替换原代码中错误的双引号模板,使用反引号实现变量插值 await ctx.reply(`Your answer was: ${user_answer}`); // 可在这里扩展更多业务逻辑,比如将内容存入数据库、调用外部接口等 return; } // 其他等待流程的逻辑可在此扩展 return next(); }); app.launch();
注意事项
- 上述内存Map缓存仅适用于单实例、小流量的个人场景,多实例部署时必须将状态存储迁移到Redis、数据库等公共存储层,避免不同服务实例的状态不一致导致逻辑错误
- 可以根据需求为等待状态增加超时机制,比如用户触发命令后2分钟内未回复,自动清除状态并发送超时提示,避免状态长期驻留
- 若业务要求用户发送的不是文本,而是图片、文件等内容,可将
app.on('text')替换为对应消息类型的监听,从消息对象的对应字段提取内容即可 - 原示例代码中用于拼接变量的字符串使用了双引号包裹,不会触发模板插值,需替换为反引号
`才能正确解析user_answer变量
小技巧:Telegraf 内置的session中间件本质就是封装了上下文的状态存储能力,不用手写Map的话,可以直接用session存储用户的等待状态,核心逻辑和上述实现完全一致。
内容的提问来源于stack exchange,提问作者kurisukun
相关产品推荐
相关产品推荐

