@hanzo/bot 2026.3.8 → 2026.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{audio-preflight-D_s-peid.js → audio-preflight-BnfuyvxO.js} +4 -4
- package/dist/{audio-preflight-BEc8i-bS.js → audio-preflight-CpAXC_Ct.js} +4 -4
- package/dist/{audio-transcription-runner-X1KzI7dF.js → audio-transcription-runner-CAOjjGxN.js} +1 -1
- package/dist/{audio-transcription-runner-BePCnZfw.js → audio-transcription-runner-GcMnO6sT.js} +1 -1
- package/dist/build-info.json +3 -3
- package/dist/bundled/boot-md/handler.js +6 -6
- package/dist/bundled/session-memory/handler.js +6 -6
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/{chrome-B24-8NDM.js → chrome--CFg5C_H.js} +8 -8
- package/dist/{chrome-C7OwLtx9.js → chrome-jCt9JCU8.js} +8 -8
- package/dist/{cloud-connect-CknfBF39.js → cloud-connect-6kdj8st_.js} +1 -1
- package/dist/{deliver-D8dBbzpu.js → deliver-BVtVDxwX.js} +1 -1
- package/dist/{deliver-DudaV86i.js → deliver-DmfS4khs.js} +1 -1
- package/dist/{deliver-runtime-C76IMU4W.js → deliver-runtime-G0G5orrZ.js} +3 -3
- package/dist/{deliver-runtime-qDmQqiF-.js → deliver-runtime-PxJvVUhh.js} +3 -3
- package/dist/{deps-send-whatsapp.runtime-Cv_awFtm.js → deps-send-whatsapp.runtime-8bLqjmui.js} +7 -7
- package/dist/{deps-send-whatsapp.runtime-Cq-TLsJw.js → deps-send-whatsapp.runtime-CrzuaVhC.js} +7 -7
- package/dist/entry.js +15 -8
- package/dist/extensionAPI.js +6 -6
- package/dist/{image-nUHQF6BX.js → image-BdZcUz8M.js} +1 -1
- package/dist/{image-BOybyCis.js → image-DSK1hSSV.js} +1 -1
- package/dist/{image-runtime-B5M_-diF.js → image-runtime-ueqmfx1a.js} +3 -3
- package/dist/{image-runtime-y4msd5bn.js → image-runtime-xqxW2PQA.js} +3 -3
- package/dist/llm-slug-generator.js +6 -6
- package/dist/{local-launch-C2RER-G3.js → local-launch-BJpBAIR5.js} +37 -33
- package/dist/{pi-embedded-BHXPs-Ix.js → pi-embedded-DBn841N-.js} +24 -24
- package/dist/{pi-embedded-DvWHP6Nn.js → pi-embedded-DYc6emwb.js} +24 -24
- package/dist/{pi-embedded-helpers-xIXwvwuE.js → pi-embedded-helpers-BtnBVL-4.js} +3 -3
- package/dist/{pi-embedded-helpers-Ck1qEeMH.js → pi-embedded-helpers-DLm1Mtr2.js} +3 -3
- package/dist/plugin-sdk/accounts-B8qv93DH.js +35 -0
- package/dist/plugin-sdk/accounts-D2p8t4UO.js +288 -0
- package/dist/plugin-sdk/accounts-D96D1U9M.js +46 -0
- package/dist/plugin-sdk/active-listener-Mha1rAbh.js +50 -0
- package/dist/plugin-sdk/api-key-rotation-D0aZfxXH.js +181 -0
- package/dist/plugin-sdk/audio-preflight-D3y8mHJa.js +69 -0
- package/dist/plugin-sdk/audio-transcription-runner-j0mQXKSH.js +2205 -0
- package/dist/plugin-sdk/audit-membership-runtime-D-Ni2WDc.js +58 -0
- package/dist/plugin-sdk/channel-activity-VpA3MxPb.js +94 -0
- package/dist/plugin-sdk/channel-web-BP3vDdim.js +2256 -0
- package/dist/plugin-sdk/chrome-5jJIDTj0.js +2447 -0
- package/dist/plugin-sdk/commands-registry-BVKCdwN_.js +1125 -0
- package/dist/plugin-sdk/config-CudVTZDi.js +18200 -0
- package/dist/plugin-sdk/deliver-4NrmrRKu.js +1744 -0
- package/dist/plugin-sdk/deliver-runtime-CB4wXMTH.js +32 -0
- package/dist/plugin-sdk/deps-send-discord.runtime-Di8ELKED.js +23 -0
- package/dist/plugin-sdk/deps-send-imessage.runtime-CWWtApbz.js +22 -0
- package/dist/plugin-sdk/deps-send-signal.runtime-C6BGyoIY.js +21 -0
- package/dist/plugin-sdk/deps-send-slack.runtime-DgtITBuc.js +19 -0
- package/dist/plugin-sdk/deps-send-telegram.runtime-DyY4XRxh.js +24 -0
- package/dist/plugin-sdk/deps-send-whatsapp.runtime-LKiQNFcF.js +57 -0
- package/dist/plugin-sdk/diagnostic-DCPixRez.js +319 -0
- package/dist/plugin-sdk/errors-D5bA02--.js +54 -0
- package/dist/plugin-sdk/fetch-guard-n0LVdzZL.js +156 -0
- package/dist/plugin-sdk/fs-safe-IQ0H7rVD.js +352 -0
- package/dist/plugin-sdk/image-n-R2HcNg.js +2314 -0
- package/dist/plugin-sdk/image-ops-BpYDXC6N.js +584 -0
- package/dist/plugin-sdk/image-runtime-CbCl82B8.js +25 -0
- package/dist/plugin-sdk/index.js +50 -50
- package/dist/plugin-sdk/ir-DsMX3GcS.js +1296 -0
- package/dist/plugin-sdk/local-roots-DR-lR22p.js +186 -0
- package/dist/plugin-sdk/logger-2A0UE34q.js +1163 -0
- package/dist/plugin-sdk/login-CxFTtHEi.js +57 -0
- package/dist/plugin-sdk/login-qr-BCkrf1Zx.js +320 -0
- package/dist/plugin-sdk/manager-ClUgSFkG.js +3943 -0
- package/dist/plugin-sdk/manager-runtime-MWzYCRyH.js +15 -0
- package/dist/plugin-sdk/outbound-Dqs8L8QW.js +212 -0
- package/dist/plugin-sdk/outbound-attachment-CPfpUcdI.js +19 -0
- package/dist/plugin-sdk/path-alias-guards-LILr7Hrs.js +43 -0
- package/dist/plugin-sdk/paths-CfGmXu9A.js +166 -0
- package/dist/plugin-sdk/pi-embedded-helpers-CeC8GbRi.js +9731 -0
- package/dist/plugin-sdk/pi-model-discovery-DycOMKYh.js +134 -0
- package/dist/plugin-sdk/pi-model-discovery-runtime-C64BYe5F.js +8 -0
- package/dist/plugin-sdk/pi-tools.before-tool-call.runtime-C-HNtPSw.js +354 -0
- package/dist/plugin-sdk/plugins-2gQWMmUN.js +1205 -0
- package/dist/plugin-sdk/proxy-fetch-sX3-xzX1.js +38 -0
- package/dist/plugin-sdk/pw-ai-D7FTxM3C.js +1938 -0
- package/dist/plugin-sdk/qmd-manager-Da3Jq30m.js +1608 -0
- package/dist/plugin-sdk/query-expansion-B5Z0In1U.js +1014 -0
- package/dist/plugin-sdk/redact-85H1J7mo.js +319 -0
- package/dist/plugin-sdk/reply-DmCyOPxV.js +102224 -0
- package/dist/plugin-sdk/resolve-outbound-target-y0Sp7gsM.js +40 -0
- package/dist/plugin-sdk/run-with-concurrency-CFRxflYW.js +1994 -0
- package/dist/plugin-sdk/runtime-whatsapp-login.runtime-fgm84Rdh.js +10 -0
- package/dist/plugin-sdk/runtime-whatsapp-outbound.runtime-DpMuLd_h.js +19 -0
- package/dist/plugin-sdk/send-BQvcPd54.js +3135 -0
- package/dist/plugin-sdk/send-Bplfz7UW.js +540 -0
- package/dist/plugin-sdk/send-C8gdhoLP.js +414 -0
- package/dist/plugin-sdk/send-CTOVZqmi.js +2602 -0
- package/dist/plugin-sdk/send-Cld7xlxq.js +503 -0
- package/dist/plugin-sdk/session-D4k86ARy.js +169 -0
- package/dist/plugin-sdk/signal.js +2 -2
- package/dist/plugin-sdk/skill-commands-BfHvtJx2.js +353 -0
- package/dist/plugin-sdk/skills-BrE5Yb5o.js +1428 -0
- package/dist/plugin-sdk/slash-commands.runtime-UpSrdY-a.js +13 -0
- package/dist/plugin-sdk/slash-dispatch.runtime-C-Ymizf2.js +52 -0
- package/dist/plugin-sdk/slash-skill-commands.runtime-Bb9wo3w0.js +16 -0
- package/dist/plugin-sdk/ssrf-CbvrROKN.js +202 -0
- package/dist/plugin-sdk/store-8XS_isi_.js +81 -0
- package/dist/plugin-sdk/subagent-registry-runtime-Cl3jJKM1.js +52 -0
- package/dist/plugin-sdk/tables-BhfDBQ58.js +55 -0
- package/dist/plugin-sdk/target-errors-0DW3k-Ae.js +195 -0
- package/dist/plugin-sdk/thinking-DE2FCBnv.js +1209 -0
- package/dist/plugin-sdk/tokens-C2tJ8uXs.js +52 -0
- package/dist/plugin-sdk/tool-images-B1I6LEp7.js +274 -0
- package/dist/plugin-sdk/web-BHzDLmns.js +56 -0
- package/dist/plugin-sdk/whatsapp-actions-BoAH0BAS.js +80 -0
- package/dist/{pw-ai-DweqbnMJ.js → pw-ai-C-Sy12jT.js} +1 -1
- package/dist/{pw-ai-DsYmOxCp.js → pw-ai-pJMhS79V.js} +1 -1
- package/dist/{run-main-CgFUs81l.js → run-main-JI9-1g4u.js} +2 -2
- package/dist/{slash-dispatch.runtime-D28-UnsO.js → slash-dispatch.runtime-DLP2IeNv.js} +6 -6
- package/dist/{slash-dispatch.runtime-DzpJjr3K.js → slash-dispatch.runtime-Vp6IDoCc.js} +6 -6
- package/dist/{subagent-registry-runtime-a7xfwPB8.js → subagent-registry-runtime-BlAI3eqU.js} +6 -6
- package/dist/{subagent-registry-runtime-Bt-LYyrB.js → subagent-registry-runtime-COKZwsHd.js} +6 -6
- package/dist/{web-CREcqhe9.js → web-BEuMJbx-.js} +6 -6
- package/dist/{web-IBqHOVI2.js → web-BvId86u4.js} +6 -6
- package/extensions/acpx/package.json +1 -1
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/ci-fix-loop/package.json +1 -1
- package/extensions/continuous-learning/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/diffs/package.json +1 -1
- package/extensions/discord/package.json +1 -1
- package/extensions/feishu/package.json +1 -1
- package/extensions/flow/package.json +1 -1
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +10 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +10 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +10 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/self-improvement/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/package.json +1 -1
- package/extensions/synology-chat/package.json +1 -1
- package/extensions/telegram/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +10 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +10 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +10 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +10 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { i as resolveWhatsAppAccount, l as logoutWeb } from "./accounts-D2p8t4UO.js";
|
|
2
|
+
import { Lr as formatCliCommand, n as loadConfig } from "./config-CudVTZDi.js";
|
|
3
|
+
import { B as success, F as danger, I as info, c as defaultRuntime, r as logInfo } from "./logger-2A0UE34q.js";
|
|
4
|
+
import { i as waitForWaConnection, n as formatError, t as createWaSocket } from "./session-D4k86ARy.js";
|
|
5
|
+
import { DisconnectReason } from "@whiskeysockets/baileys";
|
|
6
|
+
|
|
7
|
+
//#region src/web/login.ts
|
|
8
|
+
async function loginWeb(verbose, waitForConnection, runtime = defaultRuntime, accountId) {
|
|
9
|
+
const wait = waitForConnection ?? waitForWaConnection;
|
|
10
|
+
const account = resolveWhatsAppAccount({
|
|
11
|
+
cfg: loadConfig(),
|
|
12
|
+
accountId
|
|
13
|
+
});
|
|
14
|
+
const sock = await createWaSocket(true, verbose, { authDir: account.authDir });
|
|
15
|
+
logInfo("Waiting for WhatsApp connection...", runtime);
|
|
16
|
+
try {
|
|
17
|
+
await wait(sock);
|
|
18
|
+
console.log(success("✅ Linked! Credentials saved for future sends."));
|
|
19
|
+
} catch (err) {
|
|
20
|
+
const code = err?.error?.output?.statusCode ?? err?.output?.statusCode;
|
|
21
|
+
if (code === 515) {
|
|
22
|
+
console.log(info("WhatsApp asked for a restart after pairing (code 515); creds are saved. Restarting connection once…"));
|
|
23
|
+
try {
|
|
24
|
+
sock.ws?.close();
|
|
25
|
+
} catch {}
|
|
26
|
+
const retry = await createWaSocket(false, verbose, { authDir: account.authDir });
|
|
27
|
+
try {
|
|
28
|
+
await wait(retry);
|
|
29
|
+
console.log(success("✅ Linked after restart; web session ready."));
|
|
30
|
+
return;
|
|
31
|
+
} finally {
|
|
32
|
+
setTimeout(() => retry.ws?.close(), 500);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (code === DisconnectReason.loggedOut) {
|
|
36
|
+
await logoutWeb({
|
|
37
|
+
authDir: account.authDir,
|
|
38
|
+
isLegacyAuthDir: account.isLegacyAuthDir,
|
|
39
|
+
runtime
|
|
40
|
+
});
|
|
41
|
+
console.error(danger(`WhatsApp reported the session is logged out. Cleared cached web session; please rerun ${formatCliCommand("openclaw channels login")} and scan the QR again.`));
|
|
42
|
+
throw new Error("Session logged out; cache cleared. Re-run login.", { cause: err });
|
|
43
|
+
}
|
|
44
|
+
const formatted = formatError(err);
|
|
45
|
+
console.error(danger(`WhatsApp Web connection ended before fully opening. ${formatted}`));
|
|
46
|
+
throw new Error(formatted, { cause: err });
|
|
47
|
+
} finally {
|
|
48
|
+
setTimeout(() => {
|
|
49
|
+
try {
|
|
50
|
+
sock.ws?.close();
|
|
51
|
+
} catch {}
|
|
52
|
+
}, 500);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
export { loginWeb as t };
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import "./run-with-concurrency-CFRxflYW.js";
|
|
2
|
+
import { _ as webAuthExists, i as resolveWhatsAppAccount, l as logoutWeb, p as readWebSelfId } from "./accounts-D2p8t4UO.js";
|
|
3
|
+
import "./paths-MKyEVmEb.js";
|
|
4
|
+
import "./github-copilot-token-D5fdS6xD.js";
|
|
5
|
+
import { n as loadConfig } from "./config-CudVTZDi.js";
|
|
6
|
+
import { B as success, F as danger, I as info, c as defaultRuntime, r as logInfo } from "./logger-2A0UE34q.js";
|
|
7
|
+
import { i as waitForWaConnection, n as formatError, r as getStatusCode, t as createWaSocket } from "./session-D4k86ARy.js";
|
|
8
|
+
import { randomUUID } from "node:crypto";
|
|
9
|
+
import { DisconnectReason } from "@whiskeysockets/baileys";
|
|
10
|
+
import QRCodeModule from "qrcode-terminal/vendor/QRCode/index.js";
|
|
11
|
+
import QRErrorCorrectLevelModule from "qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js";
|
|
12
|
+
import { deflateSync } from "node:zlib";
|
|
13
|
+
|
|
14
|
+
//#region src/media/png-encode.ts
|
|
15
|
+
/**
|
|
16
|
+
* Minimal PNG encoder for generating simple RGBA images without native dependencies.
|
|
17
|
+
* Used for QR codes, live probes, and other programmatic image generation.
|
|
18
|
+
*/
|
|
19
|
+
const CRC_TABLE = (() => {
|
|
20
|
+
const table = new Uint32Array(256);
|
|
21
|
+
for (let i = 0; i < 256; i += 1) {
|
|
22
|
+
let c = i;
|
|
23
|
+
for (let k = 0; k < 8; k += 1) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
24
|
+
table[i] = c >>> 0;
|
|
25
|
+
}
|
|
26
|
+
return table;
|
|
27
|
+
})();
|
|
28
|
+
/** Compute CRC32 checksum for a buffer (used in PNG chunk encoding). */
|
|
29
|
+
function crc32(buf) {
|
|
30
|
+
let crc = 4294967295;
|
|
31
|
+
for (let i = 0; i < buf.length; i += 1) crc = CRC_TABLE[(crc ^ buf[i]) & 255] ^ crc >>> 8;
|
|
32
|
+
return (crc ^ 4294967295) >>> 0;
|
|
33
|
+
}
|
|
34
|
+
/** Create a PNG chunk with type, data, and CRC. */
|
|
35
|
+
function pngChunk(type, data) {
|
|
36
|
+
const typeBuf = Buffer.from(type, "ascii");
|
|
37
|
+
const len = Buffer.alloc(4);
|
|
38
|
+
len.writeUInt32BE(data.length, 0);
|
|
39
|
+
const crc = crc32(Buffer.concat([typeBuf, data]));
|
|
40
|
+
const crcBuf = Buffer.alloc(4);
|
|
41
|
+
crcBuf.writeUInt32BE(crc, 0);
|
|
42
|
+
return Buffer.concat([
|
|
43
|
+
len,
|
|
44
|
+
typeBuf,
|
|
45
|
+
data,
|
|
46
|
+
crcBuf
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
49
|
+
/** Write a pixel to an RGBA buffer. Ignores out-of-bounds writes. */
|
|
50
|
+
function fillPixel(buf, x, y, width, r, g, b, a = 255) {
|
|
51
|
+
if (x < 0 || y < 0 || x >= width) return;
|
|
52
|
+
const idx = (y * width + x) * 4;
|
|
53
|
+
if (idx < 0 || idx + 3 >= buf.length) return;
|
|
54
|
+
buf[idx] = r;
|
|
55
|
+
buf[idx + 1] = g;
|
|
56
|
+
buf[idx + 2] = b;
|
|
57
|
+
buf[idx + 3] = a;
|
|
58
|
+
}
|
|
59
|
+
/** Encode an RGBA buffer as a PNG image. */
|
|
60
|
+
function encodePngRgba(buffer, width, height) {
|
|
61
|
+
const stride = width * 4;
|
|
62
|
+
const raw = Buffer.alloc((stride + 1) * height);
|
|
63
|
+
for (let row = 0; row < height; row += 1) {
|
|
64
|
+
const rawOffset = row * (stride + 1);
|
|
65
|
+
raw[rawOffset] = 0;
|
|
66
|
+
buffer.copy(raw, rawOffset + 1, row * stride, row * stride + stride);
|
|
67
|
+
}
|
|
68
|
+
const compressed = deflateSync(raw);
|
|
69
|
+
const signature = Buffer.from([
|
|
70
|
+
137,
|
|
71
|
+
80,
|
|
72
|
+
78,
|
|
73
|
+
71,
|
|
74
|
+
13,
|
|
75
|
+
10,
|
|
76
|
+
26,
|
|
77
|
+
10
|
|
78
|
+
]);
|
|
79
|
+
const ihdr = Buffer.alloc(13);
|
|
80
|
+
ihdr.writeUInt32BE(width, 0);
|
|
81
|
+
ihdr.writeUInt32BE(height, 4);
|
|
82
|
+
ihdr[8] = 8;
|
|
83
|
+
ihdr[9] = 6;
|
|
84
|
+
ihdr[10] = 0;
|
|
85
|
+
ihdr[11] = 0;
|
|
86
|
+
ihdr[12] = 0;
|
|
87
|
+
return Buffer.concat([
|
|
88
|
+
signature,
|
|
89
|
+
pngChunk("IHDR", ihdr),
|
|
90
|
+
pngChunk("IDAT", compressed),
|
|
91
|
+
pngChunk("IEND", Buffer.alloc(0))
|
|
92
|
+
]);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/web/qr-image.ts
|
|
97
|
+
const QRCode = QRCodeModule;
|
|
98
|
+
const QRErrorCorrectLevel = QRErrorCorrectLevelModule;
|
|
99
|
+
function createQrMatrix(input) {
|
|
100
|
+
const qr = new QRCode(-1, QRErrorCorrectLevel.L);
|
|
101
|
+
qr.addData(input);
|
|
102
|
+
qr.make();
|
|
103
|
+
return qr;
|
|
104
|
+
}
|
|
105
|
+
async function renderQrPngBase64(input, opts = {}) {
|
|
106
|
+
const { scale = 6, marginModules = 4 } = opts;
|
|
107
|
+
const qr = createQrMatrix(input);
|
|
108
|
+
const modules = qr.getModuleCount();
|
|
109
|
+
const size = (modules + marginModules * 2) * scale;
|
|
110
|
+
const buf = Buffer.alloc(size * size * 4, 255);
|
|
111
|
+
for (let row = 0; row < modules; row += 1) for (let col = 0; col < modules; col += 1) {
|
|
112
|
+
if (!qr.isDark(row, col)) continue;
|
|
113
|
+
const startX = (col + marginModules) * scale;
|
|
114
|
+
const startY = (row + marginModules) * scale;
|
|
115
|
+
for (let y = 0; y < scale; y += 1) {
|
|
116
|
+
const pixelY = startY + y;
|
|
117
|
+
for (let x = 0; x < scale; x += 1) fillPixel(buf, startX + x, pixelY, size, 0, 0, 0, 255);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return encodePngRgba(buf, size, size).toString("base64");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/web/login-qr.ts
|
|
125
|
+
const ACTIVE_LOGIN_TTL_MS = 3 * 6e4;
|
|
126
|
+
const activeLogins = /* @__PURE__ */ new Map();
|
|
127
|
+
function closeSocket(sock) {
|
|
128
|
+
try {
|
|
129
|
+
sock.ws?.close();
|
|
130
|
+
} catch {}
|
|
131
|
+
}
|
|
132
|
+
async function resetActiveLogin(accountId, reason) {
|
|
133
|
+
const login = activeLogins.get(accountId);
|
|
134
|
+
if (login) {
|
|
135
|
+
closeSocket(login.sock);
|
|
136
|
+
activeLogins.delete(accountId);
|
|
137
|
+
}
|
|
138
|
+
if (reason) logInfo(reason);
|
|
139
|
+
}
|
|
140
|
+
function isLoginFresh(login) {
|
|
141
|
+
return Date.now() - login.startedAt < ACTIVE_LOGIN_TTL_MS;
|
|
142
|
+
}
|
|
143
|
+
function attachLoginWaiter(accountId, login) {
|
|
144
|
+
login.waitPromise = waitForWaConnection(login.sock).then(() => {
|
|
145
|
+
const current = activeLogins.get(accountId);
|
|
146
|
+
if (current?.id === login.id) current.connected = true;
|
|
147
|
+
}).catch((err) => {
|
|
148
|
+
const current = activeLogins.get(accountId);
|
|
149
|
+
if (current?.id !== login.id) return;
|
|
150
|
+
current.error = formatError(err);
|
|
151
|
+
current.errorStatus = getStatusCode(err);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
async function restartLoginSocket(login, runtime) {
|
|
155
|
+
if (login.restartAttempted) return false;
|
|
156
|
+
login.restartAttempted = true;
|
|
157
|
+
runtime.log(info("WhatsApp asked for a restart after pairing (code 515); retrying connection once…"));
|
|
158
|
+
closeSocket(login.sock);
|
|
159
|
+
try {
|
|
160
|
+
login.sock = await createWaSocket(false, login.verbose, { authDir: login.authDir });
|
|
161
|
+
login.connected = false;
|
|
162
|
+
login.error = void 0;
|
|
163
|
+
login.errorStatus = void 0;
|
|
164
|
+
attachLoginWaiter(login.accountId, login);
|
|
165
|
+
return true;
|
|
166
|
+
} catch (err) {
|
|
167
|
+
login.error = formatError(err);
|
|
168
|
+
login.errorStatus = getStatusCode(err);
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async function startWebLoginWithQr(opts = {}) {
|
|
173
|
+
const runtime = opts.runtime ?? defaultRuntime;
|
|
174
|
+
const account = resolveWhatsAppAccount({
|
|
175
|
+
cfg: loadConfig(),
|
|
176
|
+
accountId: opts.accountId
|
|
177
|
+
});
|
|
178
|
+
const hasWeb = await webAuthExists(account.authDir);
|
|
179
|
+
const selfId = readWebSelfId(account.authDir);
|
|
180
|
+
if (hasWeb && !opts.force) return { message: `WhatsApp is already linked (${selfId.e164 ?? selfId.jid ?? "unknown"}). Say “relink” if you want a fresh QR.` };
|
|
181
|
+
const existing = activeLogins.get(account.accountId);
|
|
182
|
+
if (existing && isLoginFresh(existing) && existing.qrDataUrl) return {
|
|
183
|
+
qrDataUrl: existing.qrDataUrl,
|
|
184
|
+
message: "QR already active. Scan it in WhatsApp → Linked Devices."
|
|
185
|
+
};
|
|
186
|
+
await resetActiveLogin(account.accountId);
|
|
187
|
+
let resolveQr = null;
|
|
188
|
+
let rejectQr = null;
|
|
189
|
+
const qrPromise = new Promise((resolve, reject) => {
|
|
190
|
+
resolveQr = resolve;
|
|
191
|
+
rejectQr = reject;
|
|
192
|
+
});
|
|
193
|
+
const qrTimer = setTimeout(() => {
|
|
194
|
+
rejectQr?.(/* @__PURE__ */ new Error("Timed out waiting for WhatsApp QR"));
|
|
195
|
+
}, Math.max(opts.timeoutMs ?? 3e4, 5e3));
|
|
196
|
+
let sock;
|
|
197
|
+
let pendingQr = null;
|
|
198
|
+
try {
|
|
199
|
+
sock = await createWaSocket(false, Boolean(opts.verbose), {
|
|
200
|
+
authDir: account.authDir,
|
|
201
|
+
onQr: (qr) => {
|
|
202
|
+
if (pendingQr) return;
|
|
203
|
+
pendingQr = qr;
|
|
204
|
+
const current = activeLogins.get(account.accountId);
|
|
205
|
+
if (current && !current.qr) current.qr = qr;
|
|
206
|
+
clearTimeout(qrTimer);
|
|
207
|
+
runtime.log(info("WhatsApp QR received."));
|
|
208
|
+
resolveQr?.(qr);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
} catch (err) {
|
|
212
|
+
clearTimeout(qrTimer);
|
|
213
|
+
await resetActiveLogin(account.accountId);
|
|
214
|
+
return { message: `Failed to start WhatsApp login: ${String(err)}` };
|
|
215
|
+
}
|
|
216
|
+
const login = {
|
|
217
|
+
accountId: account.accountId,
|
|
218
|
+
authDir: account.authDir,
|
|
219
|
+
isLegacyAuthDir: account.isLegacyAuthDir,
|
|
220
|
+
id: randomUUID(),
|
|
221
|
+
sock,
|
|
222
|
+
startedAt: Date.now(),
|
|
223
|
+
connected: false,
|
|
224
|
+
waitPromise: Promise.resolve(),
|
|
225
|
+
restartAttempted: false,
|
|
226
|
+
verbose: Boolean(opts.verbose)
|
|
227
|
+
};
|
|
228
|
+
activeLogins.set(account.accountId, login);
|
|
229
|
+
if (pendingQr && !login.qr) login.qr = pendingQr;
|
|
230
|
+
attachLoginWaiter(account.accountId, login);
|
|
231
|
+
let qr;
|
|
232
|
+
try {
|
|
233
|
+
qr = await qrPromise;
|
|
234
|
+
} catch (err) {
|
|
235
|
+
clearTimeout(qrTimer);
|
|
236
|
+
await resetActiveLogin(account.accountId);
|
|
237
|
+
return { message: `Failed to get QR: ${String(err)}` };
|
|
238
|
+
}
|
|
239
|
+
login.qrDataUrl = `data:image/png;base64,${await renderQrPngBase64(qr)}`;
|
|
240
|
+
return {
|
|
241
|
+
qrDataUrl: login.qrDataUrl,
|
|
242
|
+
message: "Scan this QR in WhatsApp → Linked Devices."
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
async function waitForWebLogin(opts = {}) {
|
|
246
|
+
const runtime = opts.runtime ?? defaultRuntime;
|
|
247
|
+
const account = resolveWhatsAppAccount({
|
|
248
|
+
cfg: loadConfig(),
|
|
249
|
+
accountId: opts.accountId
|
|
250
|
+
});
|
|
251
|
+
const activeLogin = activeLogins.get(account.accountId);
|
|
252
|
+
if (!activeLogin) return {
|
|
253
|
+
connected: false,
|
|
254
|
+
message: "No active WhatsApp login in progress."
|
|
255
|
+
};
|
|
256
|
+
const login = activeLogin;
|
|
257
|
+
if (!isLoginFresh(login)) {
|
|
258
|
+
await resetActiveLogin(account.accountId);
|
|
259
|
+
return {
|
|
260
|
+
connected: false,
|
|
261
|
+
message: "The login QR expired. Ask me to generate a new one."
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
const timeoutMs = Math.max(opts.timeoutMs ?? 12e4, 1e3);
|
|
265
|
+
const deadline = Date.now() + timeoutMs;
|
|
266
|
+
while (true) {
|
|
267
|
+
const remaining = deadline - Date.now();
|
|
268
|
+
if (remaining <= 0) return {
|
|
269
|
+
connected: false,
|
|
270
|
+
message: "Still waiting for the QR scan. Let me know when you’ve scanned it."
|
|
271
|
+
};
|
|
272
|
+
const timeout = new Promise((resolve) => setTimeout(() => resolve("timeout"), remaining));
|
|
273
|
+
if (await Promise.race([login.waitPromise.then(() => "done"), timeout]) === "timeout") return {
|
|
274
|
+
connected: false,
|
|
275
|
+
message: "Still waiting for the QR scan. Let me know when you’ve scanned it."
|
|
276
|
+
};
|
|
277
|
+
if (login.error) {
|
|
278
|
+
if (login.errorStatus === DisconnectReason.loggedOut) {
|
|
279
|
+
await logoutWeb({
|
|
280
|
+
authDir: login.authDir,
|
|
281
|
+
isLegacyAuthDir: login.isLegacyAuthDir,
|
|
282
|
+
runtime
|
|
283
|
+
});
|
|
284
|
+
const message = "WhatsApp reported the session is logged out. Cleared cached web session; please scan a new QR.";
|
|
285
|
+
await resetActiveLogin(account.accountId, message);
|
|
286
|
+
runtime.log(danger(message));
|
|
287
|
+
return {
|
|
288
|
+
connected: false,
|
|
289
|
+
message
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
if (login.errorStatus === 515) {
|
|
293
|
+
if (await restartLoginSocket(login, runtime) && isLoginFresh(login)) continue;
|
|
294
|
+
}
|
|
295
|
+
const message = `WhatsApp login failed: ${login.error}`;
|
|
296
|
+
await resetActiveLogin(account.accountId, message);
|
|
297
|
+
runtime.log(danger(message));
|
|
298
|
+
return {
|
|
299
|
+
connected: false,
|
|
300
|
+
message
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
if (login.connected) {
|
|
304
|
+
const message = "✅ Linked! WhatsApp is ready.";
|
|
305
|
+
runtime.log(success(message));
|
|
306
|
+
await resetActiveLogin(account.accountId);
|
|
307
|
+
return {
|
|
308
|
+
connected: true,
|
|
309
|
+
message
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
return {
|
|
313
|
+
connected: false,
|
|
314
|
+
message: "Login ended without a connection."
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
//#endregion
|
|
320
|
+
export { startWebLoginWithQr, waitForWebLogin };
|