Interactions

Commands

Learn how to create slash commands with djs-core.

Slash commands are the primary way users interact with your Discord bot. They appear in Discord's command menu and can accept various types of options.

Commands are automatically registered when placed in src/interactions/commands/. The command name is derived from the file path, so src/interactions/commands/ping.ts becomes /ping.

Creating a Command

Commands in djs-core are created using the Command class. Each command file in src/interactions/commands/ automatically becomes a slash command.

Basic Command

Here's a simple ping command:

import { Command } from "@djs-core/runtime";

export default new Command()
    .setDescription("Ping the bot")
    .run(async (interaction) => {
        await interaction.reply("Pong!");
    });

The command name is automatically derived from the file path:

File Path
string
The command route based on the file location
Command Name
string
The resulting slash command in Discord
File PathCommand Name
src/interactions/commands/ping.ts/ping
src/interactions/commands/admin/kick.ts/admin kick
src/interactions/commands/shop/buy.ts/shop buy
src/interactions/commands/admin/moderation/ban.ts/admin moderation ban

Command Options

Commands can accept various types of options to collect user input. Each option type serves a specific purpose:

String
option
Text input - for names, descriptions, messages, etc.
Integer/Number
option
Numeric input - for quantities, IDs, timestamps, etc.
Boolean
option
True/false checkbox - for toggles and flags
User
option
Discord user selection - for mentions and user-specific actions
Channel
option
Discord channel selection - for channel configuration
Role
option
Discord role selection - for role assignment
Mentionable
option
User or role selection - flexible mention option
Attachment
option
File upload - for images, documents, etc.

String Option

import { Command } from "@djs-core/runtime";
import { MessageFlags } from "discord.js";

export default new Command()
    .setDescription("A command with options")
    .addStringOption((option) =>
        option
            .setName("text")
            .setDescription("Enter some text")
            .setRequired(true),
    )
    .run(async (interaction) => {
        const text = interaction.options.getString("text");
        await interaction.reply(`You entered: ${text}`);
    });

Other Option Types

djs-core supports all Discord.js option types. Here are examples for each:

export default new Command()
  .setDescription("Set a number")
  .addIntegerOption((option) =>
    option
      .setName("count")
      .setDescription("Enter a number")
      .setRequired(true)
      .setMinValue(1)
      .setMaxValue(100),
  )
  .run(async (interaction) => {
    const count = interaction.options.getInteger("count");
    await interaction.reply(`You entered: ${count}`);
  });

Multiple Options

You can add multiple options to a single command:

import { Command } from "@djs-core/runtime";

export default new Command()
    .setDescription("Send a message to a user")
    .addUserOption((option) =>
        option
            .setName("user")
            .setDescription("The user to message")
            .setRequired(true),
    )
    .addStringOption((option) =>
        option
            .setName("message")
            .setDescription("The message to send")
            .setRequired(true),
    )
    .run(async (interaction) => {
        const user = interaction.options.getUser("user");
        const message = interaction.options.getString("message");
        
        await interaction.reply({
            content: `Sending "${message}" to ${user?.username}`,
        });
    });

Autocomplete

Commands can provide autocomplete suggestions for string, integer, and number options. This improves user experience by showing relevant options as they type.

Autocomplete is especially useful for commands with many possible values, like searching for items, selecting from a list, or choosing from predefined options.
import { Command } from "@djs-core/runtime";

export default new Command()
    .setDescription("Search for something")
    .addStringOption((option) =>
        option
            .setName("query")
            .setDescription("Search query")
            .setRequired(true)
            .setAutocomplete(true)
    )
    .run(async (interaction) => {
        const query = interaction.options.getString("query");
        await interaction.reply(`You searched for: ${query}`);
    })
    .runAutocomplete(async (interaction) => {
        const focusedValue = interaction.options.getFocused();
        
        // Filter suggestions based on user input
        const choices = ["apple", "banana", "cherry"].filter((choice) =>
            choice.startsWith(focusedValue),
        );
        
        await interaction.respond(
            choices.map((choice) => ({ name: choice, value: choice })),
        );
    });

Ephemeral Responses

To make a response only visible to the user who ran the command:

import { Command } from "@djs-core/runtime";
import { MessageFlags } from "discord.js";

export default new Command()
    .setDescription("A private command")
    .run(async (interaction) => {
        await interaction.reply({
            content: "This message is only visible to you!",
            flags: [MessageFlags.Ephemeral],
        });
    });

Command Organization

Commands can be organized into subcommands using the file structure:

src/interactions/commands/
  ├── ping.ts              → /ping
  ├── admin/
  │   ├── kick.ts          → /admin kick
  │   └── ban.ts           → /admin ban
  └── shop/
      ├── buy.ts           → /shop buy
      └── sell.ts          → /shop sell

Permissions

You can restrict commands to users with specific permissions. This is essential for administrative or sensitive commands.

Users without the required permissions won't see the command in Discord's command menu at all.
src/interactions/commands/admin/restart.ts
import { Command } from "@djs-core/runtime";
import { PermissionFlagsBits } from "discord.js";

export default new Command()
    .setDescription("Restart the bot")
    .setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
    .run(async (interaction) => {
        await interaction.reply("Bot restarting...");
        // Restart logic here
    });

Common Permission Flags

Administrator
PermissionFlagsBits
Full access to the server
ManageGuild
PermissionFlagsBits
Manage server settings
ManageMessages
PermissionFlagsBits
Delete and manage messages
ManageRoles
PermissionFlagsBits
Create, edit, and delete roles
KickMembers
PermissionFlagsBits
Kick members from the server
BanMembers
PermissionFlagsBits
Ban members from the server