whalibmob 5.1.21 → 5.5.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
@@ -1,22 +1,16 @@
1
1
  <div align='center'>whalibmob is a pure JavaScript Node.js library for interacting with the WhatsApp Mobile API.</div>
2
- <div align='center'>v5.1.16</div>
2
+ <div align='center'>v5.1.14</div>
3
3
 
4
4
  ##
5
5
 
6
6
  > [!CAUTION]
7
7
  > Use a dedicated phone number with this library. Connecting with a number that is already active on a real device will cause WhatsApp to log that device out.
8
8
 
9
- This product is free for everyone but if you want to support more whalibmob or others you can support me with some USD donations through Crypto at This product is free for everyone but if you want us to support more whalibmob or others you can support me with some USD donations through Crypto at 0x8AD64F47a715eC24DeF193FBb9aC64d4E857f0f3
10
-
11
-
12
-
13
-
14
-
15
9
  > [!IMPORTANT]
16
10
  > This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or affiliates. "WhatsApp" and related names are registered trademarks of their respective owners. Use at your own discretion.
17
11
 
18
12
  - whalibmob does not require a browser, Selenium, or any other external runtime — it communicates directly with WhatsApp using a **TCP socket** and the **Noise Protocol** handshake.
19
- - The library operates as a real **iOS mobile device** (iPhone), not as WhatsApp Web. It uses the Mobile API endpoint, which behaves differently from the Web API.
13
+ - The library operates as a real **iOS mobile device**, not as WhatsApp Web. It uses the Mobile API endpoint, which behaves differently from the Web API.
20
14
  - Signal Protocol encryption is **fully inlined** in pure JavaScript — no native binaries, no node-gyp, runs anywhere Node.js runs.
21
15
 
22
16
  ## Install
@@ -190,8 +184,9 @@ npm install -g whalibmob
190
184
  - [Media Encryption](#media-encryption)
191
185
  - [Device Emulation](#device-emulation)
192
186
  - [Quick Start](#device-quick-start)
193
- - [iPhone Profiles](#iphone-profiles)
194
- - [Custom iPhone Fields](#custom-iphone-fields)
187
+ - [iOS Profiles](#ios-profiles)
188
+ - [Android Profiles](#android-profiles)
189
+ - [Custom Device Fields](#custom-device-fields)
195
190
  - [Version & Token Overrides](#version--token-overrides)
196
191
 
197
192
  ---
@@ -2191,20 +2186,18 @@ See the [Receiving Media](#receiving-media) section for a complete working code
2191
2186
 
2192
2187
  ## Device Emulation
2193
2188
 
2194
- whalibmob emulates an iPhone when communicating with WhatsApp servers.
2195
- The device profile controls the User-Agent header, the Noise Protocol `platform` field, and the token computation.
2196
-
2197
- When no `WA_DEVICE` is set, the library **picks a random iPhone model** from the built-in profile list for each new session. This provides natural device diversity.
2189
+ whalibmob can emulate any iOS or Android device when communicating with WhatsApp servers.
2190
+ The device profile controls the User-Agent header, the Noise Protocol `platform` field, and the static token used in registration token computation.
2198
2191
 
2199
2192
  Configuration is done entirely through environment variables — no code changes required.
2200
2193
  Copy `.env.example` to `.env` in your project root and set the variables you need.
2201
2194
 
2202
2195
  ### Device Quick Start
2203
2196
 
2204
- Emulate an iPhone 16 Pro:
2197
+ Emulate an Android Pixel 8 Pro:
2205
2198
 
2206
2199
  ```sh
2207
- WA_DEVICE=iphone16pro node your-app.js
2200
+ WA_OS=android WA_DEVICE=pixel_8_pro node your-app.js
2208
2201
  ```
2209
2202
 
2210
2203
  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')`:
@@ -2215,86 +2208,86 @@ const { WhalibmobClient } = require('whalibmob')
2215
2208
  ```
2216
2209
 
2217
2210
  ```dotenv
2218
- WA_DEVICE=iphone16pro
2211
+ WA_OS=android
2212
+ WA_DEVICE=pixel_8_pro
2219
2213
  ```
2220
2214
 
2221
- ### iPhone Profiles
2215
+ Emulate a custom Samsung device:
2222
2216
 
2223
- Available values for `WA_DEVICE`:
2217
+ ```dotenv
2218
+ WA_OS=android
2219
+ WA_DEVICE_MODEL=SM-S928B
2220
+ WA_DEVICE_MANUFACTURER=samsung
2221
+ WA_DEVICE_OS_VERSION=14
2222
+ WA_DEVICE_BUILD=UP1A.231005.007
2223
+ WA_DEVICE_MODEL_ID=samsung-sm-s928b
2224
+ ```
2225
+
2226
+ ### iOS Profiles
2227
+
2228
+ Available values for `WA_DEVICE` when `WA_OS=ios` (default):
2224
2229
 
2225
2230
  | Profile key | Device | iOS version |
2226
2231
  |---|---|---|
2227
- | `iphone16promax` | iPhone 16 Pro Max | 18.3.2 |
2228
- | `iphone16pro` | iPhone 16 Pro | 18.3.2 |
2229
- | `iphone16plus` | iPhone 16 Plus | 18.3.2 |
2230
- | `iphone16` | iPhone 16 | 18.3.2 |
2231
- | `iphone15promax` | iPhone 15 Pro Max | 18.3.2 |
2232
- | `iphone15pro` | iPhone 15 Pro | 18.3.2 |
2233
- | `iphone15plus` | iPhone 15 Plus | 18.3.2 |
2234
- | `iphone15` | iPhone 15 | 18.3.2 |
2235
- | `iphone14promax` | iPhone 14 Pro Max | 18.3.2 |
2236
- | `iphone14pro` | iPhone 14 Pro | 18.3.2 |
2237
- | `iphone14plus` | iPhone 14 Plus | 17.7.5 |
2238
- | `iphone14` | iPhone 14 | 17.7.5 |
2239
- | `iphone13pro` | iPhone 13 Pro | 17.7.5 |
2240
- | `iphone13` | iPhone 13 | 17.7.5 |
2241
- | `iphone12pro` | iPhone 12 Pro | 17.7.5 |
2242
- | `iphone12` | iPhone 12 | 17.7.5 |
2243
- | `iphonese3` | iPhone SE (3rd gen) | 17.7.5 |
2244
- | `iphone11pro` | iPhone 11 Pro | 17.7.5 |
2245
- | `iphone11` | iPhone 11 | 17.7.5 |
2246
- | `iphonexs` | iPhone Xs | 16.7.11 |
2247
-
2248
- User-Agent format: `WhatsApp/<version> iOS/<osVersion> Device/<model>`
2249
-
2250
- The WhatsApp version is fetched automatically from the Apple App Store (iTunes API) every time you register, always using the latest published version. The result is cached for **6 hours** so repeated calls within a session are fast. If all App Store sources fail (no internet, rate limit, etc.), the built-in `IOS_VERSION_FALLBACK` constant is used as a last resort. Three iTunes API endpoints are tried in sequence for maximum reliability.
2251
-
2252
- ### Custom iPhone Fields
2253
-
2254
- These variables override individual fields to emulate a specific iPhone not in the list above.
2255
-
2256
- | Variable | Sent to WhatsApp as | Notes |
2232
+ | `iphone_15_pro` | iPhone 15 Pro | 17.4.1 |
2233
+ | `iphone_15` | iPhone 15 | 17.4.1 |
2234
+ | `iphone_14_pro` | iPhone 14 Pro | 16.7.5 |
2235
+ | `iphone_14` | iPhone 14 | 16.7.5 |
2236
+ | `iphone_13_pro` | iPhone 13 Pro | 16.7.5 |
2237
+ | `iphone_13` | iPhone 13 | 16.7.5 |
2238
+ | `iphone_12_pro` | iPhone 12 Pro | 15.8.2 |
2239
+ | `iphone_12` | iPhone 12 | 15.8.2 |
2240
+ | `iphone_11_pro` | iPhone 11 Pro | 15.8.2 |
2241
+ | `iphone_11` | iPhone 11 | 15.8.2 |
2242
+ | `iphone_se3` | iPhone SE (3rd gen) | 16.7.5 |
2243
+ | `iphone_xs` | iPhone Xs | 15.8.2 |
2244
+
2245
+ iOS User-Agent format: `WhatsApp/<version> iOS/<osVersion> Device/<model>`
2246
+
2247
+ ### Android Profiles
2248
+
2249
+ Available values for `WA_DEVICE` when `WA_OS=android`:
2250
+
2251
+ | Profile key | Device | Android version |
2257
2252
  |---|---|---|
2258
- | `WA_DEVICE_MODEL` | proto field 7 | e.g. `iPhone 16 Pro Max` |
2259
- | `WA_DEVICE_OS_VERSION` | proto field 5 | e.g. `18.3.2` or `17.4.1` |
2260
- | `WA_DEVICE_BUILD` | proto field 8 | iOS build number, e.g. `22D82` |
2261
- | `WA_DEVICE_MODEL_ID` | proto field 16 | Apple model number, e.g. `iPhone17,2` |
2262
-
2263
- > [!NOTE]
2264
- > These fields are sent in the **Noise Protocol handshake** (TCP connection to WhatsApp), not in the HTTP registration body. The HTTP registration body sends identity keys, token, `mcc`/`mnc`/`sim_mcc`/`sim_mnc` (derived from the country code), and locale (`lg`/`lc`) — it does **not** send the human-readable device strings.
2265
-
2266
- **Example custom iPhone via Node.js API:**
2253
+ | `pixel_8_pro` | Pixel 8 Pro | 14 |
2254
+ | `pixel_8` | Pixel 8 | 14 |
2255
+ | `pixel_7` | Pixel 7 | 14 |
2256
+ | `pixel_7a` | Pixel 7a | 14 |
2257
+ | `samsung_s24_ultra` | Samsung Galaxy S24 Ultra | 14 |
2258
+ | `samsung_s24` | Samsung Galaxy S24 | 14 |
2259
+ | `samsung_s23_ultra` | Samsung Galaxy S23 Ultra | 14 |
2260
+ | `samsung_s23` | Samsung Galaxy S23 | 14 |
2261
+ | `samsung_a55` | Samsung Galaxy A55 | 14 |
2262
+ | `oneplus_12` | OnePlus 12 | 14 |
2263
+ | `oneplus_11` | OnePlus 11 | 13 |
2264
+ | `xiaomi_14` | Xiaomi 14 | 14 |
2265
+ | `xiaomi_13` | Xiaomi 13 | 13 |
2266
+ | `oppo_find_x7` | OPPO Find X7 | 14 |
2267
+ | `realme_gt5` | realme GT 5 Pro | 14 |
2268
+
2269
+ Android User-Agent format: `WhatsApp/<version> A`
2270
+
2271
+ The Android version is fetched automatically from the Google Play Store on first use and cached in memory. If the fetch fails, `ANDROID_VERSION_FALLBACK` is used.
2272
+
2273
+ ### Custom Device Fields
2274
+
2275
+ These variables override individual fields on top of the selected profile:
2267
2276
 
2268
- ```js
2269
- process.env.WA_DEVICE_MODEL = 'iPhone 16 Pro Max'
2270
- process.env.WA_DEVICE_OS_VERSION = '18.3.2'
2271
- process.env.WA_DEVICE_BUILD = '22D82'
2272
- process.env.WA_DEVICE_MODEL_ID = 'iPhone17,2'
2273
-
2274
- const { createNewStore, requestSmsCode, verifyCode } = require('whalibmob')
2275
-
2276
- const store = createNewStore('919634847671')
2277
- await requestSmsCode(store, 'sms')
2278
- ```
2279
-
2280
- **Example — custom iPhone via `.env` file:**
2281
-
2282
- ```dotenv
2283
- WA_DEVICE_MODEL=iPhone 16 Pro Max
2284
- WA_DEVICE_OS_VERSION=18.3.2
2285
- WA_DEVICE_BUILD=22D82
2286
- WA_DEVICE_MODEL_ID=iPhone17,2
2287
- ```
2277
+ | Variable | Description |
2278
+ |---|---|
2279
+ | `WA_DEVICE_MODEL` | Device model string (e.g. `SM-S928B`) |
2280
+ | `WA_DEVICE_MANUFACTURER` | Manufacturer name (e.g. `samsung`) |
2281
+ | `WA_DEVICE_OS_VERSION` | OS version string (e.g. `14`) |
2282
+ | `WA_DEVICE_BUILD` | Build fingerprint (e.g. `UP1A.231005.007`) |
2283
+ | `WA_DEVICE_MODEL_ID` | Model ID slug (e.g. `samsung-sm-s928b`) |
2288
2284
 
2289
2285
  ### Version & Token Overrides
2290
2286
 
2291
2287
  | Variable | Description |
2292
2288
  |---|---|
2293
- | `WA_VERSION` | Pin a specific WhatsApp version (e.g. `2.26.10.74`). Skips the live App Store fetch entirely. |
2294
- | `WA_STATIC_TOKEN` | Replaces the built-in iOS static secret in the MD5 formula (`token = MD5(secret + MD5hex(version) + national)`). Only needed if WhatsApp rotates the built-in secret. |
2295
-
2296
- > [!NOTE]
2297
- > **No token configuration is needed.** The built-in iOS static secret (`IOS_STATIC_TOKEN`) is valid for current WhatsApp servers. `WA_STATIC_TOKEN` is only needed if that secret is rotated in a future WhatsApp update.
2289
+ | `WA_VERSION` | Pin the WhatsApp version (e.g. `2.24.13.80`). Skips the live store fetch. |
2290
+ | `WA_STATIC_TOKEN` | Override the static token used in registration token computation. |
2298
2291
 
2299
2292
  ## License
2300
2293
 
package/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  'use strict';
3
3
 
4
4
  // Load .env from the current working directory (silently — no error if missing).
5
- // This lets users configure WA_DEVICE, WA_VERSION etc. without touching
5
+ // This lets users configure WA_OS, WA_DEVICE, WA_VERSION etc. without touching
6
6
  // their shell environment. Must happen before any other require() so that
7
7
  // process.env is fully populated when modules read it at load time.
8
8
  try { require('dotenv').config(); } catch (_) {}
@@ -35,7 +35,7 @@ const {
35
35
  loadStore
36
36
  } = require('./lib/Client');
37
37
 
38
- const VERSION = '5.1.16';
38
+ const VERSION = '5.1.21';
39
39
 
40
40
  // ─── output helpers ───────────────────────────────────────────────────────────
41
41
 
package/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  const { WhalibmobClient, checkNumberStatus, fetchIosVersion, fetchWaVersion, assertRegistrationKeys } = require('./lib/Client');
4
4
  const { getDeviceConfig } = require('./lib/DeviceConfig');
5
+ const { fetchAndroidVersion } = require('./lib/Registration');
5
6
  const { createNewStore, saveStore, loadStore, toSixParts, fromSixParts, storeToJson, storeFromJson } = require('./lib/Store');
6
7
  const { checkIfRegistered, requestSmsCode, verifyCode } = require('./lib/Registration');
7
8
  const { SignalProtocol } = require('./lib/signal/SignalProtocol');
@@ -18,11 +19,12 @@ module.exports = {
18
19
  requestSmsCode,
19
20
  verifyCode,
20
21
  assertRegistrationKeys,
21
- // Version fetch — fetchWaVersion fetches from the Apple App Store.
22
+ // Version fetch — use fetchWaVersion for device-aware (iOS or Android) fetching.
22
23
  // fetchIosVersion is kept for backward compatibility.
23
24
  fetchWaVersion,
24
25
  fetchIosVersion,
25
- // Device config — reads WA_DEVICE / WA_DEVICE_* from process.env
26
+ fetchAndroidVersion,
27
+ // Device config — reads WA_OS / WA_DEVICE / WA_DEVICE_* from process.env
26
28
  getDeviceConfig,
27
29
  // Store helpers
28
30
  createNewStore,
package/lib/Client.js CHANGED
@@ -175,6 +175,17 @@ class WhalibmobClient extends EventEmitter {
175
175
  this._signal = SignalProtocol.fromStore(this._store, signalFile, skFile);
176
176
  this._devMgr = new DeviceManager(this);
177
177
 
178
+ // Restore LID ↔ phone mappings persisted from previous sessions.
179
+ // This ensures we can route to LID JIDs even on fresh connections where no
180
+ // incoming message has yet populated _pnToLid during this session.
181
+ const persistedLid = this._signal.store.getLidMappings
182
+ ? this._signal.store.getLidMappings() : {};
183
+ for (const [phone, lid] of Object.entries(persistedLid)) {
184
+ this._pnToLid.set(phone, lid);
185
+ this._lidToPn.set(lid, phone);
186
+ }
187
+ process.stderr.write('[DBG] LID_RESTORED count=' + Object.keys(persistedLid).length + '\n');
188
+
178
189
  await this._connectSocket();
179
190
  return this;
180
191
  }
@@ -530,6 +541,10 @@ class WhalibmobClient extends EventEmitter {
530
541
  if (lidUser && pnUser && lidUser !== pnUser) {
531
542
  this._lidToPn.set(lidUser, pnUser);
532
543
  this._pnToLid.set(pnUser, lidUser);
544
+ // Persist so the mapping survives reconnects / process restarts
545
+ if (this._signal && this._signal.store && this._signal.store.setLidMapping) {
546
+ this._signal.store.setLidMapping(pnUser, lidUser);
547
+ }
533
548
  }
534
549
  }
535
550
  process.stderr.write('[DBG] _handleMessage from=' + from + ' participant=' + participant + ' senderPn=' + senderPn + ' id=' + id + '\n');
@@ -1196,6 +1211,8 @@ class WhalibmobClient extends EventEmitter {
1196
1211
  const pnUser = pPhone.split('@')[0].split(':')[0];
1197
1212
  this._lidToPn.set(lidUser, pnUser);
1198
1213
  this._pnToLid.set(pnUser, lidUser);
1214
+ if (this._signal && this._signal.store && this._signal.store.setLidMapping)
1215
+ this._signal.store.setLidMapping(pnUser, lidUser);
1199
1216
  }
1200
1217
  }
1201
1218
  // Case B: participant JID is a PN, lid attribute is their LID
@@ -1204,6 +1221,8 @@ class WhalibmobClient extends EventEmitter {
1204
1221
  const lidUser = pLid.split('@')[0].split(':')[0];
1205
1222
  this._lidToPn.set(lidUser, pnUser);
1206
1223
  this._pnToLid.set(pnUser, lidUser);
1224
+ if (this._signal && this._signal.store && this._signal.store.setLidMapping)
1225
+ this._signal.store.setLidMapping(pnUser, lidUser);
1207
1226
  }
1208
1227
  return { jid: pJid, role: pRole };
1209
1228
  });
@@ -2,65 +2,80 @@
2
2
 
3
3
  const {
4
4
  IOS_DEVICE,
5
- IOS_DEVICE_PROFILES
5
+ IOS_DEVICE_PROFILES,
6
+ ANDROID_DEVICE_PROFILES
6
7
  } = require('./constants');
7
8
 
8
- // Pre-build normalised lookup table so that user-supplied profile keys in any
9
+ // Pre-build normalised lookup tables so that user-supplied profile keys in any
9
10
  // separator style (underscores, dashes, spaces, or none) always resolve.
10
11
  // Normalisation: lowercase, strip underscores / dashes / spaces.
11
12
  function _normalise(s) { return String(s).toLowerCase().replace(/[\s_-]/g, ''); }
12
13
 
13
- const _IOS_MAP = {};
14
- const _IOS_KEYS = [];
15
- for (const k of Object.keys(IOS_DEVICE_PROFILES)) {
16
- _IOS_MAP[_normalise(k)] = IOS_DEVICE_PROFILES[k];
17
- _IOS_KEYS.push(k);
18
- }
14
+ const _IOS_MAP = {};
15
+ const _ANDROID_MAP = {};
16
+ for (const k of Object.keys(IOS_DEVICE_PROFILES)) _IOS_MAP[_normalise(k)] = IOS_DEVICE_PROFILES[k];
17
+ for (const k of Object.keys(ANDROID_DEVICE_PROFILES)) _ANDROID_MAP[_normalise(k)] = ANDROID_DEVICE_PROFILES[k];
19
18
 
20
19
  // ─────────────────────────────────────────────────────────────────────────────
21
- // DeviceConfig — reads environment variables and returns the active iOS device
20
+ // DeviceConfig — reads environment variables and returns the active device
22
21
  // profile to be used during registration and connection.
23
22
  //
24
23
  // Priority order:
25
- // 1. WA_DEVICE → pick a named predefined iPhone profile
26
- // 2. WA_DEVICE_* variables → build a custom iOS profile
27
- // 3. No env vars random iPhone from the profile list
24
+ // 1. WA_OS + WA_DEVICE → pick a named predefined profile
25
+ // 2. WA_OS + individual WA_DEVICE_* vars → build a custom profile
26
+ // 3. No env vars default iOS (iPhone 15 Pro)
28
27
  //
29
28
  // Env variables:
30
- // WA_DEVICE profile key (e.g. iphone16pro, iphone15, iphonese3)
31
- // WA_DEVICE_MODEL device display name (e.g. "iPhone 16 Pro Max")
32
- // WA_DEVICE_OS_VERSION iOS version string (e.g. "18.3.2")
33
- // WA_DEVICE_BUILD iOS build number (e.g. "22D82")
34
- // WA_DEVICE_MODEL_ID internal model id (e.g. "iPhone17,2")
29
+ // WA_OS ios | android (default: ios)
30
+ // WA_DEVICE profile key (e.g. samsung-s24-ultra, pixel8, iphone14)
31
+ // WA_DEVICE_MODEL device display name
32
+ // WA_DEVICE_MANUFACTURER Apple | Samsung | Google …
33
+ // WA_DEVICE_OS_VERSION OS version string (e.g. 17.4.1 or 14)
34
+ // WA_DEVICE_BUILD OS build number
35
+ // WA_DEVICE_MODEL_ID internal model identifier (e.g. SM-S928B, iPhone16,1)
35
36
  // WA_VERSION override WhatsApp version (skips live fetch if set)
36
- // WA_STATIC_TOKEN override static registration token secret
37
+ // WA_STATIC_TOKEN override static registration token
37
38
  // ─────────────────────────────────────────────────────────────────────────────
38
39
 
39
40
  function getDeviceConfig() {
40
- // 1. Named profile via WA_DEVICE
41
- if (process.env.WA_DEVICE) {
42
- const profileKey = _normalise(process.env.WA_DEVICE);
43
- const found = _IOS_MAP[profileKey] || null;
44
- if (found) return Object.assign({}, found);
45
- }
41
+ const osType = (process.env.WA_OS || 'ios').toLowerCase().trim();
42
+
43
+ if (osType === 'android') {
44
+ const profileKey = _normalise(process.env.WA_DEVICE || 'samsungs24ultra');
45
+ const found = _ANDROID_MAP[profileKey] || null;
46
+ if (found) {
47
+ return Object.assign({}, found);
48
+ }
46
49
 
47
- // 2. Custom profile via individual WA_DEVICE_* vars
48
- if (process.env.WA_DEVICE_MODEL || process.env.WA_DEVICE_MODEL_ID) {
49
50
  return {
50
- os: 'ios',
51
- platform: 1,
52
- model: process.env.WA_DEVICE_MODEL || IOS_DEVICE.model,
53
- manufacturer: 'Apple',
54
- osVersion: process.env.WA_DEVICE_OS_VERSION || IOS_DEVICE.osVersion,
55
- osBuildNumber: process.env.WA_DEVICE_BUILD || IOS_DEVICE.osBuildNumber,
56
- modelId: process.env.WA_DEVICE_MODEL_ID || IOS_DEVICE.modelId,
51
+ os: 'android',
52
+ platform: 3,
53
+ model: process.env.WA_DEVICE_MODEL || 'Samsung Galaxy S24 Ultra',
54
+ manufacturer: process.env.WA_DEVICE_MANUFACTURER || 'Samsung',
55
+ osVersion: process.env.WA_DEVICE_OS_VERSION || '14',
56
+ osBuildNumber: process.env.WA_DEVICE_BUILD || 'UP1A.231005.007',
57
+ modelId: process.env.WA_DEVICE_MODEL_ID || 'SM-S928B',
57
58
  deviceModelType: 2
58
59
  };
59
60
  }
60
61
 
61
- // 3. No env vars → pick a random iPhone profile for device diversity
62
- const idx = Math.floor(Math.random() * _IOS_KEYS.length);
63
- return Object.assign({}, IOS_DEVICE_PROFILES[_IOS_KEYS[idx]]);
62
+ // iOS (default)
63
+ const profileKey = _normalise(process.env.WA_DEVICE || 'iphone15pro');
64
+ const found = _IOS_MAP[profileKey] || null;
65
+ if (found) {
66
+ return Object.assign({}, found);
67
+ }
68
+
69
+ return {
70
+ os: 'ios',
71
+ platform: 1,
72
+ model: process.env.WA_DEVICE_MODEL || IOS_DEVICE.model,
73
+ manufacturer: process.env.WA_DEVICE_MANUFACTURER || IOS_DEVICE.manufacturer,
74
+ osVersion: process.env.WA_DEVICE_OS_VERSION || IOS_DEVICE.osVersion,
75
+ osBuildNumber: process.env.WA_DEVICE_BUILD || IOS_DEVICE.osBuildNumber,
76
+ modelId: process.env.WA_DEVICE_MODEL_ID || IOS_DEVICE.modelId,
77
+ deviceModelType: 2
78
+ };
64
79
  }
65
80
 
66
81
  module.exports = { getDeviceConfig };