Discord.js v12监听用户加入语音频道发消息无响应及报错问题
问题原因&解决方案
第一个版本(无触发无报错)的问题
- 你在文件顶部单独
new Discord.Client()创建的client实例没有经过登录流程,和你框架run方法传入的已登录client是完全独立的两个实例,你把voiceStateUpdate事件绑定到了未登录的空client上,自然不会触发任何事件回调。
第二个版本(报错Cannot read property 'channelID' of undefined)的问题
- discord.js v12的
voiceStateUpdate事件返回的newState本身就是VoiceState类型的对象,直接自带channelID属性,不需要额外加.voice字段,你多写的.voice层级不存在,所以触发了空指针报错。 - 同时
voiceStateUpdate事件默认返回两个参数:oldState(用户更新前的语音状态)、newState(用户更新后的语音状态),只拿一个参数会导致逻辑判断有漏洞,比如用户在目标语音频道内静音、调整音量也会重复触发提醒。
修复后的可用代码
const BaseEvent = require('../../utils/structures/BaseEvent'); module.exports = class ReadyEvent extends BaseEvent { constructor() { super('ready'); } async run (client) { console.log(`Bot prêt, connecté en tant qu'${client.user.username}!`); // 绑定事件到已登录的client实例,同时接收两个状态参数 client.on('voiceStateUpdate', (oldState, newState) => { // 直接取newState的channelID,不需要加.voice const oldChannelId = oldState.channelID; const newChannelId = newState.channelID; const targetSupportChannelId = '815316796067414016'; const notifyTextChannelId = '815316823275995139'; const managerRoleId = '753367852299321404'; // 仅当用户从其他频道进入目标支持频道时触发,避免重复提醒 if (newChannelId === targetSupportChannelId && oldChannelId !== targetSupportChannelId) { const textChannel = client.channels.cache.get(notifyTextChannelId); // 加个容错,避免频道不存在导致崩溃 if (!textChannel) return; textChannel.send(`Hey ! Le <@&${managerRoleId}>, ${newState.member.user.username} (${newState.id}) est en Attente de Support !`); } }); } }
额外注意点
- 不需要在文件顶部重复创建client实例,也不需要额外引入未用到的
DiscordAPIError、Discord变量,避免冗余代码。 - 增加了状态对比逻辑,只有用户刚进入目标语音频道时才会发提醒,不会出现重复@的情况。
内容的提问来源于stack exchange,提问作者Ambre Kervran
相关产品推荐
相关产品推荐

