whalibmob 5.33.20 → 5.33.22

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
@@ -19,7 +19,7 @@ code, and bring the account into being. Both transports, one API.
19
19
 
20
20
  ### Start here
21
21
 
22
- [![Register a number](https://img.shields.io/badge/Register_a_number-SMS_or_voice-25D366?style=for-the-badge)](#register-a-new-number)
22
+ [![Register a number](https://img.shields.io/badge/Register_a_number-SMS,_voice_or_email-25D366?style=for-the-badge)](#register-a-new-number)
23
23
  [![Link an account](https://img.shields.io/badge/Link_an_account-QR_or_pairing_code-128C7E?style=for-the-badge)](#linking-to-an-existing-account-pairing-code-or-qr)
24
24
  [![Use the CLI](https://img.shields.io/badge/Use_the_CLI-no_code_needed-075E54?style=for-the-badge)](#cli--getting-started)
25
25
 
@@ -439,6 +439,9 @@ wa registration --request-code 919634847671 --method wa_old
439
439
 
440
440
  # via flash call — WhatsApp rings the number and hangs up (Android only)
441
441
  WA_OS=android wa registration --request-code 919634847671 --method flash
442
+
443
+ # via email — WhatsApp sends a 6-digit code to the email address linked to the number
444
+ wa registration --request-code 919634847671 --method email_otp
442
445
  ```
443
446
 
444
447
  **Flash call** sends no code anywhere. WhatsApp rings the number from a
@@ -471,6 +474,28 @@ Three things to know before choosing it:
471
474
  Set `WA_FLASH_CODE_LEN` if a number's server expects a different length than the
472
475
  six digits the app defaults to.
473
476
 
477
+ **Email OTP** sends a 6-digit verification code to the email address that the
478
+ phone number's WhatsApp account has associated. This method only works when the
479
+ number already has an email linked to its WhatsApp account — if there is no email
480
+ on file, the server returns an error and you should fall back to `sms` or `voice`.
481
+
482
+ ```sh
483
+ # request via email
484
+ wa registration --request-code 919634847671 --method email_otp
485
+
486
+ # then confirm with the 6-digit code WhatsApp emailed
487
+ wa registration --register 919634847671 --code 123456
488
+ ```
489
+
490
+ Two things to know before choosing it:
491
+
492
+ - **Email must be linked.** If the number has never had an email associated in
493
+ WhatsApp Settings → Account → Email address, the server rejects the request.
494
+ Use `sms` or `voice` instead.
495
+ - **Falls back to SMS.** When `email_otp` fails (no email on file or email
496
+ delivery issue), whalibmob automatically retries with `sms` so the attempt is
497
+ not wasted.
498
+
474
499
  **Set the account's display name while registering** with `--name`. This is the
475
500
  name people who have *not* saved your number see next to it — in group
476
501
  participant lists, in notifications, and beside your messages. Quote it if it
package/cli.js CHANGED
@@ -673,7 +673,7 @@ const HELP = `
673
673
 
674
674
  Registration
675
675
  /reg check <phone> check if number has WhatsApp
676
- /reg code <phone> [sms|voice|wa_old|flash] request verification code
676
+ /reg code <phone> [sms|voice|wa_old|flash|email_otp] request verification code
677
677
  /reg push <phone> [sms|voice] request code and receive it over push
678
678
  /reg confirm <phone> <code> complete registration
679
679
 
@@ -2400,7 +2400,7 @@ async function handleLine(line) {
2400
2400
  const ph = normalizePhone(p[2]);
2401
2401
  const method = (p[3] || 'sms').toLowerCase();
2402
2402
  if (!ph) {
2403
- fail('usage: /reg code <phone> [sms|voice|wa_old|flash] [--name "Your Name"]');
2403
+ fail('usage: /reg code <phone> [sms|voice|wa_old|flash|email_otp] [--name "Your Name"]');
2404
2404
  out(' --name sets the display name the account registers with — what people');
2405
2405
  out(' who have not saved your number see. It can be changed later with /name.');
2406
2406
  break;
@@ -2788,7 +2788,7 @@ options:
2788
2788
  --out <file> where apk-material writes (default: <session dir>/android-apk-material.json)
2789
2789
  --sms connect by registering this number over SMS
2790
2790
  --pair connect by linking to an existing account (8-digit code)
2791
- --method sms | voice | wa_old | flash (default: sms)
2791
+ --method sms | voice | wa_old | flash | email_otp (default: sms)
2792
2792
  flash: WhatsApp rings the number and hangs up; the code is
2793
2793
  read from the calling number automatically (Android only)
2794
2794
  --business register/connect as WhatsApp Business (same as WA_BUSINESS=1)
@@ -55,6 +55,27 @@ const GS_SERVER_KEY = Buffer.from(
55
55
  // Base stat codes for the 13 path checks; +1000 when stat() fails.
56
56
  const GS_BASE_CODES = [10, 11, 0, 100, 101, 102, 103, 104, 1, 105, 106, 107, 108];
57
57
 
58
+ // ─── _ge: environment security flags ─────────────────────────────────────────
59
+ // sb=false (no security bypass), sv=false (not security-verified by TEE).
60
+ // Always false on a headless client — matching a device that passed basic
61
+ // checks but has no hardware-backed verification.
62
+ function generateGeToken() {
63
+ return encodeURIComponent('{"sb":false,"sv":false}');
64
+ }
65
+
66
+ // ─── _ga: app analytics envelope ─────────────────────────────────────────────
67
+ // bi = SHA-512 of the session nonce (deterministic per session, unique per
68
+ // device); ap/ai/ae are numeric constants observed across Android builds;
69
+ // mp/mu are multi-profile/multi-user booleans (false on a single-user install).
70
+ function generateGaToken(nonceB64) {
71
+ const nonceBuf = Buffer.from(
72
+ (nonceB64 || '').replace(/-/g, '+').replace(/_/g, '/'), 'base64'
73
+ );
74
+ const bi = crypto.createHash('sha512').update(nonceBuf).digest('base64');
75
+ const json = '{"bi":"' + bi + '","ap":247444,"ai":145847,"mp":false,"ae":128383,"mu":false}';
76
+ return encodeURIComponent(json);
77
+ }
78
+
58
79
  function generateGsToken() {
59
80
  const nowMs = Date.now();
60
81
  const sec = Math.floor(nowMs / 1000);
@@ -246,14 +267,16 @@ async function attestationFields(device, nonceB64, opts) {
246
267
  if (device && device.os === 'android') {
247
268
  const a = await androidIntegrity(nonceB64 || '', device);
248
269
  const gs = generateGsToken();
270
+ const ge = generateGeToken();
271
+ const ga = generateGaToken(nonceB64 || '');
249
272
  _ok('_gs field generated (WASafe envelope, ' + gs.length + ' encoded chars)');
250
273
  return [
251
274
  'gpia', orNull(a.gpia),
252
275
  '_gg', orNull(a.gg),
253
276
  '_gi', orNull(a.gi),
254
277
  '_gp', orNull(a.gp),
255
- '_ge', orNull(a.ge),
256
- '_ga', orNull(a.ga),
278
+ '_ge', ge,
279
+ '_ga', ga,
257
280
  '_gs', gs,
258
281
  'push_token', pushToken
259
282
  ];
@@ -1389,7 +1389,7 @@ function getRequestVerificationCodeParameters(store, method, meta, device, attem
1389
1389
  'reason', '',
1390
1390
  'mcc', meta.mcc,
1391
1391
  'mnc', meta.mnc,
1392
- 'feo2_query_status', 'client_capabilities_cached',
1392
+ 'feo2_query_status', 'success_get_client_capabilities',
1393
1393
  'db', '1',
1394
1394
  'sim_type', '1',
1395
1395
  'recaptcha', '%7B%22stage%22%3A%22ABPROP_DISABLED%22%7D',
@@ -2216,8 +2216,11 @@ async function requestSmsCode(store, method, opts) {
2216
2216
  }
2217
2217
 
2218
2218
  // Auto-fallback: if the primary method gets no_routes, try the alternate once.
2219
- // sms → wa_old, wa_old → sms, voice → sms.
2220
- const fallbackMethod = method === 'wa_old' ? 'sms' : (method === 'sms' ? 'wa_old' : 'sms');
2219
+ // sms → wa_old, wa_old → sms, voice → sms, email_otp → sms.
2220
+ const fallbackMethod = method === 'wa_old' ? 'sms'
2221
+ : (method === 'sms' ? 'wa_old'
2222
+ : (method === 'email_otp' ? 'sms'
2223
+ : 'sms'));
2221
2224
  let autoFallbackDone = false;
2222
2225
 
2223
2226
  // Derive real MCC/MNC from the phone number being registered.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whalibmob",
3
- "version": "5.33.20",
3
+ "version": "5.33.22",
4
4
  "description": "Node.js library for WhatsApp — register a number over SMS, or link as a companion by QR. Signal E2E encryption, media, groups, channels.",
5
5
  "author": "Kunboruto20",
6
6
  "main": "index.js",