From 59d355bc48213e47a60ff8ed86e02ee5b266052d Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 15 Mar 2026 18:44:27 -0700 Subject: [PATCH] Discord: add shared interactive renderer --- extensions/discord/src/shared-interactive.ts | 44 ++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 extensions/discord/src/shared-interactive.ts diff --git a/extensions/discord/src/shared-interactive.ts b/extensions/discord/src/shared-interactive.ts new file mode 100644 index 00000000000..5a442fabf4c --- /dev/null +++ b/extensions/discord/src/shared-interactive.ts @@ -0,0 +1,44 @@ +import type { InteractiveButtonStyle, InteractiveReply } from "../../../src/interactive/payload.js"; +import type { DiscordComponentButtonStyle, DiscordComponentMessageSpec } from "./components.js"; + +function resolveDiscordButtonStyle( + style?: InteractiveButtonStyle, +): DiscordComponentButtonStyle | undefined { + return style ?? "secondary"; +} + +export function buildDiscordInteractiveComponents( + interactive?: InteractiveReply, +): DiscordComponentMessageSpec | undefined { + const blocks: NonNullable = []; + for (const block of interactive?.blocks ?? []) { + if (block.type === "buttons") { + if (block.buttons.length === 0) { + continue; + } + blocks.push({ + type: "actions", + buttons: block.buttons.map((button) => ({ + label: button.label, + style: resolveDiscordButtonStyle(button.style), + callbackData: button.value, + })), + }); + continue; + } + if (block.type === "select" && block.options.length > 0) { + blocks.push({ + type: "actions", + select: { + type: "string", + placeholder: block.placeholder, + options: block.options.map((option) => ({ + label: option.label, + value: option.value, + })), + }, + }); + } + } + return blocks.length > 0 ? { blocks } : undefined; +}