whalibmob 5.9.0 → 5.9.2

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
@@ -1112,6 +1112,7 @@ connect()
1112
1112
  | `app_state_sync` | `{ collections, applied }` | An app-state sync finished; see [Reading Changes Made Elsewhere](#app-state-sync) |
1113
1113
  | `app_state_mutation` | `{ collection, index, action, removed }` | An app-state change this library does not model |
1114
1114
  | `app_state_key_missing` | `{ collection, keyId }` | App state cannot be read until your phone shares this key |
1115
+ | `app_state_keys` | `{ keys }` | Your phone shared app-state sync keys; a sync starts automatically |
1115
1116
 
1116
1117
  `remote: true` on a chat event means the change was made on your phone or another
1117
1118
  linked device rather than by this session. Your own calls carry `synced` instead,
package/cli.js CHANGED
@@ -600,6 +600,13 @@ function attachEvents(client) {
600
600
  _rl && (_rl.resume(), _rl.prompt(true));
601
601
  });
602
602
 
603
+ client.on('app_state_keys', (e) => {
604
+ _rl && _rl.pause();
605
+ out(' app state: received ' + e.keys.length + ' sync key(s) from your phone —' +
606
+ ' pins, archives, mutes and stars will sync from now on');
607
+ _rl && (_rl.resume(), _rl.prompt(true));
608
+ });
609
+
603
610
  client.on('decrypt_error', (e) => {
604
611
  _rl && _rl.pause();
605
612
  out(' DECRYPT_ERROR from ' + e.from + ' id ' + e.id + ' : ' + (e.err && e.err.message));
package/lib/Client.js CHANGED
@@ -51,8 +51,8 @@ const CALL_VIDEO_PREFIX = 'https://call.whatsapp.com/video/';
51
51
  const INVITE_LINK_PREFIX = 'https://chat.whatsapp.com/';
52
52
 
53
53
  // The names privacy settings actually go by on the wire, and the friendly
54
- // aliases this library has always accepted for them. whatsmeow's
55
- // PrivacySettingType constants are the right-hand column.
54
+ // aliases this library has always accepted for them. The wire names are the
55
+ // right-hand column.
56
56
  const PRIVACY_NAME_ALIASES = {
57
57
  last_seen: 'last', last: 'last',
58
58
  profile_picture: 'profile', profile_pic: 'profile', profile: 'profile',
@@ -80,8 +80,8 @@ const PRIVACY_WIRE_TO_KEY = {
80
80
  stickers: 'stickers'
81
81
  };
82
82
 
83
- // Reduce a JID to its bare user — whatsmeow's ToNonAD. Blocking, and anything
84
- // else that names an account rather than one of its devices, wants this form.
83
+ // Reduce a JID to its bare user. Blocking, and anything else that names an
84
+ // account rather than one of its devices, wants this form.
85
85
  function toNonAdJid(input) {
86
86
  const s = String(input || '');
87
87
  const at = s.indexOf('@');
@@ -246,14 +246,14 @@ class WhalibmobClient extends EventEmitter {
246
246
  this._tcTokenStore = null; // TcTokenStore — loaded in init()
247
247
  this._inFlightTcTokenIssuance = new Set(); // dedupe concurrent proactive issuePrivacyTokens per JID
248
248
  this._inFlight463Recoveries = new Set(); // dedupe concurrent 463-triggered token issuances per JID (separate from proactive)
249
- // Blue-tick every message as it arrives. Set to false for whatsmeow's model,
250
- // where read is only ever sent by an explicit markRead() call.
249
+ // Blue-tick every message as it arrives. Set to false to make read receipts
250
+ // explicit, sent only by a markRead() call.
251
251
  this.autoRead = opts.autoRead !== false;
252
252
  // Flipped by setOnline(). Delivery receipts sent while this is false carry
253
253
  // type="inactive", which the sender's app records but does not render.
254
254
  this._sendActiveReceipts = false;
255
- // Cached privacy settings, as whatsmeow caches them. Warmed after connect
256
- // and refreshed whenever the server reports a change; markRead reads it.
255
+ // Cached privacy settings. Warmed after connect and refreshed whenever the
256
+ // server reports a change; markRead reads it.
257
257
  this._privacySettings = null;
258
258
  if (opts.pino !== undefined) _whaConfigLogger(opts.pino);
259
259
  }
@@ -731,9 +731,9 @@ class WhalibmobClient extends EventEmitter {
731
731
  this._saveWebStore();
732
732
  _whaDbg('[DBG] COMPANION_FINISH adv_secret derived');
733
733
 
734
- // Baileys awaits this one rather than firing and forgetting, so a server
735
- // rejection surfaces as an error here instead of as a silent stall
736
- // waiting for a pair-success that is never coming.
734
+ // Awaited rather than fired and forgotten, so a server rejection surfaces
735
+ // as an error here instead of as a silent stall waiting for a
736
+ // pair-success that is never coming.
737
737
  const finishResult = await this._sendIq(new BinaryNode('iq', {
738
738
  to: 's.whatsapp.net',
739
739
  type: 'set',
@@ -1810,10 +1810,9 @@ class WhalibmobClient extends EventEmitter {
1810
1810
  // Companion pairing — these arrive unsolicited, so they are checked before
1811
1811
  // the pending-IQ table rather than after it.
1812
1812
  //
1813
- // pair-device is matched on type=set; pair-success is matched on any type,
1814
- // the way Baileys distinguishes them ('CB:iq,type:set,pair-device' against
1815
- // a bare 'CB:iq,,pair-success'). Requiring type=set on pair-success would
1816
- // drop the stanza that completes the link.
1813
+ // pair-device is matched on type=set; pair-success is matched on any type.
1814
+ // Requiring type=set on pair-success would drop the stanza that completes
1815
+ // the link.
1817
1816
  if (this._mode === 'web') {
1818
1817
  if (type === 'set' && findChild(node, 'pair-device')) { this._handlePairDevice(node); return; }
1819
1818
  if (findChild(node, 'pair-success')) { this._handlePairSuccess(node); return; }
@@ -1984,13 +1983,13 @@ class WhalibmobClient extends EventEmitter {
1984
1983
  if (decoded.type === 'protocol') {
1985
1984
  _whaDbg('[DBG] PROTO subtype=' + decoded.subtype + ' id=' + id);
1986
1985
 
1987
- // ── HISTORY_SYNC_NOTIFICATION ─────────────────────────────────────
1988
- if (decoded.subtype === 'history_sync' && decoded.historySyncNotification) {
1986
+ // Keyed off what the message actually carried rather than off the
1987
+ // type that announced it. A payload that is present is the payload,
1988
+ // whatever the type number turns out to mean.
1989
+ if (decoded.historySyncNotification) {
1989
1990
  this._handleHistorySync(decoded.historySyncNotification, id);
1990
1991
  }
1991
-
1992
- // ── APP_STATE_SYNC_KEY_SHARE ──────────────────────────────────────
1993
- if (decoded.subtype === 'app_state_sync_key_share' && decoded.appStateSyncKeyShare) {
1992
+ if (decoded.appStateSyncKeyShare) {
1994
1993
  this._handleAppStateSyncKeyShare(decoded.appStateSyncKeyShare);
1995
1994
  }
1996
1995
 
@@ -2001,8 +2000,8 @@ class WhalibmobClient extends EventEmitter {
2001
2000
  this._sendReadReceipt(id, fromRaw, partRaw);
2002
2001
 
2003
2002
  // ── pkmsg = peer opened a new Signal session (identity/device change) ──
2004
- // Re-issue our tcToken to them so the fresh session carries a valid token.
2005
- // Mirrors Baileys' reissueTcTokenAfterIdentityChange (messages-recv.js).
2003
+ // Re-issue our tcToken to them so the fresh session carries a valid
2004
+ // token.
2006
2005
  if (encType === 'pkmsg' && this._tcTokenStore) {
2007
2006
  this._reissueTcTokenAfterIdentityChange(sigJid);
2008
2007
  }
@@ -2025,10 +2024,10 @@ class WhalibmobClient extends EventEmitter {
2025
2024
  const decoded = this._decodeMsg(plaintext);
2026
2025
  if (decoded.type === 'senderKeyDistribution') return;
2027
2026
  if (decoded.type === 'protocol') {
2028
- if (decoded.subtype === 'history_sync' && decoded.historySyncNotification) {
2027
+ if (decoded.historySyncNotification) {
2029
2028
  this._handleHistorySync(decoded.historySyncNotification, id);
2030
2029
  }
2031
- if (decoded.subtype === 'app_state_sync_key_share' && decoded.appStateSyncKeyShare) {
2030
+ if (decoded.appStateSyncKeyShare) {
2032
2031
  this._handleAppStateSyncKeyShare(decoded.appStateSyncKeyShare);
2033
2032
  }
2034
2033
  return;
@@ -2250,10 +2249,10 @@ class WhalibmobClient extends EventEmitter {
2250
2249
  }
2251
2250
 
2252
2251
  // A read receipt only tells the sender we read it when read receipts are on.
2253
- // whatsmeow's MarkRead checks the same setting and downgrades "read" to
2254
- // "read-self", which marks the message read across our own devices without
2255
- // reporting it to the other side. Nothing here looked at the setting, so a
2256
- // user who had turned read receipts off still sent blue ticks.
2252
+ // With them off, "read" is downgraded to "read-self", which marks the message
2253
+ // read across our own devices without reporting it to the other side. Nothing
2254
+ // here looked at the setting, so a user who had turned read receipts off
2255
+ // still sent blue ticks.
2257
2256
  _readReceiptType(base) {
2258
2257
  const settings = this._privacySettings;
2259
2258
  if (settings && settings.readReceipts === 'none' && base === 'read') {
@@ -2264,9 +2263,8 @@ class WhalibmobClient extends EventEmitter {
2264
2263
 
2265
2264
  // The key a privacy token is stored and looked up under.
2266
2265
  //
2267
- // Both references resolve it to the contact's LID and fall back to the plain
2268
- // JID only when no LID is known — whatsmeow's resolveTCTokenStorageLID and
2269
- // Baileys' resolveTcTokenJid are the same three lines:
2266
+ // It resolves to the contact's LID, falling back to the plain JID only when
2267
+ // no LID is known:
2270
2268
  //
2271
2269
  // if (isLidUser(jid)) return jid
2272
2270
  // const lid = await getLIDForPN(jid)
@@ -2289,9 +2287,9 @@ class WhalibmobClient extends EventEmitter {
2289
2287
  // The in-memory map starts empty and is filled by usync and by incoming
2290
2288
  // messages, so a send early in a process — or one that hits a warm device
2291
2289
  // cache and never runs usync — could find nothing and fall back to the
2292
- // phone JID. The mapping is on disk in the Signal store either way, which
2293
- // is the same place whatsmeow reads it from, so consult that before giving
2294
- // up. The consequence of not doing so is not cosmetic: the lookup lands on
2290
+ // phone JID. The mapping is on disk in the Signal store either way, so
2291
+ // consult that before giving up. The consequence of not doing so is not
2292
+ // cosmetic: the lookup lands on
2295
2293
  // a key with no token while a live one sits under the LID, and the message
2296
2294
  // goes out without one.
2297
2295
  if (!lidUser) {
@@ -2325,9 +2323,8 @@ class WhalibmobClient extends EventEmitter {
2325
2323
  //
2326
2324
  // Storage is always the LID. Issuance follows AB prop 14303
2327
2325
  // (lid_trusted_token_issue_to_lid), whose WA Web default is off — so the IQ
2328
- // names the phone JID. Baileys implements exactly this in resolveIssuanceJid
2329
- // and defaults the prop to false; whatsmeow issues to the LID instead. We
2330
- // follow WA Web, and more importantly we now follow it in one place: the
2326
+ // names the phone JID. We follow WA Web, and more importantly we now follow
2327
+ // it in one place: the
2331
2328
  // send path, the 463 recovery and the post-identity-change re-issue used to
2332
2329
  // each pick a different address family for the same contact.
2333
2330
  _resolveTcTokenIssuanceJid(jid) {
@@ -2340,9 +2337,9 @@ class WhalibmobClient extends EventEmitter {
2340
2337
 
2341
2338
  // The one way to read a token that is safe to put on the wire.
2342
2339
  //
2343
- // whatsmeow funnels every attach site through ensureTCToken, which returns
2344
- // nothing for an expired token. whalibmob had the expiry check on the message
2345
- // path only; presence subscribe, group create, participant add and the
2340
+ // Every attach site goes through here, and an expired token returns nothing.
2341
+ // The expiry check used to be on the message path only; presence subscribe,
2342
+ // group create, participant add and the
2346
2343
  // profile-picture query each tested `token.length` and nothing else, so once
2347
2344
  // a token aged past the 28-day window those four kept sending it. Same rule
2348
2345
  // everywhere now, and the dead token gets cleared on the way out.
@@ -2373,10 +2370,10 @@ class WhalibmobClient extends EventEmitter {
2373
2370
  // Delivery receipt — the sender's two grey ticks.
2374
2371
  //
2375
2372
  // Distinct from the <ack> above: the ack tells the server we took the stanza,
2376
- // the receipt tells the sender it reached a device. whatsmeow sends both for
2377
- // every incoming message (sendAck + sendMessageReceipt) and leaves the blue
2378
- // ticks to an explicit MarkRead. whalibmob only ever sent the ack and then
2379
- // jumped straight to type="read", so a sender never saw the grey stage.
2373
+ // the receipt tells the sender it reached a device. Both go out for every
2374
+ // incoming message, with the blue ticks left to markRead. Only the ack used
2375
+ // to be sent, jumping straight to type="read", so a sender never saw the grey
2376
+ // stage.
2380
2377
  //
2381
2378
  // A client that has not marked itself available sends this with
2382
2379
  // type="inactive": the sender's app records the delivery but does not render
@@ -2399,7 +2396,7 @@ class WhalibmobClient extends EventEmitter {
2399
2396
  //
2400
2397
  // Sent automatically after a message decodes unless autoRead is turned off, in
2401
2398
  // which case marking a chat read is up to the caller via markRead(). Turning
2402
- // it off gives whatsmeow's model, where read is always explicit.
2399
+ // it off makes read receipts always explicit.
2403
2400
  // fromJid / partJid are raw JID objects (AD_JID encoding for correct routing).
2404
2401
  _sendReadReceipt(msgId, fromJid, partJid) {
2405
2402
  if (!this._socket || !this._connected) return;
@@ -2543,8 +2540,8 @@ class WhalibmobClient extends EventEmitter {
2543
2540
  }
2544
2541
 
2545
2542
  // <blocklist action="..." dhash="..." prev_dhash="..."><item jid=... action=.../></blocklist>
2546
- // Mirrors whatsmeow's handleBlocklist: the action on the node describes the
2547
- // whole change, each child names one JID and what happened to it.
2543
+ // The action on the node describes the whole change; each child names one JID
2544
+ // and what happened to it.
2548
2545
  _handleBlocklistNotification(node) {
2549
2546
  const attrs = node.attrs || {};
2550
2547
  const changes = [];
@@ -2587,9 +2584,9 @@ class WhalibmobClient extends EventEmitter {
2587
2584
  // blocked only ever changed when it did the blocking itself.
2588
2585
  const blocklistNode = findChildDeep(node, 'blocklist');
2589
2586
  if (blocklistNode) this._handleBlocklistNotification(blocklistNode);
2590
- // ...and privacy setting changes, which arrive the same way. whatsmeow
2591
- // re-reads the settings on this and raises an event; nothing was watching
2592
- // the node, so a change made on the phone never reached the cache.
2587
+ // ...and privacy setting changes, which arrive the same way. The settings
2588
+ // are re-read on this and an event raised; nothing was watching the node,
2589
+ // so a change made on the phone never reached the cache.
2593
2590
  const privacyNode = findChildDeep(node, 'privacy');
2594
2591
  if (privacyNode) this._handlePrivacySettingsNotification(privacyNode);
2595
2592
  }
@@ -2847,9 +2844,9 @@ class WhalibmobClient extends EventEmitter {
2847
2844
  return;
2848
2845
  }
2849
2846
 
2850
- // Not every failure kills the session. whatsmeow's IsLoggedOut() marks the
2851
- // ones that do — 401, 403, 405, 406, 409 — and treats the rest as worth
2852
- // another attempt. A 500 or a 503 is the server having a bad minute; giving
2847
+ // Not every failure kills the session. These five do — 401, 403, 405, 406,
2848
+ // 409 — and the rest are worth another attempt. A 500 or a 503 is the
2849
+ // server having a bad minute; giving
2853
2850
  // up on the session for that would be throwing away a working registration.
2854
2851
  const LOGGED_OUT = ['401', '403', '405', '406', '409'];
2855
2852
  const spent = LOGGED_OUT.includes(reason);
@@ -3289,8 +3286,6 @@ class WhalibmobClient extends EventEmitter {
3289
3286
  * Send a `<iq type='set' xmlns='privacy'>` to issue a trusted-contact token
3290
3287
  * for `jid`. Returns the raw result node (or null on timeout).
3291
3288
  *
3292
- * Mirrors Baileys' `issuePrivacyTokens` in messages-send.js.
3293
- *
3294
3289
  * @param {string} jid - Bare or full JID of the conversation partner
3295
3290
  * @param {number} timestamp - Unix seconds to use as the token timestamp
3296
3291
  */
@@ -3378,13 +3373,12 @@ class WhalibmobClient extends EventEmitter {
3378
3373
  : (typeof tokenNode.content === 'string' && tokenNode.content.length > 0)
3379
3374
  ? Buffer.from(tokenNode.content, 'base64')
3380
3375
  : null;
3381
- // Baileys tc-token-utils.js line 137-138:
3382
- // "In notifications tokenNode.attrs.jid is your own device JID, not the sender's"
3383
- // → always prefer fallbackJid; only fall back to a.jid when fallbackJid is absent
3376
+ // In a notification, tokenNode.attrs.jid is our own device JID rather
3377
+ // than the sender's, so fallbackJid wins whenever it is present.
3384
3378
  const jid = fallbackJid || String(a.jid);
3385
3379
  const t = a.t ? parseInt(String(a.t), 10) : issueTs;
3386
- // Baileys drops anything that is not a regular user here — the guard
3387
- // is against a malformed or spoofed notification filing a token under
3380
+ // Anything that is not a regular user is dropped here, guarding
3381
+ // against a malformed or spoofed notification filing a token under
3388
3382
  // the PSA account or a bot.
3389
3383
  if (!isRegularTcTokenUser(jid)) {
3390
3384
  _whaDbg('[DBG] STORE_TCTOKEN skipped non-user jid=' + jid);
@@ -3407,8 +3401,8 @@ class WhalibmobClient extends EventEmitter {
3407
3401
  }
3408
3402
  }
3409
3403
 
3410
- // ── CRITICAL: Baileys ALWAYS persists senderTimestamp after issuing, ─────
3411
- // ── regardless of whether server returned token bytes. ─────
3404
+ // ── CRITICAL: senderTimestamp is ALWAYS persisted after issuing, ─────
3405
+ // ── regardless of whether the server returned token bytes. ─────
3412
3406
  // ── Without this, shouldSendNewTcToken() returns true every send and ─────
3413
3407
  // ── we flood the server with privacy IQs. ─────
3414
3408
  // ── For incoming privacy_token notifications saveSenderTs=false so ─────
@@ -3427,14 +3421,14 @@ class WhalibmobClient extends EventEmitter {
3427
3421
  /**
3428
3422
  * Handle a server-pushed `<notification type='privacy_token'>`.
3429
3423
  *
3430
- * Wire format (mirrors Baileys' handlePrivacyTokenNotification):
3424
+ * Wire format:
3431
3425
  * <notification type='privacy_token' from='...' [sender_lid='...@lid']>
3432
3426
  * <tokens>
3433
3427
  * <token type='trusted_contact' jid='...' t='...'>…bytes…</token>
3434
3428
  * </tokens>
3435
3429
  * </notification>
3436
3430
  *
3437
- * Key rules (from Baileys messages-recv.js lines 996-1015):
3431
+ * Key rules:
3438
3432
  * 1. Must find <tokens> wrapper inside notification; abort if absent.
3439
3433
  * 2. storage key = sender_lid (if present and @lid) else PN→LID lookup else from-JID.
3440
3434
  * 3. senderTimestamp is NOT updated here — only the peer-token bytes + timestamp.
@@ -3449,7 +3443,7 @@ class WhalibmobClient extends EventEmitter {
3449
3443
  _whaDbg('[DBG] PRIVACY_TOKEN_NOTIF_ENTER from=' + String(attrs.from || '') +
3450
3444
  ' sender_lid=' + String(attrs.sender_lid || ''));
3451
3445
 
3452
- // ── 1. Require <tokens> wrapper (matches Baileys' getBinaryNodeChild check) ──
3446
+ // ── 1. Require the <tokens> wrapper ────────────────────────────────────────
3453
3447
  const content = Array.isArray(node.content) ? node.content : [];
3454
3448
  const tokensNode = content.find(n => n && n.description === 'tokens');
3455
3449
  if (!tokensNode) {
@@ -3458,7 +3452,7 @@ class WhalibmobClient extends EventEmitter {
3458
3452
  }
3459
3453
 
3460
3454
  // ── 2. Resolve storage JID ─────────────────────────────────────────────────
3461
- // Priority (mirrors Baileys lines 1001-1006):
3455
+ // Priority:
3462
3456
  // 1. sender_lid attr if it is a @lid JID
3463
3457
  // 2. from user is a known LID user (LID comes as @s.whatsapp.net in notification)
3464
3458
  // 3. from is a PN → look up LID in _pnToLid
@@ -3494,7 +3488,7 @@ class WhalibmobClient extends EventEmitter {
3494
3488
  * Called when we successfully decrypt a pkmsg — the peer opened a fresh Signal
3495
3489
  * session (reset or new device), so we re-issue a privacy token so they can
3496
3490
  * reach us. Only fires if we've previously issued a token (senderTimestamp
3497
- * present and not expired), mirroring Baileys' reissueTcTokenAfterIdentityChange.
3491
+ * present and not expired).
3498
3492
  *
3499
3493
  * @param {string} from - Signal-session JID (PN or LID JID of the sender)
3500
3494
  */
@@ -3516,8 +3510,8 @@ class WhalibmobClient extends EventEmitter {
3516
3510
  _whaDbg('[DBG] REISSUE_TC_TOKEN_AFTER_IDENTITY_CHANGE jid=' + tcJid +
3517
3511
  ' prevSenderTs=' + senderTs);
3518
3512
 
3519
- // Baileys re-issues with the *previous* senderTimestamp, not a fresh
3520
- // one, and stores the result without touching the dedupe state. That
3513
+ // The re-issue carries the *previous* senderTimestamp, not a fresh one,
3514
+ // and the result is stored without touching the dedupe state. That
3521
3515
  // matters: this is a repair of an existing grant after the peer's
3522
3516
  // device changed, not a new grant, so it must not move the 7-day
3523
3517
  // bucket that governs regular issuance. We were stamping it with
@@ -3614,7 +3608,7 @@ class WhalibmobClient extends EventEmitter {
3614
3608
  * - Skips expired tokens (no point loading a token we'd immediately discard).
3615
3609
  * - Storage key follows TcTokenStore convention: normalized bare JID.
3616
3610
  * For LID chats (jid ends in @lid) we use the lid JID directly.
3617
- * For PN chats we try to look up the LID first (Baileys always stores under LID).
3611
+ * For PN chats we try to look up the LID first, since storage is by LID.
3618
3612
  *
3619
3613
  * @param {object|null} merged - Return value of mergeHistoryToStore()
3620
3614
  */
@@ -3642,7 +3636,7 @@ class WhalibmobClient extends EventEmitter {
3642
3636
  continue;
3643
3637
  }
3644
3638
 
3645
- // Resolve storage JID: Baileys always stores under LID.
3639
+ // Resolve storage JID — storage is always by LID.
3646
3640
  // If this chat is a @lid jid, use it directly.
3647
3641
  // If it's a PN jid, try to find its LID counterpart.
3648
3642
  let storageJid;
@@ -3700,6 +3694,15 @@ class WhalibmobClient extends EventEmitter {
3700
3694
  }
3701
3695
 
3702
3696
  this.emit('app_state_keys', { keys: keyShare.keys });
3697
+
3698
+ // The key is what app state was waiting on. Anything the server has been
3699
+ // holding for us can be read now, so go and get it rather than sitting on
3700
+ // it until the next dirty bit happens along.
3701
+ if (this._connected && this._appState) {
3702
+ this.syncAppState().catch(err => {
3703
+ _whaDbg('[DBG] APP_STATE sync after key share failed: ' + (err && err.message));
3704
+ });
3705
+ }
3703
3706
  }
3704
3707
 
3705
3708
  /**
@@ -3792,9 +3795,9 @@ class WhalibmobClient extends EventEmitter {
3792
3795
  // required in a group; type may be 'read' (default) or 'played'
3793
3796
  // to mark a voice note as listened to.
3794
3797
  //
3795
- // Shaped the way whatsmeow's MarkRead builds it: the FIRST id on the receipt
3796
- // and the rest as <item> children of a <list> node. whalibmob used the last id
3797
- // and put the items straight into <receipt>, which is not a shape the server
3798
+ // The FIRST id goes on the receipt and the rest as <item> children of a
3799
+ // <list> node. The last id used to be used instead, with the items straight
3800
+ // inside <receipt>, which is not a shape the server
3798
3801
  // reads back — the extra ids were silently ignored, so only one message per
3799
3802
  // call was ever marked. The participant was missing entirely, so a group read
3800
3803
  // never told the server whose message had been read.
@@ -3881,8 +3884,8 @@ class WhalibmobClient extends EventEmitter {
3881
3884
 
3882
3885
  // Set global online/offline status.
3883
3886
  //
3884
- // whatsmeow refuses to send this without a push name (ErrNoPushName): the
3885
- // server takes the display name from this node, and sending it empty makes
3887
+ // This is refused without a push name: the server takes the display name from
3888
+ // this node, and sending it empty makes
3886
3889
  // every other user see "-" instead of a name. Going available also flips the
3887
3890
  // client into sending active delivery receipts — see _sendDeliveryReceipt.
3888
3891
  //
@@ -3905,9 +3908,9 @@ class WhalibmobClient extends EventEmitter {
3905
3908
  // Set typing/recording presence in a specific chat.
3906
3909
  // presence: 'composing' | 'paused' | 'recording'
3907
3910
  //
3908
- // whatsmeow's SendChatPresence puts both `from` (our own JID) and `to` on the
3909
- // chatstate node and expresses recording as composing with media="audio" —
3910
- // there is no separate recording state in the protocol. The `from` was missing
3911
+ // Both `from` (our own JID) and `to` go on the chatstate node, and recording
3912
+ // is expressed as composing with media="audio" — there is no separate
3913
+ // recording state in the protocol. The `from` was missing
3911
3914
  // here, and both JIDs were raw strings, which the server ignores for @lid
3912
3915
  // chats, so the indicator never showed for a LID-addressed contact.
3913
3916
  setChatPresence(chatJid, presence) {
@@ -3931,18 +3934,17 @@ class WhalibmobClient extends EventEmitter {
3931
3934
 
3932
3935
  // Subscribe to presence updates for contacts.
3933
3936
  //
3934
- // whatsmeow attaches the contact's privacy token when it has one; without it
3935
- // the server may decline to send their presence. It also notes that the server
3936
- // only forwards presence to clients that have marked themselves available, so
3937
- // call setOnline(true) first.
3937
+ // The contact's privacy token is attached when there is one; without it the
3938
+ // server may decline to send their presence. The server also only forwards
3939
+ // presence to clients that have marked themselves available, so call
3940
+ // setOnline(true) first.
3938
3941
  subscribeToPresence(jids) {
3939
3942
  if (!this._socket || !this._connected) return;
3940
3943
  const arr = Array.isArray(jids) ? jids : [jids];
3941
3944
  const { isRegularTcTokenUser } = require('./messages/TcTokenStore');
3942
3945
  for (const raw of arr) {
3943
3946
  const jid = makeJid(raw);
3944
- // Groups and newsletters have no privacy token; Baileys guards the same
3945
- // way before building the node.
3947
+ // Groups and newsletters have no privacy token.
3946
3948
  const token = isRegularTcTokenUser(jid) ? this._tcTokenFor(jid) : null;
3947
3949
  const children = token ? [new BinaryNode('tctoken', {}, token)] : null;
3948
3950
  this._socket.sendNode(new BinaryNode('presence', {
@@ -4049,8 +4051,8 @@ class WhalibmobClient extends EventEmitter {
4049
4051
  return (info && info.url) || null;
4050
4052
  }
4051
4053
 
4052
- // Full profile picture info, the way whatsmeow's GetProfilePictureInfo returns
4053
- // it: { id, url, type, directPath, hash }, or null when the user has no
4054
+ // Full profile picture info: { id, url, type, directPath, hash }, or null
4055
+ // when the user has no
4054
4056
  // picture or it has not changed since opts.existingId.
4055
4057
  //
4056
4058
  // opts: { preview, existingId, isCommunity }
@@ -4176,8 +4178,8 @@ class WhalibmobClient extends EventEmitter {
4176
4178
 
4177
4179
  // Parse the <list> a blocklist query or update comes back with.
4178
4180
  //
4179
- // whatsmeow's parseBlocklist walks every child and takes its jid, without
4180
- // caring what the tag is called, and keeps the dhash off the list itself.
4181
+ // Every child is walked and its jid taken, whatever the tag is called, with
4182
+ // the dhash kept off the list itself.
4181
4183
  // The JIDs are stringified here: the binary decoder hands them back as JID
4182
4184
  // objects, and while those print correctly they are not strings, so the array
4183
4185
  // this used to return failed any includes() or === against a JID string —
@@ -4310,9 +4312,9 @@ class WhalibmobClient extends EventEmitter {
4310
4312
  // 'none' | 'match_last_seen' | 'known' | 'on_standard' | 'off'
4311
4313
  // excluded: JIDs to exclude — see the note below
4312
4314
  //
4313
- // The names above are friendly aliases. What goes on the wire is what
4314
- // whatsmeow sends: last, profile, status, online, readreceipts, groupadd,
4315
- // calladd, messages, defense, stickers. Four of the six names this used to
4315
+ // The names above are friendly aliases. What goes on the wire is: last,
4316
+ // profile, status, online, readreceipts, groupadd, calladd, messages,
4317
+ // defense, stickers. Four of the six names this used to
4316
4318
  // put on the wire — last_seen, profile_picture, read_receipts, groups_add —
4317
4319
  // are not names the server knows, so those settings never changed and the
4318
4320
  // discarded reply meant it never said so either.
@@ -4323,8 +4325,8 @@ class WhalibmobClient extends EventEmitter {
4323
4325
  Object.keys(PRIVACY_NAME_ALIASES).join(', '));
4324
4326
  }
4325
4327
 
4326
- // Neither whatsmeow nor WhatsApp Web puts <user> children on this IQ; the
4327
- // exclusion list is maintained separately. Kept for callers that pass it,
4328
+ // WhatsApp Web does not put <user> children on this IQ; the exclusion list
4329
+ // is maintained separately. Kept for callers that pass it,
4328
4330
  // and only emitted when they do.
4329
4331
  const children = [];
4330
4332
  if (excluded && excluded.length > 0) {
@@ -4355,8 +4357,8 @@ class WhalibmobClient extends EventEmitter {
4355
4357
  (code ? ' (' + code + (text ? ' ' + text : '') + ')' : ''));
4356
4358
  }
4357
4359
 
4358
- // whatsmeow folds the change into its cached copy and hands the whole thing
4359
- // back rather than making the caller re-query.
4360
+ // The change is folded into the cached copy and the whole thing handed back
4361
+ // rather than making the caller re-query.
4360
4362
  const key = PRIVACY_WIRE_TO_KEY[name];
4361
4363
  this._privacySettings = Object.assign({}, this._privacySettings || {},
4362
4364
  { [key]: String(value) });
@@ -4385,8 +4387,8 @@ class WhalibmobClient extends EventEmitter {
4385
4387
 
4386
4388
  // Who your Status posts go to.
4387
4389
  //
4388
- // Returns [{ type, isDefault, list }] with the default first, as whatsmeow's
4389
- // GetStatusPrivacy does. type is 'contacts', 'blacklist' or 'whitelist'; list
4390
+ // Returns [{ type, isDefault, list }] with the default first. type is
4391
+ // 'contacts', 'blacklist' or 'whitelist'; list
4390
4392
  // holds the JIDs the last two are built from. A server that has never been
4391
4393
  // told otherwise answers nothing, which means the default: all contacts.
4392
4394
  async queryStatusPrivacy() {
@@ -4427,8 +4429,8 @@ class WhalibmobClient extends EventEmitter {
4427
4429
  }
4428
4430
 
4429
4431
  // Resolve the status privacy settings into the JIDs a post actually goes to,
4430
- // the way whatsmeow's getStatusBroadcastRecipients does: a whitelist is the
4431
- // list itself, anything else is every known contact minus the blacklist, and
4432
+ // a whitelist is the list itself, anything else is every known contact minus
4433
+ // the blacklist, and
4432
4434
  // our own JID is added so the post lands on our own devices too.
4433
4435
  //
4434
4436
  // Contacts come from the synced history store — this client has no separate
@@ -4989,10 +4991,9 @@ class WhalibmobClient extends EventEmitter {
4989
4991
  // </iq>
4990
4992
  //
4991
4993
  // The item is addressed by LID, and a block carries the phone number beside
4992
- // it; an unblock carries only the LID. That is the shape Baileys'
4993
- // updateBlockStatus builds, and the one this server accepts — whatsmeow's
4994
- // UpdateBlocklist still sends the plain JID it was handed, which is what this
4995
- // used to do and what the server answered with 400 bad-request.
4994
+ // it; an unblock carries only the LID. That is the shape this server accepts
4995
+ // — sending the plain JID it was handed, which is what this used to do, got a
4996
+ // 400 bad-request back.
4996
4997
  //
4997
4998
  // Three other things were wrong with the pair this replaces. The jid went out
4998
4999
  // as a raw string rather than a binary JID. It was not reduced to its bare