Creating Commands

Reciple includes a built-in command handler for all types of commands, making command creation simple and hassle-free.

This guide will teach you how to create slash commands, context menu commands, and message commands.

Slash Commands

First, create a new JavaScript file in your modules folder. In this case, we will name it slashcommand.js.

This is what the directory should look like:

mybot/
├── reciple.mjs
├── package.json
├── package-lock.json
├── node_modules/
└── modules/
    └── commands/
        └── slashcommand.js
INFO
You can create a subfolders for the commands folder so your command files doesn't end up in the same place.

Open the file in your code editor, and export a module class

export class MySlashCommand {
    commands = [];

    onStart() {
        return true;
    }
}

export default new MySlashCommand();

To add your commands, you will need to import the SlashCommandBuilder and create new instance in the commands property of your module.

You will need to import the command builder from reciple instead of discord.js
import { SlashCommandBuilder } from 'reciple';

export class MySlashCommand {
    commands = [
        new SlashCommandBuilder()
            .setName('ping')
            .setDescription('My ping command')
            .setExecute(async ({ interaction }) => {
                await interaction.reply('Pong!');
            })
    ];

    onStart() {
        return true;
    }
}

export default new MySlashCommand();

After that, you can start your bot and see if the module has been loaded and the commands are registered.

[11:27:01 INFO] Registered (1) application commands globally
[11:27:01 WARN] Logged in as Guide Bot#6969 (1130868345672048731)
[11:27:01 INFO] Loaded 0 context menu command(s)
[11:27:01 INFO] Loaded 0 message command(s)
[11:27:01 INFO] Loaded 1 slash command(s)
[11:27:01 INFO] Loaded 2 precondition(s)

You can now use the command you created by typing /ping.

Pong!

Context Menu Commands

Context menus, unlike slash commands, can only be used by right-clicking on a message or user.

To create a context menu command, create a new JavaScript file inside your modules folder similar on how you did with slash commands. In this case we will name the file contextmenucommand.js.

This is what the directory should look like now:

mybot/
├── reciple.mjs
├── package.json
├── package-lock.json
├── node_modules/
└── modules/
    └── commands/
        ├── contextmenucommand.js
        └── slashcommand.js

Open the file in your code editor, and export a module class

export class MyContextMenuCommand {
    commands = [];

    onStart() {
        return true;
    }
}

export default new MyContextMenuCommand();

Like slash commands, import the ContextMenuCommandBuilder and create a new instance in the commands property.

import { ContextMenuCommandBuilder } from 'reciple';
import { ApplicationCommandType, AttachmentBuilder } from 'discord.js';

export class MyContextMenuCommand {
    commands = [
        new ContextMenuCommandBuilder()
            .setName('Avatar')
            .setType(ApplicationCommandType.User)
            .setExecute(async ({ interaction }) => {
                await interaction.reply({
                    files: [
                        new AttachmentBuilder(interaction.user.displayAvatarURL({ extension: 'png' }), {
                            name: 'avatar.png'
                        })
                    ]
                });
            })
    ];

    onStart() {
        return true;
    }
}

export default new MyContextMenuCommand();

You can now start your bot and verify that the module has been loaded and commands have been registered.

[11:27:01 INFO] Registered (1) application commands globally
[11:27:01 WARN] Logged in as Guide Bot#6969 (1130868345672048731)
[11:27:01 INFO] Loaded 1 context menu command(s)
[11:27:01 INFO] Loaded 0 message command(s)
[11:27:01 INFO] Loaded 1 slash command(s)
[11:27:01 INFO] Loaded 2 precondition(s)

Use the context menu command by right-clicking on a user and selecting the command you created under Apps in the context menu that appears.

Message Commands

Similar to the previous steps, create a new file in your modules folder and in this case we’ll name it messagecommand.js.

This is what the directory should look like now:

mybot/
├── reciple.mjs
├── package.json
├── package-lock.json
├── node_modules/
└── modules/
    └── commands/
        ├── contextmenucommand.js
        ├── messagecommand.js
        └── slashcommand.js

Then, open the file in your code editor, and export a module class

export class MyMessageCommand {
    commands = [];

    onStart() {
        return true;
    }
}

export default new MyMessageCommand();

Reciple provides a custom message command builder that uses methods similar to SlashCommandBuilder. Now import the MessageCommandBuilder and create a new instance in the commands property.

Instead of interactions, message commands passes the message that triggered the command into the execute function.

import { MessageCommandBuilder } from 'reciple';

export class MyMessageCommand {
    commands = [
        new MessageCommandBuilder()
            .setName('ping')
            .setDescription('Ping command')
            .setExecute(async ({ message }) => {
                await message.reply('Pong!');
            })
    ];

    onStart() {
        return true;
    }
}

export default new MyMessageCommand();

You can now start your bot and then your bot is ready with commands.

[11:27:01 INFO] Registered (1) application commands globally
[11:27:01 WARN] Logged in as Guide Bot#6969 (1130868345672048731)
[11:27:01 INFO] Loaded 1 context menu command(s)
[11:27:01 INFO] Loaded 1 message command(s)
[11:27:01 INFO] Loaded 1 slash command(s)
[11:27:01 INFO] Loaded 2 precondition(s)

You can execute a message command by sending a message with the prefix configured in your reciple.mjs file.

!ping !ping Pong!

Message Command Options

You can add options to your message commands that returns the values of arguments separated by the commandArgumentSeparator in your config.

import { MessageCommandBuilder } from 'reciple';

export class MyMessageCommand {
    commands = [
        new MessageCommandBuilder()
            .setName('ping')
            .setDescription('Ping command')
            .addOption(times => times
                .setName('times')
                .setDescription('Ping how many times')
                .setRequired(false)
                .setResolveValue(({ value }) => Number(value))
                .setValidate(({ value }) => !isNaN(Number(value)))
            )
            .setExecute(async ({ message, options }) => {
                const times = await options.getOptionValue('times', { resolveValue: true }) || 1;

                await message.reply('Pong! '.repeat(times).trim());
            })
    ];

    onStart() {
        return true;
    }
}

export default new MyMessageCommand();

After that, execute the command with an argument.

!pong 2 !pong 2 Pong! Pong!

You can also set an alias to a message command by using .addAliases().

import { MessageCommandBuilder } from 'reciple';

export class MyMessageCommand {
    commands = [
        new MessageCommandBuilder()
            .setName('ping')
            .addAliases('p')
            .setDescription('Ping command')
            .addOption(times => times
                .setName('times')
                .setDescription('Ping how many times')
                .setRequired(false)
                .setResolveValue(({ value }) => Number(value))
                .setValidate(({ value }) => !isNaN(Number(value)))
            )
            .setExecute(async ({ message, options }) => {
                const times = await options.getOptionValue('times', { resolveValue: true }) || 1;

                await message.reply('Pong! '.repeat(times).trim());
            })
    ];

    onStart() {
        return true;
    }
}

export default new MyMessageCommand();
INFO
resolveValue is true to use the function we passed to .setResodeolveValue()

Read More

You can now execute the same message command using the alias.

!p 4 !p 2 Pong! Pong! Pong! Pong!

No Builders 😡

Some people dislike builders, so we added support for command data, allowing you to create command objects directly in the commands property.

View Docs for the type definition of each command data:

Command Data Usage

import { CommandType, SlashCommandBuilder } from 'reciple';

export class MySlashCommand {
    commands = [
        {
            command_type: CommandType.SlashCommand,
            name: 'ping',
            description: 'Ping command',
            execute: async ({ interaction }) => {
                await interaction.reply('Pong!');
            }
        }
    ];

    onStart() {
        return true;
    }
}

export default new MySlashCommand();