Slack Bot接收app_mention事件后连续重复响应问题
Slack 机器人 Chochon app_mention 事件重复响应修复
问题描述
- 运行环境:Slack 平台 Socket Mode 模式开发的机器人「Chochon」
- 异常现象:机器人接收到
app_mention(用户@机器人)事件时,会连续多次发送重复响应消息,没有按预期仅发送1条后等待下一次@触发 - 异常效果参考:

问题根因
- 未按Slack Socket Mode规范确认事件:所有事件推送到客户端后,若3秒内未收到客户端的ack确认响应,Slack会判定推送失败,按重试策略重复投递同一条事件,导致回调被多次触发
- 缺少自消息过滤逻辑:未判断事件是否为机器人自身发出,极端场景下会出现自触发循环
- 异步方法未加await:
chat.postMessage为异步方法,未加await时可能出现时序异常
修复方案
核心修改点
- 事件回调增加
ack参数,收到事件第一时间调用await ack()确认接收,阻断Slack重试逻辑 - 增加bot消息判断,跳过所有机器人账号发出的消息触发的事件
- 给所有异步API调用增加
await,保证执行时序
修正后的事件监听代码
socketModeClient.on('app_mention', async ({ event, ack }) => { try { // 立刻确认事件接收,阻止Slack重复推送 await ack(); // 过滤机器人自身发送的消息,避免自触发循环 if (event.bot_id) return; console.log(event); let userBox = await Chochon.users.info({ user: event.user }); let userProfile = userBox.user.profile; console.log(cli.green(`Event received : [ ${event.type} ] from [ ${userProfile.display_name} ]`)); // 发送响应消息 await Chochon.chat.postMessage({ channel: event.channel, text: `Hello <@${event.user}>, I'm Chochon!, I'm a bot that can help you to manage your team.` }); } catch (error) { console.error(error); } });
修正后完整项目代码
// Dependencies : const dotenv = require('dotenv').config(); const path = require('path'); const cli = require('cli-color'); // Web client [CLI] const { WebClient } = require('@slack/web-api'); const Chochon = new WebClient(process.env.SLACK_BOT_TOKEN.trim()); // Socket IO const { SocketModeClient } = require('@slack/socket-mode'); const appToken = process.env.SLACK_APP_TOKEN; const socketModeClient = new SocketModeClient({ appToken }); socketModeClient.start(); // Internal functions //const eventManager = require(path.resolve(__dirname, './utils/events/manager')); socketModeClient.on('app_mention', async ({ event, ack }) => { try { await ack(); if (event.bot_id) return; console.log(event); let userBox = await Chochon.users.info({ user: event.user }); let userProfile = userBox.user.profile; console.log(cli.green(`Event received : [ ${event.type} ] from [ ${userProfile.display_name} ]`)); // Respond to the event await Chochon.chat.postMessage({ channel: event.channel, text: `Hello <@${event.user}>, I'm Chochon!, I'm a bot that can help you to manage your team.` }); } catch (error) { console.error(error); } }); socketModeClient.on('slash_commands', async ({ body, ack }) => { if (body.command === "/ping") { console.log(cli.green(`Event received : [ ${body.command} ]`)); await ack({"text": "I got it, pong!"}); } });
补充说明
原有代码里的slash_commands回调已经正确实现了ack()调用,所以斜杠命令不会出现重复响应问题,两类事件的处理逻辑要求是一致的。
内容的提问来源于stack exchange,提问作者user19144229
相关产品推荐
相关产品推荐

