This is an example of how to use this template
This project assumes that you have a passing acquaintance with these tools:
- javascript
- node.js
- discord.js
-
Clone the repo
git clone https://github.com/Chaoray/DiscordBotTemplate.git
-
Install packages
npm install
-
Enter your discord bot information in
.env
.
You may have to create the.env
file by yourself due to security issue.
Here's a template, paste it to the file and fill in the blank.TOKEN=[Your Token Here] APP_ID=[Your Application ID Here]
-
Deploy Commands
npm run build
or
Press Ctrl+Shift+B
if you're using VSCode -
Start the bot
npm start
or Press
F5
if you're using VSCode
Here's an example of creating an echo
command
-
Go to the
commands
folder and add a new file.
In this example, the filename isecho.mjs
-
Copy-paste the following command template into the file:
import { SlashCommandBuilder, CommandInteraction } from 'discord.js'; export default { data: new SlashCommandBuilder() .setName('my-command-name') .setDescription('my-command-description'), /** * execute * @param {CommandInteraction} interaction */ async execute(interaction) { }, };
-
Change the name and description into whatever you like
data: new SlashCommandBuilder() .setName('echo') .setDescription('repeat what you said'),
-
Let's add an option
data: new SlashCommandBuilder() .setName('echo') .setDescription('repeat what you said') // add the following .addStringOption(option => option.setName('message') .setDescription('the message to repeat') .setRequired(true)),
-
Now we can code the execute function
/** * execute * @param {CommandInteraction} interaction */ async execute(interaction) { const message = interaction.options.getString('message'); if (message) { await interaction.reply(message); } else { await interaction.reply('Sorry, I can\'t hear you.'); } },
Final Code:
import { SlashCommandBuilder, CommandInteraction } from 'discord.js'; export default { data: new SlashCommandBuilder() .setName('echo') .setDescription('repeat what you said') .addStringOption(option => option.setName('message') .setDescription('the message to repeat') .setRequired(true)), /** * execute * @param {CommandInteraction} interaction */ async execute(interaction) { const message = interaction.options.getString('message'); if (message) { await interaction.reply(message); } else { await interaction.reply('Sorry, I can\'t hear you.'); } }, };
-
Deploy Commands
npm run build
or Press Ctrl+Shift+B if you're using VSCode
-
Start the bot
npm start
-
You might notice that the command is nowhere to be found.
In this regard, you can pressCtrl+R
to refresh your discord to see the change.
The structure of commands with components is similar to normal commands.
You can check commands/ping-button.mjs
as an example.
Let's create an "say my name" button.
Result:
-
Complete the basic structure of a normal command
import { SlashCommandBuilder, CommandInteraction } from 'discord.js'; export default { data: new SlashCommandBuilder() .setName('create-say-my-name-button') .setDescription('Create a button that say your name'), /** * execute * @param {CommandInteraction} interaction */ async execute(interaction) { }, };
-
Add
hasComponent
property to inform the command loader.import { SlashCommandBuilder, CommandInteraction } from 'discord.js'; export default { data: new SlashCommandBuilder() .setName('create-say-my-name-button') .setDescription('Create a button that say your name'), hasComponent: true, // add this /** * execute * @param {CommandInteraction} interaction */ async execute(interaction) { }, };
-
Create a button reply in
execute
, don't forget to import modules needed.import { SlashCommandBuilder, CommandInteraction, ButtonBuilder, ButtonStyle, ActionRowBuilder, MessageComponentInteraction } from 'discord.js'; export default { data: new SlashCommandBuilder() .setName('create-say-my-name-button') .setDescription('Create a button that say your name'), hasComponent: true, /** * execute * @param {CommandInteraction} interaction */ async execute(interaction) { const sayMyName = new ButtonBuilder() .setCustomId('say-my-name-button') .setLabel('Say My Name!') .setStyle(ButtonStyle.Primary); const row = new ActionRowBuilder().addComponents(sayMyName); await interaction.reply({ content: `Press it!`, components: [row] }); }, };
-
Now we can add a
customId
field and fill it with our components' custom Idsimport { SlashCommandBuilder, CommandInteraction, ButtonBuilder, ButtonStyle, ActionRowBuilder, MessageComponentInteraction } from 'discord.js'; export default { data: new SlashCommandBuilder() .setName('create-say-my-name-button') .setDescription('Create a button that say your name'), hasComponent: true, customId: ['say-my-name-button'], // add this, the same with your button /** * execute * @param {CommandInteraction} interaction */ async execute(interaction) { const sayMyName = new ButtonBuilder() .setCustomId('say-my-name-button') // the button's custom Id .setLabel('Say My Name!') .setStyle(ButtonStyle.Primary); const row = new ActionRowBuilder().addComponents(sayMyName); await interaction.reply({ content: `Press it!`, components: [row] }); }, };
That will function as an register. When
buttonInteractionCreate
is triggered, we should be notified.
If you didn't add those ids to the array, you can handle interactions inexecute
by yourself. (only one execution) -
Insert in a new function
componentExecute
that executes when notified.import { SlashCommandBuilder, CommandInteraction, ButtonBuilder, ButtonStyle, ActionRowBuilder, MessageComponentInteraction } from 'discord.js'; export default { data: new SlashCommandBuilder() .setName('create-say-my-name-button') .setDescription('Create a button that say your name'), hasComponent: true, customId: ['say-my-name-button'], /** * execute * @param {CommandInteraction} interaction */ async execute(interaction) { const sayMyName = new ButtonBuilder() .setCustomId('say-my-name-button') .setLabel('Say My Name!') .setStyle(ButtonStyle.Primary); const row = new ActionRowBuilder().addComponents(sayMyName); await interaction.reply({ content: `Press it!`, components: [row] }); }, // add the following lines /** * execute * @param {MessageComponentInteraction} interaction * @returns */ async componentExecute(interaction) { if (interaction.component.customId === 'say-my-name-button') { return interaction.update({ content: `<@${interaction.user.id}>` }); } } // end };
Even though the
componentExecute
will be called when correct ids are received,
I still recommend you to checkcustomId
. -
We are done! Now build and run to see the result.
Final Code:import { SlashCommandBuilder, CommandInteraction, ButtonBuilder, ButtonStyle, ActionRowBuilder, MessageComponentInteraction } from 'discord.js'; export default { data: new SlashCommandBuilder() .setName('create-say-my-name-button') .setDescription('Create a button that say your name'), hasComponent: true, customId: ['say-my-name-button'], /** * execute * @param {CommandInteraction} interaction */ async execute(interaction) { const sayMyName = new ButtonBuilder() .setCustomId('say-my-name-button') .setLabel('Say My Name!') .setStyle(ButtonStyle.Primary); const row = new ActionRowBuilder().addComponents(sayMyName); await interaction.reply({ content: `Press it!`, components: [row] }); }, /** * execute * @param {MessageComponentInteraction} interaction * @returns */ async componentExecute(interaction) { if (interaction.component.customId === 'say-my-name-button') { return interaction.update({ content: `<@${interaction.user.id}>` }); } } };
Whenever the command data e.g. name, description or options is changed.
Or when a command is added / deleted.
Don't deploy on every start. It's redundant.
Please check the official tutorial: Component interactions
This command can reload a command without restarting the bot, including itself.
You can add role check or id check to prevent others from using it.