Event System
Event System
The event system is designed to handle Discord events and custom events in a type-safe, organized manner. This guide explains how the event system works and how to use it effectively.
Table of Contents
Overview
The event system uses a modular approach where:
- Event handlers are defined in separate files
- Events are automatically loaded during initialization
- Multiple handlers can respond to the same event
- Events can come from different sources (Discord client, cluster, or custom emitters)
Creating Event Handlers
Event handlers are created in the src/events/
directory, organized by source:
src/events/client/
- For Discord client events (message, interaction, etc.)src/events/cluster/
- For sharding cluster events- You can create additional directories for custom event sources
Basic Event Handler
// src/events/client/messageCreate.ts
import { eventFile } from "../../utils/types/eventTypes.js";
export const data = eventFile({
name: "messageCreate", // The name of the event to listen for
once: false, // Set to true if the event should only be handled once
// The event handler function
execute: async (client, message) => {
// Your event handling logic here
if (message.content === "ping") {
await message.channel.send("Pong!");
}
}
});
One-time Event Handler
// src/events/client/ready.ts
import { eventFile } from "../../utils/types/eventTypes.js";
export const data = eventFile({
name: "ready",
once: true, // This event will only be handled once
execute: async (client) => {
client.logger.ready(`Logged in as ${client.user.tag}!`);
}
});
Cluster Event Handler
// src/events/cluster/ready.ts
import { eventFile } from "../../utils/types/eventTypes.js";
export const data = eventFile({
name: "ready",
eventGetter: "cluster", // Specify this is a cluster event
execute: async (client, clusterClient) => {
client.logger.ready(`Cluster ${client.cluster.id} is ready!`);
}
});
Event Registration
Events are automatically registered during the initialization of the EventManager
. The registration process:
- Scans the
dist/events/
directory for event handlers - Loads and validates each event file
- Organizes events by name and source
- Registers event handlers with the appropriate emitters
How Registration Works
private registerEvents(events?: Map<string, EventConfiguration>): void {
for (const [name, configuration] of events ?? this.events) {
switch (configuration.eventGetter) {
case "discord": {
// Register with Discord client
if (configuration.once) {
this.client.once(name, async (...args) =>
await this.eventRunner(name, configuration, ...args)
);
} else {
this.client.on(name, async (...args) =>
await this.eventRunner(name, configuration, ...args)
);
}
break;
}
case "cluster": {
// Register with cluster client
if (configuration.once) {
this.client.cluster.once(name, async (...args) =>
await this.eventRunner(name, configuration, ...args)
);
} else {
this.client.cluster.on(name, async (...args) =>
await this.eventRunner(name, configuration, ...args)
);
}
break;
}
default: {
// Register with custom emitter
const emitter = (this.client as any)[configuration.eventGetter];
if (emitter && typeof emitter.on === "function" && typeof emitter.once === "function") {
if (configuration.once) {
emitter.once(name, async (...args) =>
await this.eventRunner(name, configuration, ...args)
);
} else {
emitter.on(name, async (...args) =>
await this.eventRunner(name, configuration, ...args)
);
}
} else {
this.client.logger.warn(`Unsupported event getter: ${configuration.eventGetter}`);
}
break;
}
}
}
}
Event Types
Event types are defined in src/utils/types/eventTypes.ts
, providing type safety for event handlers:
export interface EventTypes {
discord: ClientEvents; // Standard Discord.js events
cluster: ClusterClientEvents<DiscordBot>; // Cluster events
// Add your custom event types here
myCustomEmitter: MyCustomEvents;
[key: string]: any; // Allow any string key
}
export type AvailableEventGetters = keyof EventTypes;
Adding New Event Types
To add support for new event types:
- Extend the
EventTypes
interface ineventTypes.ts
- Create event handlers in appropriate directories
- Add the emitter to your
DiscordBot
class
Example:
// Step 1: Add to EventTypes
interface MyCustomEvents {
customEvent: [data: CustomEventData];
}
export interface EventTypes {
discord: ClientEvents;
cluster: ClusterClientEvents<DiscordBot>;
myCustomEmitter: MyCustomEvents; // Added custom emitter
[key: string]: any;
}
// Step 2: Create event handler
// src/events/myCustomEmitter/customEvent.ts
export const data = eventFile({
name: "customEvent",
eventGetter: "myCustomEmitter",
execute: async (client, data) => {
console.log("Custom event received:", data);
}
});
// Step 3: Add emitter to DiscordBot
import { EventEmitter } from 'events';
export default class DiscordBot extends Client {
// ...existing properties
public myCustomEmitter: EventEmitter = new EventEmitter();
// ...rest of class
}