In this episode, we make a new Discord bot from scratch and create a simple slash command!
Create a new Node.js project and install necessary dependencies.
$ npm init
$ npm install discord.js dotenv
Add a property "type": "module"
in your package.json
file in order to use ES6 module import syntax.
- Navigate to the Discord Developer Portal and create a new application.
- Optionally, set the application name, description, and avatar.
- Note down the "Application ID" (also known as "Client ID").
- In the Discord Developer Portal, select "Bot" from the left navigation.
- Set a name and icon for your bot.
- Note down the "Bot Token" (keep this secret).
- Go to your application page in the Discord developer portal.
- Navigate to "OAuth" -> "URL Generator".
- Check "application.commands" and "bot".
- Open the URL that populates at the bottom and authorize the bot to access your server.
- Enable "Developer Mode" under the "Advanced" settings tab on your Discord client.
- Right-click on the server icon, and select "Copy ID" to get the server ID.
Create a .env
file in your project root and add your client ID, server ID, and bot token:
CLIENTID=1234
SERVERID=1234
TOKEN=1234
These environment variables are used to keep sensitive data, like your bot token, out of your code. This is especially important if you're sharing your code with others or storing your code publicly on GitHub. (Notice how .env
is included in .gitignore
.)
Create bot.js
(or index.js
) and paste this code:
import { Client, Events, GatewayIntentBits } from 'discord.js';
import { config } from 'dotenv';
config();
// Create a new client instance
const client = new Client({
intents: [GatewayIntentBits.Guilds],
});
// When the client is ready, run this code (only once)
client.once(Events.ClientReady, readyDiscord);
// Login to Discord with your client's token
client.login(process.env.TOKEN);
function readyDiscord() {
console.log('💖');
}
Run to see if it works! (If you see the 💖 it's working!)
$ node bot.js
Each command should be handled in a separate JS file, there are many ways you can manage this, but I suggest putting them in a folder called commands:
import { SlashCommandBuilder } from 'discord.js';
// Command Builder export
export const data = new SlashCommandBuilder()
.setName('choochoo')
.setDescription('Replies choo choo!');
// Execute function export
export async function execute(interaction) {
await interaction.reply('Choo choo!');
}
Create deploy-commands.js
and copy the example code. Then run it!
node deploy-commands.js
You only have to do this once. If you change the command (altering descriptions, changing options, etc.), then you do need to re-run deploy-commands.js
.
You also need to handle the command in bot.js, add the equivalent code:
import * as choochoo from './commands/choochoo.js';
client.on(Events.InteractionCreate, handleInteraction);
async function handleInteraction(interaction) {
if (!interaction.isCommand()) return;
if (interaction.commandName === 'choochoo') {
await choochoo.execute(interaction);
}
}
Then run the bot again!
node bot.js
commands/choochoo.js
: Defines a simple slash command.bot.js
: Handles interactions with Discord and executes commands.deploy-commands.js
: Script to register slash commands with Discord API.