Merge ca2ab303ba into 4583f88626
This commit is contained in:
commit
06875c92a5
@ -233,11 +233,16 @@ export async function handleDiscordMessagingAction(
|
|||||||
const replyTo = readStringParam(params, "replyTo");
|
const replyTo = readStringParam(params, "replyTo");
|
||||||
const embeds =
|
const embeds =
|
||||||
Array.isArray(params.embeds) && params.embeds.length > 0 ? params.embeds : undefined;
|
Array.isArray(params.embeds) && params.embeds.length > 0 ? params.embeds : undefined;
|
||||||
|
const components =
|
||||||
|
Array.isArray(params.components) && params.components.length > 0
|
||||||
|
? params.components
|
||||||
|
: undefined;
|
||||||
const result = await sendMessageDiscord(to, content, {
|
const result = await sendMessageDiscord(to, content, {
|
||||||
...(accountId ? { accountId } : {}),
|
...(accountId ? { accountId } : {}),
|
||||||
mediaUrl,
|
mediaUrl,
|
||||||
replyTo,
|
replyTo,
|
||||||
embeds,
|
embeds,
|
||||||
|
components,
|
||||||
});
|
});
|
||||||
return jsonResult({ ok: true, result });
|
return jsonResult({ ok: true, result });
|
||||||
}
|
}
|
||||||
@ -279,18 +284,31 @@ export async function handleDiscordMessagingAction(
|
|||||||
const channelId = resolveChannelId();
|
const channelId = resolveChannelId();
|
||||||
const name = readStringParam(params, "name", { required: true });
|
const name = readStringParam(params, "name", { required: true });
|
||||||
const messageId = readStringParam(params, "messageId");
|
const messageId = readStringParam(params, "messageId");
|
||||||
|
// Optional initial content (required for forum posts).
|
||||||
|
const content = readStringParam(params, "content") ?? undefined;
|
||||||
|
// Optional applied tag ids (forum posts).
|
||||||
|
const appliedTagIds = Array.isArray(params.appliedTagIds)
|
||||||
|
? params.appliedTagIds.filter((x) => typeof x === "string" && x.trim())
|
||||||
|
: undefined;
|
||||||
const autoArchiveMinutesRaw = params.autoArchiveMinutes;
|
const autoArchiveMinutesRaw = params.autoArchiveMinutes;
|
||||||
const autoArchiveMinutes =
|
const autoArchiveMinutes =
|
||||||
typeof autoArchiveMinutesRaw === "number" && Number.isFinite(autoArchiveMinutesRaw)
|
typeof autoArchiveMinutesRaw === "number" && Number.isFinite(autoArchiveMinutesRaw)
|
||||||
? autoArchiveMinutesRaw
|
? autoArchiveMinutesRaw
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const thread = accountId
|
const thread = accountId
|
||||||
? await createThreadDiscord(
|
? await createThreadDiscord(
|
||||||
channelId,
|
channelId,
|
||||||
{ name, messageId, autoArchiveMinutes },
|
{ name, messageId, autoArchiveMinutes, content, appliedTagIds },
|
||||||
{ accountId },
|
{ accountId },
|
||||||
)
|
)
|
||||||
: await createThreadDiscord(channelId, { name, messageId, autoArchiveMinutes });
|
: await createThreadDiscord(channelId, {
|
||||||
|
name,
|
||||||
|
messageId,
|
||||||
|
autoArchiveMinutes,
|
||||||
|
content,
|
||||||
|
appliedTagIds,
|
||||||
|
});
|
||||||
return jsonResult({ ok: true, thread });
|
return jsonResult({ ok: true, thread });
|
||||||
}
|
}
|
||||||
case "threadList": {
|
case "threadList": {
|
||||||
|
|||||||
@ -87,6 +87,30 @@ function buildSendSchema(options: { includeButtons: boolean; includeCards: boole
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
embeds: Type.Optional(
|
||||||
|
Type.Array(
|
||||||
|
Type.Object(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
additionalProperties: true,
|
||||||
|
description:
|
||||||
|
"Provider-specific embed objects (Discord embeds, etc.). Passed through to the channel adapter when supported.",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
components: Type.Optional(
|
||||||
|
Type.Array(
|
||||||
|
Type.Object(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
additionalProperties: true,
|
||||||
|
description:
|
||||||
|
"Provider-specific message components (Discord buttons/selects, etc.). Passed through when supported.",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
if (!options.includeButtons) delete props.buttons;
|
if (!options.includeButtons) delete props.buttons;
|
||||||
if (!options.includeCards) delete props.card;
|
if (!options.includeCards) delete props.card;
|
||||||
|
|||||||
@ -37,6 +37,7 @@ export async function handleDiscordMessageAction(
|
|||||||
const mediaUrl = readStringParam(params, "media", { trim: false });
|
const mediaUrl = readStringParam(params, "media", { trim: false });
|
||||||
const replyTo = readStringParam(params, "replyTo");
|
const replyTo = readStringParam(params, "replyTo");
|
||||||
const embeds = Array.isArray(params.embeds) ? params.embeds : undefined;
|
const embeds = Array.isArray(params.embeds) ? params.embeds : undefined;
|
||||||
|
const components = Array.isArray(params.components) ? params.components : undefined;
|
||||||
return await handleDiscordAction(
|
return await handleDiscordAction(
|
||||||
{
|
{
|
||||||
action: "sendMessage",
|
action: "sendMessage",
|
||||||
@ -46,6 +47,7 @@ export async function handleDiscordMessageAction(
|
|||||||
mediaUrl: mediaUrl ?? undefined,
|
mediaUrl: mediaUrl ?? undefined,
|
||||||
replyTo: replyTo ?? undefined,
|
replyTo: replyTo ?? undefined,
|
||||||
embeds,
|
embeds,
|
||||||
|
components,
|
||||||
},
|
},
|
||||||
cfg,
|
cfg,
|
||||||
);
|
);
|
||||||
@ -180,6 +182,10 @@ export async function handleDiscordMessageAction(
|
|||||||
if (action === "thread-create") {
|
if (action === "thread-create") {
|
||||||
const name = readStringParam(params, "threadName", { required: true });
|
const name = readStringParam(params, "threadName", { required: true });
|
||||||
const messageId = readStringParam(params, "messageId");
|
const messageId = readStringParam(params, "messageId");
|
||||||
|
// Optional initial post content (required for forum post creation).
|
||||||
|
const content = readStringParam(params, "message");
|
||||||
|
// Optional forum tag ids.
|
||||||
|
const appliedTagIds = readStringArrayParam(params, "appliedTagIds");
|
||||||
const autoArchiveMinutes = readNumberParam(params, "autoArchiveMin", {
|
const autoArchiveMinutes = readNumberParam(params, "autoArchiveMin", {
|
||||||
integer: true,
|
integer: true,
|
||||||
});
|
});
|
||||||
@ -190,6 +196,8 @@ export async function handleDiscordMessageAction(
|
|||||||
channelId: resolveChannelId(),
|
channelId: resolveChannelId(),
|
||||||
name,
|
name,
|
||||||
messageId,
|
messageId,
|
||||||
|
content,
|
||||||
|
appliedTagIds,
|
||||||
autoArchiveMinutes,
|
autoArchiveMinutes,
|
||||||
},
|
},
|
||||||
cfg,
|
cfg,
|
||||||
|
|||||||
@ -94,10 +94,30 @@ export async function createThreadDiscord(
|
|||||||
) {
|
) {
|
||||||
const rest = resolveDiscordRest(opts);
|
const rest = resolveDiscordRest(opts);
|
||||||
const body: Record<string, unknown> = { name: payload.name };
|
const body: Record<string, unknown> = { name: payload.name };
|
||||||
|
|
||||||
if (payload.autoArchiveMinutes) {
|
if (payload.autoArchiveMinutes) {
|
||||||
body.auto_archive_duration = payload.autoArchiveMinutes;
|
body.auto_archive_duration = payload.autoArchiveMinutes;
|
||||||
}
|
}
|
||||||
const route = Routes.threads(channelId, payload.messageId);
|
|
||||||
|
// Forum posts (channel type 15) require an initial message payload.
|
||||||
|
// If content is provided, create the thread with an initial post.
|
||||||
|
if (payload.content) {
|
||||||
|
body.message = { content: payload.content };
|
||||||
|
if (Array.isArray(payload.appliedTagIds) && payload.appliedTagIds.length) {
|
||||||
|
body.applied_tags = payload.appliedTagIds;
|
||||||
|
}
|
||||||
|
// NOTE: discord-api-types Routes doesn't currently expose a helper for
|
||||||
|
// POST /channels/{channel.id}/threads (it only exposes listing archived threads),
|
||||||
|
// so use the raw route string.
|
||||||
|
const route = `/channels/${channelId}/threads`;
|
||||||
|
return await rest.post(route, { body });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular threads: create from an existing message when messageId is provided,
|
||||||
|
// otherwise create a standard thread in the channel.
|
||||||
|
const route = payload.messageId
|
||||||
|
? Routes.threads(channelId, payload.messageId)
|
||||||
|
: `/channels/${channelId}/threads`;
|
||||||
return await rest.post(route, { body });
|
return await rest.post(route, { body });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,7 @@ type DiscordSendOpts = {
|
|||||||
replyTo?: string;
|
replyTo?: string;
|
||||||
retry?: RetryConfig;
|
retry?: RetryConfig;
|
||||||
embeds?: unknown[];
|
embeds?: unknown[];
|
||||||
|
components?: unknown[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function sendMessageDiscord(
|
export async function sendMessageDiscord(
|
||||||
@ -63,6 +64,7 @@ export async function sendMessageDiscord(
|
|||||||
request,
|
request,
|
||||||
accountInfo.config.maxLinesPerMessage,
|
accountInfo.config.maxLinesPerMessage,
|
||||||
opts.embeds,
|
opts.embeds,
|
||||||
|
opts.components,
|
||||||
chunkMode,
|
chunkMode,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -74,6 +76,7 @@ export async function sendMessageDiscord(
|
|||||||
request,
|
request,
|
||||||
accountInfo.config.maxLinesPerMessage,
|
accountInfo.config.maxLinesPerMessage,
|
||||||
opts.embeds,
|
opts.embeds,
|
||||||
|
opts.components,
|
||||||
chunkMode,
|
chunkMode,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -277,6 +277,7 @@ async function sendDiscordText(
|
|||||||
request: DiscordRequest,
|
request: DiscordRequest,
|
||||||
maxLinesPerMessage?: number,
|
maxLinesPerMessage?: number,
|
||||||
embeds?: unknown[],
|
embeds?: unknown[],
|
||||||
|
components?: unknown[],
|
||||||
chunkMode?: ChunkMode,
|
chunkMode?: ChunkMode,
|
||||||
) {
|
) {
|
||||||
if (!text.trim()) {
|
if (!text.trim()) {
|
||||||
@ -297,6 +298,7 @@ async function sendDiscordText(
|
|||||||
content: chunks[0],
|
content: chunks[0],
|
||||||
message_reference: messageReference,
|
message_reference: messageReference,
|
||||||
...(embeds?.length ? { embeds } : {}),
|
...(embeds?.length ? { embeds } : {}),
|
||||||
|
...(components?.length ? { components } : {}),
|
||||||
},
|
},
|
||||||
}) as Promise<{ id: string; channel_id: string }>,
|
}) as Promise<{ id: string; channel_id: string }>,
|
||||||
"text",
|
"text",
|
||||||
@ -313,6 +315,7 @@ async function sendDiscordText(
|
|||||||
content: chunk,
|
content: chunk,
|
||||||
message_reference: isFirst ? messageReference : undefined,
|
message_reference: isFirst ? messageReference : undefined,
|
||||||
...(isFirst && embeds?.length ? { embeds } : {}),
|
...(isFirst && embeds?.length ? { embeds } : {}),
|
||||||
|
...(isFirst && components?.length ? { components } : {}),
|
||||||
},
|
},
|
||||||
}) as Promise<{ id: string; channel_id: string }>,
|
}) as Promise<{ id: string; channel_id: string }>,
|
||||||
"text",
|
"text",
|
||||||
@ -334,6 +337,7 @@ async function sendDiscordMedia(
|
|||||||
request: DiscordRequest,
|
request: DiscordRequest,
|
||||||
maxLinesPerMessage?: number,
|
maxLinesPerMessage?: number,
|
||||||
embeds?: unknown[],
|
embeds?: unknown[],
|
||||||
|
components?: unknown[],
|
||||||
chunkMode?: ChunkMode,
|
chunkMode?: ChunkMode,
|
||||||
) {
|
) {
|
||||||
const media = await loadWebMedia(mediaUrl);
|
const media = await loadWebMedia(mediaUrl);
|
||||||
@ -354,6 +358,7 @@ async function sendDiscordMedia(
|
|||||||
content: caption || undefined,
|
content: caption || undefined,
|
||||||
message_reference: messageReference,
|
message_reference: messageReference,
|
||||||
...(embeds?.length ? { embeds } : {}),
|
...(embeds?.length ? { embeds } : {}),
|
||||||
|
...(components?.length ? { components } : {}),
|
||||||
files: [
|
files: [
|
||||||
{
|
{
|
||||||
data: media.buffer,
|
data: media.buffer,
|
||||||
@ -374,6 +379,7 @@ async function sendDiscordMedia(
|
|||||||
request,
|
request,
|
||||||
maxLinesPerMessage,
|
maxLinesPerMessage,
|
||||||
undefined,
|
undefined,
|
||||||
|
undefined,
|
||||||
chunkMode,
|
chunkMode,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,9 +67,16 @@ export type DiscordMessageEdit = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type DiscordThreadCreate = {
|
export type DiscordThreadCreate = {
|
||||||
|
/** Optional message id to start a thread from (for classic threads). */
|
||||||
messageId?: string;
|
messageId?: string;
|
||||||
|
/** Thread / forum post title. */
|
||||||
name: string;
|
name: string;
|
||||||
|
/** Auto-archive duration in minutes. */
|
||||||
autoArchiveMinutes?: number;
|
autoArchiveMinutes?: number;
|
||||||
|
/** Optional initial post content (required for forum post creation). */
|
||||||
|
content?: string;
|
||||||
|
/** Optional forum tag ids (applied tags). */
|
||||||
|
appliedTagIds?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DiscordThreadList = {
|
export type DiscordThreadList = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user