Discord.js每10条消息发送Embed无报错不运行该如何解决?
问题定位
- 事件绑定逻辑错误:在
test命令的执行函数内绑定messageCreate事件,每次运行命令都会新增一个重复的监听器,多次执行会导致计数混乱、内存泄漏,不符合Discord.js的事件开发规范。 - 未过滤机器人自身消息:
messageCreate事件会捕获所有账号的消息,包括机器人自己发送的内容,未过滤会导致计数结果不符合预期。 - 版本兼容问题:若使用Discord.js v14及以上版本,原有的
MessageEmbed构造器已被重命名为EmbedBuilder,使用旧构造器无法正常生成Embed消息。 - 缺少必要权限配置:Discord.js v13及以上版本需要在Discord开发者后台开启
Message Content Intent权限,且初始化客户端时传入Guilds、GuildMessages、MessageContent三类Intent,否则messageCreate事件不会正常触发。 - 计数逻辑边界问题:运行
test命令的触发消息本身会被messageCreate事件捕获,会被计入累计数,导致实际触发条件和预期不符。
修复方案
步骤1:配置必要权限与Intent
首先登录Discord开发者平台,进入对应应用的「Bot」设置页,开启「Privileged Gateway Intents」下的Message Content Intent开关。
初始化客户端时传入对应Intent:
Discord.js v14 初始化示例
const { Client, GatewayIntentBits } = require('discord.js'); const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent ] });
Discord.js v13 初始化示例
const { Client, Intents } = require('discord.js'); const client = new Client({ intents: [ Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.MESSAGE_CONTENT ] });
步骤2:调整事件绑定与计数逻辑
不要在命令内绑定事件,统一在客户端初始化阶段注册messageCreate事件,用全局集合存储各频道的计数状态:
- 在客户端初始化时新增全局计数集合:
// 客户端初始化完成后添加,存储格式:<频道ID, 当前计数> client.channelMessageCount = new Map();
- 全局注册
messageCreate事件:
v13 版本事件代码
client.on("messageCreate", async (newMessage) => { // 过滤机器人消息 if (newMessage.author.bot) return; const channelId = newMessage.channel.id; // 仅处理开启了计数的频道 if (!client.channelMessageCount.has(channelId)) return; const newCount = client.channelMessageCount.get(channelId) + 1; client.channelMessageCount.set(channelId, newCount); if (newCount === 10) { const { MessageEmbed } = require("discord.js"); const embed = new MessageEmbed() .setDescription("Hello") .setColor("RANDOM"); await newMessage.channel.send({ embeds: [embed] }); // 可选配置:触发后关闭计数/重置计数 // client.channelMessageCount.delete(channelId); // 触发一次后关闭 // client.channelMessageCount.set(channelId, 0); // 重置计数循环触发 } });
v14 版本事件代码
client.on("messageCreate", async (newMessage) => { if (newMessage.author.bot) return; const channelId = newMessage.channel.id; if (!client.channelMessageCount.has(channelId)) return; const newCount = client.channelMessageCount.get(channelId) + 1; client.channelMessageCount.set(channelId, newCount); if (newCount === 10) { const { EmbedBuilder } = require("discord.js"); const embed = new EmbedBuilder() .setDescription("Hello") .setColor("Random"); await newMessage.channel.send({ embeds: [embed] }); } });
- 修改
test命令代码:
module.exports = { name: "test", description: "A test command", run: async(client, message, args)=>{ const channelId = message.channel.id; // 重置当前频道计数,从0开始累计 client.channelMessageCount.set(channelId, 0); await message.reply("已开启当前频道消息计数,累计10条后将发送提醒"); } }
注意事项
- 若需要机器人重启后计数不丢失,可将计数数据存储到本地JSON文件、SQLite等存储介质中,客户端启动时重新读取到
client.channelMessageCount即可。 - 若需要排除
test命令触发消息的计数,可以在命令设置计数时初始值设为-1,抵消触发消息的计数。
内容的提问来源于stack exchange,提问作者Bgroup Official
相关产品推荐
相关产品推荐

