Discord语音机器人报错修复及个性化音效实现咨询
Discord语音机器人报错修复与多用户专属音效实现
问题场景
开发Discord语音机器人时,触发voiceStateUpdate事件时报错,机器人无法正常加入频道播放指定intro音效,终端输出如下:
运行命令
cd "C:\javacode\Discord Audio Bot" node Audio.js
报错信息
On C:\javacode\Discord Audio Bot\Audio.js:29 } else if (newState.channel.members.size = 1) { ^ TypeError: Cannot read properties of null (reading 'members') at Client.<anonymous> (C:\javacode\Discord Audio Bot\Audio.js:29:31) at Client.emit (node:events:513:28) at VoiceStateUpdate.handle (C:\javacode\Discord Audio Bot\node_modules\discord.js\src\client\actions\VoiceStateUpdate.js:38:14) at module.exports [as VOICE_STATE_UPDATE] (C:\javacode\Discord Audio Bot\node_modules\discord.js\src\client\websocket\handlers\VOICE_STATE_UPDATE.js:4:35) at WebSocketManager.handlePacket (C:\javacode\Discord Audio Bot\node_modules\discord.js\src\client\websocket\WebSocketManager.js:352:31) at WebSocketShard.onPacket (C:\javacode\Discord Audio Bot\node_modules\discord.js\src\client\websocket\WebSocketShard.js:489:22) at WebSocketShard.onMessage (C:\javacode\Discord Audio Bot\node_modules\discord.js\src\client\websocket\WebSocketShard.js:328:10) at callListener (C:\javacode\Discord Audio Bot\node_modules\ws\lib\event-target.js:290:14) at WebSocket.onMessage (C:\javacode\Discord Audio Bot\node_modules\ws\lib\event-target.js:209:9) at WebSocket.emit (node:events:513:28)
原代码
console.log('On'); const { Client, GatewayIntentBits } = require('discord.js'); const client = new Client({ intents: [ GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers ] }); client.on('voiceStateUpdate', (_oldState, newState) => { // Check if the user who joined is the specific user we want if (newState.member.id === 'STtheGamer') { // Check if the user joined a voice channel if (newState.channel) { // Join the voice channel and play the specific sound newState.channel.join() .then(connection => { // Replace 'song.mp3' with the path to the audio file you want to play const dispatcher = connection.play('C:\Users\storr\Music\botsounds\swtheme.mp3'); // Leave the voice channel after the sound is played dispatcher.on('finish', () => { newState.channel.leave(); }); }) .catch(console.error); } } else if (newState.channel.members.size = 1) { if (newState.channel) { newState.channel.leave() .catch(console.error); } } }); client.login('botkey here');
报错原因与修复
核心错误点
- 赋值运算符误用:
else if条件中用=赋值而非===比较,逻辑错误且触发无效操作 - 空值未校验:用户离开频道时
newState.channel为null,直接访问members会抛出类型错误 - 路径转义问题:Windows路径的
\需转义为\\,否则会被解析为转义字符导致音频文件找不到 - 用户ID判断错误:
newState.member.id对应用户数字ID,而非用户名STtheGamer - 缺失必要意图:未添加
Guilds意图,可能导致频道数据无法正常获取
修复后代码(含多用户音效实现)
console.log('On'); const { Client, GatewayIntentBits } = require('discord.js'); const client = new Client({ intents: [ GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers, GatewayIntentBits.Guilds // 新增必要意图 ] }); // 多用户专属音效映射:用户数字ID -> 音效文件路径 const userIntroSounds = { '用户1的数字ID': 'C:\\Users\\storr\\Music\\botsounds\\user1.mp3', '用户2的数字ID': 'C:\\Users\\storr\\Music\\botsounds\\user2.mp3', 'STtheGamer的数字ID': 'C:\\Users\\storr\\Music\\botsounds\\swtheme.mp3' }; client.on('voiceStateUpdate', (_oldState, newState) => { // 判断用户是加入还是离开频道 const isJoining = !_oldState.channel && newState.channel; const isLeaving = _oldState.channel && !newState.channel; if (isJoining) { const userId = newState.member.id; // 检查当前用户是否有专属音效 if (userIntroSounds[userId]) { newState.channel.join() .then(connection => { const dispatcher = connection.play(userIntroSounds[userId]); // 播放完成后,仅频道只剩机器人时离开 dispatcher.on('finish', () => { if (newState.channel.members.size === 1) { newState.channel.leave(); } }); dispatcher.on('error', console.error); }) .catch(console.error); } } else if (isLeaving) { // 用户离开后,检查原频道是否只剩机器人,是则离开 if (_oldState.channel.members.size === 1) { _oldState.channel.leave().catch(console.error); } } }); client.login('你的机器人Token');
多用户专属音效实现说明
- 音效映射表:用对象
userIntroSounds存储用户ID与对应音效路径的映射,新增/修改用户音效只需更新该对象 - 精准状态判断:通过对比新旧状态的频道信息,避免无效逻辑触发,只在用户真正加入/离开时执行对应操作
- 智能离开逻辑:播放完成或用户离开后,仅当频道内只剩机器人时才退出,避免影响其他用户
内容的提问来源于stack exchange,提问作者stevieboi97
相关产品推荐
相关产品推荐

