feat: add ws chat attachments
This commit is contained in:
@@ -680,8 +680,12 @@ describe("web auto-reply", () => {
|
||||
|
||||
expect(resolver).toHaveBeenCalledTimes(1);
|
||||
const args = resolver.mock.calls[0][0];
|
||||
expect(args.Body).toContain("[WhatsApp +1 2025-01-01 00:00] [clawdis] first");
|
||||
expect(args.Body).toContain("[WhatsApp +1 2025-01-01 01:00] [clawdis] second");
|
||||
expect(args.Body).toContain(
|
||||
"[WhatsApp +1 2025-01-01 00:00] [clawdis] first",
|
||||
);
|
||||
expect(args.Body).toContain(
|
||||
"[WhatsApp +1 2025-01-01 01:00] [clawdis] second",
|
||||
);
|
||||
|
||||
// Max listeners bumped to avoid warnings in multi-instance test runs
|
||||
expect(process.getMaxListeners?.()).toBeGreaterThanOrEqual(50);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { chunkText } from "../auto-reply/chunk.js";
|
||||
import { formatAgentEnvelope } from "../auto-reply/envelope.js";
|
||||
import { getReplyFromConfig } from "../auto-reply/reply.js";
|
||||
import type { ReplyPayload } from "../auto-reply/types.js";
|
||||
import { waitForever } from "../cli/wait.js";
|
||||
@@ -10,7 +11,7 @@ import {
|
||||
resolveStorePath,
|
||||
saveSessionStore,
|
||||
} from "../config/sessions.js";
|
||||
import { danger, info, isVerbose, logVerbose, success } from "../globals.js";
|
||||
import { danger, isVerbose, logVerbose, success } from "../globals.js";
|
||||
import { emitHeartbeatEvent } from "../infra/heartbeat-events.js";
|
||||
import { enqueueSystemEvent } from "../infra/system-events.js";
|
||||
import { logInfo } from "../logger.js";
|
||||
@@ -18,10 +19,10 @@ import { getChildLogger } from "../logging.js";
|
||||
import { getQueueSize } from "../process/command-queue.js";
|
||||
import { defaultRuntime, type RuntimeEnv } from "../runtime.js";
|
||||
import { jidToE164, normalizeE164 } from "../utils.js";
|
||||
import { setActiveWebListener } from "./active-listener.js";
|
||||
import { monitorWebInbox } from "./inbound.js";
|
||||
import { loadWebMedia } from "./media.js";
|
||||
import { sendMessageWhatsApp } from "./outbound.js";
|
||||
import { setActiveWebListener } from "./active-listener.js";
|
||||
import {
|
||||
computeBackoff,
|
||||
newConnectionId,
|
||||
@@ -31,7 +32,6 @@ import {
|
||||
sleepWithAbort,
|
||||
} from "./reconnect.js";
|
||||
import { formatError, getWebAuthAgeMs, readWebSelfId } from "./session.js";
|
||||
import { formatAgentEnvelope } from "../auto-reply/envelope.js";
|
||||
|
||||
const WEB_TEXT_LIMIT = 4000;
|
||||
const DEFAULT_GROUP_HISTORY_LIMIT = 50;
|
||||
@@ -494,7 +494,8 @@ async function deliverWebReply(params: {
|
||||
? [replyResult.mediaUrl]
|
||||
: [];
|
||||
|
||||
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
const sleep = (ms: number) =>
|
||||
new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
const sendWithRetry = async (
|
||||
fn: () => Promise<unknown>,
|
||||
@@ -1401,11 +1402,11 @@ export async function monitorWebProvider(
|
||||
},
|
||||
"web reconnect: scheduling retry",
|
||||
);
|
||||
runtime.error(
|
||||
danger(
|
||||
`WhatsApp Web connection closed (status ${status}). Retry ${reconnectAttempts}/${reconnectPolicy.maxAttempts || "∞"} in ${formatDuration(delay)}… (${errorStr})`,
|
||||
),
|
||||
);
|
||||
runtime.error(
|
||||
danger(
|
||||
`WhatsApp Web connection closed (status ${status}). Retry ${reconnectAttempts}/${reconnectPolicy.maxAttempts || "∞"} in ${formatDuration(delay)}… (${errorStr})`,
|
||||
),
|
||||
);
|
||||
await closeListener();
|
||||
try {
|
||||
await sleep(delay, abortSignal);
|
||||
|
||||
@@ -6,8 +6,8 @@ import { logVerbose } from "../globals.js";
|
||||
import { logInfo } from "../logger.js";
|
||||
import { getChildLogger } from "../logging.js";
|
||||
import { toWhatsappJid } from "../utils.js";
|
||||
import { loadWebMedia } from "./media.js";
|
||||
import { getActiveWebListener } from "./active-listener.js";
|
||||
import { loadWebMedia } from "./media.js";
|
||||
import { createWaSocket, waitForWaConnection } from "./session.js";
|
||||
|
||||
export async function sendMessageWhatsApp(
|
||||
@@ -18,7 +18,9 @@ export async function sendMessageWhatsApp(
|
||||
const correlationId = randomUUID();
|
||||
const active = getActiveWebListener();
|
||||
const usingActive = Boolean(active);
|
||||
const sock = usingActive ? null : await createWaSocket(false, options.verbose);
|
||||
const sock = usingActive
|
||||
? null
|
||||
: await createWaSocket(false, options.verbose);
|
||||
const logger = getChildLogger({
|
||||
module: "web-outbound",
|
||||
correlationId,
|
||||
@@ -29,9 +31,12 @@ export async function sendMessageWhatsApp(
|
||||
if (!usingActive) {
|
||||
logInfo("🔌 Connecting to WhatsApp Web…");
|
||||
logger.info("connecting to whatsapp web");
|
||||
await waitForWaConnection(sock!);
|
||||
if (!sock) {
|
||||
throw new Error("WhatsApp socket unavailable");
|
||||
}
|
||||
await waitForWaConnection(sock);
|
||||
try {
|
||||
await sock!.sendPresenceUpdate("composing", jid);
|
||||
await sock.sendPresenceUpdate("composing", jid);
|
||||
} catch (err) {
|
||||
logVerbose(`Presence update skipped: ${String(err)}`);
|
||||
}
|
||||
@@ -82,6 +87,7 @@ export async function sendMessageWhatsApp(
|
||||
);
|
||||
const result = usingActive
|
||||
? await (async () => {
|
||||
if (!active) throw new Error("Active web listener missing");
|
||||
let mediaBuffer: Buffer | undefined;
|
||||
let mediaType: string | undefined;
|
||||
if (options.mediaUrl) {
|
||||
@@ -89,13 +95,17 @@ export async function sendMessageWhatsApp(
|
||||
mediaBuffer = media.buffer;
|
||||
mediaType = media.contentType;
|
||||
}
|
||||
await active!.sendComposingTo(to);
|
||||
return active!.sendMessage(to, body, mediaBuffer, mediaType);
|
||||
await active.sendComposingTo(to);
|
||||
return active.sendMessage(to, body, mediaBuffer, mediaType);
|
||||
})()
|
||||
: await sock!.sendMessage(jid, payload);
|
||||
: await (async () => {
|
||||
if (!sock) throw new Error("WhatsApp socket unavailable");
|
||||
return sock.sendMessage(jid, payload);
|
||||
})();
|
||||
const messageId = usingActive
|
||||
? (result as { messageId?: string })?.messageId ?? "unknown"
|
||||
: (result as any)?.key?.id ?? "unknown";
|
||||
? ((result as { messageId?: string })?.messageId ?? "unknown")
|
||||
: ((result as { key?: { id?: string } } | undefined)?.key?.id ??
|
||||
"unknown");
|
||||
logInfo(
|
||||
`✅ Sent via web session. Message ID: ${messageId} -> ${jid}${options.mediaUrl ? " (media)" : ""}`,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user