import type { APISectionAccessoryComponent, APISectionComponent, APITextDisplayComponent, Snowflake, ButtonBuilder, ThumbnailBuilder, } from "discord.js"; import { ComponentType, TextDisplayBuilder } from "discord.js"; const ACCESSORY_TYPES = [ ComponentType.Button, ComponentType.StringSelect, ComponentType.UserSelect, ComponentType.RoleSelect, ComponentType.MentionableSelect, ComponentType.ChannelSelect, ComponentType.Thumbnail, ] as const; type SectionAccessoryType = (typeof ACCESSORY_TYPES)[number]; type SectionAccessoryComponent = Extract< APISectionAccessoryComponent, { type: SectionAccessoryType } >; export class V2SectionBuilder { private id?: number; private components: APITextDisplayComponent[] = []; private accessory?: SectionAccessoryComponent; setId(id: number) { this.id = id; return this; } setComponents(components: APITextDisplayComponent[]) { if (components.length < 1 || components.length > 3) throw new Error( "Sections must contain between 1 and 3 text display components.", ); this.components = components; return this; } setAccessory(component: { toJSON(): SectionAccessoryComponent }) { const accessoryComponent = component.toJSON(); if (!ACCESSORY_TYPES.includes(accessoryComponent.type)) throw new Error( `Invalid accessory type: ${accessoryComponent.type}\n\nMust be one of: ${ACCESSORY_TYPES.join(", ")}`, ); this.accessory = accessoryComponent; return this; } toJSON(): APISectionComponent { if (!this.components.length) { throw new Error("Section must have at least one text display component"); } if (!this.accessory) { throw new Error("Section must have an accessory component"); } return { type: ComponentType.Section, components: this.components, accessory: this.accessory, ...(this.id !== undefined && { id: this.id }), }; } } // Helper function to create text displays from strings or builders function createTextDisplay( content: Snowflake | TextDisplayBuilder, ): APITextDisplayComponent { if (typeof content === "string") { return new TextDisplayBuilder().setContent(content).toJSON(); } return content.toJSON(); } // Simple helper function to create sections export function makeSection( texts: (Snowflake | TextDisplayBuilder)[], accessory: ButtonBuilder | ThumbnailBuilder, id?: number, ): APISectionComponent { const section = new V2SectionBuilder(); // Convert all texts to TextDisplayComponents const components = texts.map(createTextDisplay); section.setComponents(components); section.setAccessory(accessory); if (id !== undefined) { section.setId(id); } return section.toJSON(); }