Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/resynceddesign/giveawaybot/llms.txt

Use this file to discover all available pages before exploring further.

GiveawayBot uses a modular command handler that discovers and registers slash commands automatically at startup. You never need to edit the core bot files — just drop a new TypeScript file into src/commands/, build, and restart.

How the handler works

src/handlers/Command.ts runs once when the bot starts. It uses readdirSync to scan the compiled build/commands/ directory for every .js file, imports each one, and registers it both with Discord’s API (via REST.put) and locally in client.slashCommands for routing.
readdirSync(slashCommandsDir).forEach((file) => {
    if (!file.endsWith(".js")) return;
    let command: SlashCommand = require(`${slashCommandsDir}/${file}`).default;
    slashCommands.push(command.command);
    client.slashCommands.set(command.command.name, command);
});
Any file you add to src/commands/ is picked up on the next restart — no registration step needed.

The SlashCommand interface

Every command file must export a default object that satisfies the SlashCommand interface defined in src/types.d.ts:
export interface SlashCommand {
    command: SlashCommandOptionsOnlyBuilder;
    execute: (interaction: ChatInputCommandInteraction) => void;
    autocomplete?: (interaction: AutocompleteInteraction) => void;
    modal?: (interaction: ModalSubmitInteraction<CacheType>) => void;
    cooldown?: number; // seconds
}
  • command — a Discord.js SlashCommandBuilder (or subclass) that defines the command name, description, and options.
  • execute — called when a user runs the command.
  • autocomplete — optional; called for autocomplete interactions on any of the command’s string options.
  • modal — optional; called when a modal submit matches this command’s name via customId.
  • cooldown — optional number of seconds. When set, the interactionCreate event handler automatically enforces the cooldown per user and sends a temporary reply if the user tries to run it too soon.

Adding a custom command

1

Create a new file in src/commands/

Create src/commands/myCommand.ts. The filename becomes part of your workflow but does not affect the command name — that is set by SlashCommandBuilder.setName().
2

Write the command

Implement the SlashCommand interface. Here is a minimal, working example modeled on the existing command pattern:
import { SlashCommandBuilder } from "discord.js";
import { SlashCommand } from "../types";

const command: SlashCommand = {
    command: new SlashCommandBuilder()
        .setName("ping")
        .setDescription("Check the bot's response time"),
    execute: (interaction) => {
        const latency = Date.now() - interaction.createdTimestamp;
        interaction.reply({
            content: `Pong! Latency: ${latency}ms`,
            ephemeral: true,
        });
    },
    cooldown: 5,
};

export default command;
3

Build the project

Compile TypeScript to JavaScript so the handler can load it:
npm run build
4

Restart the bot

Restart the bot process. On startup, Command.ts scans build/commands/, finds your new .js file, and registers it with Discord automatically.

Cooldowns

Set the optional cooldown property to a number of seconds to rate-limit a command per user:
cooldown: 10, // users must wait 10 seconds between uses
The interactionCreate event handler reads this value, tracks per-user timestamps in client.cooldowns, and replies with a countdown message if the user triggers the command too early. The cooldown reply is automatically deleted after 5 seconds.
Use ephemeral: true on any reply that is only relevant to the invoking user — such as confirmation messages, error feedback, or admin-only output. Ephemeral replies are visible only to that user and keep channels clean.

Build docs developers (and LLMs) love