or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

client.mdcomponents.mdevents.mdguilds.mdindex.mdinteractions.mdmessages.mdutilities.md
tile.json

interactions.mddocs/

Interactions & Commands

Modern Discord interactions system including slash commands, context menus, button interactions, modal forms, and application command management.

Capabilities

Base Interaction System

Foundation for all Discord interactions with common properties and methods.

/**
 * Base class for all Discord interactions
 * @extends Base
 */
class BaseInteraction extends Base {
  readonly id: Snowflake;
  readonly applicationId: Snowflake;
  readonly type: InteractionType;
  readonly token: string;
  readonly channelId: Snowflake | null;
  readonly channel: TextBasedChannel | null;
  readonly guildId: Snowflake | null;
  readonly guild: Guild | null;
  readonly user: User;
  readonly member: GuildMember | null;
  readonly version: number;
  readonly appPermissions: Readonly<PermissionsBitField> | null;
  readonly memberPermissions: Readonly<PermissionsBitField> | null;
  readonly locale: Locale;
  readonly guildLocale: Locale | null;
  readonly createdAt: Date;
  
  // Type guards
  isApplicationCommand(): this is ApplicationCommandInteraction;
  isAutocomplete(): this is AutocompleteInteraction;
  isChatInputCommand(): this is ChatInputCommandInteraction;
  isContextMenuCommand(): this is ContextMenuCommandInteraction;
  isMessageComponent(): this is MessageComponentInteraction;
  isButton(): this is ButtonInteraction;
  isAnySelectMenu(): this is AnySelectMenuInteraction;
  isModalSubmit(): this is ModalSubmitInteraction;
  
  // Utility methods
  inGuild(): this is BaseInteraction & { guildId: Snowflake; guild: Guild; member: GuildMember };
  inCachedGuild(): this is BaseInteraction & { guild: Guild; member: GuildMember };
  inRawGuild(): this is BaseInteraction & { guildId: Snowflake; member: APIGuildMember | null };
  isRepliable(): this is BaseInteraction & InteractionResponseMixin;
}

Slash Commands (Chat Input Commands)

Modern slash command interactions with options and autocomplete support.

/**
 * Represents a slash command interaction
 * @extends CommandInteraction
 */
class ChatInputCommandInteraction extends CommandInteraction {
  readonly type: InteractionType.ApplicationCommand;
  readonly commandType: ApplicationCommandType.ChatInput;
  readonly options: CommandInteractionOptionResolver;
  
  toString(): string;
}

/**
 * Base class for application command interactions
 * @extends BaseInteraction
 */
class CommandInteraction extends BaseInteraction {
  readonly commandId: Snowflake;
  readonly commandName: string;
  readonly commandGuildId: Snowflake | null;
  
  // Response methods
  reply(options: InteractionReplyOptions): Promise<InteractionResponse>;
  editReply(options: InteractionEditReplyOptions): Promise<Message>;
  deferReply(options?: InteractionDeferReplyOptions): Promise<InteractionResponse>;
  fetchReply(): Promise<Message>;
  followUp(options: InteractionReplyOptions): Promise<Message>;
  deleteReply(message?: MessageResolvable | '@original'): Promise<void>;
  
  // State checks
  readonly replied: boolean;
  readonly deferred: boolean;
}

/**
 * Resolves and provides access to command options
 */
class CommandInteractionOptionResolver {
  constructor(client: Client, options: CommandInteractionOption[], resolved: CommandInteractionResolvedData);
  
  // Value getters
  get(name: string, required: true): CommandInteractionOption;
  get(name: string, required?: boolean): CommandInteractionOption | null;
  getSubcommandGroup(required?: boolean): string | null;
  getSubcommand(required?: boolean): string | null;
  
  // Typed getters
  getString(name: string, required: true): string;
  getString(name: string, required?: boolean): string | null;
  getInteger(name: string, required: true): number;
  getInteger(name: string, required?: boolean): number | null;
  getNumber(name: string, required: true): number;
  getNumber(name: string, required?: boolean): number | null;
  getBoolean(name: string, required: true): boolean;
  getBoolean(name: string, required?: boolean): boolean | null;
  getChannel(name: string, required: true): GuildChannel | APIInteractionDataResolvedChannel | ThreadChannel;
  getChannel(name: string, required?: boolean): GuildChannel | APIInteractionDataResolvedChannel | ThreadChannel | null;
  getUser(name: string, required: true): User;
  getUser(name: string, required?: boolean): User | null;
  getMember(name: string): GuildMember | APIInteractionDataResolvedGuildMember | null;
  getRole(name: string, required: true): Role | APIRole;
  getRole(name: string, required?: boolean): Role | APIRole | null;
  getMentionable(name: string, required: true): User | GuildMember | APIInteractionDataResolvedGuildMember | Role | APIRole;
  getMentionable(name: string, required?: boolean): User | GuildMember | APIInteractionDataResolvedGuildMember | Role | APIRole | null;
  getAttachment(name: string, required: true): Attachment;
  getAttachment(name: string, required?: boolean): Attachment | null;
  
  // Focused option for autocomplete
  getFocused(getFull?: false): string;
  getFocused(getFull: true): AutocompleteFocusedOption;
}

interface InteractionReplyOptions extends BaseMessageOptions {
  ephemeral?: boolean;
  fetchReply?: boolean;
}

interface InteractionEditReplyOptions extends Omit<BaseMessageOptions, 'reply'> {
  attachments?: JSONEncodable<AttachmentPayload>[];
}

interface InteractionDeferReplyOptions {
  ephemeral?: boolean;
  fetchReply?: boolean;
}

Usage Examples:

// Handle slash command interaction
client.on(Events.InteractionCreate, async interaction => {
  if (!interaction.isChatInputCommand()) return;
  
  if (interaction.commandName === 'ping') {
    await interaction.reply('Pong!');
  }
  
  if (interaction.commandName === 'userinfo') {
    const user = interaction.options.getUser('user', true);
    const member = interaction.options.getMember('user');
    
    await interaction.reply({
      content: `User: ${user.tag}`,
      ephemeral: true
    });
  }
  
  if (interaction.commandName === 'slow-command') {
    // Defer reply for long operations
    await interaction.deferReply();
    
    // Do some long operation...
    await new Promise(resolve => setTimeout(resolve, 5000));
    
    await interaction.editReply('Operation completed!');
  }
});

// Register slash commands
const commands = [
  {
    name: 'ping',
    description: 'Replies with Pong!'
  },
  {
    name: 'userinfo',
    description: 'Get information about a user',
    options: [
      {
        name: 'user',
        description: 'The user to get info about',
        type: ApplicationCommandOptionType.User,
        required: true
      }
    ]
  }
];

await rest.put(Routes.applicationCommands(client.user.id), { body: commands });

Context Menu Commands

Right-click context menu commands for users and messages.

/**
 * Base class for context menu command interactions
 * @extends CommandInteraction
 */
class ContextMenuCommandInteraction extends CommandInteraction {
  readonly commandType: ApplicationCommandType.User | ApplicationCommandType.Message;
  readonly targetId: Snowflake;
}

/**
 * User context menu command interaction
 * @extends ContextMenuCommandInteraction
 */
class UserContextMenuCommandInteraction extends ContextMenuCommandInteraction {
  readonly commandType: ApplicationCommandType.User;
  readonly targetUser: User;
  readonly targetMember: GuildMember | null;
}

/**
 * Message context menu command interaction
 * @extends ContextMenuCommandInteraction
 */
class MessageContextMenuCommandInteraction extends ContextMenuCommandInteraction {
  readonly commandType: ApplicationCommandType.Message;
  readonly targetMessage: Message;
}

Autocomplete Interactions

Provide dynamic autocomplete suggestions for slash command options.

/**
 * Represents an autocomplete interaction
 * @extends BaseInteraction
 */
class AutocompleteInteraction extends BaseInteraction {
  readonly type: InteractionType.ApplicationCommandAutocomplete;
  readonly commandId: Snowflake;
  readonly commandName: string;
  readonly commandType: ApplicationCommandType;
  readonly commandGuildId: Snowflake | null;
  readonly options: CommandInteractionOptionResolver;
  
  respond(options: ApplicationCommandOptionChoiceData[]): Promise<void>;
}

interface ApplicationCommandOptionChoiceData {
  name: string;
  name_localizations?: LocalizationMap;
  value: string | number;
}

interface AutocompleteFocusedOption {
  name: string;
  type: ApplicationCommandOptionType;
  value: string;
  focused: true;
}

Usage Examples:

// Handle autocomplete interactions
client.on(Events.InteractionCreate, async interaction => {
  if (!interaction.isAutocomplete()) return;
  
  if (interaction.commandName === 'music') {
    const focusedOption = interaction.options.getFocused(true);
    
    if (focusedOption.name === 'song') {
      const searchQuery = focusedOption.value;
      
      // Search for songs matching the query
      const songs = await searchSongs(searchQuery);
      
      const choices = songs.slice(0, 25).map(song => ({
        name: `${song.title} - ${song.artist}`,
        value: song.id
      }));
      
      await interaction.respond(choices);
    }
  }
});

Button Interactions

Handle button component interactions from messages.

/**
 * Represents a button interaction
 * @extends MessageComponentInteraction
 */
class ButtonInteraction extends MessageComponentInteraction {
  readonly componentType: ComponentType.Button;
  readonly component: ButtonComponent;
  
  update(options: InteractionUpdateOptions): Promise<InteractionResponse>;
}

/**
 * Base class for message component interactions
 * @extends BaseInteraction
 */
class MessageComponentInteraction extends BaseInteraction {
  readonly type: InteractionType.MessageComponent;
  readonly customId: string;
  readonly componentType: ComponentType;
  readonly message: Message;
  readonly component: MessageActionRowComponent;
  
  // Response methods (inherited from RepliableInteraction)
  reply(options: InteractionReplyOptions): Promise<InteractionResponse>;
  update(options: InteractionUpdateOptions): Promise<InteractionResponse>;
  deferUpdate(options?: InteractionDeferUpdateOptions): Promise<InteractionResponse>;
  followUp(options: InteractionReplyOptions): Promise<Message>;
  
  // Utility methods
  inGuild(): this is MessageComponentInteraction & { guildId: Snowflake; guild: Guild; member: GuildMember };
}

interface InteractionUpdateOptions extends BaseMessageOptions {
  fetchReply?: boolean;
}

interface InteractionDeferUpdateOptions {
  fetchReply?: boolean;
}

Select Menu Interactions

Handle various types of select menu interactions.

/**
 * Base class for select menu interactions
 * @extends MessageComponentInteraction
 */
class SelectMenuInteraction extends MessageComponentInteraction {
  readonly values: string[];
  readonly component: BaseSelectMenuComponent;
}

/**
 * String select menu interaction
 * @extends SelectMenuInteraction
 */
class StringSelectMenuInteraction extends SelectMenuInteraction {
  readonly componentType: ComponentType.StringSelect;
  readonly component: StringSelectMenuComponent;
}

/**
 * User select menu interaction
 * @extends SelectMenuInteraction
 */
class UserSelectMenuInteraction extends SelectMenuInteraction {
  readonly componentType: ComponentType.UserSelect;
  readonly component: UserSelectMenuComponent;
  readonly users: Collection<Snowflake, User>;
  readonly members: Collection<Snowflake, GuildMember>;
}

/**
 * Role select menu interaction
 * @extends SelectMenuInteraction
 */
class RoleSelectMenuInteraction extends SelectMenuInteraction {
  readonly componentType: ComponentType.RoleSelect;
  readonly component: RoleSelectMenuComponent;
  readonly roles: Collection<Snowflake, Role>;
}

/**
 * Channel select menu interaction
 * @extends SelectMenuInteraction
 */
class ChannelSelectMenuInteraction extends SelectMenuInteraction {
  readonly componentType: ComponentType.ChannelSelect;
  readonly component: ChannelSelectMenuComponent;
  readonly channels: Collection<Snowflake, APIInteractionDataResolvedChannel | GuildChannel | ThreadChannel>;
}

/**
 * Mentionable select menu interaction
 * @extends SelectMenuInteraction  
 */
class MentionableSelectMenuInteraction extends SelectMenuInteraction {
  readonly componentType: ComponentType.MentionableSelect;  
  readonly component: MentionableSelectMenuComponent;
  readonly users: Collection<Snowflake, User>;
  readonly members: Collection<Snowflake, GuildMember>;
  readonly roles: Collection<Snowflake, Role>;
}

Modal Interactions

Handle modal form submissions with input validation.

/**
 * Represents a modal submit interaction
 * @extends BaseInteraction
 */
class ModalSubmitInteraction extends BaseInteraction {
  readonly type: InteractionType.ModalSubmit;
  readonly customId: string;
  readonly fields: ModalSubmitFields;
  readonly components: ActionRow<ModalActionRowComponent>[];
  readonly message: Message | null;
  
  // Response methods (inherited from RepliableInteraction)
  reply(options: InteractionReplyOptions): Promise<InteractionResponse>;
  update(options: InteractionUpdateOptions): Promise<InteractionResponse>; 
  deferReply(options?: InteractionDeferReplyOptions): Promise<InteractionResponse>;
  deferUpdate(options?: InteractionDeferUpdateOptions): Promise<InteractionResponse>;
  followUp(options: InteractionReplyOptions): Promise<Message>;
}

/**
 * Handles modal form field values
 */
class ModalSubmitFields {
  constructor(components: ModalActionRowComponent[][], interaction: ModalSubmitInteraction);
  
  getTextInputValue(customId: string): string;
  getField(customId: string, type: ComponentType): ModalActionRowComponent;
  getFields(customId?: string, type?: ComponentType): ModalActionRowComponent[];
}

Usage Examples:

// Handle button interactions
client.on(Events.InteractionCreate, async interaction => {
  if (!interaction.isButton()) return;
  
  if (interaction.customId === 'confirm_action') {
    await interaction.update({
      content: 'Action confirmed!',
      components: [] // Remove buttons
    });
  }
  
  if (interaction.customId === 'show_modal') {
    const modal = new ModalBuilder()
      .setCustomId('feedback_modal')
      .setTitle('Feedback Form')
      .addComponents(
        new ActionRowBuilder<TextInputBuilder>()
          .addComponents(
            new TextInputBuilder()
              .setCustomId('feedback_input')
              .setLabel('Your feedback')
              .setStyle(TextInputStyle.Paragraph)
              .setPlaceholder('Tell us what you think...')
              .setRequired(true)
          )
      );
    
    await interaction.showModal(modal);
  }
});

// Handle select menu interactions
client.on(Events.InteractionCreate, async interaction => {
  if (!interaction.isAnySelectMenu()) return;
  
  if (interaction.customId === 'role_select') {
    if (interaction.isRoleSelectMenu()) {
      const selectedRoles = interaction.roles;
      await interaction.reply({
        content: `You selected: ${selectedRoles.map(role => role.name).join(', ')}`,
        ephemeral: true
      });
    }
  }
});

// Handle modal submissions
client.on(Events.InteractionCreate, async interaction => {
  if (!interaction.isModalSubmit()) return;
  
  if (interaction.customId === 'feedback_modal') {
    const feedback = interaction.fields.getTextInputValue('feedback_input');
    
    await interaction.reply({
      content: `Thank you for your feedback: ${feedback}`,
      ephemeral: true
    });
  }
});

Application Command Management

Create, update, and manage application commands.

/**
 * Represents an application command
 */
class ApplicationCommand extends Base {
  readonly id: Snowflake;
  readonly applicationId: Snowflake;
  readonly guildId: Snowflake | null;
  readonly guild: Guild | null;
  readonly name: string;
  readonly nameLocalizations: LocalizationMap | null;
  readonly description: string;
  readonly descriptionLocalizations: LocalizationMap | null;
  readonly type: ApplicationCommandType;
  readonly options: ApplicationCommandOption[];
  readonly defaultMemberPermissions: Readonly<PermissionsBitField> | null;
  readonly dmPermission: boolean | null;
  readonly nsfw: boolean;
  readonly version: Snowflake;
  
  // Command management
  edit(options: ApplicationCommandEditOptions): Promise<ApplicationCommand>;
  delete(): Promise<ApplicationCommand>;
  setName(name: string): Promise<ApplicationCommand>;
  setDescription(description: string): Promise<ApplicationCommand>;
  setDefaultMemberPermissions(defaultMemberPermissions: PermissionResolvable | null): Promise<ApplicationCommand>;
  setDMPermission(dmPermission?: boolean): Promise<ApplicationCommand>;
}

/**
 * Manages application commands for a client
 */
class ApplicationCommandManager extends CachedManager<Snowflake, ApplicationCommand, ApplicationCommandResolvable> {
  create(command: ApplicationCommandData): Promise<ApplicationCommand>;
  edit(command: ApplicationCommandResolvable, data: ApplicationCommandEditOptions): Promise<ApplicationCommand>;
  delete(command: ApplicationCommandResolvable): Promise<ApplicationCommand | null>;
  set(commands: ApplicationCommandData[]): Promise<Collection<Snowflake, ApplicationCommand>>;
}

/**
 * Manages application commands for a guild
 */  
class GuildApplicationCommandManager extends ApplicationCommandManager {
  readonly guild: Guild;
  readonly permissions: GuildApplicationCommandPermissionsManager;
  
  create(command: ApplicationCommandData): Promise<ApplicationCommand>;
  set(commands: ApplicationCommandData[]): Promise<Collection<Snowflake, ApplicationCommand>>;
}

interface ApplicationCommandData {
  name: string;
  nameLocalizations?: LocalizationMap;
  description: string;
  descriptionLocalizations?: LocalizationMap;
  type?: ApplicationCommandType;
  options?: ApplicationCommandOptionData[];
  defaultMemberPermissions?: PermissionResolvable | null;
  dmPermission?: boolean;
  nsfw?: boolean;
}

Interaction Responses

Advanced interaction response handling and management.

/**
 * Represents an interaction response
 */
class InteractionResponse {
  constructor(interaction: BaseInteraction, id?: Snowflake);
  
  readonly interaction: BaseInteraction;
  readonly id: Snowflake | null;
  
  // Response management
  edit(options: InteractionEditReplyOptions): Promise<Message>;
  delete(): Promise<void>;
  fetch(): Promise<Message>;
}

/**
 * Interaction webhook for advanced response handling
 */
class InteractionWebhook extends PartialWebhookMixin() {
  constructor(client: Client, id: Snowflake, token: string);
  
  readonly token: string;
  readonly client: Client;
  
  editMessage(message: MessageResolvable | '@original', options: InteractionEditReplyOptions): Promise<Message>;
  fetchMessage(message: Snowflake | '@original'): Promise<Message>;
  deleteMessage(message: MessageResolvable | '@original'): Promise<void>;
}

Usage Examples:

// Register commands with different types
const commands = [
  // Slash command with options
  {
    name: 'ban',
    description: 'Ban a user from the server',
    type: ApplicationCommandType.ChatInput,
    options: [
      {
        name: 'user',
        description: 'User to ban',
        type: ApplicationCommandOptionType.User,
        required: true
      },
      {
        name: 'reason',
        description: 'Reason for ban',
        type: ApplicationCommandOptionType.String,
        required: false
      }
    ],
    defaultMemberPermissions: PermissionFlagsBits.BanMembers
  },
  // User context menu command
  {
    name: 'Get User Info',
    type: ApplicationCommandType.User
  },
  // Message context menu command
  {
    name: 'Report Message',
    type: ApplicationCommandType.Message
  }
];

// Set commands globally
await client.application?.commands.set(commands);

// Set commands for specific guild
await guild.commands.set(commands);

// Advanced interaction handling with error management
client.on(Events.InteractionCreate, async interaction => {
  try {
    if (interaction.isChatInputCommand()) {
      await handleSlashCommand(interaction);
    } else if (interaction.isButton()) {
      await handleButtonInteraction(interaction);
    } else if (interaction.isModalSubmit()) {
      await handleModalSubmit(interaction);
    }
  } catch (error) {
    console.error('Interaction error:', error);
    
    const errorMessage = { 
      content: 'There was an error while executing this interaction!', 
      ephemeral: true 
    };
    
    if (interaction.replied || interaction.deferred) {
      await interaction.followUp(errorMessage);
    } else {
      await interaction.reply(errorMessage);
    }
  }
});