Sunar

Interactions handling

Learn how to effectively manage interactions between your bot and users using Sunar. From responding to slash commands, context menu clicks, button presses, to select menu choices, Sunar offers robust mechanisms to handle diverse interactions within Discord.

Overview

Discord interactions are the way users communicate with your bot through various UI elements like commands, buttons, and menus. Sunar provides two approaches to handle these interactions:

  1. Global handler: A single handler for all interaction types (recommended for most bots)
  2. Specific handlers: Individual handlers for each interaction type (useful for complex bots)

The simplest way to handle all interactions is using the global handleInteraction function. This approach:

  • Automatically routes interactions to the correct handlers
  • Handles all interaction types out of the box
  • Reduces boilerplate code
  • Applies protectors and cooldowns automatically
src/signals/interaction-create.js
import { Signal, execute } from 'sunar';
import { handleInteraction } from 'sunar/handlers';

const signal = new Signal('interactionCreate');

execute(signal, async (interaction) => {
	await handleInteraction(interaction);
});

export { signal };

Handle only specific interactions

This configuration sets up Sunar to selectively manage and respond to specific types of Discord interactions based on their nature, such as slash commands, context menu commands, buttons, modals, select menus, and autocomplete commands.

src/signals/interaction-create.js
import { Signal, execute } from 'sunar';

import {
	handleAutocomplete,
	handleModal,
	handleSelectMenu,
	handleSlash,
	handleButton,
	handleContextMenu,
} from 'sunar/handlers';

const signal = new Signal('interactionCreate');

execute(signal, async (interaction) => {
	if (interaction.isChatInputCommand()) await handleSlash(interaction);
	if (interaction.isContextMenuCommand()) await handleContextMenu(interaction);
	if (interaction.isButton()) await handleButton(interaction);
	if (interaction.isModalSubmit()) await handleModal(interaction);
	if (interaction.isAnySelectMenu()) await handleSelectMenu(interaction);
	if (interaction.isAutocomplete()) await handleAutocomplete(interaction);
});

export { signal };

Specific Handlers

For more complex bots that need granular control over interaction handling, you can use specific handlers for each interaction type. This approach allows you to:

  • Add custom logic before/after handling specific interactions
  • Handle only certain types of interactions
  • Implement custom error handling per interaction type
  • Add logging or monitoring for specific interaction types

Available Handlers

Sunar provides these specialized handlers:

HandlerInteraction TypeUse Case
handleSlashSlash CommandsProcess /commands
handleContextMenuContext MenusHandle right-click menu actions
handleButtonButtonsProcess button clicks
handleModalModalsHandle form submissions
handleSelectMenuSelect MenusProcess dropdown selections
handleAutocompleteAutocompleteHandle command option suggestions

Error Handling

You can implement custom error handling by wrapping the interaction handler in a try-catch block. This allows you to handle different types of errors and provide appropriate responses:

src/signals/interaction-create.js
import { Signal, Signals, execute, clearCooldownsForInteraction } from 'sunar';
import { handleInteraction } from 'sunar/handlers';

const signal = new Signal(Signals.InteractionCreate);

execute(signal, async (interaction) => {
	try {
		await handleInteraction(interaction);
	} catch (error) {
		await handleError(interaction, error);
	}
});

async function handleError(interaction, error) {
	// Clear any cooldowns that might have been set
	clearCooldownsForInteraction(interaction);

	if (!interaction.isRepliable()) {
		console.error('Non-repliable interaction error:', error);
		return;
	}

	// Handle different types of errors
	if (error instanceof UserError) {
		return interaction.reply({
			content: `❌ ${error.message}`,
			ephemeral: true
		});
	}

	// Log unexpected errors
	console.error('Unexpected error:', error);

	return interaction.reply({
		content: '⚠️ An unexpected error occurred.',
		ephemeral: true
	});
}

export { signal };

This example shows a basic error handling setup. You can extend it with custom error classes, error tracking services, and more sophisticated cooldown management for production use.

Best Practices

  1. Use Global Handler: Start with handleInteraction unless you have specific needs
  2. Error Handling: Always set up an error signal to catch and log interaction errors
  3. Type Safety: Use TypeScript to ensure type safety when working with interactions
  4. Validation: Use protectors to validate interactions before processing them
  5. Response Times: Always respond to interactions within 3 seconds or defer them

Discord requires interactions to be acknowledged within 3 seconds. If your command takes longer, use interaction.deferReply().

Further Reading

How is this guide?

Last updated on