人人都会AI编程

9.4 自定义斜杠命令创建

更新时间:2026-06-28

斜杠命令(Slash Commands)已成为现代聊天机器人(Discord、Slack、飞书等)的标准交互方式。相比传统的 !help 前缀命令,它能提供自动补全、参数提示和更清晰的界面。

9.4.1 基础注册流程

以 Discord.js v14 为例,创建斜杠命令只需三步:

1. 定义命令结构

const { SlashCommandBuilder } = require('discord.js');

const command = new SlashCommandBuilder()
    .setName('查天气')           // 命令名称(小写,无空格)
    .setDescription('查询指定城市天气')
    .addStringOption(option => 
        option.setName('城市')
              .setDescription('城市名称,如:北京')
              .setRequired(true)  // 必填参数
    );

2. 向 Discord 注册
命令需要注册到 Discord 服务器才能显示在输入框里:

// 全局注册(最多1小时生效,适合生产环境)
await client.application.commands.create(command);

// 或仅测试服务器注册(立即生效,适合开发)
await guild.commands.create(command);

3. 监听并响应

client.on('interactionCreate', async interaction => {
    if (!interaction.isChatInputCommand()) return;
    
    if (interaction.commandName === '查天气') {
        const city = interaction.options.getString('城市');
        
        // 模拟API调用
        await interaction.deferReply(); // 延迟回复(处理耗时操作必加)
        const weather = await fetchWeather(city);
        
        await interaction.editReply(`${city}今天晴,25°C`);
    }
});

9.4.2 实用技巧

参数类型选择

  • addStringOption: 文本输入(适合名称、查询内容)
  • addIntegerOption: 整数(适合数量、页码)
  • addUserOption: @用户(自动显示成员列表)
  • addChannelOption: #频道(自动显示频道列表)
  • addChoice: 限定选项(如 addChoice('开启', 'on')

错误处理必加

try {
    await interaction.reply('处理中...');
} catch (error) {
    // 如果回复已发送,使用 followUp;否则用 reply
    if (interaction.replied || interaction.deferred) {
        await interaction.followUp({ content: '出错了,请重试', ephemeral: true });
    } else {
        await interaction.reply({ content: '出错了', ephemeral: true });
    }
}

注:ephemeral: true 表示仅命令执行者可见,适合错误提示。

9.4.3 本地调试与部署

开发环境快速刷新
每次修改命令定义后,必须重新注册才能看到变化。建议单独写一个 deploy-commands.js 脚本:

// 只在 Node 环境变量为 development 时执行
if (process.env.NODE_ENV === 'development') {
    const rest = new REST({ version: '10' }).setToken(token);
    await rest.put(
        Routes.applicationGuildCommands(clientId, guildId),
        { body: commands }
    );
    console.log('测试服务器命令已更新');
}

生产环境注意事项

  • 全局命令有每日注册次数限制(约200次),不要在代码里每次启动都注册
  • 修改命令描述或选项属于结构性变更,必须重新注册
  • 仅修改回复逻辑无需重新注册

9.4.4 完整示例:工单系统

// commands/ticket.js
module.exports = {
    data: new SlashCommandBuilder()
        .setName('工单')
        .setDescription('创建技术支持工单')
        .addStringOption(opt => 
            opt.setName('类型')
               .setDescription('问题类型')
               .setRequired(true)
               .addChoices(
                   { name: '账号问题', value: 'account' },
                   { name: '支付故障', value: 'payment' },
                   { name: '功能咨询', value: 'feature' }
               ))
        .addStringOption(opt => 
            opt.setName('描述')
               .setDescription('详细描述您的问题')
               .setRequired(true)),

    async execute(interaction) {
        const type = interaction.options.getString('类型');
        const desc = interaction.options.getString('描述');
        
        await interaction.reply({
            content: `✅ 工单已创建\n类型:${type}\n描述:${desc}`,
            ephemeral: true  // 仅自己可见,避免刷屏
        });
        
        // 转发到管理员频道(实际项目中使用)
        // await adminChannel.send(`新工单来自 ${interaction.user.tag}...`);
    }
};

关键要点总结:

  1. 命令名称必须小写,支持中文但建议英文(避免编码问题)
  2. 耗时操作务必先 deferReply(),否则3秒内无响应会报错
  3. 选项超过25个时用 Autocomplete 动态加载,而非静态 addChoices
  4. 权限控制通过 setDefaultMemberPermissions(PermissionFlagsBits.Administrator) 实现

完成上述代码后,在 Discord 输入 / 即可看到你的自定义命令及参数提示。