Files
openclaw/extensions/slack/src/blocks-render.ts
2026-03-15 21:55:45 -07:00

86 lines
2.6 KiB
TypeScript

import type { Block, KnownBlock } from "@slack/web-api";
import { reduceInteractiveReply } from "../../../src/channels/plugins/outbound/interactive.js";
import type { InteractiveReply } from "../../../src/interactive/payload.js";
import { truncateSlackText } from "./truncate.js";
export const SLACK_REPLY_BUTTON_ACTION_ID = "openclaw:reply_button";
export const SLACK_REPLY_SELECT_ACTION_ID = "openclaw:reply_select";
const SLACK_SECTION_TEXT_MAX = 3000;
const SLACK_PLAIN_TEXT_MAX = 75;
export type SlackBlock = Block | KnownBlock;
export function buildSlackInteractiveBlocks(interactive?: InteractiveReply): SlackBlock[] {
const initialState = {
blocks: [] as SlackBlock[],
buttonIndex: 0,
selectIndex: 0,
};
return reduceInteractiveReply(interactive, initialState, (state, block) => {
if (block.type === "text") {
const trimmed = block.text.trim();
if (!trimmed) {
return state;
}
state.blocks.push({
type: "section",
text: {
type: "mrkdwn",
text: truncateSlackText(trimmed, SLACK_SECTION_TEXT_MAX),
},
});
return state;
}
if (block.type === "buttons") {
if (block.buttons.length === 0) {
return state;
}
state.blocks.push({
type: "actions",
block_id: `openclaw_reply_buttons_${++state.buttonIndex}`,
elements: block.buttons.map((button, choiceIndex) => ({
type: "button",
action_id: SLACK_REPLY_BUTTON_ACTION_ID,
text: {
type: "plain_text",
text: truncateSlackText(button.label, SLACK_PLAIN_TEXT_MAX),
emoji: true,
},
value: button.value,
})),
});
return state;
}
if (block.options.length === 0) {
return state;
}
state.blocks.push({
type: "actions",
block_id: `openclaw_reply_select_${++state.selectIndex}`,
elements: [
{
type: "static_select",
action_id: SLACK_REPLY_SELECT_ACTION_ID,
placeholder: {
type: "plain_text",
text: truncateSlackText(
block.placeholder?.trim() || "Choose an option",
SLACK_PLAIN_TEXT_MAX,
),
emoji: true,
},
options: block.options.map((option, choiceIndex) => ({
text: {
type: "plain_text",
text: truncateSlackText(option.label, SLACK_PLAIN_TEXT_MAX),
emoji: true,
},
value: option.value,
})),
},
],
});
return state;
}).blocks;
}