Search code examples
node.jsdiscorddiscord.js

(Discord.js) Is there any way to add a string input after/in a subcommand?


Basically, I recently got into making discord bots and I have an issue on adding string inputs after a subcommand. My bot has a 'blacklist' function that will allow a user to add/delete/view the contents of the blacklisted words list.

Here is the syntax of how I wanted it to be if that'd help
add a word: /blacklist add *word*
remove word: /blacklist remove *word*
view list: /blacklist list


When I added a main command 'blacklist' and added sub-commands for 'add', 'remove' and 'list', I was given an error after I added a string input field underneath.

At first I tried:
The error I got was
DiscordAPIError[50035]: Invalid Form Body
options[3][APPLICATION_COMMAND_OPTIONS_TYPE_INVALID]: Sub-command and sub-command group option types are mutually exclusive to all other types

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

module.exports = {
    data: new SlashCommandBuilder()
        .setName('blacklist')
        .setDescription('Add, remove or view the list of blacklisted words!')
        .addSubcommand(subcommand =>
            subcommand
                .setName('add')
                .setDescription('add a word to the blacklist list'))
        .addSubcommand(subcommand =>
            subcommand
                .setName('remove')
                .setDescription('remove a word to the blacklist list')) 
        .addSubcommand(subcommand =>
            subcommand
                .setName('list')
                .setDescription('view the blacklist list'))

        .addStringOption(option =>
            option.setName('input')
                .setDescription('The word you want to add/delete (leave empty if list)')),
        
    async execute(interaction) {
        await interaction.reply(interaction.options.getString("input")})
    },
};

I then tried to add the string input inside each of the sub-commands, but unfortunately I got the same result.

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

module.exports = {
    data: new SlashCommandBuilder()
        .setName('blacklist')
        .setDescription('Add, remove or view the list of blacklisted words!')

        .addSubcommand(subcommand =>
            subcommand
                .setName('add')
                .setDescription('add a word to the blacklist list'))
                .addStringOption(option =>
                    option.setName('adds')
                        .setDescription('The word you want to add'))
        .addSubcommand(subcommand =>
            subcommand
                .setName('remove')
                .setDescription('remove a word to the blacklist list'))
                .addStringOption(option =>
                    option.setName('del')
                        .setDescription('The word you want to remove'))
        .addSubcommand(subcommand =>
            subcommand
                .setName('list')
                .setDescription('view the blacklist list')),
    async execute(interaction) {
        await interaction.reply(interaction.option.getString("input"))
    },
};

DiscordAPIError[50035]: Invalid Form Body
options[1][APPLICATION_COMMAND_OPTIONS_TYPE_INVALID]: Sub-command and sub-command group option types are mutually exclusive to all other types
options[3][APPLICATION_COMMAND_OPTIONS_TYPE_INVALID]: Sub-command and sub-command group option types are mutually exclusive to all other types

Also I am not sure why it said there was an issue with the first and third, as opposed to first and second

I understand why the code does not work, as said by the error message, but is there a way to go around it? And why can't we add other option types?


Solution

  • const { SlashCommandBuilder } = require('discord.js');
    
    module.exports = {
        data: new SlashCommandBuilder()
            .setName('blacklist')
            .setDescription('Add, remove or view the list of blacklisted words!')
            .addSubcommand(subcommand =>
                subcommand
                .setName('add')
                .setDescription('add a word to the blacklist list')
                .addStringOption(option =>
                    option.setName('input')
                    .setDescription('The word you want to add'))
            )
            .addSubcommand(subcommand =>
                subcommand
                .setName('remove')
                .setDescription('remove a word to the blacklist list')
                .addStringOption(option =>
                    option.setName('input')
                    .setDescription('The word you want to remove'))
            )
            .addSubcommand(subcommand =>
                subcommand
                .setName('list')
                .setDescription('view the blacklist list')
                .addStringOption(option =>
                    option.setName('input')
                    .setDescription('The word you want to add/delete (leave empty if list)'))
            ), // the addStringOption() should be inside addSubcommand()
        async execute(interaction) {
            // you should start a subcommand like this
            switch (interaction.options.getSubcommand()) {
                case "add":
                default:
                    {
                        // and then define its options like you would in a normal command . e.x. :
                        const input = interaction.options.getString('input');
                        interaction.reply({ content: input });
                        break;
                    }
    
                case "remove":
                    {
                        // and then define its options like you would in a normal command . e.x. :
                        const input = interaction.options.getString('input');
                        interaction.reply({ content: input });
                        break;
    
                    }
    
                case "list":
                    {
                        // and then define its options like you would in a normal command . e.x. :
                        const input = interaction.options.getString('input');
                        interaction.reply({ content: input });
                        break;
    
                    }
    
    
            }
    
    
        },
    };
    

    I think u can do it now ;)