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

Discord机器人慢模式命令拆分:子命令调用问题求助

Discord.js v14 Slowmode子命令调用问题

我正在为个人Discord Bot开发Slowmode命令,想拆分为set(设置)和clear(清除)两个子命令,这是第一次实现子命令,遇到了困难。主要问题是不知道如何调用子命令的选项。

补充说明:

  • 使用reconlx的DJS Base Handler,已修改部分代码适配Discord.js(DJS)v14
  • 参考过reconlx的Slash Commands指南,但帮助不大

以下是我的源代码:

const { Command } = require("reconlx");
const { EmbedBuilder, ApplicationCommandOptionType, ApplicationCommandType, PermissionsBitField } = require("discord.js");
const ms = require("ms");

module.exports = new Command({
    name: "slowmode2",
    description: "Sets a custom channel slowmode, version 2",
    userPermissions: PermissionsBitField.Flags.ManageGuild,
    type: ApplicationCommandType.ChatInput,
    options: [
        {
            name: "set",
            description: "Set a channel rate limit",
            type: ApplicationCommandOptionType.Subcommand,
            options: [
                {
                    name: "rate-limit",
                    description: "Duration of channel slowmode [s|m|h]",
                    type: ApplicationCommandOptionType.String,
                    required: true
                },
                {
                    name: "channel",
                    description: "Channel to rate-limit",
                    type: ApplicationCommandOptionType.Channel,
                    required: false
                },
            ]
        },
        {
            name: "clear",
            description: "Clears the rate limit for a specific channel",
            type: ApplicationCommandOptionType.Subcommand,
            options: [
                {
                    name: "channel",
                    description: "the channel to set the welcome message to.",
                    type: ApplicationCommandOptionType.Channel,
                    required: false
                },
            ]
        },
    ],

    run: async ({ interaction }) => {

        const [ subcommand ] = args;

        if (interaction.options.getSubcommand() === 'set') {
            const rateLimit = interaction.options.getString('rate-limit');
            const rateLimitChannel = interaction.options.getChannel('channel');
        }
        

        const timeInMs = ms(rateLimit);

        if (interaction.options.getSubcommand() === 'clear') {
            const clearChannel = interaction.options.getChannel("channel")
        }

        const slowmodeSuccess = new EmbedBuilder()
            .setColor("#2F3136")
            .setTitle(`🚅  SLOWING DOWN...`)
            .addFields(
                {
                    name: "Slowmode has been enabled for everyone in this channel!",
                    value: `To clear your slowmode, use \`/slowmode clear\``,
                    inline: false
                },
                {
                    name: "Rate Limit",
                    value: `${rateLimit}`,
                    inline: true
                },
                {   
                    name: "Channel",
                    value: `${rateLimitChannel}`,
                    inline: true
                }
            )

        const slowmodeClear = new EmbedBuilder()
            .setColor("#2F3136")
            .setTitle(`🏃🏻‍♂️  SLOWMODE CLEARED!`)
            .addFields(
                {
                    name: "Slowmode has been cleared for everyone in this channel!",
                    value: `Everyone may now talk freely at a normal pace!`,
                    inline: false
                },
                {   
                    name: "Channel",
                    value: `${clearChannel}`,
                    inline: true
                }
            )
        
        const invalidFormat = new EmbedBuilder()
            .setColor("#2F3136")
            .setTitle(`❌  ERROR`)
            .addFields(
                {
                    name: "Invalid Format!",
                    value: `Please provide your duration in [s|m|h] format!`,
                    inline: true
                },
            )
        
        const error = new EmbedBuilder()
            .setColor("#2F3136")
            .setTitle(`❌  ERROR`)
            .addFields(
                {
                    name: "Unknown Error: Oops!",
                    value: `Something seems to have gone wrong!`,
                    inline: true
                },
            )
        
        if (subcommand === "set") {
            if (!timeInMs || timeInMs === false) {
                interaction.followUp({ embeds: [invalidFormat] })
            } else {
                interaction.channel.setRateLimitPerUser(timeInMs/1000).then( () => {
                    interaction.followUp({ embeds: [slowmodeSuccess] })
                }).catch( () => {
                    interaction.followUp({ embeds: [error] })
                })
            }
        }

        if (subcommand === "clear") {
            interaction.channel.setRateLimitPerUser(false)
            interaction.followUp({ embeds: [slowmodeClear] })
        }
    }
});

问题分析与修复方案

原代码存在几个核心问题:

  1. 子命令获取错误:const [ subcommand ] = args;中args未定义,Discord.js v14中需通过interaction.options.getSubcommand()获取子命令名称
  2. 变量作用域问题:rateLimit、rateLimitChannel等变量定义在if块内部,外部无法访问,导致Embed和逻辑代码报错
  3. 频道处理逻辑缺失:未处理用户未指定频道的情况,应默认使用当前交互频道
  4. 慢模式清除错误:setRateLimitPerUser(false)无效,需传入0来清除慢模式
  5. 交互超时风险:未先调用interaction.deferReply(),长时间处理可能导致交互超时

修正后的完整代码

const { Command } = require("reconlx");
const { EmbedBuilder, ApplicationCommandOptionType, ApplicationCommandType, PermissionsBitField } = require("discord.js");
const ms = require("ms");

module.exports = new Command({
    name: "slowmode2",
    description: "Sets a custom channel slowmode, version 2",
    userPermissions: PermissionsBitField.Flags.ManageGuild,
    type: ApplicationCommandType.ChatInput,
    options: [
        {
            name: "set",
            description: "Set a channel rate limit",
            type: ApplicationCommandOptionType.Subcommand,
            options: [
                {
                    name: "rate-limit",
                    description: "Duration of channel slowmode [s|m|h]",
                    type: ApplicationCommandOptionType.String,
                    required: true
                },
                {
                    name: "channel",
                    description: "Channel to rate-limit",
                    type: ApplicationCommandOptionType.Channel,
                    required: false
                },
            ]
        },
        {
            name: "clear",
            description: "Clears the rate limit for a specific channel",
            type: ApplicationCommandOptionType.Subcommand,
            options: [
                {
                    name: "channel",
                    description: "Channel to clear slowmode from",
                    type: ApplicationCommandOptionType.Channel,
                    required: false
                },
            ]
        },
    ],

    run: async ({ interaction }) => {
        // 先回复交互避免超时
        await interaction.deferReply({ ephemeral: false });
        
        const subcommand = interaction.options.getSubcommand();

        if (subcommand === 'set') {
            const rateLimit = interaction.options.getString('rate-limit');
            const targetChannel = interaction.options.getChannel('channel') || interaction.channel;
            const timeInMs = ms(rateLimit);

            if (!timeInMs) {
                const invalidFormat = new EmbedBuilder()
                    .setColor("#2F3136")
                    .setTitle(`❌  ERROR`)
                    .addFields({
                        name: "Invalid Format!",
                        value: `Please provide your duration in [s|m|h] format!`,
                        inline: true
                    });
                return interaction.editReply({ embeds: [invalidFormat] });
            }

            try {
                await targetChannel.setRateLimitPerUser(timeInMs / 1000);
                const successEmbed = new EmbedBuilder()
                    .setColor("#2F3136")
                    .setTitle(`🚅  SLOWING DOWN...`)
                    .addFields(
                        {
                            name: "Slowmode enabled!",
                            value: `To clear slowmode, use \`/slowmode2 clear\``,
                            inline: false
                        },
                        {
                            name: "Rate Limit",
                            value: `${rateLimit}`,
                            inline: true
                        },
                        {   
                            name: "Channel",
                            value: targetChannel.toString(),
                            inline: true
                        }
                    );
                await interaction.editReply({ embeds: [successEmbed] });
            } catch (err) {
                const errorEmbed = new EmbedBuilder()
                    .setColor("#2F3136")
                    .setTitle(`❌  ERROR`)
                    .addFields({
                        name: "Unknown Error",
                        value: `Failed to set slowmode: ${err.message}`,
                        inline: true
                    });
                await interaction.editReply({ embeds: [errorEmbed] });
            }
        } else if (subcommand === 'clear') {
            const targetChannel = interaction.options.getChannel('channel') || interaction.channel;
            
            try {
                await targetChannel.setRateLimitPerUser(0);
                const clearEmbed = new EmbedBuilder()
                    .setColor("#2F3136")
                    .setTitle(`🏃🏻‍♂️  SLOWMODE CLEARED!`)
                    .addFields(
                        {
                            name: "Slowmode cleared!",
                            value: `Everyone can now talk freely!`,
                            inline: false
                        },
                        {   
                            name: "Channel",
                            value: targetChannel.toString(),
                            inline: true
                        }
                    );
                await interaction.editReply({ embeds: [clearEmbed] });
            } catch (err) {
                const errorEmbed = new EmbedBuilder()
                    .setColor("#2F3136")
                    .setTitle(`❌  ERROR`)
                    .addFields({
                        name: "Unknown Error",
                        value: `Failed to clear slowmode: ${err.message}`,
                        inline: true
                    });
                await interaction.editReply({ embeds: [errorEmbed] });
            }
        }
    }
});

关键修复点说明

  1. 子命令获取:使用const subcommand = interaction.options.getSubcommand()正确获取当前触发的子命令
  2. 变量作用域:将子命令相关逻辑封装在对应的if块内,避免变量访问问题
  3. 频道默认值:通过targetChannel = ... || interaction.channel处理用户未指定频道的情况
  4. 慢模式清除:使用setRateLimitPerUser(0)替代false,符合Discord.js API要求
  5. 交互超时处理:先调用interaction.deferReply(),后续用editReply回复,避免超时
  6. 错误处理:添加try-catch捕获API调用异常,并在Embed中显示具体错误信息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:55:18