Web: improve WhatsApp error formatting
parent
0241f1a29c
commit
9a4fc3e086
|
|
@ -9,9 +9,8 @@ import {
|
||||||
resetLoadConfigMock,
|
resetLoadConfigMock,
|
||||||
} from "./test-helpers.js";
|
} from "./test-helpers.js";
|
||||||
|
|
||||||
const { createWaSocket, logWebSelfId, waitForWaConnection } = await import(
|
const { createWaSocket, formatError, logWebSelfId, waitForWaConnection } =
|
||||||
"./session.js"
|
await import("./session.js");
|
||||||
);
|
|
||||||
|
|
||||||
describe("web session", () => {
|
describe("web session", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
@ -89,4 +88,23 @@ describe("web session", () => {
|
||||||
existsSpy.mockRestore();
|
existsSpy.mockRestore();
|
||||||
readSpy.mockRestore();
|
readSpy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("formatError prints Boom-like payload message", () => {
|
||||||
|
const err = {
|
||||||
|
error: {
|
||||||
|
isBoom: true,
|
||||||
|
output: {
|
||||||
|
statusCode: 408,
|
||||||
|
payload: {
|
||||||
|
statusCode: 408,
|
||||||
|
error: "Request Time-out",
|
||||||
|
message: "QR refs attempts ended",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(formatError(err)).toContain("status=408");
|
||||||
|
expect(formatError(err)).toContain("Request Time-out");
|
||||||
|
expect(formatError(err)).toContain("QR refs attempts ended");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -186,14 +186,88 @@ export function getStatusCode(err: unknown) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function safeStringify(value: unknown, limit = 800): string {
|
||||||
|
try {
|
||||||
|
const seen = new WeakSet<object>();
|
||||||
|
const raw = JSON.stringify(
|
||||||
|
value,
|
||||||
|
(_key, v) => {
|
||||||
|
if (typeof v === "bigint") return v.toString();
|
||||||
|
if (typeof v === "function") return `[Function ${(v as Function).name || "anonymous"}]`;
|
||||||
|
if (typeof v === "object" && v) {
|
||||||
|
if (seen.has(v)) return "[Circular]";
|
||||||
|
seen.add(v);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
},
|
||||||
|
2,
|
||||||
|
);
|
||||||
|
if (!raw) return String(value);
|
||||||
|
return raw.length > limit ? `${raw.slice(0, limit)}…` : raw;
|
||||||
|
} catch {
|
||||||
|
return String(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractBoomDetails(err: unknown): {
|
||||||
|
statusCode?: number;
|
||||||
|
error?: string;
|
||||||
|
message?: string;
|
||||||
|
} | null {
|
||||||
|
if (!err || typeof err !== "object") return null;
|
||||||
|
const output = (err as { output?: unknown })?.output as
|
||||||
|
| { statusCode?: unknown; payload?: unknown }
|
||||||
|
| undefined;
|
||||||
|
if (!output || typeof output !== "object") return null;
|
||||||
|
const payload = (output as { payload?: unknown }).payload as
|
||||||
|
| { error?: unknown; message?: unknown; statusCode?: unknown }
|
||||||
|
| undefined;
|
||||||
|
const statusCode =
|
||||||
|
typeof (output as { statusCode?: unknown }).statusCode === "number"
|
||||||
|
? ((output as { statusCode?: unknown }).statusCode as number)
|
||||||
|
: typeof payload?.statusCode === "number"
|
||||||
|
? (payload.statusCode as number)
|
||||||
|
: undefined;
|
||||||
|
const error = typeof payload?.error === "string" ? payload.error : undefined;
|
||||||
|
const message =
|
||||||
|
typeof payload?.message === "string" ? payload.message : undefined;
|
||||||
|
if (!statusCode && !error && !message) return null;
|
||||||
|
return { statusCode, error, message };
|
||||||
|
}
|
||||||
|
|
||||||
export function formatError(err: unknown): string {
|
export function formatError(err: unknown): string {
|
||||||
if (err instanceof Error) return err.message;
|
if (err instanceof Error) return err.message;
|
||||||
if (typeof err === "string") return err;
|
if (typeof err === "string") return err;
|
||||||
const status = getStatusCode(err);
|
if (!err || typeof err !== "object") return String(err);
|
||||||
|
|
||||||
|
// Baileys frequently wraps errors under `error` with a Boom-like shape.
|
||||||
|
const boom =
|
||||||
|
extractBoomDetails(err) ??
|
||||||
|
extractBoomDetails((err as { error?: unknown })?.error) ??
|
||||||
|
extractBoomDetails((err as { lastDisconnect?: { error?: unknown } })?.lastDisconnect?.error);
|
||||||
|
|
||||||
|
const status = boom?.statusCode ?? getStatusCode(err);
|
||||||
const code = (err as { code?: unknown })?.code;
|
const code = (err as { code?: unknown })?.code;
|
||||||
if (status || code)
|
|
||||||
return `status=${status ?? "unknown"} code=${code ?? "unknown"}`;
|
const messageCandidates = [
|
||||||
return String(err);
|
boom?.message,
|
||||||
|
typeof (err as { message?: unknown })?.message === "string"
|
||||||
|
? ((err as { message?: unknown }).message as string)
|
||||||
|
: undefined,
|
||||||
|
typeof (err as { error?: { message?: unknown } })?.error?.message === "string"
|
||||||
|
? ((err as { error?: { message?: unknown } }).error?.message as string)
|
||||||
|
: undefined,
|
||||||
|
].filter((v): v is string => Boolean(v && v.trim().length > 0));
|
||||||
|
const message = messageCandidates[0];
|
||||||
|
|
||||||
|
const pieces: string[] = [];
|
||||||
|
if (typeof status === "number") pieces.push(`status=${status}`);
|
||||||
|
if (boom?.error) pieces.push(boom.error);
|
||||||
|
if (message) pieces.push(message);
|
||||||
|
if (code !== undefined && code !== null) pieces.push(`code=${String(code)}`);
|
||||||
|
|
||||||
|
if (pieces.length > 0) return pieces.join(" ");
|
||||||
|
return safeStringify(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function webAuthExists() {
|
export async function webAuthExists() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue