From d06ee86292d02f2eb70087b0bc293d344ce67b9b Mon Sep 17 00:00:00 2001 From: David Friedland Date: Sat, 28 Feb 2026 15:36:08 -0800 Subject: [PATCH] feat(adapters): add sendPayload to batch-d adapters --- extensions/zalo/src/channel.ts | 19 ++++++++++++++++ extensions/zalouser/src/channel.ts | 19 ++++++++++++++++ .../plugins/outbound/direct-text-media.ts | 22 ++++++++++++++++++- src/channels/plugins/outbound/discord.ts | 19 ++++++++++++++++ src/channels/plugins/outbound/slack.ts | 19 ++++++++++++++++ src/channels/plugins/outbound/whatsapp.ts | 19 ++++++++++++++++ 6 files changed, 116 insertions(+), 1 deletion(-) diff --git a/extensions/zalo/src/channel.ts b/extensions/zalo/src/channel.ts index 34706e16882..1b2e013a167 100644 --- a/extensions/zalo/src/channel.ts +++ b/extensions/zalo/src/channel.ts @@ -302,6 +302,25 @@ export const zaloPlugin: ChannelPlugin = { chunker: chunkTextForOutbound, chunkerMode: "text", textChunkLimit: 2000, + sendPayload: async (ctx) => { + const urls = ctx.payload.mediaUrls?.length + ? ctx.payload.mediaUrls + : ctx.payload.mediaUrl + ? [ctx.payload.mediaUrl] + : []; + if (urls.length > 0) { + let lastResult; + for (let i = 0; i < urls.length; i++) { + lastResult = await zaloPlugin.outbound!.sendMedia!({ + ...ctx, + text: i === 0 ? (ctx.payload.text ?? "") : "", + mediaUrl: urls[i], + }); + } + return lastResult!; + } + return zaloPlugin.outbound!.sendText!({ ...ctx }); + }, sendText: async ({ to, text, accountId, cfg }) => { const result = await sendMessageZalo(to, text, { accountId: accountId ?? undefined, diff --git a/extensions/zalouser/src/channel.ts b/extensions/zalouser/src/channel.ts index a6325656926..4d8931f60a3 100644 --- a/extensions/zalouser/src/channel.ts +++ b/extensions/zalouser/src/channel.ts @@ -518,6 +518,25 @@ export const zalouserPlugin: ChannelPlugin = { chunker: chunkTextForOutbound, chunkerMode: "text", textChunkLimit: 2000, + sendPayload: async (ctx) => { + const urls = ctx.payload.mediaUrls?.length + ? ctx.payload.mediaUrls + : ctx.payload.mediaUrl + ? [ctx.payload.mediaUrl] + : []; + if (urls.length > 0) { + let lastResult; + for (let i = 0; i < urls.length; i++) { + lastResult = await zalouserPlugin.outbound!.sendMedia!({ + ...ctx, + text: i === 0 ? (ctx.payload.text ?? "") : "", + mediaUrl: urls[i], + }); + } + return lastResult!; + } + return zalouserPlugin.outbound!.sendText!({ ...ctx }); + }, sendText: async ({ to, text, accountId, cfg }) => { const account = resolveZalouserAccountSync({ cfg: cfg, accountId }); const result = await sendMessageZalouser(to, text, { profile: account.profile }); diff --git a/src/channels/plugins/outbound/direct-text-media.ts b/src/channels/plugins/outbound/direct-text-media.ts index 02b97078d1e..098e861880f 100644 --- a/src/channels/plugins/outbound/direct-text-media.ts +++ b/src/channels/plugins/outbound/direct-text-media.ts @@ -86,11 +86,30 @@ export function createDirectTextMediaOutbound< return { channel: params.channel, ...result }; }; - return { + const outbound: ChannelOutboundAdapter = { deliveryMode: "direct", chunker: chunkText, chunkerMode: "text", textChunkLimit: 4000, + sendPayload: async (ctx) => { + const urls = ctx.payload.mediaUrls?.length + ? ctx.payload.mediaUrls + : ctx.payload.mediaUrl + ? [ctx.payload.mediaUrl] + : []; + if (urls.length > 0) { + let lastResult; + for (let i = 0; i < urls.length; i++) { + lastResult = await outbound.sendMedia!({ + ...ctx, + text: i === 0 ? (ctx.payload.text ?? "") : "", + mediaUrl: urls[i], + }); + } + return lastResult; + } + return outbound.sendText!({ ...ctx }); + }, sendText: async ({ cfg, to, text, accountId, deps, replyToId }) => { return await sendDirect({ cfg, @@ -116,4 +135,5 @@ export function createDirectTextMediaOutbound< }); }, }; + return outbound; } diff --git a/src/channels/plugins/outbound/discord.ts b/src/channels/plugins/outbound/discord.ts index 69026db2734..76dd0165bea 100644 --- a/src/channels/plugins/outbound/discord.ts +++ b/src/channels/plugins/outbound/discord.ts @@ -80,6 +80,25 @@ export const discordOutbound: ChannelOutboundAdapter = { textChunkLimit: 2000, pollMaxOptions: 10, resolveTarget: ({ to }) => normalizeDiscordOutboundTarget(to), + sendPayload: async (ctx) => { + const urls = ctx.payload.mediaUrls?.length + ? ctx.payload.mediaUrls + : ctx.payload.mediaUrl + ? [ctx.payload.mediaUrl] + : []; + if (urls.length > 0) { + let lastResult; + for (let i = 0; i < urls.length; i++) { + lastResult = await discordOutbound.sendMedia!({ + ...ctx, + text: i === 0 ? (ctx.payload.text ?? "") : "", + mediaUrl: urls[i], + }); + } + return lastResult; + } + return discordOutbound.sendText!({ ...ctx }); + }, sendText: async ({ to, text, accountId, deps, replyToId, threadId, identity, silent }) => { if (!silent) { const webhookResult = await maybeSendDiscordWebhookText({ diff --git a/src/channels/plugins/outbound/slack.ts b/src/channels/plugins/outbound/slack.ts index 37cfe1943e9..b18da300e5e 100644 --- a/src/channels/plugins/outbound/slack.ts +++ b/src/channels/plugins/outbound/slack.ts @@ -93,6 +93,25 @@ export const slackOutbound: ChannelOutboundAdapter = { deliveryMode: "direct", chunker: null, textChunkLimit: 4000, + sendPayload: async (ctx) => { + const urls = ctx.payload.mediaUrls?.length + ? ctx.payload.mediaUrls + : ctx.payload.mediaUrl + ? [ctx.payload.mediaUrl] + : []; + if (urls.length > 0) { + let lastResult; + for (let i = 0; i < urls.length; i++) { + lastResult = await slackOutbound.sendMedia!({ + ...ctx, + text: i === 0 ? (ctx.payload.text ?? "") : "", + mediaUrl: urls[i], + }); + } + return lastResult; + } + return slackOutbound.sendText!({ ...ctx }); + }, sendText: async ({ to, text, accountId, deps, replyToId, threadId, identity }) => { return await sendSlackOutboundMessage({ to, diff --git a/src/channels/plugins/outbound/whatsapp.ts b/src/channels/plugins/outbound/whatsapp.ts index 5cd189d6848..d8a17842b41 100644 --- a/src/channels/plugins/outbound/whatsapp.ts +++ b/src/channels/plugins/outbound/whatsapp.ts @@ -12,6 +12,25 @@ export const whatsappOutbound: ChannelOutboundAdapter = { pollMaxOptions: 12, resolveTarget: ({ to, allowFrom, mode }) => resolveWhatsAppOutboundTarget({ to, allowFrom, mode }), + sendPayload: async (ctx) => { + const urls = ctx.payload.mediaUrls?.length + ? ctx.payload.mediaUrls + : ctx.payload.mediaUrl + ? [ctx.payload.mediaUrl] + : []; + if (urls.length > 0) { + let lastResult; + for (let i = 0; i < urls.length; i++) { + lastResult = await whatsappOutbound.sendMedia!({ + ...ctx, + text: i === 0 ? (ctx.payload.text ?? "") : "", + mediaUrl: urls[i], + }); + } + return lastResult; + } + return whatsappOutbound.sendText!({ ...ctx }); + }, sendText: async ({ to, text, accountId, deps, gifPlayback }) => { const send = deps?.sendWhatsApp ?? (await import("../../../web/outbound.js")).sendMessageWhatsApp;