Event handling
Node.js uses an event-driven architecture, making it possible to execute code when a specific event occurs. The discord.js library takes full advantage of this. You can visit the Client
open in new window documentation to see the full list of events.
Here's the base code we'll be using:
const { Client, Intents } = require('discord.js');
const { token } = require('./config.json');
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
client.once('ready', c => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
client.on('interactionCreate', interaction => {
console.log(`${interaction.user.tag} in #${interaction.channel.name} triggered an interaction.`);
});
client.login(token);
2
3
4
5
6
7
8
9
10
11
12
13
14
Currently, the event listeners are in the index.js
file. Client#event:ready
open in new window emits once when the Client
becomes ready for use, and Client#event:interactionCreate
open in new window emits whenever an interaction is received. Moving the event listener code into individual files is simple, and we'll be taking a similar approach to the command handler.
Individual event files
Your project directory should look something like this:
discord-bot/
├── node_modules
├── config.json
├── index.js
├── package-lock.json
└── package.json
Create an events
folder in the same directory. You can then take your existing events code in index.js
and move them to events/ready.js
and events/interactionCreate.js
files.
module.exports = {
name: 'ready',
once: true,
execute(client) {
console.log(`Ready! Logged in as ${client.user.tag}`);
},
};
2
3
4
5
6
7
module.exports = {
name: 'interactionCreate',
execute(interaction) {
console.log(`${interaction.user.tag} in #${interaction.channel.name} triggered an interaction.`);
},
};
2
3
4
5
6
The name
property states which event this file is for, and the once
property is a boolean that specifies if the event should run only once. The execute
function is for your event logic, which will be called by the event handler whenever the event emits.
Reading event files
Next, let's write the code for dynamically retrieving all the event files in the events
folder. We'll be taking a similar approach to our command handler.
fs.readdirSync().filter()
returns an array of all the file names in the given directory and filters for only .js
files, i.e. ['ready.js', 'interactionCreate.js']
.
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));
for (const file of eventFiles) {
const filePath = path.join(eventsPath, file);
const event = require(filePath);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
The Client
open in new window class in discord.js extends the EventEmitter
open in new window class. Therefore, the client
object exposes the .on()
open in new window and .once()
open in new window methods that you can use to register event listeners. These methods take two arguments: the event name and a callback function.
The callback function passed takes argument(s) returned by its respective event, collects them in an args
array using the ...
rest parameter syntaxopen in new window, then calls event.execute()
while passing in the args
array using the ...
spread syntaxopen in new window. They are used here because different events in discord.js have different numbers of arguments. The rest parameter collects these variable number of arguments into a single array, and the spread syntax then takes these elements and passes them to the execute
function.
After this, listening for other events is as easy as creating a new file in the events
folder. The event handler will automatically retrieve and register it whenever you restart your bot.
TIP
In most cases, you can access your client
instance in other files by obtaining it from one of the other discord.js structures, e.g. interaction.client
in the interactionCreate
event.
Resulting code
If you want to compare your code to the code we've constructed so far, you can review it over on the GitHub repository here open in new window.