whalibmob 5.29.3 → 5.29.4

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
@@ -5507,6 +5507,30 @@ These variables override individual fields on top of the selected profile:
5507
5507
  | `WA_DEVICE_OS_VERSION` | OS version string (e.g. `14`) |
5508
5508
  | `WA_DEVICE_BUILD` | Build fingerprint (e.g. `UP1A.231005.007`) |
5509
5509
  | `WA_DEVICE_MODEL_ID` | Model ID slug (e.g. `samsung-sm-s928b`) |
5510
+ | `WA_DEVICE_RAM` | Usable RAM in GiB, as Android reports it (e.g. `7.53`). Each named profile carries its own; set this only for a different memory variant of the same model. |
5511
+
5512
+ ### Declaring your SIM
5513
+
5514
+ Registration sends `sim_mcc` / `sim_mnc` to say which network the SIM belongs
5515
+ to. The built-in table can only name **one operator per country** — Romania is
5516
+ always Orange, Brazil always Vivo — and it cannot do better, because number
5517
+ portability broke the prefix→operator link years ago. Guessing from the number
5518
+ would be wrong more often than the table is.
5519
+
5520
+ So say which SIM is in the phone:
5521
+
5522
+ ```js
5523
+ const store = createNewStore('40712345678', { simMcc: '226', simMnc: '01' })
5524
+ ```
5525
+
5526
+ | Variable | Description |
5527
+ |---|---|
5528
+ | `WA_SIM_MCC` | Mobile country code of the SIM (e.g. `226`) |
5529
+ | `WA_SIM_MNC` | Mobile network code. **Width matters** — `10` and `010` are different networks to the server, so write it exactly as your operator does. |
5530
+
5531
+ Either half can be given on its own; the other keeps the table's value, and the
5532
+ country's language and locale are unaffected either way. Leave both unset and
5533
+ nothing changes from before.
5510
5534
 
5511
5535
  ### Version & Token Overrides
5512
5536
 
@@ -5691,6 +5715,24 @@ registered, no code is requested, and the session is never written to.
5691
5715
  the problem.** The difference is then in what the CLI reads and this tool does
5692
5716
  not — `WA_VERSION`, from `.env`. Go back to the top of this section.
5693
5717
 
5718
+ ## Support this project
5719
+
5720
+ If whalibmob saves you time, you can support its development.
5721
+
5722
+ **USDT — TRC-20 (Tron network only)**
5723
+
5724
+ ```
5725
+ TNxxWvAc5m5YS89uz5uSrbXC9EKPuS27aP
5726
+ ```
5727
+
5728
+ > [!WARNING]
5729
+ > This address is **TRC-20 on the Tron network**. Send **only USDT on TRC-20** to
5730
+ > it. USDT sent on any other network — ERC-20 (Ethereum), BEP-20 (BSC), Polygon,
5731
+ > or anything else — will be **lost and cannot be recovered**. Always double-check
5732
+ > the network in your wallet before sending, and copy the address in full.
5733
+
5734
+ The **Sponsor** button at the top of the repository leads back here.
5735
+
5694
5736
  ## License
5695
5737
 
5696
5738
  MIT
package/index.d.ts CHANGED
@@ -1228,7 +1228,17 @@ export declare function fetchWaWebVersion(): Promise<{ version: [number, number,
1228
1228
  // Stores
1229
1229
  // ────────────────────────────────────────────────────────────────────────────
1230
1230
 
1231
- export declare function createNewStore(phoneNumber: string, opts?: { name?: string }): WhalibmobStore;
1231
+ export declare function createNewStore(phoneNumber: string, opts?: {
1232
+ name?: string;
1233
+ /**
1234
+ * The MCC of the SIM actually in the phone. Without it the country table's
1235
+ * one-operator-per-country guess stands — number portability means the
1236
+ * number's prefix cannot tell you. Also settable as `WA_SIM_MCC`.
1237
+ */
1238
+ simMcc?: string;
1239
+ /** The matching MNC. Width matters: `10` and `010` are different networks. */
1240
+ simMnc?: string;
1241
+ }): WhalibmobStore;
1232
1242
  /** What the CLI uses for every new SMS session; prefer it over `createNewStore`. */
1233
1243
  export declare function initAuthCreds(phoneNumber: string, opts?: { name?: string }): WhalibmobStore;
1234
1244
  export declare function saveStore(store: WhalibmobStore, filePath: string): void;
@@ -55,9 +55,13 @@ function getDeviceConfig() {
55
55
  const profileKey = _normalise(process.env.WA_DEVICE || 'samsungs24ultra');
56
56
  const found = _ANDROID_MAP[profileKey] || null;
57
57
  if (found) {
58
- return Object.assign({}, found, business
58
+ const picked = Object.assign({}, found, business
59
59
  ? { business: true, platform: PLATFORM.ANDROID_BUSINESS }
60
60
  : { business: false });
61
+ // A named profile carries the handset's own RAM; WA_DEVICE_RAM overrides
62
+ // it for someone running the same model in a different memory variant.
63
+ if (process.env.WA_DEVICE_RAM) picked.ram = process.env.WA_DEVICE_RAM;
64
+ return picked;
61
65
  }
62
66
 
63
67
  return {
@@ -69,6 +73,9 @@ function getDeviceConfig() {
69
73
  osVersion: process.env.WA_DEVICE_OS_VERSION || '14',
70
74
  osBuildNumber: process.env.WA_DEVICE_BUILD || 'UP1A.231005.007',
71
75
  modelId: process.env.WA_DEVICE_MODEL_ID || 'SM-S928B',
76
+ // What the handset reports as usable RAM, in GiB. Registration sends it,
77
+ // and it has to belong to the handset beside it — see deviceRam().
78
+ ram: process.env.WA_DEVICE_RAM || '11.55',
72
79
  deviceModelType: 2
73
80
  };
74
81
  }
@@ -478,8 +478,32 @@ const COUNTRY_META = {
478
478
  '998': { mcc: '434', mnc: '03', lg: 'ru', lc: 'UZ' }, // Uzbekistan (UzMobile)
479
479
  };
480
480
 
481
- function getCountryMeta(cc) {
482
- return COUNTRY_META[cc] || { mcc: '000', mnc: '000', lg: 'en', lc: 'US' };
481
+ // The carrier metadata for a country calling code.
482
+ //
483
+ // The table names one operator per country — Romania is always Orange, Brazil
484
+ // always Vivo — because that is the best a table keyed by calling code can do.
485
+ // It cannot be better: number portability means the prefix stopped naming the
486
+ // operator years ago, so guessing from the number would be wrong more often
487
+ // than the table is.
488
+ //
489
+ // So the caller can say instead. Whoever is registering knows which SIM is in
490
+ // the phone, and sim_mcc/sim_mnc are meant to describe that SIM; WA_SIM_MCC and
491
+ // WA_SIM_MNC (or `simMcc`/`simMnc` in the options) override the guess with the
492
+ // truth. The language and locale stay with the country either way.
493
+ //
494
+ // MNC keeps whatever width it is given: 226/10 and 226/010 are different
495
+ // networks to the server, and normalising them would break one of the two.
496
+ function getCountryMeta(cc, opts) {
497
+ const base = COUNTRY_META[cc] || { mcc: '000', mnc: '000', lg: 'en', lc: 'US' };
498
+
499
+ const mcc = (opts && opts.simMcc) || process.env.WA_SIM_MCC;
500
+ const mnc = (opts && opts.simMnc) || process.env.WA_SIM_MNC;
501
+ if (!mcc && !mnc) return base;
502
+
503
+ const out = Object.assign({}, base);
504
+ if (mcc) out.mcc = String(mcc).trim();
505
+ if (mnc) out.mnc = String(mnc).trim();
506
+ return out;
483
507
  }
484
508
 
485
509
  // ---------- Phone number parsing ----------
@@ -1201,6 +1225,57 @@ function waitHint(response, method) {
1201
1225
  return retry > 0 ? retry : null;
1202
1226
  }
1203
1227
 
1228
+ // ---------- device_ram ----------
1229
+ //
1230
+ // What the handset reports as usable RAM, in GiB, from
1231
+ // ActivityManager.MemoryInfo.totalMem — which is always below the nominal
1232
+ // figure on the box, because the kernel, the GPU and the secure world reserve a
1233
+ // slice before Android ever sees it. A 12 GB phone reports around 11.5.
1234
+ //
1235
+ // This was the constant 3.57 on every request, while the same payload declared
1236
+ // a Galaxy S24 Ultra beside it. There is no such handset: the S24 Ultra ships
1237
+ // with 12 GB and no variant of it has ever had 3.57. Two fields of one request
1238
+ // describing two different phones is not a fingerprint worth defending — it is
1239
+ // simply wrong, in the way a wrong `os_version` would be. It now comes off the
1240
+ // declared profile, so whichever handset the caller says they are on, the
1241
+ // memory belongs to it.
1242
+ const DEFAULT_DEVICE_RAM = '5.62';
1243
+
1244
+ function deviceRam(device) {
1245
+ const ram = device && device.ram;
1246
+ if (ram == null) return DEFAULT_DEVICE_RAM;
1247
+ const n = Number(ram);
1248
+ // Two decimals, the way the client formats it.
1249
+ return Number.isFinite(n) && n > 0 ? n.toFixed(2) : DEFAULT_DEVICE_RAM;
1250
+ }
1251
+
1252
+ // ---------- pid ----------
1253
+ //
1254
+ // The process id of the app making the request.
1255
+ //
1256
+ // This sent `process.pid` — the Node process. Inside a container that is 1, and
1257
+ // pid 1 on Android is `init`; no application process is ever 1. Elsewhere it is
1258
+ // whatever the host happened to hand out, which is as likely to be 7 as 24000.
1259
+ //
1260
+ // Android hands out pids from a counter that starts near 300 and wraps at
1261
+ // /proc/sys/kernel/pid_max, 32768 by default, so an app launched on a phone
1262
+ // that has been up any length of time lands well inside that range. One is
1263
+ // derived per store here, from the same identity material everything else in
1264
+ // the payload comes from — deterministic on purpose, because /exist, /code and
1265
+ // /register are three requests from one running app and a process does not
1266
+ // change its pid between them. Restoring a saved session keeps the pid it had,
1267
+ // for the same reason.
1268
+ function getAppPid(store) {
1269
+ if (store._appPid) return store._appPid;
1270
+ const seed = (store.identityId && Buffer.isBuffer(store.identityId))
1271
+ ? store.identityId
1272
+ : Buffer.from(String(store.phoneNumber || ''), 'utf8');
1273
+ const h = crypto.createHash('sha256').update(seed).update('pid').digest();
1274
+ // 1024..32767 — clear of the kernel and early-boot range, inside pid_max.
1275
+ store._appPid = String(1024 + (h.readUInt32BE(0) % (32768 - 1024)));
1276
+ return store._appPid;
1277
+ }
1278
+
1204
1279
  function buildClientMetrics(attempt) {
1205
1280
  const json = '{"attempts":' + (attempt || 1)
1206
1281
  + ',"app_campaign_download_source":"google-play|unknown"'
@@ -1250,9 +1325,9 @@ function getRequestVerificationCodeParameters(store, method, meta, device, attem
1250
1325
  'advertising_id', store.advertisingId || '',
1251
1326
  'hasinrc', '1',
1252
1327
  'roaming_type', '0',
1253
- 'device_ram', '3.57',
1328
+ 'device_ram', deviceRam(device),
1254
1329
  'education_screen_displayed', 'true',
1255
- 'pid', String(process.pid),
1330
+ 'pid', getAppPid(store),
1256
1331
  'cellular_strength', '5',
1257
1332
  'backup_token', store.backupToken ? toUrlHex(store.backupToken) : '',
1258
1333
  'tos_version', '5',
@@ -1354,7 +1429,7 @@ function buildVerifiedNameCertificate(store, device) {
1354
1429
 
1355
1430
  async function buildPayload(store, waVersion, useToken, extraPairs) {
1356
1431
  const { cc, national } = parsePhone(store.phoneNumber);
1357
- const meta = getCountryMeta(cc);
1432
+ const meta = getCountryMeta(cc, store);
1358
1433
  const device = store.device || getDeviceConfig();
1359
1434
  const token = useToken ? computeToken(waVersion, national, device) : null;
1360
1435
  // Android formats fdid lowercase, iOS uppercase (matches the native clients).
@@ -1826,7 +1901,7 @@ async function checkNumberStatus(phoneNumber) {
1826
1901
  const store = createNewStore(phoneNumber);
1827
1902
  const waVersion = await fetchWaVersion(_device);
1828
1903
  const { cc } = parsePhone(phoneNumber);
1829
- const meta = getCountryMeta(cc);
1904
+ const meta = getCountryMeta(cc, store);
1830
1905
 
1831
1906
  function hasBlock(r) {
1832
1907
  return r && !!r.custom_block_screen;
@@ -1988,7 +2063,7 @@ async function requestSmsCode(store, method, opts) {
1988
2063
 
1989
2064
  // Derive real MCC/MNC from the phone number being registered.
1990
2065
  const { cc: _regCc } = parsePhone(store.phoneNumber);
1991
- const _regMeta = getCountryMeta(_regCc);
2066
+ const _regMeta = getCountryMeta(_regCc, store);
1992
2067
 
1993
2068
  async function _tryMethod(m) {
1994
2069
  // Retry loop:
package/lib/Store.js CHANGED
@@ -113,6 +113,12 @@ function createNewStore(phoneNumber, opts) {
113
113
  registered: false,
114
114
  codePending: false, // true after /code request, cleared on successful /register
115
115
  name: normalizePushName(opts.name) || 'User',
116
+ // Which SIM is actually in the phone. The country table can only guess one
117
+ // operator per calling code — number portability broke the prefix→operator
118
+ // link long ago — so whoever is registering can name theirs instead. Null
119
+ // leaves the table's guess in place. See getCountryMeta in Registration.js.
120
+ simMcc: opts.simMcc ? String(opts.simMcc).trim() : null,
121
+ simMnc: opts.simMnc ? String(opts.simMnc).trim() : null,
116
122
  version,
117
123
  device,
118
124
  // ADVSignedDeviceIdentity bytes received from server <success> node.
@@ -194,6 +200,8 @@ function storeToJson(store) {
194
200
  advertisingId: store.advertisingId || null,
195
201
  backupToken: store.backupToken ? store.backupToken.toString('base64') : null,
196
202
  registered: !!store.registered,
203
+ simMcc: store.simMcc || null,
204
+ simMnc: store.simMnc || null,
197
205
  codePending: store.codePending || false,
198
206
  // Which delivery method the pending code actually went out by. The two
199
207
  // registration steps are normally separate commands, so the confirmation
@@ -246,6 +254,10 @@ function storeFromJson(obj) {
246
254
  advertisingId: obj.advertisingId || uuidv4(),
247
255
  backupToken: obj.backupToken ? Buffer.from(obj.backupToken, 'base64') : crypto.randomBytes(20),
248
256
  registered: !!obj.registered,
257
+ // Null on stores written before the SIM could be declared, which simply
258
+ // means the country table's guess stands.
259
+ simMcc: obj.simMcc || null,
260
+ simMnc: obj.simMnc || null,
249
261
  codePending: obj.codePending || false,
250
262
  codeMethod: obj.codeMethod || null,
251
263
  // Absent on stores written before push tokens existed; null simply means
package/lib/constants.js CHANGED
@@ -169,91 +169,91 @@ const ANDROID_DEVICE_PROFILES = {
169
169
  os: 'android', platform: PLATFORM.ANDROID,
170
170
  model: 'Samsung Galaxy S24 Ultra', manufacturer: 'Samsung',
171
171
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
172
- modelId: 'SM-S928B', deviceModelType: 2
172
+ modelId: 'SM-S928B', deviceModelType: 2, ram: '11.55'
173
173
  },
174
174
  'samsung-s24': {
175
175
  os: 'android', platform: PLATFORM.ANDROID,
176
176
  model: 'Samsung Galaxy S24', manufacturer: 'Samsung',
177
177
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
178
- modelId: 'SM-S921B', deviceModelType: 2
178
+ modelId: 'SM-S921B', deviceModelType: 2, ram: '7.63'
179
179
  },
180
180
  'samsung-s23': {
181
181
  os: 'android', platform: PLATFORM.ANDROID,
182
182
  model: 'Samsung Galaxy S23', manufacturer: 'Samsung',
183
183
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
184
- modelId: 'SM-S911B', deviceModelType: 2
184
+ modelId: 'SM-S911B', deviceModelType: 2, ram: '7.63'
185
185
  },
186
186
  'samsung-s23-ultra': {
187
187
  os: 'android', platform: PLATFORM.ANDROID,
188
188
  model: 'Samsung Galaxy S23 Ultra', manufacturer: 'Samsung',
189
189
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
190
- modelId: 'SM-S918B', deviceModelType: 2
190
+ modelId: 'SM-S918B', deviceModelType: 2, ram: '11.55'
191
191
  },
192
192
  'samsung-a55': {
193
193
  os: 'android', platform: PLATFORM.ANDROID,
194
194
  model: 'Samsung Galaxy A55', manufacturer: 'Samsung',
195
195
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
196
- modelId: 'SM-A556B', deviceModelType: 1
196
+ modelId: 'SM-A556B', deviceModelType: 1, ram: '7.44'
197
197
  },
198
198
  'pixel8pro': {
199
199
  os: 'android', platform: PLATFORM.ANDROID,
200
200
  model: 'Pixel 8 Pro', manufacturer: 'Google',
201
201
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
202
- modelId: 'Pixel 8 Pro', deviceModelType: 2
202
+ modelId: 'Pixel 8 Pro', deviceModelType: 2, ram: '11.44'
203
203
  },
204
204
  'pixel8': {
205
205
  os: 'android', platform: PLATFORM.ANDROID,
206
206
  model: 'Pixel 8', manufacturer: 'Google',
207
207
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
208
- modelId: 'Pixel 8', deviceModelType: 2
208
+ modelId: 'Pixel 8', deviceModelType: 2, ram: '7.53'
209
209
  },
210
210
  'pixel7': {
211
211
  os: 'android', platform: PLATFORM.ANDROID,
212
212
  model: 'Pixel 7', manufacturer: 'Google',
213
213
  osVersion: '14', osBuildNumber: 'TP1A.221005.002',
214
- modelId: 'Pixel 7', deviceModelType: 2
214
+ modelId: 'Pixel 7', deviceModelType: 2, ram: '7.53'
215
215
  },
216
216
  'pixel7a': {
217
217
  os: 'android', platform: PLATFORM.ANDROID,
218
218
  model: 'Pixel 7a', manufacturer: 'Google',
219
219
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
220
- modelId: 'Pixel 7a', deviceModelType: 1
220
+ modelId: 'Pixel 7a', deviceModelType: 1, ram: '7.44'
221
221
  },
222
222
  'xiaomi14': {
223
223
  os: 'android', platform: PLATFORM.ANDROID,
224
224
  model: 'Xiaomi 14', manufacturer: 'Xiaomi',
225
225
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
226
- modelId: '23127PN0CG', deviceModelType: 2
226
+ modelId: '23127PN0CG', deviceModelType: 2, ram: '11.36'
227
227
  },
228
228
  'xiaomi13': {
229
229
  os: 'android', platform: PLATFORM.ANDROID,
230
230
  model: 'Xiaomi 13', manufacturer: 'Xiaomi',
231
231
  osVersion: '13', osBuildNumber: 'TQ3A.230901.001',
232
- modelId: '2211133G', deviceModelType: 2
232
+ modelId: '2211133G', deviceModelType: 2, ram: '7.51'
233
233
  },
234
234
  'oneplus12': {
235
235
  os: 'android', platform: PLATFORM.ANDROID,
236
236
  model: 'OnePlus 12', manufacturer: 'OnePlus',
237
237
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
238
- modelId: 'CPH2573', deviceModelType: 2
238
+ modelId: 'CPH2573', deviceModelType: 2, ram: '11.48'
239
239
  },
240
240
  'oneplus11': {
241
241
  os: 'android', platform: PLATFORM.ANDROID,
242
242
  model: 'OnePlus 11', manufacturer: 'OnePlus',
243
243
  osVersion: '13', osBuildNumber: 'TQ3A.230901.001',
244
- modelId: 'CPH2449', deviceModelType: 2
244
+ modelId: 'CPH2449', deviceModelType: 2, ram: '15.32'
245
245
  },
246
246
  'oppo-find-x7': {
247
247
  os: 'android', platform: PLATFORM.ANDROID,
248
248
  model: 'OPPO Find X7', manufacturer: 'OPPO',
249
249
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
250
- modelId: 'CPH2599', deviceModelType: 2
250
+ modelId: 'CPH2599', deviceModelType: 2, ram: '11.40'
251
251
  },
252
252
  'realme-gt5': {
253
253
  os: 'android', platform: PLATFORM.ANDROID,
254
254
  model: 'realme GT 5 Pro', manufacturer: 'realme',
255
255
  osVersion: '14', osBuildNumber: 'UP1A.231005.007',
256
- modelId: 'RMX3888', deviceModelType: 2
256
+ modelId: 'RMX3888', deviceModelType: 2, ram: '15.28'
257
257
  }
258
258
  };
259
259
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whalibmob",
3
- "version": "5.29.3",
3
+ "version": "5.29.4",
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",