whalibmob 5.16.0 → 5.17.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/README.md CHANGED
@@ -9,6 +9,8 @@
9
9
 
10
10
  CONTACT ME ON TELEGRAM IF YOU WANT TO WORK WITH ME AND IF YOU HAVE PROBLEM WITH WHALIBMOB : @brtyu545
11
11
 
12
+ **Need test numbers to try whalibmob with?** Message me on Telegram at **@brtyu545** — I can provide phone numbers for receiving SMS verification codes, so you can register and test whalibmob without using your own number.
13
+
12
14
  If you want News about whalibmob enter this whalibmob channel: https://t.me/+sHN4MDCyB7U5OWY0
13
15
 
14
16
 
@@ -2005,6 +2007,7 @@ Every option is optional; `sessionDir` is the only one most senders ever set.
2005
2007
  | `sessionDir` | `~/.waSession` | The authentication folder. Each number gets its own subfolder inside it — see [Saving & Restoring Sessions](#saving--restoring-sessions). |
2006
2008
  | `autoFixNumber` | `true` | Re-file the session automatically when the server reports the account under a different number. Set `false` to be told instead of fixed — see [The Number WhatsApp Files Your Account Under](#the-number-whatsapp-files-your-account-under). |
2007
2009
  | `autoRead` | `true` | Send read receipts for incoming messages. `false` leaves them unread. |
2010
+ | `refreshVersion` | `true` | **iOS sessions only.** Check the App Store for the current build on every `init()` and write it into the session file. Set `false` to keep announcing whatever the session registered with — see [Keeping the Announced Version Current](#keeping-the-announced-version-current). Android is unaffected either way. |
2008
2011
  | `pino` | off | Debug logging. `true` turns it on at `debug` level; an object is passed to `pino` as-is. |
2009
2012
  | `sentCacheSize` | `2000` | How many sent messages keep their plaintext so a retry receipt naming them can be answered. |
2010
2013
  | `maxRetryResends` | `5` | How many times one message may be re-sent in answer to retry receipts before the client gives up. |
@@ -2571,6 +2574,60 @@ of a pile by prefix.
2571
2574
  > is moved unless you ask — `wa migrate-sessions` does that, one number or all
2572
2575
  > of them, and re-running it is safe.
2573
2576
 
2577
+ ### Keeping the Announced Version Current
2578
+
2579
+ Every connection announces the WhatsApp build it claims to be. The server checks
2580
+ it, and when it stops recognising the number it refuses the handshake with
2581
+ `405` — a failure that says nothing about the version and has nothing to do with
2582
+ the account.
2583
+
2584
+ A session records the version it registered with. Left alone it announces that
2585
+ same number forever, so a number registered in spring is still claiming a spring
2586
+ build in autumn, and one day the connect simply stops working.
2587
+
2588
+ **iOS sessions now refresh themselves.** On every `init()` the client asks the
2589
+ App Store what the current build is and writes it into `<phone>.json` before the
2590
+ handshake. Nothing to run, nothing to remember:
2591
+
2592
+ ```js
2593
+ client.on('version_update', ({ from, to }) => {
2594
+ console.log('announcing', to, 'instead of', from)
2595
+ })
2596
+
2597
+ await client.init('40756469325')
2598
+ ```
2599
+
2600
+ Three rules keep this from being the thing that breaks a working session:
2601
+
2602
+ - **It never goes backwards.** The App Store lookup answers with a pinned
2603
+ fallback rather than failing when it cannot reach the network, and that
2604
+ fallback can easily be older than what the session holds. Moving a session to
2605
+ an older version is the one outcome that makes a `405` *more* likely.
2606
+ - **`WA_VERSION` still wins.** A version pinned on the way out of a `405` is a
2607
+ decision, and is never quietly replaced.
2608
+ - **A failed lookup changes nothing.** The session keeps the version it has and
2609
+ the connect carries on.
2610
+
2611
+ Set `{ refreshVersion: false }` on the client to turn it off.
2612
+
2613
+ > [!NOTE]
2614
+ > **Android is deliberately left alone.** Its version comes out of the APK the
2615
+ > token material was read from, and the two have to agree — the registration
2616
+ > token is computed from that build. Refreshing the announced version behind the
2617
+ > caller's back would put it out of step with the token. Android keeps the
2618
+ > explicit flow: `wa apk-material --download`, then `wa refresh-version`.
2619
+
2620
+ The manual tool still works on both platforms, and is the only way to move an
2621
+ Android session:
2622
+
2623
+ ```bash
2624
+ wa refresh-version 40756469325 # current build for the platform
2625
+ wa refresh-version 40756469325 --version 2.25.1.2 # or one you name
2626
+ ```
2627
+
2628
+ Companion sessions have never had this problem: `connectWeb()` reads the live
2629
+ web revision on every connect already.
2630
+
2574
2631
  ### One-time Pre-keys
2575
2632
 
2576
2633
  A pre-key is a one-shot Diffie-Hellman key the account leaves with the server so
package/lib/Client.js CHANGED
@@ -379,6 +379,13 @@ class WhalibmobClient extends EventEmitter {
379
379
  // automatically on the first refused login. Set { autoFixNumber: false } to
380
380
  // be told about it instead.
381
381
  this._autoFixNumber = opts.autoFixNumber !== false;
382
+ // An iOS session checks the App Store for the current build on every
383
+ // connect and writes it back — see _refreshIosVersion(). Set
384
+ // { refreshVersion: false } to keep announcing whatever the session
385
+ // registered with. Android is not affected either way: its version comes
386
+ // out of the APK the token material was read from, and that stays a
387
+ // deliberate step.
388
+ this._refreshVersion = opts.refreshVersion !== false;
382
389
  this._numberFixAttempted = false;
383
390
  this._pingTimer = null;
384
391
  this._keepTimer = null;
@@ -497,6 +504,67 @@ class WhalibmobClient extends EventEmitter {
497
504
  return this.init(phoneNumber);
498
505
  }
499
506
 
507
+ /**
508
+ * Bring an iOS session's announced version up to date, on every connect.
509
+ *
510
+ * A session records the version it registered with and announces that
511
+ * forever after. Months later the server stops accepting it and the connect
512
+ * is refused with a 405 that says nothing about why — and the only remaining
513
+ * move, before this, was to run `wa refresh-version` by hand or register the
514
+ * number again. The companion path never had that problem because
515
+ * connectWeb() reads the live revision every time; this is the same idea for
516
+ * the primary one.
517
+ *
518
+ * iOS only, and deliberately so. Android's version comes out of the APK the
519
+ * token material was read from — the two have to agree, because the token is
520
+ * computed from that build — so refreshing it behind the caller's back would
521
+ * put the announced version and the token out of step. Android keeps its
522
+ * Play Store flow exactly as it was.
523
+ *
524
+ * Three rules keep this from being the thing that breaks a working session:
525
+ *
526
+ * • It never goes backwards. fetchIosVersion() answers with the pinned
527
+ * fallback rather than failing when the lookup does not work, and that
528
+ * fallback can easily be older than what a session already holds. Moving
529
+ * a session to an older version is the one outcome that makes a 405 more
530
+ * likely rather than less.
531
+ * • WA_VERSION still wins. Someone who has pinned a version on the way out
532
+ * of a 405 must not have it quietly replaced.
533
+ * • It never throws, and it never blocks for long. A lookup that fails
534
+ * leaves the session exactly as it was and the connect carries on.
535
+ */
536
+ async _refreshIosVersion() {
537
+ if (!this._refreshVersion || this._mode === 'web' || !this._store) return;
538
+ if (process.env.WA_VERSION) {
539
+ _whaDbg('[DBG] VERSION refresh skipped — WA_VERSION is set');
540
+ return;
541
+ }
542
+
543
+ const device = this._store.device || getDeviceConfig();
544
+ if (device.os === 'android') return; // the APK flow owns this
545
+
546
+ try {
547
+ const { compareVersions } = require('./Registration');
548
+ const before = this._store.version;
549
+ const live = await fetchIosVersion(!!device.business);
550
+ if (!live) return;
551
+
552
+ if (before && compareVersions(live, before) <= 0) {
553
+ _whaDbg('[DBG] VERSION already current (' + before + ', App Store says ' + live + ')');
554
+ return;
555
+ }
556
+
557
+ this._store.version = live;
558
+ this._persistStore();
559
+ _whaDbg('[DBG] VERSION refreshed ' + (before || 'none') + ' → ' + live +
560
+ ' (App Store listing)');
561
+ this.emit('version_update', { from: before || null, to: live, source: 'App Store listing' });
562
+ } catch (err) {
563
+ // A session that cannot ask keeps the version it has.
564
+ _whaDbg('[DBG] VERSION refresh failed: ' + (err && err.message));
565
+ }
566
+ }
567
+
500
568
  async init(phoneNumber) {
501
569
  phoneNumber = String(phoneNumber).replace(/\D/g, '');
502
570
  this._phoneNumber = phoneNumber;
@@ -526,6 +594,10 @@ class WhalibmobClient extends EventEmitter {
526
594
  );
527
595
  }
528
596
 
597
+ // Before the handshake, which reads the version straight out of the store.
598
+ // iOS only; Android keeps its APK flow. See _refreshIosVersion().
599
+ await this._refreshIosVersion();
600
+
529
601
  const signalFile = path.join(this._sessionDir, `${phoneNumber}.signal.json`);
530
602
  const skFile = path.join(this._sessionDir, `${phoneNumber}.sk.json`);
531
603
  const tcTokenFile = path.join(this._sessionDir, `${phoneNumber}.tctoken.json`);
@@ -2137,7 +2137,7 @@ async function verifyCode(store, code, opts) {
2137
2137
  throw new Error(`Verification failed: ${reason || JSON.stringify(result)}`);
2138
2138
  }
2139
2139
 
2140
- module.exports = { checkIfRegistered, checkNumberStatus, requestSmsCode, verifyCode, fetchIosVersion, fetchAndroidVersion, fetchWaVersion, currentVersionFor, refreshSessionVersion, parsePhone, getCountryMeta, assertRegistrationKeys, parseSocksProxy, socksProxyUrl };
2140
+ module.exports = { checkIfRegistered, checkNumberStatus, requestSmsCode, verifyCode, fetchIosVersion, fetchAndroidVersion, fetchWaVersion, currentVersionFor, refreshSessionVersion, compareVersions, parsePhone, getCountryMeta, assertRegistrationKeys, parseSocksProxy, socksProxyUrl };
2141
2141
 
2142
2142
  // The HTTP reader, exposed for tests. Not part of the public API.
2143
2143
  module.exports._http = { readHttpResponse, parseHttpResponse, decodeChunkedBody };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whalibmob",
3
- "version": "5.16.0",
3
+ "version": "5.17.0",
4
4
  "description": "WhatsApp library for interaction with WhatsApp Mobile API and web ",
5
5
  "author": "Kunboruto20",
6
6
  "main": "index.js",