Discord.js机器人语音状态检测异常,重启才生效求助
Discord.js机器人语音状态检测缓存问题解决
问题场景
我写了一段Discord.js代码,用来检测用户是否在语音频道里,如果没在就提醒他们别在特定频道发消息。代码如下:
const { Client, GatewayIntentBits } = require('discord.js'); require('dotenv/config') var guildID = "1128642534483****" const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildPresences ], }); client.on('ready', (c) => { console.log('The bot is ready') }) client.on('messageCreate', message => { console.log(1) if (message.content !== "") { console.log(2) if(!message.author.bot) { const Guild = client.guilds.cache.get(guildID); // Getting the guild. const Member = Guild.members.cache.get(message.author.id); // Getting the member. if (Member.voice.channel) { console.log(`${Member.user.tag} is connected to ${Member.voice.channel.name}!`); } if (!Member.voice.channel) { console.log(`${Member.user.tag} is not connected.`); message.reply({ content: 'This is the voice chat channel.'}) .then(msg => { setTimeout(() => msg.delete(), 7500) }) }; } } }) client.login(process.env.TOKEN)
遇到的问题:先加入语音频道再部署Node服务,之后离开语音频道发消息,机器人还是认为我在语音频道,不会发提示。不管我怎么切换语音状态,结果都一样,必须重启Node服务才会更新判断。我是JS和Discord.js新手,试过async函数但没解决,求帮忙。
问题原因
你现在是从Guild.members.cache里取成员数据,但Discord.js的缓存不会自动实时同步用户的语音状态变化。服务启动时缓存了用户当时的语音状态,之后的状态变更不会自动更新到缓存里,所以机器人一直用旧数据判断。
解决方法
方法1:直接用message.member获取实时成员状态
message对象自带的member属性就是当前服务器里发消息的成员实例,会实时反映最新状态,不用从全局缓存里查:
client.on('messageCreate', message => { console.log(1) if (message.content !== "" && !message.author.bot) { console.log(2) const member = message.member; if (member.voice.channel) { console.log(`${member.user.tag} is connected to ${member.voice.channel.name}!`); } else { console.log(`${member.user.tag} is not connected.`); message.reply({ content: 'This is the voice chat channel.'}) .then(msg => setTimeout(() => msg.delete(), 7500)) } } })
方法2:启用语音状态意图并监听状态更新(可选)
如果需要全局跟踪所有用户的语音状态变化,先添加GuildVoiceStates意图,再监听voiceStateUpdate事件确保缓存同步:
首先修改客户端的intents配置:
const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildPresences, GatewayIntentBits.GuildVoiceStates // 新增这个意图 ], });
然后添加监听事件:
client.on('voiceStateUpdate', (oldState, newState) => { console.log(`${newState.member.user.tag} 从 ${oldState.channel?.name || '无频道'} 切换到 ${newState.channel?.name || '无频道'}`); // 状态变化时缓存会自动更新,这里可按需加额外处理 });
方法3:主动拉取最新成员数据(备选)
如果必须从guild获取成员,用fetch方法主动拉取最新数据,不要依赖缓存:
client.on('messageCreate', async message => { // 加async支持await console.log(1) if (message.content !== "" && !message.author.bot) { console.log(2) const guild = client.guilds.cache.get(guildID); const member = await guild.members.fetch(message.author.id); // 主动获取最新数据 if (member.voice.channel) { console.log(`${member.user.tag} is connected to ${member.voice.channel.name}!`); } else { console.log(`${member.user.tag} is not connected.`); message.reply({ content: 'This is the voice chat channel.'}) .then(msg => setTimeout(() => msg.delete(), 7500)) } } })
内容的提问来源于stack exchange,提问作者Noctis Ren
相关产品推荐
相关产品推荐

