114 lines
3.5 KiB
TypeScript
114 lines
3.5 KiB
TypeScript
import { resolveOutboundSendDep } from "../../infra/outbound/send-deps.js";
|
|
import type { PluginRuntimeChannel } from "../../plugins/runtime/types-channel.js";
|
|
import { escapeRegExp } from "../../utils.js";
|
|
import { resolveWhatsAppOutboundTarget } from "../../whatsapp/resolve-outbound-target.js";
|
|
import type { ChannelOutboundAdapter } from "./types.js";
|
|
|
|
export const WHATSAPP_GROUP_INTRO_HINT =
|
|
"WhatsApp IDs: SenderId is the participant JID (group participant id).";
|
|
|
|
export function resolveWhatsAppGroupIntroHint(): string {
|
|
return WHATSAPP_GROUP_INTRO_HINT;
|
|
}
|
|
|
|
export function resolveWhatsAppMentionStripPatterns(ctx: { To?: string | null }): string[] {
|
|
const selfE164 = (ctx.To ?? "").replace(/^whatsapp:/, "");
|
|
if (!selfE164) {
|
|
return [];
|
|
}
|
|
const escaped = escapeRegExp(selfE164);
|
|
return [escaped, `@${escaped}`];
|
|
}
|
|
|
|
export function resolveWhatsAppMentionStripRegexes(ctx: { To?: string | null }): RegExp[] {
|
|
return resolveWhatsAppMentionStripPatterns(ctx).map((pattern) => new RegExp(pattern, "g"));
|
|
}
|
|
|
|
type WhatsAppChunker = NonNullable<ChannelOutboundAdapter["chunker"]>;
|
|
type WhatsAppSendMessage = PluginRuntimeChannel["whatsapp"]["sendMessageWhatsApp"];
|
|
type WhatsAppSendPoll = PluginRuntimeChannel["whatsapp"]["sendPollWhatsApp"];
|
|
|
|
type CreateWhatsAppOutboundBaseParams = {
|
|
chunker: WhatsAppChunker;
|
|
sendMessageWhatsApp: WhatsAppSendMessage;
|
|
sendPollWhatsApp: WhatsAppSendPoll;
|
|
shouldLogVerbose: () => boolean;
|
|
resolveTarget?: ChannelOutboundAdapter["resolveTarget"];
|
|
normalizeText?: (text: string | undefined) => string;
|
|
skipEmptyText?: boolean;
|
|
};
|
|
|
|
export function createWhatsAppOutboundBase({
|
|
chunker,
|
|
sendMessageWhatsApp,
|
|
sendPollWhatsApp,
|
|
shouldLogVerbose,
|
|
resolveTarget = ({ to, allowFrom, mode }) =>
|
|
resolveWhatsAppOutboundTarget({ to, allowFrom, mode }),
|
|
normalizeText = (text) => text ?? "",
|
|
skipEmptyText = false,
|
|
}: CreateWhatsAppOutboundBaseParams): Pick<
|
|
ChannelOutboundAdapter,
|
|
| "deliveryMode"
|
|
| "chunker"
|
|
| "chunkerMode"
|
|
| "textChunkLimit"
|
|
| "pollMaxOptions"
|
|
| "resolveTarget"
|
|
| "sendText"
|
|
| "sendMedia"
|
|
| "sendPoll"
|
|
> {
|
|
return {
|
|
deliveryMode: "gateway",
|
|
chunker,
|
|
chunkerMode: "text",
|
|
textChunkLimit: 4000,
|
|
pollMaxOptions: 12,
|
|
resolveTarget,
|
|
sendText: async ({ cfg, to, text, accountId, deps, gifPlayback }) => {
|
|
const normalizedText = normalizeText(text);
|
|
if (skipEmptyText && !normalizedText) {
|
|
return { channel: "whatsapp", messageId: "" };
|
|
}
|
|
const send =
|
|
resolveOutboundSendDep<WhatsAppSendMessage>(deps, "whatsapp") ?? sendMessageWhatsApp;
|
|
const result = await send(to, normalizedText, {
|
|
verbose: false,
|
|
cfg,
|
|
accountId: accountId ?? undefined,
|
|
gifPlayback,
|
|
});
|
|
return { channel: "whatsapp", ...result };
|
|
},
|
|
sendMedia: async ({
|
|
cfg,
|
|
to,
|
|
text,
|
|
mediaUrl,
|
|
mediaLocalRoots,
|
|
accountId,
|
|
deps,
|
|
gifPlayback,
|
|
}) => {
|
|
const send =
|
|
resolveOutboundSendDep<WhatsAppSendMessage>(deps, "whatsapp") ?? sendMessageWhatsApp;
|
|
const result = await send(to, normalizeText(text), {
|
|
verbose: false,
|
|
cfg,
|
|
mediaUrl,
|
|
mediaLocalRoots,
|
|
accountId: accountId ?? undefined,
|
|
gifPlayback,
|
|
});
|
|
return { channel: "whatsapp", ...result };
|
|
},
|
|
sendPoll: async ({ cfg, to, poll, accountId }) =>
|
|
await sendPollWhatsApp(to, poll, {
|
|
verbose: shouldLogVerbose(),
|
|
accountId: accountId ?? undefined,
|
|
cfg,
|
|
}),
|
|
};
|
|
}
|