Learn how to handle Discord events effectively with CommandKit
Events allow your bot to respond to actions on Discord like messages, member joins, reactions, and more. CommandKit provides a structured way to organize and handle events.
import type { EventHandler } from 'commandkit';const handler: EventHandler<'voiceStateUpdate'> = async (oldState, newState) => { const member = newState.member; if (!member) return; // User joined a voice channel if (!oldState.channel && newState.channel) { console.log(`${member.user.username} joined ${newState.channel.name}`); } // User left a voice channel else if (oldState.channel && !newState.channel) { console.log(`${member.user.username} left ${oldState.channel.name}`); } // User switched channels else if (oldState.channel && newState.channel && oldState.channel.id !== newState.channel.id) { console.log(`${member.user.username} moved from ${oldState.channel.name} to ${newState.channel.name}`); } // User muted/unmuted if (oldState.selfMute !== newState.selfMute) { console.log(`${member.user.username} ${newState.selfMute ? 'muted' : 'unmuted'} themselves`); } // User deafened/undeafened if (oldState.selfDeaf !== newState.selfDeaf) { console.log(`${member.user.username} ${newState.selfDeaf ? 'deafened' : 'undeafened'} themselves`); }};export default handler;
import type { EventHandler } from 'commandkit';const REACTION_ROLES = new Map([ ['👾', '1234567890123456789'], // Gamer role ['🎨', '1234567890123456790'], // Artist role ['🎵', '1234567890123456791'], // Musician role]);const REACTION_ROLE_MESSAGE_ID = '1234567890123456792';const handler: EventHandler<'messageReactionAdd'> = async (reaction, user) => { // Ignore bot reactions if (user.bot) return; // Fetch partial data if needed if (reaction.partial) { try { await reaction.fetch(); } catch (error) { console.error('Error fetching reaction:', error); return; } } // Check if it's the reaction role message if (reaction.message.id !== REACTION_ROLE_MESSAGE_ID) return; // Get the role ID for this emoji const roleId = REACTION_ROLES.get(reaction.emoji.name!); if (!roleId) return; // Add the role const member = await reaction.message.guild?.members.fetch(user.id); if (!member) return; try { await member.roles.add(roleId); console.log(`Added role to ${user.username}`); } catch (error) { console.error('Error adding role:', error); }};export default handler;
const handler: EventHandler<'messageCreate'> = async (message) => { if (message.author.bot) return; if (!message.guild) return; if (message.content.length < 3) return; // Main logic here};
2
Cache frequently accessed data
Reduce API calls by caching:
const prefixCache = new Map<string, string>();const handler: EventHandler<'messageCreate'> = async (message) => { let prefix = prefixCache.get(message.guildId!); if (!prefix) { prefix = await fetchPrefix(message.guildId!); prefixCache.set(message.guildId!, prefix); } // Use cached prefix};
3
Use event partials wisely
Only fetch partials when needed:
const handler: EventHandler<'messageUpdate'> = async (oldMessage, newMessage) => { // Only fetch if we need the full data if (newMessage.partial) { try { await newMessage.fetch(); } catch (error) { // Handle error or return early return; } } // Use full message data};