SSL send.components.ts
Interaktion und PortierbarkeitJAVA
import {
serializePayload,
type MessagePayloadFile,
type MessagePayloadObject,
type RequestClient,
} from "@buape/carbon"; import { ChannelType, Routes } from "discord-api-types/v10"; import {
requireRuntimeConfig,
type MarkdownTableMode,
type OpenClawConfig,
} from "openclaw/plugin-sdk/config-runtime"; import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime"; import type { ChunkMode } from "openclaw/plugin-sdk/reply-chunking"; import { resolveDiscordAccount } from "./accounts.js"; import { registerDiscordComponentEntries } from "./components-registry.js"; import {
buildDiscordComponentMessage,
buildDiscordComponentMessageFlags,
resolveDiscordComponentAttachmentName,
type DiscordComponentBuildResult,
type DiscordComponentMessageSpec,
} from "./components.js"; import { parseAndResolveRecipient } from "./recipient-resolution.js"; import { loadOutboundMediaFromUrl } from "./runtime-api.js"; import { sendMessageDiscord } from "./send.outbound.js"; import {
buildDiscordSendError,
createDiscordClient,
resolveChannelId,
resolveDiscordChannelType,
toDiscordFileBlob,
stripUndefinedFields,
SUPPRESS_NOTIFICATIONS_FLAG,
} from "./send.shared.js"; import type { DiscordSendResult } from "./send.types.js";
const DISCORD_FORUM_LIKE_TYPES = new Set<number>([ChannelType.GuildForum, ChannelType.GuildMedia]);
function extractComponentAttachmentNames(spec: DiscordComponentMessageSpec): string[] { const names: string[] = []; for (const block of spec.blocks ?? []) { if (block.type === "file") {
names.push(resolveDiscordComponentAttachmentName(block.file));
}
} return names;
}
function withImplicitComponentAttachmentBlock(
spec: DiscordComponentMessageSpec,
attachmentName: string | undefined,
): DiscordComponentMessageSpec { if (!attachmentName || hasComponentAttachmentBlock(spec)) { return spec;
} // Discord File components must point at the uploaded attachment name. Add the // matching file block automatically so callers do not have to duplicate it. return {
...spec,
blocks: [
...(spec.blocks ?? []),
{
type: "file",
file: `attachment://${attachmentName}`,
},
],
};
}
const attachmentNames = extractComponentAttachmentNames(spec); const uniqueAttachmentNames = [...new Set(attachmentNames)]; if (uniqueAttachmentNames.length > 1) { thrownew Error( "Discord component attachments currently support a single file. Use media-gallery for multiple files.",
);
} const expectedAttachmentName = uniqueAttachmentNames[0]; if (expectedAttachmentName && resolvedFileName && expectedAttachmentName !== resolvedFileName) { thrownew Error(
`Component file block expects attachment "${expectedAttachmentName}", but the uploaded file is "${resolvedFileName}". Update components.blocks[].file or provide a matching filename.`,
);
} if (!params.opts.mediaUrl && expectedAttachmentName) { thrownew Error( "Discord component file blocks require a media attachment (media/path/filePath).",
);
}