Discord.js:返回用户当前的 voice.channelId 已过时

Posted

技术标签:

【中文标题】Discord.js:返回用户当前的 voice.channelId 已过时【英文标题】:Discord.js: Returning the current voice.channelId of a user is outdated 【发布时间】:2021-12-04 12:32:49 【问题描述】:

对于我的不和谐机器人的命令,我需要获取用户当前连接的语音通道的 ID。我目前有类似的工作:

module.exports = 
 name: 'hit',
 description: "Return your voiceChannel ID",
 execute(message) 
    console.log('User ' + message.author.username + ' // ' + message.author.id + ' used the hit command.');

    console.log(message.member.voice.channelId);
 
;

问题在于,这仅返回启动机器人时用户所在频道的语音频道 ID。如果用户切换频道或离开每个频道,此处返回的语音频道 ID 仍然保持不变。 我也试过这个,有完全相同的问题:

module.exports = 
    name: 'hit',
    description: "Return your voiceChannel ID",
    execute(message, config, commands) 
        console.log('User ' + message.author.username + ' // ' + message.author.id + ' used the hit command.');

        awaitFetch(message);
    
;

async function awaitFetch(message) 
    let newInfo = await message.member.fetch(true);
    console.log(newInfo.voice.channelId);

我认为是因为 discord.js 在启动时缓存了这些信息。但我不知道如何更新所说的缓存......

编辑:不确定这是否有帮助,但这是调用每个命令的 main.js:

const Discord = require('discord.js');
let config = require('./config.json');

const client = new Discord.Client(
    intents: [
        Discord.Intents.FLAGS.GUILDS,
        Discord.Intents.FLAGS.GUILD_MESSAGES,
        Discord.Intents.FLAGS.GUILD_MEMBERS,
        Discord.Intents.FLAGS.GUILD_PRESENCES,
    ]
);

const fs = require('fs');

client.commands = new Discord.Collection();

const commandFiles = fs.readdirSync('./commands/').filter(file => file.endsWith('.js'));
for(const file of commandFiles) 
    const command = require(`./commands/$file`);

    client.commands.set(command.name, command);


client.once('ready', () => 
    console.log('Online!');
);

client.on('messageCreate', message => 

    console.log (message.member.voice.channelId);

    if(message.author.bot || message.mentions.everyone === true) return;

    if(fs.existsSync(`guildConfigs/$message.guild.id.json`)) 
        delete require.cache[require.resolve(`./guildConfigs/$message.guild.id.json`)];
        config = Object.assign(, require(`./guildConfigs/$message.guild.id.json`));
    
    else
        config = require('./config.json');
    

    let prefix = config.prefix;

    if(message.mentions.has(client.user) && !message.author.bot) 
        client.commands.get('pinged').execute(message, config);
    
    else if(!message.content.startsWith(prefix)) return;

    const args = message.content.slice(prefix.length).split(' ');
    const command = args.shift().toLowerCase();

    if(command === 'help') 
        client.commands.get('help').execute(message, config, client.commands);
     else if(command === 'ping') 
        client.commands.get('ping').execute(message);
     else if(command === 'hit') 
        client.commands.get('hit').execute(message, args, config);
     else if(command === 'topic') 
        client.commands.get('topic').execute(message);
     else if(command === 'fact') 
        client.commands.get('fact').execute(message);
     else if(command === 'settings') 
        if(message.member.permissions.has('ADMINISTRATOR')) 
            client.commands.get('settings').execute(message, args, config);
        
        else
            message.channel.send('Sorry bro, but this command is only available for server admins ????');
        
    
);

client.login(config.token);

【问题讨论】:

我不知道为什么会这样;我从来没有遇到过message.member.voice.channelId 过时的问题。但是,您可以尝试的一件事是在.fetch() 上使用force 布尔值,如docs 所示。像这样:message.member.fetch(true)。这会跳过缓存检查并强制 djs 直接请求 Discord API。 我试过了,但遗憾的是它仍然过时了...... 您是否尝试过使用message.member.voice.channel.id?根据官方docs,语音状态的只读属性channel为:The channel that the member is connected to。我猜他们的意思是当前已连接 另外,如果用户在没有进入频道的情况下调用该命令,您的代码将抛出异常,请改用 message.member.voice?.channel?.id。会更安全 @Nick 仍然过时,只显示机器人启动时用户所在的频道...:/ 【参考方案1】:

好的,我要说明几点:

我看到您没有使用数据库,而是为每个公会创建了几个 json 文件,这不是野兽方法(如果您计划为多个公会服务),以解决您可以考虑使用 MongoDB,它字面上的工作方式相同(BSON 不是 JSON,但您不会看到区别)。 除非触发 ready 事件,否则不会触发您正在侦听的事件,因此一个好的做法是将所有侦听器(消息、加入或其他)移动到就绪事件回调中 (只是提示):您将消息与.split(' ') 分开,但如果用户输入!ping user(有两个空格)怎么办?这将导致['ping', '', 'user'],您可以使用正则表达式调用拆分函数:.split(/ +/),这样您将用至少一个空格拆分消息 一旦您拥有带有const commandName = args.shift().toLowerCase() 的命令名称,您可以执行以下操作:
const command = client.commands.get(commandName);
if(!command) return;
// The permissions check you do for the settings command should be moved on the
// command logic itself, what you should do in the main file is just take a message,
// get a command and execute it
command.execute(message, args) // from the message instance you can get the client and the config can be required(using a db would resolve this 'issue')

说了这么多,解决你的问题很简单,你只是忘了在客户端添加GUILD_VOICE_STATESintent,就是这样,应该可以解决这个问题

【讨论】:

这就是解决方案,不敢相信这么简单的东西被我和其他许多人偷走了......对于其他事情:1)这将更麻烦,因为机器人正在运行在一台可能是 2 或 3 台服务器上。 2)所有事件都按预期触发,该消息就在那里,以便我知道机器人何时完全启动 3)谢谢,很高兴知道! ^^ 4) 有趣...

以上是关于Discord.js:返回用户当前的 voice.channelId 已过时的主要内容,如果未能解决你的问题,请参考以下文章

Discord.JS 录音和数据压缩

Discord.js 错误:错误:找不到 FFmpeg/avconv!即使安装

带有斜杠命令的 Discord.js 语音通道

Discord.js 13 channel.join 不是函数

Discord Bot 不播放音频 discord.js v13

discord.js 机器人在没有声音的情况下播放音频