DBI provides a powerful event system for handling both Discord events and custom events. This guide covers how to work with events effectively.
- Basic Events
- Multiple Event Handlers
- Event Configuration
- Custom Events
- DBI Events
- Event Order and Flow
dbi.register(({ Event }) => {
Event({
name: "clientReady", // Discord.js event name
id: "ready-logger", // Unique ID for this handler
onExecute({ client }) {
console.log(`✅ Bot is online as ${client.user.tag}`);
console.log(`📊 Serving ${client.guilds.cache.size} guilds`);
}
});
});Each event receives its parameters in an object format:
dbi.register(({ Event }) => {
// Message events
Event({
name: "messageCreate",
id: "message-logger",
onExecute({ message }) {
if (message.author.bot) return;
console.log(`[${message.guild?.name}] ${message.author.tag}: ${message.content}`);
}
});
// Member events
Event({
name: "guildMemberAdd",
id: "welcome-handler",
async onExecute({ member }) {
const channel = member.guild.systemChannel;
if (channel) {
await channel.send(`Welcome ${member}! 👋`);
}
}
});
// Reaction events
Event({
name: "messageReactionAdd",
id: "reaction-roles",
onExecute({ reaction, user }) {
if (user.bot) return;
console.log(`${user.tag} reacted with ${reaction.emoji.name}`);
}
});
});| Event Name | Parameters | Description |
|---|---|---|
clientReady |
{ client } |
Bot is connected and ready |
messageCreate |
{ message } |
New message received |
messageDelete |
{ message } |
Message was deleted |
messageUpdate |
{ oldMessage, newMessage } |
Message was edited |
guildCreate |
{ guild } |
Bot joined a guild |
guildDelete |
{ guild } |
Bot left a guild |
guildMemberAdd |
{ member } |
Member joined guild |
guildMemberRemove |
{ member } |
Member left guild |
guildMemberUpdate |
{ oldMember, newMember } |
Member updated |
interactionCreate |
{ interaction } |
Any interaction received |
voiceStateUpdate |
{ oldState, newState } |
Voice state changed |
channelCreate |
{ channel } |
Channel created |
channelDelete |
{ channel } |
Channel deleted |
roleCreate |
{ role } |
Role created |
roleDelete |
{ role } |
Role deleted |
You can register multiple handlers for the same event using unique IDs.
dbi.register(({ Event }) => {
// First handler - logging
Event({
name: "messageCreate",
id: "message-logger",
onExecute({ message }) {
console.log(`Message: ${message.id}`);
}
});
// Second handler - auto-moderation
Event({
name: "messageCreate",
id: "auto-mod",
onExecute({ message }) {
if (containsBadWords(message.content)) {
message.delete();
}
}
});
// Third handler - leveling system
Event({
name: "messageCreate",
id: "leveling",
async onExecute({ message }) {
if (message.author.bot) return;
await addXP(message.author.id, 10);
}
});
});dbi.register(({ Event }) => {
Event({
name: "messageCreate",
id: "togglable-logger",
disabled: false, // Can start disabled
onExecute({ message }) {
console.log(message.content);
}
});
});
// Toggle the handler programmatically
const handler = dbi.event("togglable-logger");
handler.toggle(); // Toggle state
handler.toggle(true); // Disable
handler.toggle(false); // Enable
console.log(handler.disabled); // Check stateControl how events are handled across multiple clients:
dbi.register(({ Event }) => {
Event({
name: "messageCreate",
id: "my-handler",
// "OneByOne" - Each client triggers sequentially
// "OneByOneGlobal" - Global sequential (default)
// "Random" - Random client handles
// "First" - First client only
triggerType: "OneByOneGlobal",
onExecute({ message, nextClient }) {
// nextClient is available for multi-client setups
console.log(`Handled by: ${nextClient?.namespace}`);
}
});
});Control execution order with delays:
dbi.register(({ Event }) => {
Event({
name: "messageCreate",
id: "ordered-handler",
ordered: {
await: true, // Wait for async completion
delayBefore: 100, // Wait 100ms before executing
delayAfter: 50 // Wait 50ms after executing
},
async onExecute({ message }) {
await doAsyncWork(message);
}
});
});dbi.register(({ Event }) => {
Event({
name: "messageCreate",
id: "debug-logger",
flag: "debug", // Only load with debug flag
onExecute({ message }) {
console.log("[DEBUG]", message);
}
});
});
// Load with debug events
await dbi.load("debug");
// Load without debug events
await dbi.load();dbi.register(({ createInlineEvent }) => {
// Create a temporary event that auto-removes
createInlineEvent({
name: "messageCreate",
ttl: 60000, // Auto-remove after 1 minute
onExecute({ message }) {
if (message.content === "special") {
message.reply("You found it!");
}
}
});
});Define your own events that can be triggered programmatically.
dbi.register(({ CustomEvent, Event }) => {
// Define a custom event structure
CustomEvent({
name: "userLevelUp",
map: {
userId: "userId",
newLevel: "newLevel",
guild: "guild"
}
});
// Listen for the custom event
Event({
name: "userLevelUp",
id: "levelup-announcer",
onExecute({ userId, newLevel, guild }) {
const channel = guild.systemChannel;
if (channel) {
channel.send(`🎉 <@${userId}> reached level ${newLevel}!`);
}
}
});
});
// Trigger the custom event from anywhere
dbi.emit("userLevelUp", {
userId: "123456789",
newLevel: 10,
guild: someGuild
});dbi.register(({ CustomEvent }) => {
const levelUpEvent = CustomEvent({
name: "playerLevelUp",
map: {
playerId: "playerId",
level: "level",
rewards: "rewards"
}
});
// Trigger using the returned object
levelUpEvent.trigger({
playerId: "12345",
level: 5,
rewards: ["gold", "exp_boost"]
});
});DBI provides internal events for interaction and event lifecycle management.
| Event | Description | Data |
|---|---|---|
clientsReady |
All clients connected | - |
beforeInteraction |
Before handling interaction | Context object |
afterInteraction |
After handling interaction | Context object |
interactionError |
Error during interaction | Context + error |
interactionRateLimit |
Rate limit triggered | Rate limit info |
beforeEvent |
Before event handler | Event data |
afterEvent |
After event handler | Event data |
eventError |
Error during event | Event data + error |
messageCommandArgumentError |
Invalid message command arg | Error details |
messageCommandDirectMessageUsageError |
DM command not allowed | Error details |
messageCommandDefaultMemberPermissionsError |
Missing permissions | Error details |
// Listen for interaction events
dbi.events.on("beforeInteraction", async (ctx) => {
console.log(`Interaction: ${ctx.dbiInteraction.name}`);
console.log(`User: ${ctx.interaction.user.tag}`);
// Return true to continue, false to stop
return true;
});
dbi.events.on("afterInteraction", async (ctx) => {
console.log(`Completed: ${ctx.dbiInteraction.name}`);
return true;
});dbi.events.on("interactionError", async ({ interaction, dbiInteraction, error }) => {
console.error(`Error in ${dbiInteraction.name}:`, error);
// Notify the user
try {
if (interaction.replied || interaction.deferred) {
await interaction.followUp({
content: "An error occurred. Please try again later.",
ephemeral: true
});
} else {
await interaction.reply({
content: "An error occurred. Please try again later.",
ephemeral: true
});
}
} catch (e) {
console.error("Could not send error message:", e);
}
return true;
});
dbi.events.on("eventError", async ({ eventName, dbiEvent, error }) => {
console.error(`Error in event ${eventName}:`, error);
return true;
});dbi.events.on("interactionRateLimit", async ({
interaction,
dbiInteraction,
rateLimit,
remainingTime
}) => {
const seconds = Math.ceil(remainingTime / 1000);
await interaction.reply({
content: `⏳ Slow down! Try again in ${seconds} seconds.`,
ephemeral: true
});
return false; // Don't execute the interaction
});const { ApplicationCommandOptionType } = require("discord.js");
dbi.events.on("messageCommandArgumentError", ({
message,
interaction,
dbiInteraction,
error
}) => {
message.reply(
`❌ Invalid argument \`${error.option.name}\` (Index: ${error.index}).\n` +
`Error: \`${error.type}\`\n` +
`Expected: \`${ApplicationCommandOptionType[error.option.type]}\``
);
return false; // Don't execute the command
});
dbi.events.on("messageCommandDirectMessageUsageError", ({ message }) => {
message.reply("❌ This command cannot be used in DMs.");
return false;
});
dbi.events.on("messageCommandDefaultMemberPermissionsError", ({
message,
permissions
}) => {
message.reply(`❌ You need these permissions: ${permissions.join(", ")}`);
return false;
});// Handler that runs only once
dbi.events.on("clientsReady", () => {
console.log("Bot is ready!");
}, { once: true });// on() returns a function to remove the handler
const removeHandler = dbi.events.on("beforeInteraction", (ctx) => {
console.log("Interaction received");
return true;
});
// Later, remove the handler
removeHandler();- Discord sends interaction
beforeInteractionevent fires- Rate limit check
interactionRateLimitevent if limited- Interaction handler executes
afterInteractionevent fires- If error:
interactionErrorevent fires
- Discord sends event
beforeEventevent fires- Event handler executes
afterEventevent fires- If error:
eventErrorevent fires
// ✅ Good - Use specific event IDs
Event({
name: "messageCreate",
id: "spam-filter-v1", // Descriptive ID
onExecute({ message }) { /* ... */ }
});
// ❌ Bad - Missing ID causes conflicts
Event({
name: "messageCreate",
// No ID - will throw error if strict mode is on
onExecute({ message }) { /* ... */ }
});
// ✅ Good - Return early from bot messages
Event({
name: "messageCreate",
id: "my-handler",
onExecute({ message }) {
if (message.author.bot) return; // Ignore bots
// Handle user messages
}
});
// ✅ Good - Use async/await properly
Event({
name: "guildMemberAdd",
id: "welcome",
async onExecute({ member }) {
try {
await member.send("Welcome!");
} catch (error) {
console.error("Could not DM member:", error);
}
}
});Access guild locale in events:
dbi.register(({ Event }) => {
Event({
name: "messageCreate",
id: "localized-response",
onExecute({ message, locale }) {
if (message.content === "!hello") {
// Use guild's locale for response
const greeting = locale?.guild?.data?.greeting?.() || "Hello!";
message.reply(greeting);
}
}
});
});- Localization - Multi-language support
- Advanced Features - Message commands, multi-client
- API Reference - Complete API documentation
📄 LLM-optimized version: llm/EVENTS.txt