Event handlingโ
๐ก This page requires you to have a valid main file, have at least created one command following these steps and followed the last step command handling.
โน๏ธ This section can be done for both slash-commands and message-commands, as Client#messageCreate as message-commands are executed from within the Client#messageCreate event.
Before you continueโ
Assuming you've followed the guide so far, your project directory should look something like this:
discord-bot/
โโโ node_modules/
โโโ src/
โ โโโ commands/
โ โ โโโ play.js
โ โโ โ config.js
โ โโโ index.js
โโโ package-lock.json
โโโ package.json
Individual event filesโ
Loading event filesโ
To begin, remove any code from index.js that is related to client.on().
Then, add the following event-loading code into the index.js file, right after the command-loading section:
const loadEvents = (folderPath) => {
// Read all files from the specified folder
const eventFiles = fs.readdirSync(folderPath);
for (const file of eventFiles) {
const filePath = path.join(folderPath, file);
const stat = fs.statSync(filePath);
// If it's a directory, recursively load events from it
if (stat.isDirectory()) {
loadEvents(filePath);
} else if (file.endsWith('.js')) {
// Require the event module
const event = require(filePath);
// If the event should be handled only once
if (event.once) {
if (filePath.includes(`${path.sep}magmastream${path.sep}`)) {
// Handle Magmastream events differently
client.manager.on(event.name, (...args) => event.execute(client, ...args));
} else {
// Register a one-time event listener
client.once(event.name, (...args) => event.execute(client, ...args));
}
} else {
if (filePath.includes(`${path.sep}magmastream${path.sep}`)) {
// Handle Magmastream events differently
client.manager.on(event.name, (...args) => event.execute(client, ...args));
} else {
// Register a persistent event listener
client.on(event.name, (...args) => event.execute(client, ...args));
}
}
console.log(`[INFO] Loaded event: ${event.name}`);
}
}
};
This code uses a the exact method to load files as the command loader.
If you want to make sure, you have the exact code for the index.js file, you can review it on the GitHub repository here .
Event files structureโ
Create a new folder inside the src/ folder, named events and two subfolder named discord and magmastream inside it.
โ ๏ธ Please make sure to select below the command creation "step" you need. The section below is divided into "Discord Events" and "Magmastream Events".
- Discord Events
- Magmastream Events
Letโs begin by creating three files named raw.js, ready.js and interactionCreate.js inside the events/discord folder.
The files should be structured as follows:
- events/discord/ready.js
- events/discord/interactionCreate.js
- events/discord/raw.js
const { Events } = require("discord.js");
module.exports = {
name: Events.ClientReady,
once: true,
execute(client) {
// Initialize Lavalink
client.manager.init(client.user.id);
// Print a message to the console indicating that the client is ready
console.log(`[INFO] Ready! Logged in as ${client.user.tag}`);
},
};
const { Events, MessageFlags } = require('discord.js');
module.exports = {
name: Events.InteractionCreate,
async execute(client, interaction) {
// Only handle chat input commands
if (!interaction.isChatInputCommand()) return;
// Get the command from the command collection
const command = client.commands.get(interaction.commandName);
// If no command is found, log an error
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
try {
// Execute the command
await command.execute(client, interaction);
} catch (error) {
// Log the error
console.error(error);
// Reply with an ephemeral message if the interaction has already been replied to
if (interaction.replied || interaction.deferred) {
await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
} else {
await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
}
}
},
};
const { Events } = require("discord.js");
module.exports = {
name: Events.Raw,
execute(client, data) {
// This is required by magmastream!
// Update the voice state in the Lavalink manager
client.manager.updateVoiceState(data);
},
};
Letโs begin by creating three files named nodeConnet.js, trackStart.js and queueEnd.js inside the events/magmastream folder.
The files should be structured as follows:
- events/magmastream/nodeConnect.js
- events/magmastream/trackStart.js
- events/magmastream/queueEnd.js
const { ManagerEventTypes } = require("magmastream");
module.exports = {
name: ManagerEventTypes.NodeConnect,
execute(client, node) {
console.log(`[NODECONNECT] Connected to node ${node.options.identifier}`);
},
};
const { ManagerEventTypes } = require("magmastream");
module.exports = {
name: ManagerEventTypes.TrackStart,
async execute(client, player, track) {
const channel = client.channels.cache.get(player.textChannelId);
if (!channel) return;
channel
.send(`Now playing: \`${track.title}\`, requested by \`${track.requester.username}\`.`)
.catch((error) => console.log(`[TRACKSTART] Failed to send message to channel: ${player.textChannelId}`));
},
};
const { ManagerEventTypes } = require("magmastream");
module.exports = {
name: ManagerEventTypes.QueueEnd,
async execute(client, player, track) {
const channel = client.channels.cache.get(player.textChannelId);
if (!channel) return;
channel.send(`Queue has ended!`).catch((error) => console.log(`[QUEUEEND] Failed to send message to channel: ${player.textChannelId}`));
},
};
If you want to make sure, you have the exact code for the different events etc. take a look at the example GitHub repository here .
Next stepsโ
You can implement additional events by creating new files within a dedicated subfolder in the events folder, but these are the ones we're going to use for the examples as we go on.
Next: We'll create a [deployment script] for our slash commands.
Resulting codeโ
If you want to compare your code to the final result after completing all the steps in this guide, you can review it on the GitHub repository here .