aunubaileys 1.0.11 → 1.0.12

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/README.md CHANGED
@@ -64,6 +64,10 @@ Everything else is pure upstream. When upstream moves, we rebase the patch layer
64
64
 
65
65
 
66
66
 
67
+ ### 🆕 What's new in 1.0.12 / Baru di 1.0.12
68
+
69
+ - 🔑 **Pairing waits for the socket — and explains itself when it can't.** Field report from a real VPS deploy: `requestPairingCode` threw a bare Boom 428 "Connection Closed" every time, leaving consumers unable to tell an unready socket from a server rejection. Now `requestPairingCode` **waits internally (up to 30s) for the transport to open** before sending the pairing IQ, fails fast if the connection dies while waiting, and **every pairing failure carries the last disconnect reason** (status code + message) instead of the generic text. The 1.0.10 single-flight guard is kept and covers the wait.
70
+
67
71
  ### 🆕 What's new in 1.0.11 / Baru di 1.0.11
68
72
 
69
73
  - 🚑 **Hotfix for broken 1.0.9 / 1.0.10 tarballs** — the published packages exported `./Utils/antiban.js` from `lib/index.js` but the file itself was never committed to the repository, so every install crashed on import with `ERR_MODULE_NOT_FOUND`. The AntiBan module (and its types) is now in the repo, and this release's tarball was verified with a clean install + import test. Also in: RafaelPivots' `INITIAL_PREKEY_COUNT` type correction (30 → 812, matching the runtime) and repository URLs updated to the repo's new home, **AunuCore/AunuBaileys-lib**. If you are on 1.0.9 or 1.0.10, upgrade to 1.0.11.
@@ -49,6 +49,7 @@ export const makeSocket = (config) => {
49
49
  let keepAliveReq;
50
50
  let qrTimer;
51
51
  let closed = false;
52
+ let lastDisconnectError;
52
53
  const uqTagId = generateMdTagPrefix();
53
54
  const generateMessageTag = () => `${uqTagId}${epoch++}`;
54
55
  const sendPromise = promisify(ws.send);
@@ -255,6 +256,7 @@ export const makeSocket = (config) => {
255
256
  return;
256
257
  }
257
258
  closed = true;
259
+ lastDisconnectError = error;
258
260
  logger.info({ trace: error?.stack }, error ? 'connection errored' : 'connection closed');
259
261
  clearInterval(keepAliveReq);
260
262
  clearTimeout(qrTimer);
@@ -371,6 +373,59 @@ export const makeSocket = (config) => {
371
373
  end(new Boom(msg || 'Intentional Logout', { statusCode: DisconnectReason.loggedOut }));
372
374
  };
373
375
  let pairingCodeRequestInFlight = false;
376
+ const PAIRING_READY_TIMEOUT_MS = 30000;
377
+ const describeLastDisconnect = () => {
378
+ if (!lastDisconnectError) {
379
+ return 'no disconnect recorded yet';
380
+ }
381
+ const code = lastDisconnectError?.data?.statusCode ?? lastDisconnectError?.output?.statusCode;
382
+ return `${code ? `status ${code} — ` : ''}${lastDisconnectError?.message || String(lastDisconnectError)}`;
383
+ };
384
+ // AunuBaileys: pairing must not fire its IQ into a socket that is not
385
+ // open yet (upstream throws a bare 428 'Connection Closed'). Wait for
386
+ // the transport to open, fail fast when the connection dies meanwhile,
387
+ // and always surface WHY via the last disconnect reason.
388
+ const waitForPairingReady = async () => {
389
+ if (ws.isOpen) {
390
+ return;
391
+ }
392
+ if (closed || ws.isClosed || ws.isClosing) {
393
+ throw new Boom(`requestPairingCode: connection is already closed (last disconnect: ${describeLastDisconnect()})`, { statusCode: DisconnectReason.connectionClosed });
394
+ }
395
+ let onUpdate;
396
+ const closedWhileWaiting = new Promise((_, reject) => {
397
+ onUpdate = (update) => {
398
+ if (update.connection === 'close') {
399
+ reject(new Boom(`requestPairingCode: connection closed while waiting for the socket to open (last disconnect: ${describeLastDisconnect()})`, { statusCode: DisconnectReason.connectionClosed }));
400
+ }
401
+ };
402
+ ev.on('connection.update', onUpdate);
403
+ });
404
+ let timer;
405
+ const timedOut = new Promise((_, reject) => {
406
+ timer = setTimeout(() => {
407
+ reject(new Boom(`requestPairingCode: socket did not open within ${PAIRING_READY_TIMEOUT_MS / 1000}s (last disconnect: ${describeLastDisconnect()})`, { statusCode: DisconnectReason.timedOut }));
408
+ }, PAIRING_READY_TIMEOUT_MS);
409
+ });
410
+ try {
411
+ await Promise.race([
412
+ waitForSocketOpen().catch(() => {
413
+ throw new Boom(`requestPairingCode: connection closed while waiting for the socket to open (last disconnect: ${describeLastDisconnect()})`, { statusCode: DisconnectReason.connectionClosed });
414
+ }),
415
+ closedWhileWaiting,
416
+ timedOut
417
+ ]);
418
+ }
419
+ finally {
420
+ clearTimeout(timer);
421
+ if (onUpdate) {
422
+ try {
423
+ ev.off('connection.update', onUpdate);
424
+ }
425
+ catch { }
426
+ }
427
+ }
428
+ };
374
429
  const requestPairingCode = async (phoneNumber, customPairingCode) => {
375
430
  if (authState.creds.registered) {
376
431
  throw new Error('requestPairingCode: this session is already registered — pairing codes are only for new logins');
@@ -384,6 +439,7 @@ export const makeSocket = (config) => {
384
439
  }
385
440
  pairingCodeRequestInFlight = true;
386
441
  try {
442
+ await waitForPairingReady();
387
443
  authState.creds.pairingCode = pairingCode;
388
444
  authState.creds.me = {
389
445
  id: jidEncode(phoneNumber, 's.whatsapp.net'),
@@ -438,6 +494,14 @@ export const makeSocket = (config) => {
438
494
  });
439
495
  return authState.creds.pairingCode;
440
496
  }
497
+ catch (err) {
498
+ const msg = err?.message || '';
499
+ const isClosedErr = err?.output?.statusCode === DisconnectReason.connectionClosed || /connection closed/i.test(msg);
500
+ if (isClosedErr && !msg.startsWith('requestPairingCode')) {
501
+ throw new Boom(`requestPairingCode failed: connection closed before the pairing request could be delivered (last disconnect: ${describeLastDisconnect()}). Original error: ${msg}`, { statusCode: DisconnectReason.connectionClosed });
502
+ }
503
+ throw err;
504
+ }
441
505
  finally {
442
506
  pairingCodeRequestInFlight = false;
443
507
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aunubaileys",
3
3
  "type": "module",
4
- "version": "1.0.11",
4
+ "version": "1.0.12",
5
5
  "description": "AunuBaileys \u2014 a WhatsApp Web API for bots that never sleep. Full upstream power with the beloved in-memory store restored and pairing that just works. Forged by AunuCore.",
6
6
  "keywords": [
7
7
  "whatsapp",