import type { Snowflake, APIMessageComponentEmoji, APIButtonComponent, } from "discord.js"; import { ButtonBuilder, ButtonStyle } from "discord.js"; export class V2ButtonBuilder extends ButtonBuilder { setCustomId(custom_id: Snowflake) { if (custom_id.length > 100) throw new Error("Max length for custom ids is 100 characters."); super.setCustomId(custom_id); return this; } setLabel(label: Snowflake) { if (label.length > 80) throw new Error("Max length for labels is 80 characters."); super.setLabel(label); return this; } setEmoji(emoji: APIMessageComponentEmoji) { super.setEmoji(emoji); return this; } setStyle(style: ButtonStyle) { super.setStyle(style); return this; } setURL(url: Snowflake) { super.setURL(url); return this; } setDisabled(disabled: boolean) { super.setDisabled(disabled); return this; } // Add setSKUId to match Discord.js ButtonBuilder setSKUId(sku_id: Snowflake) { super.setCustomId(sku_id); // SKU ID is handled as a custom ID internally return this; } toJSON(): APIButtonComponent { // Validate required style const data = super.toJSON(); // Additional validation if (!data.style) throw new Error("Button must have a style"); if (data.style === ButtonStyle.Link) { if (!("url" in data) || !data.url) { throw new Error("Link buttons must have a URL"); } } else if (!("custom_id" in data) || !data.custom_id) { throw new Error("Non-link buttons must have a custom_id"); } return data; } } interface ButtonOptions { custom_id?: Snowflake; label?: Snowflake; emoji?: APIMessageComponentEmoji; style?: ButtonStyle; url?: Snowflake; disabled?: boolean; sku_id?: Snowflake; } /** * Helper function to create a button component with a more convenient interface * @param options Configuration options for the button * @returns A configured button builder instance * * @example * ```typescript * // Create a primary button with minimal config * const button = makeButton({ * customId: 'my_button', * label: 'Click me' * }); // Defaults to Primary style * * // Create a link button * const linkButton = makeButton({ * label: 'Visit website', * url: 'https://example.com', * style: ButtonStyle.Link * }); * * // Create a button with emoji * const emojiButton = makeButton({ * customId: 'emoji_button', * label: 'React', * emoji: '👍', * style: ButtonStyle.Success * }); * ``` */ export function makeButton(options: ButtonOptions = {}): V2ButtonBuilder { const button = new V2ButtonBuilder(); // Apply defaults and options if (options.custom_id) button.setCustomId(options.custom_id); if (options.label) button.setLabel(options.label); if (options.emoji) button.setEmoji(options.emoji); if (options.url) button.setURL(options.url); if (options.disabled) button.setDisabled(options.disabled); if (options.sku_id) button.setSKUId(options.sku_id); // Set style with smart defaults // If URL is provided, default to Link style // Otherwise, default to Primary style button.setStyle( options.style ?? (options.url ? ButtonStyle.Link : ButtonStyle.Primary), ); return button; }