refactor: share outbound media payload sequencing

This commit is contained in:
Peter Steinberger 2026-03-13 16:26:42 +00:00
parent a37e25fa21
commit 501837058c
2 changed files with 52 additions and 31 deletions

View File

@ -28,34 +28,58 @@ type SendPayloadAdapter = Pick<
"sendMedia" | "sendText" | "chunker" | "textChunkLimit" "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<TResult>(params: {
text: string;
mediaUrls: readonly string[];
send: (input: {
text: string;
mediaUrl: string;
index: number;
isFirst: boolean;
}) => Promise<TResult>;
}): Promise<TResult | undefined> {
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: { export async function sendTextMediaPayload(params: {
channel: string; channel: string;
ctx: SendPayloadContext; ctx: SendPayloadContext;
adapter: SendPayloadAdapter; adapter: SendPayloadAdapter;
}): Promise<SendPayloadResult> { }): Promise<SendPayloadResult> {
const text = params.ctx.payload.text ?? ""; const text = params.ctx.payload.text ?? "";
const urls = params.ctx.payload.mediaUrls?.length const urls = resolvePayloadMediaUrls(params.ctx.payload);
? params.ctx.payload.mediaUrls
: params.ctx.payload.mediaUrl
? [params.ctx.payload.mediaUrl]
: [];
if (!text && urls.length === 0) { if (!text && urls.length === 0) {
return { channel: params.channel, messageId: "" }; return { channel: params.channel, messageId: "" };
} }
if (urls.length > 0) { if (urls.length > 0) {
let lastResult = await params.adapter.sendMedia!({ const lastResult = await sendPayloadMediaSequence({
...params.ctx,
text, 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++) { return lastResult ?? { channel: params.channel, messageId: "" };
lastResult = await params.adapter.sendMedia!({
...params.ctx,
text: "",
mediaUrl: urls[i],
});
}
return lastResult;
} }
const limit = params.adapter.textChunkLimit; const limit = params.adapter.textChunkLimit;
const chunks = limit && params.adapter.chunker ? params.adapter.chunker(text, limit) : [text]; const chunks = limit && params.adapter.chunker ? params.adapter.chunker(text, limit) : [text];

View File

@ -8,6 +8,7 @@ import {
} from "../../../telegram/outbound-params.js"; } from "../../../telegram/outbound-params.js";
import { sendMessageTelegram } from "../../../telegram/send.js"; import { sendMessageTelegram } from "../../../telegram/send.js";
import type { ChannelOutboundAdapter } from "../types.js"; import type { ChannelOutboundAdapter } from "../types.js";
import { resolvePayloadMediaUrls, sendPayloadMediaSequence } from "./direct-text-media.js";
type TelegramSendFn = typeof sendMessageTelegram; type TelegramSendFn = typeof sendMessageTelegram;
type TelegramSendOpts = Parameters<TelegramSendFn>[2]; type TelegramSendOpts = Parameters<TelegramSendFn>[2];
@ -55,11 +56,7 @@ export async function sendTelegramPayloadMessages(params: {
const quoteText = const quoteText =
typeof telegramData?.quoteText === "string" ? telegramData.quoteText : undefined; typeof telegramData?.quoteText === "string" ? telegramData.quoteText : undefined;
const text = params.payload.text ?? ""; const text = params.payload.text ?? "";
const mediaUrls = params.payload.mediaUrls?.length const mediaUrls = resolvePayloadMediaUrls(params.payload);
? params.payload.mediaUrls
: params.payload.mediaUrl
? [params.payload.mediaUrl]
: [];
const payloadOpts = { const payloadOpts = {
...params.baseOpts, ...params.baseOpts,
quoteText, quoteText,
@ -73,16 +70,16 @@ export async function sendTelegramPayloadMessages(params: {
} }
// Telegram allows reply_markup on media; attach buttons only to the first send. // Telegram allows reply_markup on media; attach buttons only to the first send.
let finalResult: Awaited<ReturnType<TelegramSendFn>> | undefined; const finalResult = await sendPayloadMediaSequence({
for (let i = 0; i < mediaUrls.length; i += 1) { text,
const mediaUrl = mediaUrls[i]; mediaUrls,
const isFirst = i === 0; send: async ({ text, mediaUrl, isFirst }) =>
finalResult = await params.send(params.to, isFirst ? text : "", { await params.send(params.to, text, {
...payloadOpts, ...payloadOpts,
mediaUrl, mediaUrl,
...(isFirst ? { buttons: telegramData?.buttons } : {}), ...(isFirst ? { buttons: telegramData?.buttons } : {}),
}); }),
} });
return finalResult ?? { messageId: "unknown", chatId: params.to }; return finalResult ?? { messageId: "unknown", chatId: params.to };
} }