whalibmob 5.12.15 → 5.12.16

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/.env.example CHANGED
@@ -52,11 +52,13 @@
52
52
 
53
53
  # ─── WhatsApp version ────────────────────────────────────────────────────────
54
54
  # Pin the WhatsApp client version. When set, the live version lookup is skipped
55
- # entirely. Leave unset to fetch the current version automatically (recommended).
55
+ # entirely, and this is what is announced on connect in place of the version
56
+ # stored in the session. Leave unset to fetch the current version automatically.
56
57
  #
57
- # On Android this is normally not needed either way: the version is taken from
58
- # the APK the token material came from, since the token is signed over that
59
- # build. Setting this still overrides it.
58
+ # On Android this is normally not needed: the version comes from the APK the
59
+ # token material was read from. On iOS it is looked up on the App Store, and a
60
+ # lookup that fails leaves a built-in fallback version in the session — which
61
+ # the server refuses at connect with a 405. That is what this is for.
60
62
  # WA_VERSION=2.24.10.75
61
63
 
62
64
  # Override the static registration token. iOS only — Android has no static token
package/README.md CHANGED
@@ -254,6 +254,7 @@ npm install -g whalibmob
254
254
  - [Android Profiles](#android-profiles)
255
255
  - [Custom Device Fields](#custom-device-fields)
256
256
  - [Version & Token Overrides](#version--token-overrides)
257
+ - [When the server answers 405 on connect](#when-the-server-answers-405-on-connect)
257
258
 
258
259
  ---
259
260
 
@@ -291,14 +292,36 @@ wa registration --request-code 919634847671 --method wa_old
291
292
  ```
292
293
 
293
294
  **Registering as Android** is the same command with the platform named. Nothing
294
- else to prepare — see [what it does behind that one command](#registering-as-android):
295
+ else to prepare — see [what it does behind that one command](#registering-as-android).
296
+
297
+ Linux, macOS, Termux:
295
298
 
296
299
  ```sh
297
300
  WA_OS=android WA_DEVICE=samsung-s24-ultra wa registration --request-code 919634847671 --debug
298
301
  ```
299
302
 
300
- Set `WA_OS=android` in a `.env` file instead and the plain command is enough.
301
- `--debug` prints every request and reply, which is worth having the first time.
303
+ Windows, Command Prompt — `set` on its own line, because `VAR=value` in front of
304
+ a command is Unix syntax and Windows refuses it:
305
+
306
+ ```bat
307
+ set WA_OS=android
308
+ set WA_DEVICE=samsung-s24-ultra
309
+ wa registration --request-code 919634847671 --debug
310
+ ```
311
+
312
+ Windows, PowerShell:
313
+
314
+ ```powershell
315
+ $env:WA_OS = "android"
316
+ $env:WA_DEVICE = "samsung-s24-ultra"
317
+ wa registration --request-code 919634847671 --debug
318
+ ```
319
+
320
+ A `.env` file in the directory you run from works the same everywhere and saves
321
+ repeating it — see [Device Quick Start](#device-quick-start). `--debug` prints
322
+ every request and reply, which is worth having the first time: its first line
323
+ names the platform that actually went out, so you can see whether the variables
324
+ arrived.
302
325
 
303
326
  The variables only matter for the command that *creates* the session. What a
304
327
  session registered as is written into it, so the confirmation step and every
@@ -4308,12 +4331,56 @@ Copy `.env.example` to `.env` in your project root and set the variables you nee
4308
4331
 
4309
4332
  ### Device Quick Start
4310
4333
 
4311
- Emulate an Android Pixel 8 Pro:
4334
+ Emulate an Android Pixel 8 Pro. **The syntax for setting a variable differs per
4335
+ shell**, and getting it wrong is the most common reason a device profile appears
4336
+ to be ignored:
4337
+
4338
+ **Linux, macOS, Termux** — set them for the one command:
4312
4339
 
4313
4340
  ```sh
4314
4341
  WA_OS=android WA_DEVICE=pixel_8_pro node your-app.js
4342
+ WA_OS=android WA_DEVICE=pixel_8_pro wa registration --request-code 919634847671
4343
+ ```
4344
+
4345
+ **Windows, Command Prompt** — `set` first, one per line. `VAR=value` in front of
4346
+ a command is Unix syntax and Windows answers it with
4347
+ `'WA_OS' is not recognized as an internal or external command`:
4348
+
4349
+ ```bat
4350
+ set WA_OS=android
4351
+ set WA_DEVICE=pixel_8_pro
4352
+ wa registration --request-code 919634847671
4353
+ ```
4354
+
4355
+ Keep them on separate lines. Chaining with `&&` puts the space before the `&&`
4356
+ inside the value.
4357
+
4358
+ **Windows, PowerShell**:
4359
+
4360
+ ```powershell
4361
+ $env:WA_OS = "android"
4362
+ $env:WA_DEVICE = "pixel_8_pro"
4363
+ wa registration --request-code 919634847671
4364
+ ```
4365
+
4366
+ **Anywhere, and the one worth preferring** — a `.env` file in the directory you
4367
+ run from, which behaves identically on every platform:
4368
+
4369
+ ```dotenv
4370
+ WA_OS=android
4371
+ WA_DEVICE=pixel_8_pro
4315
4372
  ```
4316
4373
 
4374
+ ```sh
4375
+ wa registration --request-code 919634847671
4376
+ ```
4377
+
4378
+ The CLI reads `.env` from the **current directory**, not from where whalibmob is
4379
+ installed, so `cd` to the directory holding it before running. Whichever way you
4380
+ choose, the first line of `--debug` output tells you whether it took:
4381
+ `User-Agent: WhatsApp/… Android/14 Device/Google-Pixel 8 Pro`. An `iOS/…` there
4382
+ means the variables never arrived.
4383
+
4317
4384
  Or put the variables in a `.env` file. When using the **CLI** (`wa` command) the file is loaded automatically. When using the **library directly**, load it before `require('whalibmob')`:
4318
4385
 
4319
4386
  ```js
@@ -4400,8 +4467,46 @@ These variables override individual fields on top of the selected profile:
4400
4467
 
4401
4468
  | Variable | Description |
4402
4469
  |---|---|
4403
- | `WA_VERSION` | Pin the WhatsApp version (e.g. `2.24.13.80`). Skips the live store fetch. |
4404
- | `WA_STATIC_TOKEN` | Override the static token used in registration token computation. |
4470
+ | `WA_VERSION` | Pin the WhatsApp version (e.g. `2.24.13.80`). Skips the live store fetch, and is announced on connect in place of the version stored in the session. |
4471
+ | `WA_STATIC_TOKEN` | Override the static token used in registration token computation. iOS only — Android has no static token. |
4472
+
4473
+ ### When the server answers 405 on connect
4474
+
4475
+ ```
4476
+ WhatsApp auth failure 405 — client outdated — the version this session
4477
+ announces is not one the server accepts.
4478
+ ```
4479
+
4480
+ **The session is fine and the number is still registered.** 405 is the server
4481
+ declining the *client*, not the account: the version being announced is one it no
4482
+ longer accepts. Registering the number again is the one move that cannot help —
4483
+ the same version would go out and be refused identically, at the cost of a real
4484
+ phone number and a code request.
4485
+
4486
+ Announce a current version instead:
4487
+
4488
+ ```sh
4489
+ WA_VERSION=2.26.30.3 wa connect 919634847671
4490
+ ```
4491
+
4492
+ Or put `WA_VERSION` in the `.env` file, where it applies to every command.
4493
+
4494
+ **Where the stale version comes from.** Each platform learns its version
4495
+ differently:
4496
+
4497
+ | | how the version is found | what happens when that fails |
4498
+ |---|---|---|
4499
+ | iOS | looked up on the App Store | falls back to a version compiled into the library, which goes stale |
4500
+ | Android | read from the APK the token material came from | `wa apk-material --download` fetches the current one |
4501
+
4502
+ So this is mostly an iOS story: a lookup that times out or is rate limited leaves
4503
+ a months-old fallback version in the session, and nothing says so until the
4504
+ handshake is refused. On Android the version travels with the APK, and refreshing
4505
+ the material refreshes the version with it:
4506
+
4507
+ ```sh
4508
+ wa apk-material --download
4509
+ ```
4405
4510
 
4406
4511
  ## License
4407
4512
 
@@ -575,6 +575,39 @@ function tryLoadAndroidMaterial() {
575
575
  try { return loadAndroidMaterial(); } catch (_) { return null; }
576
576
  }
577
577
 
578
+ /**
579
+ * Which platform a registration speaks.
580
+ *
581
+ * Once a session has an account behind it, or has a code outstanding, its
582
+ * platform is settled: the account was created as that, the token and the
583
+ * User-Agent have to keep saying so, and re-reading WA_OS could only break it.
584
+ * A confirmation run from a shell without the variables must not flip to iOS
585
+ * halfway through.
586
+ *
587
+ * Before that, a session holds nothing but keys. Re-running the code request is
588
+ * how you start it over, and the environment is how you say what to start it
589
+ * over as — so the environment decides, and this stops being consulted the
590
+ * moment a code goes out.
591
+ *
592
+ * When the two disagree on a session that is settled, that is said out loud.
593
+ * Silently ignoring WA_OS is how you end up watching an Android registration go
594
+ * out under an iOS User-Agent and not knowing why.
595
+ */
596
+ function deviceForRegistration(store, opts) {
597
+ const env = getDeviceConfig();
598
+ const stored = store && store.device;
599
+ const settled = !!(store && (store.registered || store.codePending));
600
+ if (!settled || !stored) return env;
601
+
602
+ if (stored.os !== env.os) {
603
+ const say = (opts && opts.onProgress) || (m => _whaDbg('[DBG] REG ' + m));
604
+ say('note: this session was started as ' + stored.os + ', so it stays ' + stored.os +
605
+ ' — WA_OS=' + env.os + ' does not apply to a number that is already part-way ' +
606
+ 'through registering. Delete the session file to start it over as ' + env.os + '.');
607
+ }
608
+ return stored;
609
+ }
610
+
578
611
  /**
579
612
  * Have the Android token material ready, fetching the APK if it is not.
580
613
  *
@@ -1333,11 +1366,7 @@ async function requestSmsCode(store, method, opts) {
1333
1366
  opts = opts || {};
1334
1367
  // Before the version is read, since on Android the version comes out of the
1335
1368
  // APK this fetches.
1336
- // What a session registered as is settled when it is created, so it is the
1337
- // store that decides — not whatever WA_OS the shell happens to carry now. A
1338
- // confirmation run from a shell without the variables would otherwise sign an
1339
- // Android registration with an iOS token.
1340
- const _device = store.device || getDeviceConfig();
1369
+ const _device = deviceForRegistration(store, opts);
1341
1370
  await ensureAndroidMaterial(opts, _device);
1342
1371
  const waVersion = await fetchWaVersion(_device);
1343
1372
  store.version = waVersion;
@@ -1459,11 +1488,7 @@ async function verifyCode(store, code, opts) {
1459
1488
  opts = opts || {};
1460
1489
  // Normally already there from the code request, but a confirmation can be run
1461
1490
  // from a fresh shell that never made one.
1462
- // What a session registered as is settled when it is created, so it is the
1463
- // store that decides — not whatever WA_OS the shell happens to carry now. A
1464
- // confirmation run from a shell without the variables would otherwise sign an
1465
- // Android registration with an iOS token.
1466
- const _device = store.device || getDeviceConfig();
1491
+ const _device = deviceForRegistration(store, opts);
1467
1492
  await ensureAndroidMaterial(opts, _device);
1468
1493
  const waVersion = await fetchWaVersion(_device);
1469
1494
  store.version = waVersion;
@@ -1559,7 +1584,7 @@ module.exports = { checkIfRegistered, checkNumberStatus, requestSmsCode, verifyC
1559
1584
  module.exports._http = { readHttpResponse, parseHttpResponse, decodeChunkedBody };
1560
1585
 
1561
1586
  // Token computation, exposed for tests. Not part of the public API.
1562
- module.exports._token = { computeToken, androidMaterialPath, registrationHeaders, ensureAndroidMaterial };
1587
+ module.exports._token = { computeToken, androidMaterialPath, registrationHeaders, ensureAndroidMaterial, deviceForRegistration };
1563
1588
 
1564
1589
  // Challenge / two-factor internals, exposed for tests. Not part of the public API.
1565
1590
  module.exports._verify = {
package/lib/noise.js CHANGED
@@ -375,7 +375,12 @@ class NoiseSocket extends EventEmitter {
375
375
  oc: false,
376
376
  userAgent: {
377
377
  platform: (this.store.device && this.store.device.platform) || 1,
378
- version: this.store.version,
378
+ // The version the session was registered with, unless WA_VERSION says
379
+ // otherwise. Without that override there is no way out of a 405: the
380
+ // version lives in the session file, the server refuses it, and the
381
+ // only remaining move is to register the number again — which is the
382
+ // one thing that should never be the answer to a client-side problem.
383
+ version: process.env.WA_VERSION || this.store.version,
379
384
  mcc: _phoneMeta.mcc,
380
385
  mnc: _phoneMeta.mnc,
381
386
  osVersion: this.store.device.osVersion,
@@ -463,8 +468,20 @@ class NoiseSocket extends EventEmitter {
463
468
  '402': { wipe: false, text: 'temporarily banned.' },
464
469
  '403': { wipe: true, text: "the account's primary device is gone " +
465
470
  '— it is no longer a multi-device account.' },
466
- '405': { wipe: true, text: 'client outdated — the announced ' +
467
- 'version is not one the server accepts.' },
471
+ // Not a spent session, however much it looks like one. The server
472
+ // declined the *client*: the version we announced is not one it
473
+ // accepts. The registration behind the session is untouched, and
474
+ // telling people to register again over this costs them a real
475
+ // phone number for nothing — the same version would be announced
476
+ // and refused identically. _handleFailure already reads it this way
477
+ // once a session is up; this is the same code arriving during the
478
+ // handshake, and it was the one path still calling it revoked.
479
+ '405': { wipe: false, text: 'client outdated — the version this ' +
480
+ 'session announces is not one the server accepts. The ' +
481
+ 'session itself is fine: set WA_VERSION to a current ' +
482
+ 'WhatsApp version and connect again. On Android, ' +
483
+ '`wa apk-material --download` picks the current one up on ' +
484
+ 'its own.' },
468
485
  '406': { wipe: true, text: 'banned.' },
469
486
  '409': { wipe: true, text: 'bad user agent — the client identified ' +
470
487
  'itself in a way the server rejects.' },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whalibmob",
3
- "version": "5.12.15",
3
+ "version": "5.12.16",
4
4
  "description": "WhatsApp library for interaction with WhatsApp Mobile API and web ",
5
5
  "author": "Kunboruto20",
6
6
  "main": "index.js",