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

Telegraf.js开发Telegram Bot:Wizard Scene需注释bot.on('text')才能工作

Telegraf.js全局text处理器与Wizard Scene冲突解决方案

问题根源

Telegraf的中间件按注册顺序执行,全局bot.on('text')会拦截所有文本消息,且你的代码里没有调用next()传递控制权,导致Wizard Scene的步骤处理器永远无法接收到消息,自然无法正常运行。

解决方案

方案1:全局处理器中判断场景状态,按需传递控制权

修改全局text处理器,当用户处于Wizard Scene中时,调用next()把消息交给场景处理器;否则执行全局逻辑。

bot.on('text', async (ctx, next) => {
    try {
        // 检查当前是否有运行中的场景
        if (!ctx.scene.current) {
            switch (ctx.message.text) {
                // 你的原有业务逻辑
                case '/start':
                    await ctx.reply('全局Start响应');
                    break;
                default:
                    await ctx.reply('全局默认文本响应');
                    break;
            }
        } else {
            // 处于场景中,转交控制权给场景处理器
            await next();
        }
    } catch (e) {
        console.error(e);
        // 即使出错,也建议调用next避免阻塞后续中间件
        await next();
    }
})

方案2:调整中间件注册顺序,让场景优先处理

把Wizard Scene的中间件注册放在全局text处理器之前,这样场景的处理器会先拦截文本消息,只有场景未处理的消息才会流到全局处理器。

// 先注册会话和场景中间件
bot.use(session());
const myWizard = new WizardScene('my-wizard', stepHandler, /* 其他步骤 */);
bot.use(myWizard.middleware());

// 再注册全局text处理器
bot.on('text', async (ctx) => {
    try {
        switch (ctx.message.text) {
            // 你的原有逻辑
        }
    } catch (e) {
        console.error(e);
    }
})

方案3:用bot.hears()替代全局bot.on('text')(推荐)

放弃拦截所有文本的全局处理器,改用bot.hears()针对特定文本/命令单独处理,从根源上避免冲突,代码也更清晰。

// 替代原来的switch逻辑
bot.hears('/start', async (ctx) => {
    // 处理/start命令
    await ctx.reply('全局Start响应');
});

bot.hears('帮助', async (ctx) => {
    // 处理"帮助"文本
    await ctx.reply('全局帮助内容');
});

// 其他需要监听的特定文本

注意事项

  • 所有Telegraf中间件如果需要后续逻辑执行,必须调用next();
  • 场景运行时,ctx.scene.current会返回当前场景的ID,可用于判断用户是否在场景中;
  • 推荐优先使用方案3,既避免冲突,又符合Telegraf的最佳实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 03:24:38