From 501837058cb811d0f310b2473b2bfd18d2b562ba Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 13 Mar 2026 16:26:42 +0000 Subject: [PATCH] refactor: share outbound media payload sequencing --- .../plugins/outbound/direct-text-media.ts | 56 +++++++++++++------ src/channels/plugins/outbound/telegram.ts | 27 ++++----- 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/src/channels/plugins/outbound/direct-text-media.ts b/src/channels/plugins/outbound/direct-text-media.ts index 9617798325d..ea813fcf75b 100644 --- a/src/channels/plugins/outbound/direct-text-media.ts +++ b/src/channels/plugins/outbound/direct-text-media.ts @@ -28,34 +28,58 @@ type SendPayloadAdapter = Pick< "sendMedia" | "sendText" | "chunker" | "textChunkLimit" >; +export function resolvePayloadMediaUrls(payload: SendPayloadContext["payload"]): string[] { + return payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : []; +} + +export async function sendPayloadMediaSequence(params: { + text: string; + mediaUrls: readonly string[]; + send: (input: { + text: string; + mediaUrl: string; + index: number; + isFirst: boolean; + }) => Promise; +}): Promise { + let lastResult: TResult | undefined; + for (let i = 0; i < params.mediaUrls.length; i += 1) { + const mediaUrl = params.mediaUrls[i]; + if (!mediaUrl) { + continue; + } + lastResult = await params.send({ + text: i === 0 ? params.text : "", + mediaUrl, + index: i, + isFirst: i === 0, + }); + } + return lastResult; +} + export async function sendTextMediaPayload(params: { channel: string; ctx: SendPayloadContext; adapter: SendPayloadAdapter; }): Promise { const text = params.ctx.payload.text ?? ""; - const urls = params.ctx.payload.mediaUrls?.length - ? params.ctx.payload.mediaUrls - : params.ctx.payload.mediaUrl - ? [params.ctx.payload.mediaUrl] - : []; + const urls = resolvePayloadMediaUrls(params.ctx.payload); if (!text && urls.length === 0) { return { channel: params.channel, messageId: "" }; } if (urls.length > 0) { - let lastResult = await params.adapter.sendMedia!({ - ...params.ctx, + const lastResult = await sendPayloadMediaSequence({ text, - mediaUrl: urls[0], + mediaUrls: urls, + send: async ({ text, mediaUrl }) => + await params.adapter.sendMedia!({ + ...params.ctx, + text, + mediaUrl, + }), }); - for (let i = 1; i < urls.length; i++) { - lastResult = await params.adapter.sendMedia!({ - ...params.ctx, - text: "", - mediaUrl: urls[i], - }); - } - return lastResult; + return lastResult ?? { channel: params.channel, messageId: "" }; } const limit = params.adapter.textChunkLimit; const chunks = limit && params.adapter.chunker ? params.adapter.chunker(text, limit) : [text]; diff --git a/src/channels/plugins/outbound/telegram.ts b/src/channels/plugins/outbound/telegram.ts index 8af1b5831ee..c96a44a7047 100644 --- a/src/channels/plugins/outbound/telegram.ts +++ b/src/channels/plugins/outbound/telegram.ts @@ -8,6 +8,7 @@ import { } from "../../../telegram/outbound-params.js"; import { sendMessageTelegram } from "../../../telegram/send.js"; import type { ChannelOutboundAdapter } from "../types.js"; +import { resolvePayloadMediaUrls, sendPayloadMediaSequence } from "./direct-text-media.js"; type TelegramSendFn = typeof sendMessageTelegram; type TelegramSendOpts = Parameters[2]; @@ -55,11 +56,7 @@ export async function sendTelegramPayloadMessages(params: { const quoteText = typeof telegramData?.quoteText === "string" ? telegramData.quoteText : undefined; const text = params.payload.text ?? ""; - const mediaUrls = params.payload.mediaUrls?.length - ? params.payload.mediaUrls - : params.payload.mediaUrl - ? [params.payload.mediaUrl] - : []; + const mediaUrls = resolvePayloadMediaUrls(params.payload); const payloadOpts = { ...params.baseOpts, quoteText, @@ -73,16 +70,16 @@ export async function sendTelegramPayloadMessages(params: { } // Telegram allows reply_markup on media; attach buttons only to the first send. - let finalResult: Awaited> | undefined; - for (let i = 0; i < mediaUrls.length; i += 1) { - const mediaUrl = mediaUrls[i]; - const isFirst = i === 0; - finalResult = await params.send(params.to, isFirst ? text : "", { - ...payloadOpts, - mediaUrl, - ...(isFirst ? { buttons: telegramData?.buttons } : {}), - }); - } + const finalResult = await sendPayloadMediaSequence({ + text, + mediaUrls, + send: async ({ text, mediaUrl, isFirst }) => + await params.send(params.to, text, { + ...payloadOpts, + mediaUrl, + ...(isFirst ? { buttons: telegramData?.buttons } : {}), + }), + }); return finalResult ?? { messageId: "unknown", chatId: params.to }; }