You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

discord.js机器人启动时命令无法自动刷新的问题求助

Discord机器人命令不刷新问题的解决方案

核心问题

你的代码仅在本地将命令加载到了client.commands集合中,但没有通过Discord REST API将命令数据同步到Discord服务器。Discord的Slash命令必须经过API注册才会在客户端显示,本地加载不影响Discord端的命令列表。

问题代码分析

  • 缺失命令注册逻辑:现有代码初始化了REST实例,但从未调用rest.put()向Discord提交命令数据,导致新命令无法被识别,旧命令也不会被移除。
  • reload函数局限:reload_command仅刷新了本地Node.js缓存和client.commands集合,未同步更新Discord端的命令。
  • 路径错误:reload.js中command.category未在命令文件中定义,会导致require.resolve路径错误,无法正确重载命令。

修复方案

1. 添加命令部署函数

在index.js中添加同步命令到Discord的函数:

async function deployCommands() {
  const commands = [];
  const foldersPath = path.join(__dirname, 'commands');
  const commandFolders = fs.readdirSync(foldersPath);

  // 遍历所有命令文件,收集命令的data结构
  for (const folder of commandFolders) {
    const commandsPath = path.join(foldersPath, folder);
    const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
    for (const file of commandFiles) {
      const filePath = path.join(commandsPath, file);
      const command = require(filePath);
      if ('data' in command && 'execute' in command) {
        commands.push(command.data.toJSON());
      } else {
        console.log(`[WARNING] 命令文件 ${filePath} 缺少必填的"data"或"execute"属性。`);
      }
    }
  }

  try {
    console.log(`正在刷新 ${commands.length} 个应用命令...`);
    // 全局注册命令(生效需约1小时),测试阶段可替换为服务器专属路由
    const data = await rest.put(
      Routes.applicationCommands(clientId),
      { body: commands },
    );
    console.log(`成功刷新 ${data.length} 个应用命令!`);
  } catch (error) {
    console.error(error);
  }
}

测试推荐用服务器专属命令(即时生效),将Routes.applicationCommands(clientId)替换为Routes.applicationGuildCommands(clientId, '你的服务器ID')

2. 修改ClientReady事件

在机器人就绪时调用部署函数,替换原有的reload_command调用:

client.once(Events.ClientReady, async readyClient => {
  await deployCommands(); // 同步命令到Discord
  console.log(`已就绪!登录账号:${readyClient.user.tag}`);
});

3. 修复reload函数的路径与同步逻辑

首先在每个命令文件中添加category属性,比如addkey.js:

module.exports = {
  category: 'utility', // 添加分类标记
  data: new SlashCommandBuilder()
    .setName('addkey')
    .setDescription('Add a key.'),
  async execute(interaction) {
    await interaction.reply("Running add key");
  },
};

然后修改index.js中的reload_command函数:

async function reload_command(command_name) {
  const command = client.commands.get(command_name);
  if (!command) {
    return console.log(`不存在名为 \`${command_name}\` 的命令!`);
  }
  
  const filePath = path.join(__dirname, 'commands', command.category, `${command.data.name}.js`);
  delete require.cache[require.resolve(filePath)];

  try {
    client.commands.delete(command.data.name);
    const newCommand = require(filePath);
    client.commands.set(newCommand.data.name, newCommand);
    console.log(`命令 \`${newCommand.data.name}\` 已重载本地缓存!`);
    await deployCommands(); // 重载后同步到Discord
  } catch (error) {
    console.error(error);
    console.log(`重载命令 \`${command.data.name}\` 时出错:\n\`${error.message}\``);
  }
}

4. 修复reload.js的路径问题

修改reload.js中的路径处理与同步逻辑:

const { SlashCommandBuilder, REST, Routes } = require('discord.js');
const path = require('node:path');
const { token } = require('../../config.json');
const clientId = '1184598822593253477';

module.exports = {
  category: 'utility',
  data: new SlashCommandBuilder()
    .setName('reload')
    .setDescription('Reloads a command.')
    .addStringOption(option => 
      option.setName('command')
        .setDescription('要重载的命令名称')
        .setRequired(true)),
  async execute(interaction) {
    const commandName = interaction.options.getString('command', true).toLowerCase();
    const command = interaction.client.commands.get(commandName);

    if (!command) {
      return interaction.reply(`不存在名为 \`${commandName}\` 的命令!`);
    }

    const filePath = path.join(__dirname, '..', command.category, `${command.data.name}.js`);
    delete require.cache[require.resolve(filePath)];

    try {
      interaction.client.commands.delete(command.data.name);
      const newCommand = require(filePath);
      interaction.client.commands.set(newCommand.data.name, newCommand);
      
      // 同步更新到Discord
      const rest = new REST().setToken(token);
      const commands = interaction.client.commands.map(cmd => cmd.data.toJSON());
      await rest.put(Routes.applicationCommands(clientId), { body: commands });
      
      await interaction.reply(`命令 \`${newCommand.data.name}\` 已重载并同步到Discord!`);
    } catch (error) {
      console.error(error);
      await interaction.reply(`重载命令 \`${command.data.name}\` 时出错:\n\`${error.message}\``);
    }
  },
};

注意事项

  • 全局命令刷新后需等待约1小时生效,测试阶段优先使用服务器专属命令。
  • 修改命令的名称、描述或选项后,必须调用deployCommands()同步到Discord。
  • rest.put()会用新命令数组完全覆盖Discord端的命令列表,旧命令会被自动移除。

内容的提问来源于stack exchange,提问作者Jacob Cooper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:57:33