Skip to content

Commit f889219

Browse files
vincentkocsteipete
authored andcommitted
Discord: render shared interactive payloads outbound
1 parent 59d355b commit f889219

1 file changed

Lines changed: 88 additions & 4 deletions

File tree

extensions/discord/src/outbound-adapter.ts

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
1-
import { sendTextMediaPayload } from "../../../src/channels/plugins/outbound/direct-text-media.js";
1+
import {
2+
resolvePayloadMediaUrls,
3+
sendPayloadMediaSequence,
4+
sendTextMediaPayload,
5+
} from "../../../src/channels/plugins/outbound/direct-text-media.js";
26
import type { ChannelOutboundAdapter } from "../../../src/channels/plugins/types.js";
37
import type { OpenClawConfig } from "../../../src/config/config.js";
48
import type { OutboundIdentity } from "../../../src/infra/outbound/identity.js";
59
import { resolveOutboundSendDep } from "../../../src/infra/outbound/send-deps.js";
10+
import { resolveInteractiveTextFallback } from "../../../src/interactive/payload.js";
11+
import type { DiscordComponentMessageSpec } from "./components.js";
612
import { getThreadBindingManager, type ThreadBindingRecord } from "./monitor/thread-bindings.js";
713
import { normalizeDiscordOutboundTarget } from "./normalize.js";
8-
import { sendMessageDiscord, sendPollDiscord, sendWebhookMessageDiscord } from "./send.js";
14+
import {
15+
sendDiscordComponentMessage,
16+
sendMessageDiscord,
17+
sendPollDiscord,
18+
sendWebhookMessageDiscord,
19+
} from "./send.js";
20+
import { buildDiscordInteractiveComponents } from "./shared-interactive.js";
921

1022
function resolveDiscordOutboundTarget(params: {
1123
to: string;
@@ -78,8 +90,80 @@ export const discordOutbound: ChannelOutboundAdapter = {
7890
textChunkLimit: 2000,
7991
pollMaxOptions: 10,
8092
resolveTarget: ({ to }) => normalizeDiscordOutboundTarget(to),
81-
sendPayload: async (ctx) =>
82-
await sendTextMediaPayload({ channel: "discord", ctx, adapter: discordOutbound }),
93+
sendPayload: async (ctx) => {
94+
const payload = {
95+
...ctx.payload,
96+
text:
97+
resolveInteractiveTextFallback({
98+
text: ctx.payload.text,
99+
interactive: ctx.payload.interactive,
100+
}) ?? "",
101+
};
102+
const discordData = payload.channelData?.discord as
103+
| { components?: DiscordComponentMessageSpec }
104+
| undefined;
105+
const rawComponentSpec =
106+
discordData?.components ?? buildDiscordInteractiveComponents(payload.interactive);
107+
const componentSpec = rawComponentSpec
108+
? rawComponentSpec.text
109+
? rawComponentSpec
110+
: {
111+
...rawComponentSpec,
112+
text: payload.text?.trim() ? payload.text : undefined,
113+
}
114+
: undefined;
115+
if (!componentSpec) {
116+
return await sendTextMediaPayload({
117+
channel: "discord",
118+
ctx: {
119+
...ctx,
120+
payload,
121+
},
122+
adapter: discordOutbound,
123+
});
124+
}
125+
const send =
126+
resolveOutboundSendDep<typeof sendMessageDiscord>(ctx.deps, "discord") ?? sendMessageDiscord;
127+
const target = resolveDiscordOutboundTarget({ to: ctx.to, threadId: ctx.threadId });
128+
const mediaUrls = resolvePayloadMediaUrls(payload);
129+
if (mediaUrls.length === 0) {
130+
const result = await sendDiscordComponentMessage(target, componentSpec, {
131+
replyTo: ctx.replyToId ?? undefined,
132+
accountId: ctx.accountId ?? undefined,
133+
silent: ctx.silent ?? undefined,
134+
cfg: ctx.cfg,
135+
});
136+
return { channel: "discord", ...result };
137+
}
138+
const lastResult = await sendPayloadMediaSequence({
139+
text: payload.text ?? "",
140+
mediaUrls,
141+
send: async ({ text, mediaUrl, isFirst }) => {
142+
if (isFirst) {
143+
return await sendDiscordComponentMessage(target, componentSpec, {
144+
mediaUrl,
145+
mediaLocalRoots: ctx.mediaLocalRoots,
146+
replyTo: ctx.replyToId ?? undefined,
147+
accountId: ctx.accountId ?? undefined,
148+
silent: ctx.silent ?? undefined,
149+
cfg: ctx.cfg,
150+
});
151+
}
152+
return await send(target, text, {
153+
verbose: false,
154+
mediaUrl,
155+
mediaLocalRoots: ctx.mediaLocalRoots,
156+
replyTo: ctx.replyToId ?? undefined,
157+
accountId: ctx.accountId ?? undefined,
158+
silent: ctx.silent ?? undefined,
159+
cfg: ctx.cfg,
160+
});
161+
},
162+
});
163+
return lastResult
164+
? { channel: "discord", ...lastResult }
165+
: { channel: "discord", messageId: "" };
166+
},
83167
sendText: async ({ cfg, to, text, accountId, deps, replyToId, threadId, identity, silent }) => {
84168
if (!silent) {
85169
const webhookResult = await maybeSendDiscordWebhookText({

0 commit comments

Comments
 (0)