75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
import { randomUUID } from "node:crypto";
|
|
|
|
import { logInfo } from "../logger.js";
|
|
import { getChildLogger } from "../logging.js";
|
|
import { toWhatsappJid } from "../utils.js";
|
|
import { getActiveWebListener } from "./active-listener.js";
|
|
import { loadWebMedia } from "./media.js";
|
|
|
|
export async function sendMessageWhatsApp(
|
|
to: string,
|
|
body: string,
|
|
options: { verbose: boolean; mediaUrl?: string },
|
|
): Promise<{ messageId: string; toJid: string }> {
|
|
let text = body;
|
|
const correlationId = randomUUID();
|
|
const active = getActiveWebListener();
|
|
if (!active) {
|
|
throw new Error(
|
|
"No active gateway listener. Start the gateway before sending WhatsApp messages.",
|
|
);
|
|
}
|
|
const logger = getChildLogger({
|
|
module: "web-outbound",
|
|
correlationId,
|
|
to,
|
|
});
|
|
try {
|
|
const jid = toWhatsappJid(to);
|
|
let mediaBuffer: Buffer | undefined;
|
|
let mediaType: string | undefined;
|
|
if (options.mediaUrl) {
|
|
const media = await loadWebMedia(options.mediaUrl);
|
|
const caption = text || undefined;
|
|
mediaBuffer = media.buffer;
|
|
mediaType = media.contentType;
|
|
if (media.kind === "audio") {
|
|
// WhatsApp expects explicit opus codec for PTT voice notes.
|
|
mediaType =
|
|
media.contentType === "audio/ogg"
|
|
? "audio/ogg; codecs=opus"
|
|
: (media.contentType ?? "application/octet-stream");
|
|
} else if (media.kind === "video") {
|
|
text = caption ?? "";
|
|
} else if (media.kind === "image") {
|
|
text = caption ?? "";
|
|
} else {
|
|
text = caption ?? "";
|
|
}
|
|
}
|
|
logInfo(
|
|
`📤 Sending via web session -> ${jid}${options.mediaUrl ? " (media)" : ""}`,
|
|
);
|
|
logger.info(
|
|
{ jid, hasMedia: Boolean(options.mediaUrl) },
|
|
"sending message",
|
|
);
|
|
if (!active) throw new Error("Active web listener missing");
|
|
await active.sendComposingTo(to);
|
|
const result = await active.sendMessage(to, text, mediaBuffer, mediaType);
|
|
const messageId =
|
|
(result as { messageId?: string })?.messageId ?? "unknown";
|
|
logInfo(
|
|
`✅ Sent via web session. Message ID: ${messageId} -> ${jid}${options.mediaUrl ? " (media)" : ""}`,
|
|
);
|
|
logger.info({ jid, messageId }, "sent message");
|
|
return { messageId, toJid: jid };
|
|
} catch (err) {
|
|
logger.error(
|
|
{ err: String(err), to, hasMedia: Boolean(options.mediaUrl) },
|
|
"failed to send via web session",
|
|
);
|
|
throw err;
|
|
}
|
|
}
|