discord.js中VoiceState无法一致更新 移动语音频道成员命令故障
问题解决办法
问题原因
你遇到的VoiceState更新不一致问题,核心有两点:
- 直接读取discord.js本地缓存的voiceStates数据,缓存没有和网关事件实时同步,用户断开连接的事件推送延迟时就会出现状态滞后
- 没有在Discord开发者后台开启对应的特权网关权限,导致用户断开语音的事件没有推送给机器人,本地缓存永远不会更新
修复步骤
第一步:开启开发者后台特权Intent
打开Discord Developer Portal,进入你的机器人应用的「Bot」设置页,找到Privileged Gateway Intents板块,打开Server Voice States的开关,保存设置。你代码里已经声明了GUILD_VOICE_STATES intent,配合后台开关就能完整接收所有语音状态变更事件。
第二步:修改代码,优先取实时状态,避免直接读缓存
不要从全局guild缓存取语音状态,直接用interaction.member.voice获取和当前交互绑定的最新语音状态,准确度更高;如果需要全服务器的语音状态,先主动fetch再操作,不要直接读cache。
修改后的命令执行代码如下:
//The command file const Discord= require('discord.js'); const {SlashCommandBuilder} = require("@discordjs/builders"); module.exports = { data: new SlashCommandBuilder() .setName('move') .setDescription('Move all the members to a specific voice channel') .addChannelOption(option => option.setName('voicechannel') .setDescription('The voice channel to move everyone in') .setRequired(true)), async execute(interaction) { const authorVoiceState = interaction.member.voice; const targetChannel = interaction.options.getChannel('voicechannel'); // 直接用实时状态判断,不走缓存 if (!authorVoiceState.channel) { return await interaction.reply({content : 'You need to be in a voice channel first', ephemeral: true}); } if (targetChannel.id === authorVoiceState.channel.id) { return await interaction.reply({content : 'Can\'t move to the same channel', ephemeral: true}); } // 拉取全服最新的语音状态,主动fetch不走缓存 const allVoiceStates = await interaction.guild.voiceStates.fetch(); // 实现移动成员逻辑:遍历触发者所在频道的所有成员,移动到目标频道 authorVoiceState.channel.members.each(async member => { if (member.voice.channel) await member.voice.setChannel(targetChannel); }); await interaction.reply({content : 'ok', ephemeral: true}); }, };
如果还是偶现状态不一致的情况,可以额外给语音状态对象加判断,channelId为null的时候直接视为用户已经断开语音即可。
内容的提问来源于stack exchange,提问作者itsaikara
相关产品推荐
相关产品推荐

