Discord.js中检测指定提及用户语音状态变化并触发音频播放的问题
问题原因与修复方案
问题根源
- 变量名冲突:外层
message事件中定义的被@目标用户变量名为user,与speaking事件回调的入参user重名,回调作用域内会优先读取当前触发事件的发言用户,覆盖了外层的指定目标用户,无法做匹配校验 - 缺少目标用户过滤逻辑:
speaking事件的触发判断仅检查了用户存在、用户正在发言两个条件,没有校验触发用户是否为你之前@指定的用户,导致所有频道内发言用户都会触发音频播放
修复后的代码
client.on('message', async message => { const voiceChannel = message.member.voice.channel; // 变量改名避免和speaking回调的入参冲突 let targetUser = message.mentions.users.first(); let cleanMessage = message.content.toLowerCase(); // 先检查消息是否包含有效指令 if (!cleanMessage.match(start) && !cleanMessage.startsWith('quit') && !targetUser) return; // 加入频道的逻辑 if (cleanMessage.match(start) && targetUser && voiceChannel) { console.log('已连接!'); voiceChannel.join() .then(connection => { connection.on('speaking', (currentUser, speaking) => { // 新增判断:当前发言用户是指定的目标用户再触发播放 if(currentUser && speaking && currentUser.id === targetUser.id) { // 给dispatch加声明避免变成全局变量 const dispatch = connection.play(fs.createReadStream(require("path").join(__dirname, './shush.webm')), { type: 'webm/opus'}); console.log(currentUser); } }) console.log(`${targetUser.username} 已被禁言提醒!`); setTimeout(() => { voiceChannel.leave() }, 10000); }).catch(err => console.log(err)); message.channel.send(`${targetUser.username} 安静点。`); } })
改动点说明
- 将外层被@的目标用户变量从
user改名为targetUser,避免和speaking回调的入参currentUser重名冲突 speaking事件的触发判断中新增currentUser.id === targetUser.id的匹配逻辑,仅当指定用户发言时才会播放音频- 给
dispatch变量添加const声明,避免意外泄漏为全局变量
内容的提问来源于stack exchange,提问作者Brody Spearman
相关产品推荐
相关产品推荐

