mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-17 13:00:48 +00:00
86 lines
2.6 KiB
TypeScript
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;
|
|
}
|