whalibmob 5.33.6 β†’ 5.33.8

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
@@ -39,7 +39,7 @@ code, and bring the account into being. Both transports, one API.
39
39
 
40
40
  ### πŸ’¬ Need help? Talk to me on Telegram
41
41
 
42
- [![whalibmob channel](https://img.shields.io/badge/whalibmob_channel-News_%26_updates-229ED9?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/+sHN4MDCyB7U5OWY0)
42
+ [![whalibmob channel](https://img.shields.io/badge/whalibmob_channel-News_%26_updates-229ED9?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/whalibmob)
43
43
 
44
44
  [![Contact me on Telegram](https://img.shields.io/badge/Contact_me-%40brtyu545-229ED9?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/brtyu545)
45
45
 
package/cli.js CHANGED
@@ -496,10 +496,13 @@ function normalizePhone(s) {
496
496
  // describe a call that is never coming.
497
497
  function printCodeNextSteps(store, phone, confirmCmd) {
498
498
  if (store && store.codeMethod === 'flash') {
499
+ const cc = store.flashCliCc ? ' (from +' + store.flashCliCc + ')' : '';
500
+ const timeout = Number(store.flashTimeout) > 0 ? Number(store.flashTimeout) : null;
499
501
  out(' a call will ring +' + phone + ' and hang up by itself β€” do not answer it');
500
- out(' the code is the LAST 6 DIGITS of the number that called');
501
- out(' pasting the whole number works too β€” only its last 6 digits are sent');
502
- out(' run: ' + confirmCmd + ' <last-6-digits>');
502
+ out(' it comes from a foreign number' + cc + ' β€” paste that WHOLE number here');
503
+ out(' whalibmob reads the code out of it for you (no need to pick out digits)');
504
+ if (timeout) out(' ⚠ be quick β€” the flash code expires about ' + timeout + 's after the call');
505
+ out(' run: ' + confirmCmd + ' <number-that-called>');
503
506
  return;
504
507
  }
505
508
  out(' important: enter the code within 10 minutes');
@@ -2742,7 +2745,7 @@ options:
2742
2745
  --pair connect by linking to an existing account (8-digit code)
2743
2746
  --method sms | voice | wa_old | flash | email (default: sms)
2744
2747
  flash: WhatsApp rings the number and hangs up; the code is
2745
- the last 6 digits of the calling number (Android only)
2748
+ read from the calling number automatically (Android only)
2746
2749
  --email <address> email address (required when --method email)
2747
2750
  --business register/connect as WhatsApp Business (same as WA_BUSINESS=1)
2748
2751
  --all refresh-version: every session in the session directory
package/lib/Client.js CHANGED
@@ -1904,8 +1904,8 @@ class WhalibmobClient extends EventEmitter {
1904
1904
  // the bit means naming that moment back. A <clean> without it does not
1905
1905
  // acknowledge anything in particular, so the server keeps announcing the
1906
1906
  // same change on every connection from now on β€” which is what it did:
1907
- // the timestamp was on the wire and never read off it. whatsmeow's
1908
- // MarkNotDirty takes it as an argument for exactly this reason.
1907
+ // the timestamp was on the wire and never read off it. The reference
1908
+ // client's mark-not-dirty takes it as an argument for exactly this reason.
1909
1909
  dirtyTypes.push({
1910
1910
  type: String(attrs.type),
1911
1911
  timestamp: attrs.timestamp ? String(attrs.timestamp) : null
@@ -1940,8 +1940,8 @@ class WhalibmobClient extends EventEmitter {
1940
1940
  * The timestamp is half of that acknowledgement: it says *which* change is
1941
1941
  * being cleared. Every `<clean>` this sent went out without one, because the
1942
1942
  * attribute was never read off the `<dirty>` that carried it β€” so nothing was
1943
- * acknowledged in particular and the server kept announcing. whatsmeow's
1944
- * MarkNotDirty takes it as an argument for the same reason.
1943
+ * acknowledged in particular and the server kept announcing. The reference
1944
+ * client's mark-not-dirty takes it as an argument for the same reason.
1945
1945
  *
1946
1946
  * @param {string} type the dirty type, e.g. 'groups'
1947
1947
  * @param {number|string} [fromTs] the timestamp the announcement carried
@@ -2135,8 +2135,8 @@ class WhalibmobClient extends EventEmitter {
2135
2135
  * chat message to yourself.
2136
2136
  *
2137
2137
  * Asking twice for the same key inside a day achieves nothing, so each id is
2138
- * remembered and held down for that long. This is what whatsmeow does with
2139
- * `requestAppStateKeys`, and for the same reason.
2138
+ * remembered and held down for that long. This is what the reference client
2139
+ * does when it requests app-state keys, and for the same reason.
2140
2140
  *
2141
2141
  * @param {string[]} keyIds base64 (or hex) key ids, as the decoder reports
2142
2142
  * @returns {Promise<string|null>} the id of the message that carried it
@@ -2910,9 +2910,9 @@ class WhalibmobClient extends EventEmitter {
2910
2910
  // ever holds one. A primary (an SMS session) has no salt on file and sends no
2911
2911
  // cstoken, which is what the real primary does until it has minted its own.
2912
2912
  //
2913
- // This mirrors whatsmeow's generateCsToken line for line: a regular user, not
2914
- // the PSA account and not a bot; the recipient resolved to a LID; the HMAC
2915
- // taken over that LID's bare `user@lid` string.
2913
+ // This mirrors the reference client's cstoken generation line for line: a
2914
+ // regular user, not the PSA account and not a bot; the recipient resolved to
2915
+ // a LID; the HMAC taken over that LID's bare `user@lid` string.
2916
2916
 
2917
2917
  /** The stored NCT salt as bytes, or null when this session has none. */
2918
2918
  _nctSalt() {
@@ -2927,7 +2927,8 @@ class WhalibmobClient extends EventEmitter {
2927
2927
  *
2928
2928
  * A JID already on the LID server is used as-is; a phone JID is resolved
2929
2929
  * through the same PNβ†’LID map every send uses. Device and agent parts are
2930
- * dropped β€” the token is taken over the non-AD address, as whatsmeow does.
2930
+ * dropped β€” the token is taken over the non-AD address, as the reference
2931
+ * client does.
2931
2932
  */
2932
2933
  _bareLidFor(jid) {
2933
2934
  if (!jid) return null;
@@ -4077,7 +4078,7 @@ class WhalibmobClient extends EventEmitter {
4077
4078
  * someone linking a laptop and a tablet in the same sitting produced two
4078
4079
  * children, two hashes, and the whole thing was thrown away β€” cache dropped,
4079
4080
  * full usync round-trip on the next send. Steps are now kept separately and
4080
- * applied one at a time, the way whatsmeow's handleDeviceNotification does.
4081
+ * applied one at a time.
4081
4082
  *
4082
4083
  * Children are `add`, `remove`, or `update`. `update` does not name what it
4083
4084
  * changed, so it survives as a step that tells the applier to drop the cache
@@ -4357,7 +4358,7 @@ class WhalibmobClient extends EventEmitter {
4357
4358
 
4358
4359
  // The acknowledgement a server push gets, whatever tag it came in on.
4359
4360
  //
4360
- // Mirrors the one whatsmeow sends: the stanza's own tag as the class, its id,
4361
+ // Mirrors the one the reference client sends: the stanza's own tag as the class, its id,
4361
4362
  // and back to whoever sent it, carrying `participant` and `recipient` through
4362
4363
  // when the stanza named them. `type` rides along for everything but a message,
4363
4364
  // where it means something else entirely.
@@ -6335,7 +6336,7 @@ class WhalibmobClient extends EventEmitter {
6335
6336
  * directPath, its own mediaKey, its own digests β€” carried beside the text
6336
6337
  * rather than inside it, and encrypted under a key name of its own. So
6337
6338
  * `downloadMedia` cannot fetch it: that reads the message's own media, and a
6338
- * text message has none. This is whatsmeow's DownloadThumbnail.
6339
+ * text message has none. This is the reference client's thumbnail download.
6339
6340
  *
6340
6341
  * The small inline preview is a different thing and needs no download: it is
6341
6342
  * already on the decoded message as `jpegThumbnail`.
@@ -7391,7 +7392,7 @@ class WhalibmobClient extends EventEmitter {
7391
7392
  *
7392
7393
  * Both JIDs are taken without their device: a vote belongs to an account.
7393
7394
  *
7394
- * This is whatsmeow's DecryptPollVote. Nothing here could read a vote before:
7395
+ * This is the reference client's poll-vote decryption. Nothing here could read a vote before:
7395
7396
  * `sendPoll` handed back the key and left the rest to the caller.
7396
7397
  *
7397
7398
  * @param {object} vote the `message` event payload, or its `decoded`
@@ -1211,14 +1211,12 @@ class DeviceManager {
1211
1211
  * notification as a whole. A contact linking two devices in one sitting sends
1212
1212
  * two children with two different hashes, and reading them as one change with
1213
1213
  * one hash β€” which is what this did β€” meant the notification could never
1214
- * verify and the cache was dropped every time. Stepping through them the way
1215
- * whatsmeow's handleDeviceNotification does keeps the cache across exactly
1216
- * the case that used to defeat it.
1214
+ * verify and the cache was dropped every time. Stepping through them one at a
1215
+ * time keeps the cache across exactly the case that used to defeat it.
1217
1216
  *
1218
1217
  * A step that fails to verify drops the cache but not the running list, so a
1219
- * later step whose hash does match puts a proven list back β€” the same
1220
- * recovery whatsmeow gets from mutating its local copy after deleting the
1221
- * cached one.
1218
+ * later step whose hash does match puts a proven list back β€” the recovery
1219
+ * that comes from mutating the local copy after deleting the cached one.
1222
1220
  *
1223
1221
  * @param {object} opts
1224
1222
  * @param {string} opts.priKey the cache entry: digits, or 'lid:<user>'
@@ -1259,7 +1257,7 @@ class DeviceManager {
1259
1257
 
1260
1258
  // `update` does not say what changed. The list on file cannot be trusted
1261
1259
  // and cannot be repaired, so it goes β€” and the remaining steps still get
1262
- // their turn, as they do in whatsmeow.
1260
+ // their turn.
1263
1261
  if (step.tag === 'update') {
1264
1262
  this._dcDel([priKey]);
1265
1263
  out.primaryOk = false;
@@ -266,8 +266,8 @@ function _digestMismatch(actual, expected, what) {
266
266
  * The MAC is the guarantee β€” its key comes from the mediaKey, which only the
267
267
  * sender and the recipients hold β€” and it was always checked. The two digests
268
268
  * were not: fileEncSha256 only when the caller asked for it, and fileSha256
269
- * never at all, though it was written on every upload. whatsmeow checks both on
270
- * every download (ErrInvalidMediaSHA256), and now so does this.
269
+ * never at all, though it was written on every upload. Both are meant to be
270
+ * checked on every download, and now so does this.
271
271
  *
272
272
  * They tell failures apart, too. A truncated or substituted download is caught
273
273
  * before any work is spent decrypting it, and a plaintext that decrypts but is
package/lib/PushClient.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use strict';
2
-
2
+ //push here
3
3
  // ─── Push clients ─────────────────────────────────────────────────────────────
4
4
  //
5
5
  // Every real WhatsApp install can be woken by the server, and which line it is
@@ -1,5 +1,5 @@
1
1
  'use strict';
2
-
2
+ //registration tool
3
3
  const crypto = require('crypto');
4
4
  const https = require('https');
5
5
  const tls = require('tls');
@@ -1838,13 +1838,50 @@ function flashCodeLength() {
1838
1838
  return raw > 0 ? raw : FLASH_CODE_LENGTH;
1839
1839
  }
1840
1840
 
1841
- function flashCodeFromCallerId(input, len) {
1841
+ // The server's own rule for pulling the code out of the number that rang.
1842
+ //
1843
+ // The /code reply for a flash call carries cli_filter β€” a regex such as
1844
+ // "(.*)373(.*)" β€” alongside cli_prefix and the code length. The code is the
1845
+ // part the filter isolates after the prefix: for a caller id "393739799312"
1846
+ // the filter's trailing group is "9799312", and the code is its last `length`
1847
+ // digits. Applying this is the whole fix for a flash "mismatch" on a correctly
1848
+ // read number β€” the national part of an Italian +39 373 XXXXXXX caller id has
1849
+ // more digits after the prefix than the six-digit code, so the old assumption
1850
+ // that the code was simply the last six digits took the wrong slice.
1851
+ //
1852
+ // Returns null when there is no filter, it does not compile, or it does not
1853
+ // match, so the caller can fall back to the plain last-`length` behaviour.
1854
+ function applyFlashFilter(digits, filter) {
1855
+ if (!filter) return null;
1856
+ let re;
1857
+ try { re = new RegExp(String(filter)); } catch (_) { return null; }
1858
+ const m = re.exec(digits);
1859
+ if (!m) return null;
1860
+ // The code follows the prefix, so it is the last capture group that has any
1861
+ // digits in it; earlier groups hold the country code and prefix.
1862
+ for (let i = m.length - 1; i >= 1; i--) {
1863
+ const g = m[i] && m[i].replace(/\D/g, '');
1864
+ if (g) return g;
1865
+ }
1866
+ return null;
1867
+ }
1868
+
1869
+ // `opts` may be a bare length (the historical signature) or
1870
+ // { length, filter }. The filter, when it matches, decides which digits are the
1871
+ // code; the length then trims them. Without a filter this is the old behaviour:
1872
+ // the last `length` digits of whatever was typed.
1873
+ function flashCodeFromCallerId(input, opts) {
1842
1874
  const digits = normalizeCodeResult(input);
1843
- const want = len > 0 ? len : flashCodeLength();
1875
+ const o = (opts && typeof opts === 'object') ? opts : { length: opts };
1876
+ const want = Number(o.length) > 0 ? Number(o.length) : flashCodeLength();
1877
+
1878
+ const filtered = applyFlashFilter(digits, o.filter);
1879
+ const base = (filtered && filtered.length) ? filtered : digits;
1880
+
1844
1881
  // Shorter than the code means the caller already typed just the tail (or the
1845
1882
  // handset showed a short number); there is nothing to trim and guessing would
1846
1883
  // only corrupt it.
1847
- return digits.length > want ? digits.slice(-want) : digits;
1884
+ return base.length > want ? base.slice(-want) : base;
1848
1885
  }
1849
1886
 
1850
1887
  // The digits /register is given, for whichever method the pending code came by.
@@ -1859,9 +1896,20 @@ function codeForSubmission(store, code, opts) {
1859
1896
  const pending = String(
1860
1897
  (opts && opts.method) || (store && store.codeMethod) || ''
1861
1898
  ).toLowerCase();
1862
- return pending === 'flash'
1863
- ? flashCodeFromCallerId(code)
1864
- : normalizeCodeResult(code);
1899
+ if (pending !== 'flash') return normalizeCodeResult(code);
1900
+
1901
+ // Length: an explicit WA_FLASH_CODE_LEN / opts.flashCodeLen wins, else the
1902
+ // length the server named in its /code reply (captured as store.flashCodeLength),
1903
+ // else the six-digit default inside flashCodeFromCallerId.
1904
+ const envLen = parseInt(process.env.WA_FLASH_CODE_LEN, 10);
1905
+ const length = envLen > 0 ? envLen
1906
+ : (opts && Number(opts.flashCodeLen) > 0 ? Number(opts.flashCodeLen)
1907
+ : (store && Number(store.flashCodeLength) > 0 ? Number(store.flashCodeLength) : 0));
1908
+ // Filter: the server's cli_filter from the /code reply, isolating the code
1909
+ // after the prefix. opts.flashFilter lets a caller state it outright.
1910
+ const filter = (opts && opts.flashFilter) || (store && store.flashCliFilter) || null;
1911
+
1912
+ return flashCodeFromCallerId(code, { length, filter });
1865
1913
  }
1866
1914
 
1867
1915
  // Take the digits the server filed the account under. Brazilian mobiles are the
@@ -2214,6 +2262,27 @@ async function requestSmsCode(store, method, opts) {
2214
2262
  // The confirmation step is usually a separate command, so this is
2215
2263
  // written to the session rather than kept in memory.
2216
2264
  store.codeMethod = m;
2265
+
2266
+ // A flash /code reply states exactly how to read the code out of the
2267
+ // number that will ring: cli_filter is a regex isolating the code after
2268
+ // cli_prefix, and `length` is how many digits it is. Confirmation is
2269
+ // usually a separate command, so these are written to the session for
2270
+ // codeForSubmission to use rather than kept in memory. flash_timeout is
2271
+ // the window the call is valid for, carried so the CLI can warn.
2272
+ if (m === 'flash') {
2273
+ const srvLen = Number(result.length);
2274
+ store.flashCliFilter = result.cli_filter || null;
2275
+ store.flashCliPrefix = result.cli_prefix || null;
2276
+ store.flashCliCc = result.cli_cc || null;
2277
+ store.flashCodeLength = srvLen > 0 ? srvLen : null;
2278
+ store.flashTimeout = Number(result.flash_timeout) > 0 ? Number(result.flash_timeout) : null;
2279
+ _whaDbg('[DBG] REG ← /code flash cli: cc=' + (result.cli_cc || '?')
2280
+ + ' prefix=' + (result.cli_prefix || '?')
2281
+ + ' filter=' + (result.cli_filter || '?')
2282
+ + ' length=' + (srvLen > 0 ? srvLen : '?')
2283
+ + ' timeout=' + (result.flash_timeout || '?') + 's');
2284
+ }
2285
+
2217
2286
  await sendFunnelLog(store, waVersion, verifyScreen, 'request_code', 'request_code_success');
2218
2287
  return result;
2219
2288
  }
@@ -2426,7 +2495,7 @@ module.exports._token = { computeToken, androidMaterialPath, registrationHeaders
2426
2495
  module.exports._verify = {
2427
2496
  hasChallenge, is2FARequired, decodeOrNull, isSuccessful,
2428
2497
  normalizeCodeResult, currentVerifyScreen, adoptCanonicalNumber, funnelEnabled, waitHint,
2429
- flashCodeFromCallerId, flashCodeLength, codeForSubmission,
2498
+ flashCodeFromCallerId, flashCodeLength, applyFlashFilter, codeForSubmission,
2430
2499
  getRequestVerificationCodeParameters
2431
2500
  };
2432
2501
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  // What an outgoing WAM buffer is assembled from.
4
4
  //
5
- // Identical to Baileys' BinaryInfo: a protocol version, a sequence number that
6
- // the server uses to order buffers, the events queued for the next flush, and
7
- // the scratch list the encoder fills with byte chunks.
5
+ // A protocol version, a sequence number that the server uses to order buffers,
6
+ // the events queued for the next flush, and the scratch list the encoder fills
7
+ // with byte chunks.
8
8
 
9
9
  class BinaryInfo {
10
10
  constructor(options = {}) {
@@ -2,10 +2,10 @@
2
2
 
3
3
  // The WAM event and global tables, exactly as the reference client defines them.
4
4
  //
5
- // Ported verbatim from Baileys' WAM/constants.js β€” every event id, every field
6
- // id and every type, unchanged. This is a generated table scraped from
7
- // WhatsApp Web itself, not something to hand-edit: an id that drifts from what
8
- // the server expects makes the whole buffer unparseable on the other side.
5
+ // Every event id, every field id and every type is taken unchanged from
6
+ // WhatsApp Web itself β€” a generated table scraped from the client, not
7
+ // something to hand-edit: an id that drifts from what the server expects makes
8
+ // the whole buffer unparseable on the other side.
9
9
  //
10
10
  // WEB_EVENTS one entry per event: { name, id, props: { field: [id, type] },
11
11
  // wamChannel, weight }
package/lib/WAM/encode.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // The WAM binary encoder, ported line for line from Baileys' WAM/encode.js.
3
+ // The WAM binary encoder.
4
4
  //
5
5
  // A buffer is a 'WAM' magic header, then a run of length-prefixed values whose
6
6
  // flags say whether each one is a global attribute, an event, or a field of the
@@ -1,5 +1,5 @@
1
1
  // Aurora-style device profile posted to the anonymous token dispenser.
2
- // Copied verbatim from Cobalt's sdk-gphone64-x86_64.json β€” the dispenser
2
+ // Describes an emulator-class device (sdk-gphone64-x86_64) β€” the dispenser
3
3
  // mints an account shaped for this device, and the Play catalogue decides
4
4
  // what it is allowed to download from it.
5
5
 
@@ -360,8 +360,7 @@ function encodeMessage(type, payload) {
360
360
  // message is buried inside a DeviceSentMessage the copy inside it is a level
361
361
  // too deep for anything that does not know to go looking. A poll echoed to our
362
362
  // own devices reached them without a message secret, so none of them could ever
363
- // decrypt a vote on it. whatsmeow (`MessageContextInfo: message.MessageContextInfo`
364
- // in marshalMessage) and Baileys both duplicate it for the same reason.
363
+ // decrypt a vote on it. The reference clients duplicate it for the same reason.
365
364
  //
366
365
  // phash is left unset, as it is by every other implementation: it describes the
367
366
  // participant list, the server checks that against the hash on the stanza, and
@@ -770,7 +769,8 @@ function decodeMessageContainer(buf, depth) {
770
769
  // own JID and names nothing: the conversation it belongs to is only ever
771
770
  // written here, in the envelope. It was being opened and thrown away, so
772
771
  // a message sent from the phone arrived with no way to tell which chat
773
- // it was in. whatsmeow keeps the same two fields as Info.DeviceSentMeta.
772
+ // it was in. The reference client keeps the same two fields on its
773
+ // device-sent metadata.
774
774
  if (w.field === 31) {
775
775
  try {
776
776
  const env = _decodeFields(f[31]);
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "whalibmob",
3
- "version": "5.33.6",
3
+ "version": "5.33.8",
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",
7
7
  "types": "index.d.ts",
8
8
  "bin": {
9
- "wa": "cli.js"
9
+ "wa": "./cli.js"
10
10
  },
11
11
  "files": [
12
12
  "index.js",