Discord.js开发modmail系统时消息收集器重复收集同一条消息怎么办?
Discord.js Modmail系统消息重复收集问题解决方案
问题根因
你代码的核心问题是频道消息收集器被错误放在了DM收集器的collect事件回调中:
- 每收到1条用户DM,就会新增1个独立的频道消息收集器监听同一个modmail频道
- 即使每个频道收集器都设置了
max:1,多个并行的收集器会同时捕获同一条管理员消息,导致重复给用户发私信 - 你的DM收集器本身没有设置max参数,会持续接收消息不断创建新的频道收集器,重复问题会随着用户发消息次数增加越来越严重
如果你确实需要限制单方向消息收集次数,直接在初始化收集器时添加
max参数即可,不要在消息触发回调中重复创建收集器。
修复方案
将频道收集器和DM收集器都放在会话初始化阶段创建,整个会话仅维护2个收集器即可,不要每次收到消息重复创建。
修正后代码如下:
const discord = require("discord.js") // config引入放在文件顶部,避免每次执行命令重复读取文件 const config = require("/home/runner/Bot2/Handlers/config.json") module.exports = { name: 'modmail', aliases: ['mail'], execute: async (client, message, args) => { const mes = await message.channel.send("I have sent you a dm.") try { // 给用户发DM初始化会话 const dmMsg = await message.author.send("Start typing to chat with the moderators.") const dmChannel = dmMsg.channel // 创建modmail专属频道 const modmailChannel = await message.guild.channels.create(`${message.author.username}s-modmail`, { permissionOverwrites: [{ id: config.mainrole, deny: ["VIEW_CHANNEL"], }] }) // 全局过滤器:忽略机器人消息 const noBotFilter = m => !m.author.bot // 1. 初始化DM收集器:整个会话仅一个,需要限制条数可在此处加max参数 const dmCollector = dmChannel.createMessageCollector({ filter: noBotFilter }) // 2. 初始化频道收集器:整个会话仅一个,需要限制条数可在此处加max参数 const channelCollector = modmailChannel.createMessageCollector({ filter: noBotFilter }) // 监听用户DM消息,转发到modmail频道 dmCollector.on("collect", m => { if (m.content === "?mmclose") { m.reply("Modmail will be closing.") // 结束会话:销毁收集器+删除频道 dmCollector.stop() channelCollector.stop() modmailChannel.delete().catch(() => {}) return } modmailChannel.send(`${m.author.tag}: ${m.content}`) }) // 监听modmail频道管理员消息,转发给用户 channelCollector.on("collect", mm => { if (mm.content === "?mmclose") { modmailChannel.delete().catch(() => {}) dmCollector.stop() channelCollector.stop() return } message.author.send(`${mm.author.tag}: ${mm.content}`) console.log(mm.content) }) // 收集器结束事件兜底处理,避免残留监听运行 dmCollector.on("end", () => { channelCollector.stop() modmailChannel.delete().catch(() => {}) }) channelCollector.on("end", () => { dmCollector.stop() modmailChannel.delete().catch(() => {}) }) } catch (error) { mes.delete() message.reply("Something went wrong. Make sure your dms are open. If this happens if when your dms are on then dm !Kweeper#8053") } } }
内容的提问来源于stack exchange,提问作者Kweeper
相关产品推荐
相关产品推荐

