import { chunkText } from "../../../auto-reply/chunk.js"; import { shouldLogVerbose } from "../../../globals.js"; import { sendMessageWhatsApp, sendPollWhatsApp } from "../../../web/outbound.js"; import { isWhatsAppGroupJid, normalizeWhatsAppTarget } from "../../../whatsapp/normalize.js"; import type { ChannelOutboundAdapter } from "../types.js"; export const whatsappOutbound: ChannelOutboundAdapter = { deliveryMode: "gateway", chunker: chunkText, textChunkLimit: 4000, pollMaxOptions: 12, resolveTarget: ({ to, allowFrom, mode }) => { const trimmed = to?.trim() ?? ""; const allowListRaw = (allowFrom ?? []).map((entry) => String(entry).trim()).filter(Boolean); const hasWildcard = allowListRaw.includes("*"); const allowList = allowListRaw .filter((entry) => entry !== "*") .map((entry) => normalizeWhatsAppTarget(entry)) .filter((entry): entry is string => Boolean(entry)); if (trimmed) { const normalizedTo = normalizeWhatsAppTarget(trimmed); if (!normalizedTo) { if ((mode === "implicit" || mode === "heartbeat") && allowList.length > 0) { return { ok: true, to: allowList[0] }; } return { ok: false, error: new Error( "Delivering to WhatsApp requires target or channels.whatsapp.allowFrom[0]", ), }; } if (isWhatsAppGroupJid(normalizedTo)) { return { ok: true, to: normalizedTo }; } if (mode === "implicit" || mode === "heartbeat") { if (hasWildcard || allowList.length === 0) { return { ok: true, to: normalizedTo }; } if (allowList.includes(normalizedTo)) { return { ok: true, to: normalizedTo }; } return { ok: true, to: allowList[0] }; } return { ok: true, to: normalizedTo }; } if (allowList.length > 0) { return { ok: true, to: allowList[0] }; } return { ok: false, error: new Error( "Delivering to WhatsApp requires target or channels.whatsapp.allowFrom[0]", ), }; }, sendText: async ({ to, text, accountId, deps, gifPlayback }) => { const send = deps?.sendWhatsApp ?? sendMessageWhatsApp; const result = await send(to, text, { verbose: false, accountId: accountId ?? undefined, gifPlayback, }); return { channel: "whatsapp", ...result }; }, sendMedia: async ({ to, text, mediaUrl, accountId, deps, gifPlayback }) => { const send = deps?.sendWhatsApp ?? sendMessageWhatsApp; const result = await send(to, text, { verbose: false, mediaUrl, accountId: accountId ?? undefined, gifPlayback, }); return { channel: "whatsapp", ...result }; }, sendPoll: async ({ to, poll, accountId }) => await sendPollWhatsApp(to, poll, { verbose: shouldLogVerbose(), accountId: accountId ?? undefined, }), };