discord.js v13创建VoiceState对象实现语音禁音功能遇到问题
你不需要手动构造VoiceState对象,discord.js 已经为服务器内的所有成员预生成了对应的VoiceState实例,直接从目标成员的voice属性获取即可使用setMute方法。
你现有代码的问题:
seconds变量在if/else块内部用const声明,属于块级作用域,块外无法访问,需要提升声明位置- 错误调用
selfMute方法,该属性仅用于读取用户自己触发的静音状态,服务器端禁音需要调用setMute方法 - 缺少必要的判断逻辑:未校验目标用户是否处于语音频道、未校验机器人和命令发起者是否有禁言权限,会直接触发报错
- 没有实现定时解除禁音的逻辑
- 错误使用
getUser获取目标对象,该方法返回的全局用户对象没有语音相关属性,需要用getMember获取服务器成员对象
修正后的执行函数代码:
async execute(interaction) { // 权限校验:判断命令发起者是否有禁言成员权限 if (!interaction.member.permissions.has('MUTE_MEMBERS')) { return interaction.reply({ content: '你没有禁言成员的权限', ephemeral: true }); } // 校验机器人自身是否有禁言权限 if (!interaction.guild.me.permissions.has('MUTE_MEMBERS')) { return interaction.reply({ content: '我没有禁言成员的权限,请调整权限配置', ephemeral: true }); } const targetMember = interaction.options.getMember('target'); // 校验目标用户是否在服务器中 if (!targetMember) { return interaction.reply({ content: '找不到该用户', ephemeral: true }); } // 校验目标用户是否在语音频道中 if (!targetMember.voice.channel) { return interaction.reply({ content: '该用户当前不在语音频道中,无法禁音', ephemeral: true }); } // 校验目标用户的权限是否比自己高,避免无法禁言 if (targetMember.permissions.has('ADMINISTRATOR') || targetMember.roles.highest.position >= interaction.member.roles.highest.position) { return interaction.reply({ content: '你无法禁言权限高于或等于你的用户', ephemeral: true }); } // 处理禁言时长 const seconds = interaction.options.getNumber('seconds') ?? 60; // 限制最大时长避免异常,可根据需要调整 if (seconds > 86400) { return interaction.reply({ content: '禁音时长最长不能超过1天', ephemeral: true }); } try { // 直接调用目标成员voice属性的setMute方法,不需要自己构造VoiceState await targetMember.voice.setMute(true, `由${interaction.user.tag}触发的语音禁言,时长${seconds}秒`); await interaction.reply(`已成功禁音 ${targetMember.user.tag} ${seconds} 秒`); // 定时解除禁言 setTimeout(async () => { // 解除前先判断用户还在语音频道且还是禁音状态 if (targetMember.voice.channel && targetMember.voice.mute) { await targetMember.voice.setMute(false, '禁言时长已到自动解除'); } }, seconds * 1000); } catch (err) { console.error(err); return interaction.reply({ content: '禁言操作失败,请检查权限配置', ephemeral: true }); } }
额外说明
你不需要对现有的Command Builder代码做修改,原有配置可以正常使用。如果需要永久禁音,不传第二个时长参数即可,或者调整逻辑取消定时解除的代码。
内容的提问来源于stack exchange,提问作者Vignesh PS
相关产品推荐
相关产品推荐

