Tyler2P
Tyler2P

Reputation: 2370

Creating slash commands without options Discord.js V14

In attempt to create slash commands in Discord.JS V14 following the official guide, I came across the following error:

DiscordAPIError[50035]: Invalid Form Body
0[LIST_TYPE_CONVERT]: Only iterables may be used in a ListType

The specific command (ping) that I would like to create doesn't have any additional options as it's a very basic command and simply is just unethical to add any options.

ping.js:

module.exports = {
  name: "ping",
  description: "View the reaction times",
  slashInfo: {
    enabled: true,
    public: false,
  },
  getSlashInfo: function() {
    const { SlashCommandBuilder } = require("discord.js");
    const builder = new SlashCommandBuilder();
    // Set basic command information
    builder.setName(this.name);
    builder.setDescription(this.description);
    // If the command can be used in DMs
    builder.setDMPermission(true);
    // Return the information in JSON format
    return builder.toJSON();
  },
  async execute(interaction, _prefix, client) {
    interaction.reply({ content: `**Pong** in ${client.ws.ping}ms` });
  }
}

commandHandler.js:

function postSlashCommand(data, to, client) {
  if (!to) {
    // Post command to all guilds
    rest.put(
      Routes.applicationCommands(client.user.id),
      { body: data }
    );
  } else {
    // Post command for use only in a specific server
    rest.put(
      Routes.applicationGuildCommands(client.user.id, to),
      { body: data }
    );
  }
}

async function setupSlashCommands(directory, client) {
  // Loop through known command files
  const commandFolders = fs.readdirSync(`./${directory}`).filter(file => !file.endsWith(".js") && !file.endsWith(".json"));
  for (const folder of commandFolders) {
    const commandFiles = fs.readdirSync(`./${directory}/${folder}`).filter(file => file.endsWith(".js"));
    for (const file of commandFiles) {
      // Find the command object
      const command = require(`../../${directory}/${folder}/${file}`);
      // Ensure the command supports slash
      if (!command.slashInfo?.enabled) return;

      // Get the slash data
      let data = command.getSlashInfo();

      // Post the command to Discord
      if (command.slashInfo.public) { // If the slash command is public
        // Post command to all guilds
        postSlashCommand(data, null, client);
      } else { // If the slash command is in testing
        // Post command for use only in the dev server
        postSlashCommand(data, require("../../utils/config.json").DevServer, client);
      }
    }
  }
}

module.exports = (client) => setupSlashCommands("commands", client);

Full error:

throw new DiscordAPIError.DiscordAPIError(data, "code" in data ? data.code : data.error, status, method, url, requestData);
              ^

DiscordAPIError[50035]: Invalid Form Body
0[LIST_TYPE_CONVERT]: Only iterables may be used in a ListType
    at SequentialHandler.runRequest (D:\Projects\...\node_modules\@discordjs\rest\dist\lib\handlers\SequentialHandler.cjs:287:15)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async SequentialHandler.queueRequest (D:\Projects\...\node_modules\@discordjs\rest\dist\lib\handlers\SequentialHandler.cjs:99:14)
    at async REST.request (D:\Projects\...\node_modules\@discordjs\rest\dist\lib\REST.cjs:52:22) {
  rawError: {
    code: 50035,
    errors: {
      _errors: [
        {
          code: 'LIST_TYPE_CONVERT',
          message: 'Only iterables may be used in a ListType'
        }
      ]
    },
    message: 'Invalid Form Body'
  },
  code: 50035,
  status: 400,
  method: 'PUT',
  url: 'https://discord.com/api/v10/applications/<application_id>/guilds/<guild_id>/commands',
  requestBody: {
    files: undefined,
    json: {
      options: [],
      name: 'ping',
      name_localizations: undefined,
      description: 'View the reaction times',
      description_localizations: undefined,
      default_permission: undefined,
      default_member_permissions: undefined,
      dm_permission: true
    }
  }
}

Is there any way to simply create a slash command without providing the options property?

Upvotes: 0

Views: 2056

Answers (1)

MrMythical
MrMythical

Reputation: 9041

That endpoint takes an array of application commands. Instead of attempting to put a single command at a time, put all of them at once. Add the data to an array, then you will register them

const globalCommands = [],
guildCommands = [];
// Loop through known command files
  const commandFolders = fs.readdirSync(`./${directory}`).filter(file => !file.endsWith(".js") && !file.endsWith(".json"));
  for (const folder of commandFolders) {
    const commandFiles = fs.readdirSync(`./${directory}/${folder}`).filter(file => file.endsWith(".js"));
    for (const file of commandFiles) {
      const command = require(`../../${directory}/${folder}/${file}`);
      // Ensure the command supports slash
      if (!command.slashInfo?.enabled) return;

      // Add the slash data to the array
      if (command.slashInfo.public) globalCommands.push(command.getSlashInfo());
      else guildCommands.push(command.getSlashInfo())
    }
  }

Afterward, simply put the commands, and with what I see, you want to do global and guild commands, separately

postSlashCommand(guildCommands, require("../../utils/config.json").DevServer, client)
postSlashCommand(globalCommands, null, client)

Upvotes: 1

Related Questions