import type { ChatInputCommandInteraction } from "discord.js"; import { UserError } from "@shared/lib/errors"; import { createErrorEmbed } from "./embeds"; /** * Wraps a command's core logic with standardized error handling. * * - Calls `interaction.deferReply()` automatically * - On success, invokes `onSuccess` callback or sends `successMessage` * - On `UserError`, shows the error message in an error embed * - On unexpected errors, logs to console and shows a generic error embed * * @example * ```typescript * export const myCommand = createCommand({ * execute: async (interaction) => { * await withCommandErrorHandling( * interaction, * async () => { * const result = await doSomething(); * await interaction.editReply({ embeds: [createSuccessEmbed(result)] }); * } * ); * } * }); * ``` * * @example * ```typescript * // With deferReply options (e.g. ephemeral) * await withCommandErrorHandling( * interaction, * async () => doSomething(), * { * ephemeral: true, * successMessage: "Done!", * } * ); * ``` */ export async function withCommandErrorHandling( interaction: ChatInputCommandInteraction, operation: () => Promise, options?: { /** Message to send on success (if no onSuccess callback is provided) */ successMessage?: string; /** Callback invoked with the operation result on success */ onSuccess?: (result: T) => Promise; /** Whether the deferred reply should be ephemeral */ ephemeral?: boolean; } ): Promise { try { await interaction.deferReply({ ephemeral: options?.ephemeral }); const result = await operation(); if (options?.onSuccess) { await options.onSuccess(result); } else if (options?.successMessage) { await interaction.editReply({ content: options.successMessage, }); } return result; } catch (error) { if (error instanceof UserError) { await interaction.editReply({ embeds: [createErrorEmbed(error.message)], }); } else { console.error("Unexpected error in command:", error); await interaction.editReply({ embeds: [createErrorEmbed("An unexpected error occurred.")], }); } return undefined; } }