mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-06 08:03:39 +00:00
feat(whatsapp): support Baileys WebSocket URL override (#97155)
* Allow WhatsApp monitor socket substitution * Refine WhatsApp socket substitution surface * Keep WhatsApp socket seam on existing API * Tighten WhatsApp socket seam type exports * Simplify WhatsApp monitor runtime option state * Use WhatsApp WebSocket URL override
This commit is contained in:
@@ -41,6 +41,7 @@ const useMultiFileAuthStateMock = vi.mocked(baileys.useMultiFileAuthState);
|
||||
let createWaSocket: typeof import("./session.js").createWaSocket;
|
||||
let formatError: typeof import("./session.js").formatError;
|
||||
let logWebSelfId: typeof import("./session.js").logWebSelfId;
|
||||
let OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV: typeof import("./session.js").OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV;
|
||||
let renderQrTerminalMock: ReturnType<typeof vi.fn>;
|
||||
let waitForWaConnection: typeof import("./session.js").waitForWaConnection;
|
||||
let waitForCredsSaveQueue: typeof import("./session.js").waitForCredsSaveQueue;
|
||||
@@ -153,6 +154,7 @@ function readLastSocketOptions(): {
|
||||
fetchAgent?: unknown;
|
||||
keepAliveIntervalMs?: number;
|
||||
printQRInTerminal?: boolean;
|
||||
waWebSocketUrl?: string | URL;
|
||||
logger?: { level?: string; trace?: unknown };
|
||||
} {
|
||||
const [options] = firstMockCall(
|
||||
@@ -169,6 +171,7 @@ function readLastSocketOptions(): {
|
||||
fetchAgent?: unknown;
|
||||
keepAliveIntervalMs?: number;
|
||||
printQRInTerminal?: boolean;
|
||||
waWebSocketUrl?: string | URL;
|
||||
logger?: { level?: string; trace?: unknown };
|
||||
};
|
||||
}
|
||||
@@ -224,6 +227,7 @@ describe("web session", () => {
|
||||
createWaSocket,
|
||||
formatError,
|
||||
logWebSelfId,
|
||||
OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV,
|
||||
waitForWaConnection,
|
||||
waitForCredsSaveQueue,
|
||||
writeCredsJsonAtomically,
|
||||
@@ -411,6 +415,40 @@ describe("web session", () => {
|
||||
expect(passed.defaultQueryTimeoutMs).toBe(120_000);
|
||||
});
|
||||
|
||||
it("passes explicit Baileys WebSocket URL overrides", async () => {
|
||||
await createWaSocket(false, false, {
|
||||
waWebSocketUrl: " ws://127.0.0.1:49152/ws/chat ",
|
||||
});
|
||||
|
||||
expect(readLastSocketOptions().waWebSocketUrl).toBe("ws://127.0.0.1:49152/ws/chat");
|
||||
});
|
||||
|
||||
it("uses OPENCLAW_WHATSAPP_WEB_SOCKET_URL as the default Baileys WebSocket URL", async () => {
|
||||
vi.stubEnv(OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV, " ws://127.0.0.1:49153/ws/chat ");
|
||||
|
||||
await createWaSocket(false, false);
|
||||
|
||||
expect(readLastSocketOptions().waWebSocketUrl).toBe("ws://127.0.0.1:49153/ws/chat");
|
||||
});
|
||||
|
||||
it("preserves explicit Baileys WebSocket URL options over environment", async () => {
|
||||
vi.stubEnv(OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV, "ws://127.0.0.1:49153/ws/chat");
|
||||
|
||||
await createWaSocket(false, false, {
|
||||
waWebSocketUrl: "ws://127.0.0.1:49154/ws/chat",
|
||||
});
|
||||
|
||||
expect(readLastSocketOptions().waWebSocketUrl).toBe("ws://127.0.0.1:49154/ws/chat");
|
||||
});
|
||||
|
||||
it("ignores blank Baileys WebSocket URL environment overrides", async () => {
|
||||
vi.stubEnv(OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV, " ");
|
||||
|
||||
await createWaSocket(false, false);
|
||||
|
||||
expect(readLastSocketOptions().waWebSocketUrl).toBeUndefined();
|
||||
});
|
||||
|
||||
it("uses ambient env proxy agent when HTTPS_PROXY is configured", async () => {
|
||||
vi.stubEnv("HTTPS_PROXY", "http://proxy.test:8080");
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ const LOGGED_OUT_STATUS = 401;
|
||||
const WHATSAPP_WEBSOCKET_PROXY_TARGET = "https://mmg.whatsapp.net/";
|
||||
const CREDS_FLUSH_TIMEOUT_MESSAGE =
|
||||
"Queued WhatsApp creds save did not finish before auth bootstrap; skipping repair and continuing with primary creds.";
|
||||
export const OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV = "OPENCLAW_WHATSAPP_WEB_SOCKET_URL";
|
||||
|
||||
async function rejectUnsafeWebCredsPath(authDir: string): Promise<void> {
|
||||
await assertWebCredsPathRegularFileOrMissing(resolveWebCredsPath(authDir));
|
||||
@@ -125,6 +126,13 @@ async function printTerminalQr(qr: string): Promise<void> {
|
||||
process.stdout.write(output.endsWith("\n") ? output : `${output}\n`);
|
||||
}
|
||||
|
||||
function resolveWaWebSocketUrl(value: string | URL | undefined): string | URL | undefined {
|
||||
if (typeof value !== "string") {
|
||||
return value;
|
||||
}
|
||||
return value.trim() || undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Baileys socket backed by the multi-file auth store we keep on disk.
|
||||
* Consumers can opt into QR printing for interactive login flows.
|
||||
@@ -137,6 +145,7 @@ export async function createWaSocket(
|
||||
onQr?: (qr: string) => void;
|
||||
getMessage?: (key: WAMessageKey) => Promise<proto.IMessage | undefined>;
|
||||
cachedGroupMetadata?: (jid: string) => Promise<GroupMetadata | undefined>;
|
||||
waWebSocketUrl?: string | URL;
|
||||
} & WhatsAppSocketTimingOptions = {},
|
||||
): Promise<ReturnType<typeof makeWASocket>> {
|
||||
const baseLogger = getChildLogger(
|
||||
@@ -172,6 +181,9 @@ export async function createWaSocket(
|
||||
defaultQueryTimeoutMs:
|
||||
opts.defaultQueryTimeoutMs ?? DEFAULT_WHATSAPP_SOCKET_TIMING.defaultQueryTimeoutMs,
|
||||
};
|
||||
const waWebSocketUrl =
|
||||
resolveWaWebSocketUrl(opts.waWebSocketUrl) ??
|
||||
resolveWaWebSocketUrl(process.env[OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV]);
|
||||
const sock = makeWASocket({
|
||||
auth: {
|
||||
creds: state.creds,
|
||||
@@ -188,6 +200,7 @@ export async function createWaSocket(
|
||||
// Baileys types still model `fetchAgent` as a Node agent even though the
|
||||
// runtime path accepts an undici dispatcher for upload fetches.
|
||||
fetchAgent: fetchAgent as Agent | undefined,
|
||||
...(waWebSocketUrl ? { waWebSocketUrl } : {}),
|
||||
...(opts.getMessage ? { getMessage: opts.getMessage } : {}),
|
||||
...(opts.cachedGroupMetadata ? { cachedGroupMetadata: opts.cachedGroupMetadata } : {}),
|
||||
});
|
||||
|
||||
@@ -921,6 +921,7 @@ describe("workspace .env blocklist completeness", () => {
|
||||
"OPENCLAW_DISABLE_BUNDLED_PLUGINS",
|
||||
"OPENCLAW_ALLOW_INSECURE_PRIVATE_WS",
|
||||
"OPENCLAW_BROWSER_EXECUTABLE_PATH",
|
||||
"OPENCLAW_WHATSAPP_WEB_SOCKET_URL",
|
||||
"EXAMPLE_API_HOST",
|
||||
"HOMEBREW_BREW_FILE",
|
||||
"HOMEBREW_PREFIX",
|
||||
|
||||
Reference in New Issue
Block a user