@diegoaltoworks/chatter 0.36.0 → 0.38.0
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/bin/wa-pair.js +225 -94
- package/dist/channels/whatsapp/pairing.d.ts +106 -0
- package/dist/channels/whatsapp/pairing.d.ts.map +1 -0
- package/dist/channels/whatsapp/pairing.test.d.ts +2 -0
- package/dist/channels/whatsapp/pairing.test.d.ts.map +1 -0
- package/dist/channels/whatsapp/qr.d.ts +25 -0
- package/dist/channels/whatsapp/qr.d.ts.map +1 -0
- package/dist/channels/whatsapp/qr.test.d.ts +2 -0
- package/dist/channels/whatsapp/qr.test.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/bin/wa-pair.js
CHANGED
|
@@ -150,6 +150,144 @@ function loadBaileys() {
|
|
|
150
150
|
return cached;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
// src/channels/whatsapp/pairing.ts
|
|
154
|
+
var RESTART_REQUIRED_STATUS = 515;
|
|
155
|
+
var MAX_PAIRING_RECONNECTS = 12;
|
|
156
|
+
var PAIRING_RECONNECT_DELAY_MS = 2e3;
|
|
157
|
+
var PAIRING_RECONNECT_MAX_DELAY_MS = 8e3;
|
|
158
|
+
var RESTART_REQUIRED_DELAY_MS = 500;
|
|
159
|
+
function pairingReconnectDelayMs(statusCode, attempt) {
|
|
160
|
+
if (statusCode === RESTART_REQUIRED_STATUS) return RESTART_REQUIRED_DELAY_MS;
|
|
161
|
+
return Math.min(
|
|
162
|
+
PAIRING_RECONNECT_DELAY_MS * 2 ** Math.max(0, attempt - 1),
|
|
163
|
+
PAIRING_RECONNECT_MAX_DELAY_MS
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
function decidePairingClose(input) {
|
|
167
|
+
if (input.statusCode === input.loggedOutCode) return { kind: "fatal", reason: "loggedOut" };
|
|
168
|
+
if (input.attempts >= input.maxAttempts) return { kind: "fatal", reason: "exhausted" };
|
|
169
|
+
const attempt = input.attempts + 1;
|
|
170
|
+
return {
|
|
171
|
+
kind: "reconnect",
|
|
172
|
+
attempt,
|
|
173
|
+
delayMs: pairingReconnectDelayMs(input.statusCode, attempt)
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function describeError(error) {
|
|
177
|
+
return error instanceof Error ? error.message : String(error);
|
|
178
|
+
}
|
|
179
|
+
function runPairing(deps) {
|
|
180
|
+
const maxAttempts = deps.maxAttempts ?? MAX_PAIRING_RECONNECTS;
|
|
181
|
+
const schedule = deps.schedule ?? ((fn, ms) => {
|
|
182
|
+
setTimeout(fn, ms);
|
|
183
|
+
});
|
|
184
|
+
return new Promise((resolve) => {
|
|
185
|
+
let attempts = 0;
|
|
186
|
+
let generation = 0;
|
|
187
|
+
let codeRequested = false;
|
|
188
|
+
let settled = false;
|
|
189
|
+
const settle = (result) => {
|
|
190
|
+
if (settled) return;
|
|
191
|
+
settled = true;
|
|
192
|
+
resolve(result);
|
|
193
|
+
};
|
|
194
|
+
const status = (message) => deps.onStatus?.(message);
|
|
195
|
+
const requestCode = async (sock) => {
|
|
196
|
+
if (settled || codeRequested || !deps.phoneNumber) return;
|
|
197
|
+
try {
|
|
198
|
+
const code = await sock.requestPairingCode(deps.phoneNumber);
|
|
199
|
+
codeRequested = true;
|
|
200
|
+
deps.onPairingCode?.(code);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
settle({
|
|
203
|
+
ok: false,
|
|
204
|
+
reason: "error",
|
|
205
|
+
message: `Failed to request pairing code: ${describeError(error)}`
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
const handleUpdate = async (update, sock) => {
|
|
210
|
+
const { connection, lastDisconnect, qr } = update;
|
|
211
|
+
if (qr && !deps.phoneNumber && deps.onQr) {
|
|
212
|
+
try {
|
|
213
|
+
await deps.onQr(qr);
|
|
214
|
+
} catch (error) {
|
|
215
|
+
status(`QR render failed: ${describeError(error)}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (connection === "open") {
|
|
219
|
+
settle({ ok: true, userId: sock.user?.id });
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (connection === "close") {
|
|
223
|
+
const statusCode = lastDisconnect?.error?.output?.statusCode;
|
|
224
|
+
const action = decidePairingClose({
|
|
225
|
+
statusCode,
|
|
226
|
+
loggedOutCode: deps.loggedOutCode,
|
|
227
|
+
attempts,
|
|
228
|
+
maxAttempts
|
|
229
|
+
});
|
|
230
|
+
if (action.kind === "fatal") {
|
|
231
|
+
settle({
|
|
232
|
+
ok: false,
|
|
233
|
+
reason: action.reason,
|
|
234
|
+
message: action.reason === "loggedOut" ? "Pairing rejected (logged out). Run wa-pair again for a fresh code." : `Gave up after ${maxAttempts} reconnect attempts (last close: ${statusCode ?? "?"}). Run wa-pair again.`
|
|
235
|
+
});
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
attempts = action.attempt;
|
|
239
|
+
generation += 1;
|
|
240
|
+
try {
|
|
241
|
+
sock.end?.();
|
|
242
|
+
} catch (error) {
|
|
243
|
+
status(`Failed to close the previous socket: ${describeError(error)}`);
|
|
244
|
+
}
|
|
245
|
+
status(
|
|
246
|
+
statusCode === RESTART_REQUIRED_STATUS ? `Registered \u2014 WhatsApp asked for a restart (515). Reconnecting to finish the link (${action.attempt}/${maxAttempts})...` : `Connection closed (${statusCode ?? "?"}) \u2014 reconnecting with the stored session (${action.attempt}/${maxAttempts})...`
|
|
247
|
+
);
|
|
248
|
+
schedule(() => void attach(), action.delayMs);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
const attach = async () => {
|
|
252
|
+
if (settled) return;
|
|
253
|
+
const mine = generation;
|
|
254
|
+
const attempt = attempts;
|
|
255
|
+
let sock;
|
|
256
|
+
try {
|
|
257
|
+
sock = await deps.connect(attempt);
|
|
258
|
+
} catch (error) {
|
|
259
|
+
settle({ ok: false, reason: "error", message: describeError(error) });
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
sock.ev.on("connection.update", (update) => {
|
|
263
|
+
if (mine !== generation || settled) return;
|
|
264
|
+
handleUpdate(update, sock).catch((error) => {
|
|
265
|
+
const message = `connection.update handler error: ${describeError(error)}`;
|
|
266
|
+
status(message);
|
|
267
|
+
settle({ ok: false, reason: "error", message });
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
if (deps.phoneNumber && !codeRequested) {
|
|
271
|
+
schedule(() => {
|
|
272
|
+
if (mine !== generation) return;
|
|
273
|
+
void requestCode(sock);
|
|
274
|
+
}, deps.requestCodeDelayMs ?? 3e3);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
void attach();
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// src/channels/whatsapp/qr.ts
|
|
282
|
+
function resolveQrGenerate(mod) {
|
|
283
|
+
if (!mod) return void 0;
|
|
284
|
+
if (mod.default && typeof mod.default.generate === "function") {
|
|
285
|
+
return mod.default.generate.bind(mod.default);
|
|
286
|
+
}
|
|
287
|
+
if (typeof mod.generate === "function") return mod.generate.bind(mod);
|
|
288
|
+
return void 0;
|
|
289
|
+
}
|
|
290
|
+
|
|
153
291
|
// bin/wa-pair.ts
|
|
154
292
|
var args = process.argv.slice(2);
|
|
155
293
|
function flagValue(name) {
|
|
@@ -199,10 +337,36 @@ var db = (0, import_client.createClient)({
|
|
|
199
337
|
url: process.env.TURSO_URL,
|
|
200
338
|
authToken: process.env.TURSO_AUTH_TOKEN || ""
|
|
201
339
|
});
|
|
202
|
-
var
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
340
|
+
var printedQrFallbackHelp = false;
|
|
341
|
+
function printQrFallback(qr) {
|
|
342
|
+
if (!printedQrFallbackHelp) {
|
|
343
|
+
printedQrFallbackHelp = true;
|
|
344
|
+
console.log(
|
|
345
|
+
"\nCouldn't render a QR image here. Raw code below (rarely scannable as text\ndirectly, but confirms pairing is alive) \u2014 re-run with --code <phoneNumber>\nfor pairing-code mode instead:\n"
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
console.log(qr);
|
|
349
|
+
}
|
|
350
|
+
async function renderQr(qr) {
|
|
351
|
+
const qrcodeTerminal = await import("qrcode-terminal").catch(() => void 0);
|
|
352
|
+
const generate = resolveQrGenerate(qrcodeTerminal);
|
|
353
|
+
if (!generate) {
|
|
354
|
+
if (!printedQrFallbackHelp) {
|
|
355
|
+
console.error(
|
|
356
|
+
"\u274C QR mode requires the optional peer dependency 'qrcode-terminal' (not installed, or its exports weren't recognized). Install it with `bun add qrcode-terminal`, or re-run with --code <phoneNumber> for pairing-code mode instead."
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
printQrFallback(qr);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
console.log("\nScan this QR code: WhatsApp -> Settings -> Linked Devices -> Link a Device.\n");
|
|
363
|
+
try {
|
|
364
|
+
generate(qr, { small: true });
|
|
365
|
+
} catch (error) {
|
|
366
|
+
console.error(`\u274C QR render failed: ${error.message}`);
|
|
367
|
+
printQrFallback(qr);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
206
370
|
async function start() {
|
|
207
371
|
const baileys = await loadBaileys().catch((error) => {
|
|
208
372
|
console.error(`\u274C ${error.message}`);
|
|
@@ -213,106 +377,73 @@ async function start() {
|
|
|
213
377
|
initAuthCreds: baileys.initAuthCreds,
|
|
214
378
|
appStateSyncKeyFromObject: (value) => baileys.proto.Message.AppStateSyncKeyData.fromObject(value)
|
|
215
379
|
};
|
|
216
|
-
|
|
217
|
-
db,
|
|
218
|
-
sessionSecret,
|
|
219
|
-
sessionId,
|
|
220
|
-
runtime
|
|
221
|
-
);
|
|
222
|
-
if (reset && !didReset) {
|
|
223
|
-
didReset = true;
|
|
380
|
+
if (reset) {
|
|
381
|
+
const { clear } = await useTursoAuthState(db, sessionSecret, sessionId, runtime);
|
|
224
382
|
await clear();
|
|
225
383
|
console.log(`Session "${sessionId}" wiped. Pairing fresh...`);
|
|
226
|
-
return start();
|
|
227
|
-
}
|
|
228
|
-
if (state.creds.registered && !codeRequested) {
|
|
229
|
-
console.log(
|
|
230
|
-
`Already paired. Session "${sessionId}" is connected-ready. Run with --reset to re-pair.`
|
|
231
|
-
);
|
|
232
|
-
process.exit(0);
|
|
233
384
|
}
|
|
234
385
|
const { version } = await baileys.fetchLatestBaileysVersion();
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
fatal: noop
|
|
244
|
-
};
|
|
245
|
-
logger.child = () => logger;
|
|
246
|
-
const sock = baileys.makeWASocket({
|
|
247
|
-
version,
|
|
248
|
-
auth: {
|
|
249
|
-
creds: state.creds,
|
|
250
|
-
// biome-ignore lint/suspicious/noExplicitAny: structural pino-compatible logger
|
|
251
|
-
keys: baileys.makeCacheableSignalKeyStore(state.keys, logger)
|
|
252
|
-
},
|
|
253
|
-
// biome-ignore lint/suspicious/noExplicitAny: structural pino-compatible logger
|
|
254
|
-
logger,
|
|
255
|
-
markOnlineOnConnect: false
|
|
256
|
-
});
|
|
257
|
-
sock.ev.on("creds.update", saveCreds);
|
|
258
|
-
sock.ev.on("connection.update", async (update) => {
|
|
259
|
-
const { connection, lastDisconnect, qr } = update;
|
|
260
|
-
if (qr && !phoneNumber) {
|
|
261
|
-
const qrcodeTerminal = await import("qrcode-terminal").catch(() => void 0);
|
|
262
|
-
if (!qrcodeTerminal) {
|
|
263
|
-
console.error(
|
|
264
|
-
"\u274C QR mode requires the optional peer dependency 'qrcode-terminal'. Install it with `bun add qrcode-terminal`, or re-run with --code <phoneNumber> for pairing-code mode instead."
|
|
265
|
-
);
|
|
266
|
-
process.exit(1);
|
|
267
|
-
}
|
|
268
|
-
console.log(
|
|
269
|
-
"\nScan this QR code: WhatsApp -> Settings -> Linked Devices -> Link a Device.\n"
|
|
270
|
-
);
|
|
271
|
-
qrcodeTerminal.default.generate(qr, { small: true });
|
|
272
|
-
}
|
|
273
|
-
if (connection === "open") {
|
|
386
|
+
const connect = async (attempt) => {
|
|
387
|
+
const { state, saveCreds } = await useTursoAuthState(
|
|
388
|
+
db,
|
|
389
|
+
sessionSecret,
|
|
390
|
+
sessionId,
|
|
391
|
+
runtime
|
|
392
|
+
);
|
|
393
|
+
if (attempt === 0 && state.creds.registered) {
|
|
274
394
|
console.log(
|
|
275
|
-
`
|
|
276
|
-
\u2705 Paired session "${sessionId}" as ${sock.user?.id}. Session saved (encrypted).`
|
|
395
|
+
`Already paired. Session "${sessionId}" is connected-ready. Run with --reset to re-pair.`
|
|
277
396
|
);
|
|
278
|
-
console.log("The running server will pick this session up on its next connect.");
|
|
279
397
|
process.exit(0);
|
|
280
398
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
399
|
+
const noop = () => void 0;
|
|
400
|
+
const logger = {
|
|
401
|
+
level: "silent",
|
|
402
|
+
trace: noop,
|
|
403
|
+
debug: noop,
|
|
404
|
+
info: noop,
|
|
405
|
+
warn: noop,
|
|
406
|
+
error: noop,
|
|
407
|
+
fatal: noop
|
|
408
|
+
};
|
|
409
|
+
logger.child = () => logger;
|
|
410
|
+
const sock = baileys.makeWASocket({
|
|
411
|
+
version,
|
|
412
|
+
auth: {
|
|
413
|
+
creds: state.creds,
|
|
414
|
+
// biome-ignore lint/suspicious/noExplicitAny: structural pino-compatible logger
|
|
415
|
+
keys: baileys.makeCacheableSignalKeyStore(state.keys, logger)
|
|
416
|
+
},
|
|
417
|
+
// biome-ignore lint/suspicious/noExplicitAny: structural pino-compatible logger
|
|
418
|
+
logger,
|
|
419
|
+
markOnlineOnConnect: false
|
|
420
|
+
});
|
|
421
|
+
sock.ev.on("creds.update", saveCreds);
|
|
422
|
+
return sock;
|
|
423
|
+
};
|
|
424
|
+
const result = await runPairing({
|
|
425
|
+
connect,
|
|
426
|
+
loggedOutCode: baileys.DisconnectReason.loggedOut,
|
|
427
|
+
phoneNumber,
|
|
428
|
+
onQr: renderQr,
|
|
429
|
+
onPairingCode: (code) => {
|
|
430
|
+
console.log("\n==============================================");
|
|
431
|
+
console.log(` Pairing code for +${phoneNumber}: ${code}`);
|
|
432
|
+
console.log("==============================================");
|
|
433
|
+
console.log("On the phone: WhatsApp -> Settings -> Linked Devices ->");
|
|
434
|
+
console.log("Link a Device -> 'Link with phone number instead' -> enter the code.");
|
|
435
|
+
console.log("Waiting for confirmation (leave this running)...");
|
|
436
|
+
},
|
|
437
|
+
onStatus: (message) => console.log(message)
|
|
298
438
|
});
|
|
299
|
-
if (
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
const code = await sock.requestPairingCode(phoneNumber);
|
|
303
|
-
codeRequested = true;
|
|
304
|
-
console.log("\n==============================================");
|
|
305
|
-
console.log(` Pairing code for +${phoneNumber}: ${code}`);
|
|
306
|
-
console.log("==============================================");
|
|
307
|
-
console.log("On the phone: WhatsApp -> Settings -> Linked Devices ->");
|
|
308
|
-
console.log("Link a Device -> 'Link with phone number instead' -> enter the code.");
|
|
309
|
-
console.log("Waiting for confirmation (leave this running)...");
|
|
310
|
-
} catch (error) {
|
|
311
|
-
console.error("\u274C Failed to request pairing code:", error);
|
|
312
|
-
process.exit(1);
|
|
313
|
-
}
|
|
314
|
-
}, 3e3);
|
|
439
|
+
if (!result.ok) {
|
|
440
|
+
console.error(`\u274C ${result.message}`);
|
|
441
|
+
process.exit(1);
|
|
315
442
|
}
|
|
443
|
+
console.log(`
|
|
444
|
+
\u2705 Paired session "${sessionId}" as ${result.userId}. Session saved (encrypted).`);
|
|
445
|
+
console.log("The running server will pick this session up on its next connect.");
|
|
446
|
+
process.exit(0);
|
|
316
447
|
}
|
|
317
448
|
start().catch((error) => {
|
|
318
449
|
console.error("\u274C Unexpected error:", error);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pairing loop for the `wa-pair` CLI — the transport-independent half, kept
|
|
3
|
+
* out of the bin so it can be unit-tested against a faked socket.
|
|
4
|
+
*
|
|
5
|
+
* Both pairing modes close the socket mid-flow as a matter of course:
|
|
6
|
+
*
|
|
7
|
+
* - QR mode: the moment a scan registers the device, WhatsApp ALWAYS closes
|
|
8
|
+
* with 515 ("restart required"). The link only completes if the client comes
|
|
9
|
+
* straight back with the SAME credentials it just registered — the phone is
|
|
10
|
+
* sitting on "linking" waiting for exactly that. Exiting there (or wiping
|
|
11
|
+
* creds and starting over) fails the pairing every time.
|
|
12
|
+
* - Pairing-code mode: the socket bounces while the code is being typed.
|
|
13
|
+
*
|
|
14
|
+
* So a close during pairing is normal, not fatal: reconnect with stored creds,
|
|
15
|
+
* bounded, until `open` confirms the link. Only an explicit logout or running
|
|
16
|
+
* out of attempts ends the run.
|
|
17
|
+
*/
|
|
18
|
+
/** Baileys' "restart required" — emitted immediately after a QR scan registers the device. */
|
|
19
|
+
export declare const RESTART_REQUIRED_STATUS = 515;
|
|
20
|
+
/** Bounded so a genuinely broken pairing terminates instead of looping forever. */
|
|
21
|
+
export declare const MAX_PAIRING_RECONNECTS = 12;
|
|
22
|
+
/**
|
|
23
|
+
* Backoff between pairing attempts. Deliberately tighter than the transport's
|
|
24
|
+
* 5s→10min ladder (`reconnectDelayMs`): that one protects a long-lived
|
|
25
|
+
* connection from hammering WhatsApp during an outage, whereas here a human is
|
|
26
|
+
* holding a phone that gives the link a limited window — a 515 restart has to
|
|
27
|
+
* be answered at once, and other bounces within seconds.
|
|
28
|
+
*/
|
|
29
|
+
export declare function pairingReconnectDelayMs(statusCode: number | undefined, attempt: number): number;
|
|
30
|
+
export type PairingCloseAction = {
|
|
31
|
+
kind: "reconnect";
|
|
32
|
+
attempt: number;
|
|
33
|
+
delayMs: number;
|
|
34
|
+
} | {
|
|
35
|
+
kind: "fatal";
|
|
36
|
+
reason: "loggedOut" | "exhausted";
|
|
37
|
+
};
|
|
38
|
+
export interface PairingCloseInput {
|
|
39
|
+
statusCode?: number;
|
|
40
|
+
/** `DisconnectReason.loggedOut` from the loaded Baileys build. */
|
|
41
|
+
loggedOutCode: number;
|
|
42
|
+
/** Reconnects already spent. */
|
|
43
|
+
attempts: number;
|
|
44
|
+
maxAttempts: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Pure: what to do about a `connection: "close"` during pairing. A logout is
|
|
48
|
+
* final (the credentials just got revoked — retrying re-revokes them); every
|
|
49
|
+
* other close is transient until the attempt budget runs out.
|
|
50
|
+
*/
|
|
51
|
+
export declare function decidePairingClose(input: PairingCloseInput): PairingCloseAction;
|
|
52
|
+
/** The slice of a Baileys socket the pairing loop uses. */
|
|
53
|
+
export interface PairingSocket {
|
|
54
|
+
ev: {
|
|
55
|
+
on: (event: "connection.update", listener: (update: PairingConnectionUpdate) => void) => void;
|
|
56
|
+
};
|
|
57
|
+
user?: {
|
|
58
|
+
id?: string;
|
|
59
|
+
} | null;
|
|
60
|
+
requestPairingCode: (phoneNumber: string) => Promise<string>;
|
|
61
|
+
/** Closes a superseded socket so it stops writing to the session. */
|
|
62
|
+
end?: (error?: Error) => void;
|
|
63
|
+
}
|
|
64
|
+
export interface PairingConnectionUpdate {
|
|
65
|
+
connection?: string;
|
|
66
|
+
qr?: string;
|
|
67
|
+
lastDisconnect?: {
|
|
68
|
+
error?: unknown;
|
|
69
|
+
} | null;
|
|
70
|
+
}
|
|
71
|
+
export type PairingResult = {
|
|
72
|
+
ok: true;
|
|
73
|
+
userId?: string;
|
|
74
|
+
} | {
|
|
75
|
+
ok: false;
|
|
76
|
+
reason: "loggedOut" | "exhausted" | "error";
|
|
77
|
+
message: string;
|
|
78
|
+
};
|
|
79
|
+
export interface PairingRunDeps {
|
|
80
|
+
/**
|
|
81
|
+
* Opens a socket for `attempt` (0 = first). MUST reuse the stored
|
|
82
|
+
* credentials — a reconnect that starts from blank creds shows a fresh QR
|
|
83
|
+
* instead of finishing the link the phone is waiting on.
|
|
84
|
+
*/
|
|
85
|
+
connect: (attempt: number) => PairingSocket | Promise<PairingSocket>;
|
|
86
|
+
loggedOutCode: number;
|
|
87
|
+
/** Digits-only number for pairing-code mode; omit for QR mode. */
|
|
88
|
+
phoneNumber?: string;
|
|
89
|
+
maxAttempts?: number;
|
|
90
|
+
/** Delay before asking for a pairing code, giving the socket time to handshake. */
|
|
91
|
+
requestCodeDelayMs?: number;
|
|
92
|
+
/** Overridable for tests; defaults to `setTimeout`. */
|
|
93
|
+
schedule?: (fn: () => void, ms: number) => void;
|
|
94
|
+
/** Renders the QR (QR mode only). A throw is reported, never swallowed. */
|
|
95
|
+
onQr?: (qr: string) => void | Promise<void>;
|
|
96
|
+
onPairingCode?: (code: string) => void;
|
|
97
|
+
/** Progress lines for the operator (reconnect notices, QR render failures). */
|
|
98
|
+
onStatus?: (message: string) => void;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Runs one pairing to a verdict: resolves `{ ok: true }` when the connection
|
|
102
|
+
* reaches `open` (the link is live), or `{ ok: false }` on logout, attempt
|
|
103
|
+
* exhaustion, or a connect/pairing-code failure. Never rejects.
|
|
104
|
+
*/
|
|
105
|
+
export declare function runPairing(deps: PairingRunDeps): Promise<PairingResult>;
|
|
106
|
+
//# sourceMappingURL=pairing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairing.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/pairing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairing.test.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/pairing.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `qrcode-terminal` is a plain CJS module (`module.exports = { generate, ... }`).
|
|
3
|
+
* Loading it via dynamic `import()` gets interop-wrapped differently depending
|
|
4
|
+
* on the runtime and how the caller itself is bundled: some expose the
|
|
5
|
+
* function only under `.default`, others expose it as a named export too (or
|
|
6
|
+
* only). Resolve every shape here so `wa-pair` never depends on one bundler's
|
|
7
|
+
* interop guess.
|
|
8
|
+
*/
|
|
9
|
+
export type QrGenerateFn = (qr: string, options?: {
|
|
10
|
+
small?: boolean;
|
|
11
|
+
}, callback?: (output: string) => void) => void;
|
|
12
|
+
export interface QrTerminalModule {
|
|
13
|
+
default?: {
|
|
14
|
+
generate?: QrGenerateFn;
|
|
15
|
+
};
|
|
16
|
+
generate?: QrGenerateFn;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* `generate` reads `this.error` internally (the module's configured error
|
|
20
|
+
* correction level), so it must stay bound to the object it came from —
|
|
21
|
+
* returning it detached, as a bare function reference, throws the moment it
|
|
22
|
+
* runs (`this.error` is `undefined` instead of the module's setting).
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveQrGenerate(mod: QrTerminalModule | undefined): QrGenerateFn | undefined;
|
|
25
|
+
//# sourceMappingURL=qr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/qr.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,YAAY,GAAG,CACzB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EAC7B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,KAChC,IAAI,CAAC;AAEV,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,YAAY,CAAA;KAAE,CAAC;IACtC,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,gBAAgB,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAO7F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr.test.d.ts","sourceRoot":"","sources":["../../../src/channels/whatsapp/qr.test.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED