@crysnovax/baileys 2.5.2 → 2.5.6

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.
@@ -1,31 +1,24 @@
1
1
  import NodeCache from '@cacheable/node-cache';
2
2
  import { Boom } from '@hapi/boom';
3
3
  import { proto } from '../../WAProto/index.js';
4
- import { DEFAULT_CACHE_TTLS, HISTORY_SYNC_PAUSED_TIMEOUT_MS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
4
+ import { DEFAULT_CACHE_TTLS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
5
5
  import { ALL_WA_PATCH_NAMES } from '../Types/index.js';
6
6
  import { SyncState } from '../Types/State.js';
7
- import { chatModificationToAppPatch, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, ensureLTHashStateVersion, extractSyncdPatches, generateProfilePicture, getHistoryMsg, isAppStateSyncIrrecoverable, isMissingKeyError, MAX_SYNC_ATTEMPTS, newLTHashState, processSyncAction } from '../Utils/index.js';
7
+ import { chatModificationToAppPatch, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, extractSyncdPatches, generateProfilePicture, getHistoryMsg, newLTHashState, processSyncAction } from '../Utils/index.js';
8
8
  import { makeMutex } from '../Utils/make-mutex.js';
9
9
  import processMessage from '../Utils/process-message.js';
10
10
  import { buildTcTokenFromJid } from '../Utils/tc-token-utils.js';
11
- import { getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isLidUser, isPnUser, jidDecode, jidNormalizedUser, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary/index.js';
11
+ import { getBinaryNodeChild, getBinaryNodeChildren, isLidUser, isPnUser, jidDecode, jidNormalizedUser, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary/index.js';
12
12
  import { USyncQuery, USyncUser } from '../WAUSync/index.js';
13
13
  import { makeSocket } from './socket.js';
14
+ const MAX_SYNC_ATTEMPTS = 2;
15
+ // Lia@Note 08-02-26 --- I know it's not efficient for RSS ಥ⁠‿⁠ಥ
16
+ const USER_ID_CACHE = new Map();
14
17
  export const makeChatsSocket = (config) => {
15
18
  const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, getMessage } = config;
16
19
  const sock = makeSocket(config);
17
20
  const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError, sendUnifiedSession, registerSocketEndHandler } = sock;
18
- const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
19
21
  let privacySettings;
20
- /** Server-assigned AB props for protocol behavior. */
21
- const serverProps = {
22
- /** AB prop 10518: gate tctoken on 1:1 messages. Default true (safe: avoids 463). */
23
- privacyTokenOn1to1: true,
24
- /** AB prop 9666: gate tctoken on profile picture IQs. WA Web default: true. */
25
- profilePicPrivacyToken: true,
26
- /** AB prop 14303: issue tctokens to LID instead of PN. WA Web default: false. */
27
- lidTrustedTokenIssueToLid: false
28
- };
29
22
  let syncState = SyncState.Connecting;
30
23
  /** this mutex ensures that messages are processed in order */
31
24
  const messageMutex = makeMutex();
@@ -37,20 +30,14 @@ export const makeChatsSocket = (config) => {
37
30
  const notificationMutex = makeMutex();
38
31
  // Timeout for AwaitingInitialSync state
39
32
  let awaitingSyncTimeout;
40
- // In-memory history sync completion tracking (resets on reconnection)
41
- const historySyncStatus = {
42
- initialBootstrapComplete: false,
43
- recentSyncComplete: false
44
- };
45
- let historySyncPausedTimeout;
46
- // Collections blocked on missing app state sync keys (mirrors WA Web's "Blocked" state).
47
- // When a key arrives via APP_STATE_SYNC_KEY_SHARE, these are re-synced.
48
- const blockedCollections = new Set();
49
33
  const placeholderResendCache = config.placeholderResendCache ||
50
34
  new NodeCache({
51
35
  stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
52
36
  useClones: false
53
37
  });
38
+ // if (!config.placeholderResendCache) {
39
+ // config.placeholderResendCache = placeholderResendCache;
40
+ // }
54
41
  /** helper function to fetch the given app state sync key */
55
42
  const getAppStateSyncKey = async (keyId) => {
56
43
  const { [keyId]: key } = await authState.keys.get('app-state-sync-key', [keyId]);
@@ -187,24 +174,37 @@ export const makeChatsSocket = (config) => {
187
174
  return result.list;
188
175
  }
189
176
  };
190
- // crysnovax@Note 06-02-26 --- Quick helper only. This function exists solely for faster lookup with caching.
177
+ // Lia@Note 06-02-26 --- Quick helper only. This function exists solely for faster lookup with caching.
191
178
  const findUserId = async (pnLid) => {
192
- const normalizedJid = jidNormalizedUser(pnLid);
193
- const userId = {
194
- lid: undefined,
195
- phoneNumber: undefined
196
- };
197
- if (isPnUser(normalizedJid) || isHostedPnUser(normalizedJid)) {
198
- userId.phoneNumber = normalizedJid;
199
- userId.lid = jidNormalizedUser((await signalRepository.lidMapping.getLIDsForPNs([normalizedJid]))?.[0]?.lid);
179
+ const cachedId = USER_ID_CACHE.get(pnLid);
180
+ if (cachedId) {
181
+ return cachedId;
182
+ }
183
+ const userId = {};
184
+ if (isPnUser(pnLid)) {
185
+ userId.phoneNumber = pnLid;
186
+ userId.lid = (await signalRepository.lidMapping.getLIDsForPNs([pnLid]))?.[0]?.lid;
187
+ if (!userId.lid) {
188
+ userId.lid = 'id-not-found';
189
+ return userId; // Lia@Note 06-02-26 --- Early return to skip caching for non-existent ID
190
+ }
200
191
  }
201
- else if (isLidUser(normalizedJid) || isHostedLidUser(normalizedJid)) {
202
- userId.lid = normalizedJid;
203
- userId.phoneNumber = jidNormalizedUser((await signalRepository.lidMapping.getPNsForLIDs([normalizedJid]))?.[0]?.pn);
192
+ else if (isLidUser(pnLid)) {
193
+ userId.lid = pnLid;
194
+ userId.phoneNumber = (await signalRepository.lidMapping.getPNsForLIDs([pnLid]))?.[0]?.pn;
195
+ if (!userId.phoneNumber) {
196
+ userId.phoneNumber = 'id-not-found';
197
+ return userId; // Lia@Note 06-02-26 --- Early return to skip caching for non-existent ID
198
+ }
204
199
  }
205
200
  else {
206
201
  throw new Boom('Invalid id input to find user ids', { statusCode: 400 });
207
202
  }
203
+ userId.phoneNumber = jidNormalizedUser(userId.phoneNumber);
204
+ userId.lid = jidNormalizedUser(userId.lid);
205
+ // Lia@Note 06-02-26 --- I know... it's dirty (⁠╯⁠︵⁠╰⁠,⁠)
206
+ USER_ID_CACHE.set(userId.phoneNumber, userId);
207
+ USER_ID_CACHE.set(userId.lid, userId);
208
208
  return userId;
209
209
  };
210
210
  /** update the profile picture for yourself or a group */
@@ -293,42 +293,6 @@ export const makeChatsSocket = (config) => {
293
293
  return getBinaryNodeChildren(listNode, 'item').map(n => n.attrs.jid);
294
294
  };
295
295
  const updateBlockStatus = async (jid, action) => {
296
- const normalizedJid = jidNormalizedUser(jid);
297
- let lid;
298
- let pn_jid;
299
- if (isLidUser(normalizedJid) || isHostedLidUser(normalizedJid)) {
300
- lid = normalizedJid;
301
- if (action === 'block') {
302
- const pn = (await findUserId(normalizedJid)).phoneNumber;
303
- if (!pn) {
304
- throw new Boom(`Unable to resolve PN JID for LID: ${jid}`, { statusCode: 400 });
305
- }
306
- pn_jid = jidNormalizedUser(pn);
307
- }
308
- }
309
- else if (isPnUser(normalizedJid) || isHostedPnUser(normalizedJid)) {
310
- const mapped = (await findUserId(normalizedJid)).lid;
311
- if (!mapped) {
312
- throw new Boom(`Unable to resolve LID for PN JID: ${jid}`, { statusCode: 400 });
313
- }
314
- lid = mapped;
315
- if (action === 'block') {
316
- pn_jid = jidNormalizedUser(normalizedJid);
317
- }
318
- }
319
- else {
320
- throw new Boom(`Invalid jid: ${jid}`, { statusCode: 400 });
321
- }
322
- const itemAttrs = {
323
- action,
324
- jid: lid
325
- };
326
- if (action === 'block') {
327
- if (!pn_jid) {
328
- throw new Boom(`pn_jid required for block: ${jid}`, { statusCode: 400 });
329
- }
330
- itemAttrs.pn_jid = pn_jid;
331
- }
332
296
  await query({
333
297
  tag: 'iq',
334
298
  attrs: {
@@ -339,7 +303,10 @@ export const makeChatsSocket = (config) => {
339
303
  content: [
340
304
  {
341
305
  tag: 'item',
342
- attrs: itemAttrs
306
+ attrs: {
307
+ action,
308
+ jid
309
+ }
343
310
  }
344
311
  ]
345
312
  });
@@ -438,9 +405,6 @@ export const makeChatsSocket = (config) => {
438
405
  const collectionsToHandle = new Set(collections);
439
406
  // in case something goes wrong -- ensure we don't enter a loop that cannot be exited from
440
407
  const attemptsMap = {};
441
- // collections that failed and need a full snapshot on retry
442
- // mirrors WA Web's ErrorFatal -> force snapshot behavior
443
- const forceSnapshotCollections = new Set();
444
408
  // keep executing till all collections are done
445
409
  // sometimes a single patch request will not return all the patches (God knows why)
446
410
  // so we fetch till they're all done (this is determined by the "has_more_patches" flag)
@@ -451,7 +415,6 @@ export const makeChatsSocket = (config) => {
451
415
  const result = await authState.keys.get('app-state-sync-version', [name]);
452
416
  let state = result[name];
453
417
  if (state) {
454
- state = ensureLTHashStateVersion(state);
455
418
  if (typeof initialVersionMap[name] === 'undefined') {
456
419
  initialVersionMap[name] = state.version;
457
420
  }
@@ -460,18 +423,14 @@ export const makeChatsSocket = (config) => {
460
423
  state = newLTHashState();
461
424
  }
462
425
  states[name] = state;
463
- const shouldForceSnapshot = forceSnapshotCollections.has(name);
464
- if (shouldForceSnapshot) {
465
- forceSnapshotCollections.delete(name);
466
- }
467
- logger.info(`resyncing ${name} from v${state.version}${shouldForceSnapshot ? ' (forcing snapshot)' : ''}`);
426
+ logger.info(`resyncing ${name} from v${state.version}`);
468
427
  nodes.push({
469
428
  tag: 'collection',
470
429
  attrs: {
471
430
  name,
472
431
  version: state.version.toString(),
473
- // return snapshot if syncing from scratch or forcing after a failed attempt
474
- return_snapshot: (shouldForceSnapshot || !state.version).toString()
432
+ // return snapshot if being synced from scratch
433
+ return_snapshot: (!state.version).toString()
475
434
  }
476
435
  });
477
436
  }
@@ -497,7 +456,7 @@ export const makeChatsSocket = (config) => {
497
456
  const { patches, hasMorePatches, snapshot } = decoded[name];
498
457
  try {
499
458
  if (snapshot) {
500
- const { state: newState, mutationMap } = await decodeSyncdSnapshot(name, snapshot, getCachedAppStateSyncKey, initialVersionMap[name], appStateMacVerification.snapshot, logger);
459
+ const { state: newState, mutationMap } = await decodeSyncdSnapshot(name, snapshot, getCachedAppStateSyncKey, initialVersionMap[name], appStateMacVerification.snapshot);
501
460
  states[name] = newState;
502
461
  Object.assign(globalMutationMap, mutationMap);
503
462
  logger.info(`restored state of ${name} from snapshot to v${newState.version} with mutations`);
@@ -520,37 +479,19 @@ export const makeChatsSocket = (config) => {
520
479
  }
521
480
  }
522
481
  catch (error) {
482
+ // if retry attempts overshoot
483
+ // or key not found
484
+ const isIrrecoverableError = attemptsMap[name] >= MAX_SYNC_ATTEMPTS ||
485
+ error.output?.statusCode === 404 ||
486
+ error.name === 'TypeError';
487
+ logger.info({ name, error: error.stack }, `failed to sync state from version${isIrrecoverableError ? '' : ', removing and trying from scratch'}`);
488
+ await authState.keys.set({ 'app-state-sync-version': { [name]: null } });
489
+ // increment number of retries
523
490
  attemptsMap[name] = (attemptsMap[name] || 0) + 1;
524
- const logData = {
525
- name,
526
- attempt: attemptsMap[name],
527
- version: states[name].version,
528
- statusCode: error.output?.statusCode,
529
- errorType: error.name,
530
- error: error.stack
531
- };
532
- if (isMissingKeyError(error) && attemptsMap[name] >= MAX_SYNC_ATTEMPTS) {
533
- // WA Web treats missing keys as "Blocked" — park the collection
534
- // until the key arrives via APP_STATE_SYNC_KEY_SHARE.
535
- logger.warn(logData, `${name} blocked on missing key from v${states[name].version}, parking after ${attemptsMap[name]} attempts`);
536
- blockedCollections.add(name);
491
+ if (isIrrecoverableError) {
492
+ // stop retrying
537
493
  collectionsToHandle.delete(name);
538
494
  }
539
- else if (isMissingKeyError(error)) {
540
- // Retry with a snapshot which may use a different key.
541
- logger.info(logData, `${name} blocked on missing key from v${states[name].version}, retrying with snapshot`);
542
- forceSnapshotCollections.add(name);
543
- }
544
- else if (isAppStateSyncIrrecoverable(error, attemptsMap[name])) {
545
- logger.warn(logData, `failed to sync ${name} from v${states[name].version}, giving up`);
546
- collectionsToHandle.delete(name);
547
- }
548
- else {
549
- logger.info(logData, `failed to sync ${name} from v${states[name].version}, forcing snapshot retry`);
550
- // force a full snapshot on retry to recover from
551
- // corrupted local state (e.g. LTHash MAC mismatch)
552
- forceSnapshotCollections.add(name);
553
- }
554
495
  }
555
496
  }
556
497
  }
@@ -565,25 +506,25 @@ export const makeChatsSocket = (config) => {
565
506
  * type = "preview" for a low res picture
566
507
  * type = "image for the high res picture"
567
508
  */
568
- const profilePictureUrl = async (jid, type = 'image', timeoutMs = 5000, shouldIncludeTcToken = false) => {
569
- const baseContent = [{ tag: 'picture', attrs: { type, query: 'url' } }];
570
- // WA Web only includes tctoken for user JIDs (not groups/newsletters)
571
- // and never for own profile pic (Chat model for self has no tcToken).
572
- // Including tctoken for own JID causes the server to never respond.
573
- const normalizedJid = jidNormalizedUser(jid);
574
- const isUserJid = isPnUser(normalizedJid) || isLidUser(normalizedJid);
575
- const me = authState.creds.me;
576
- const isSelf = me && (normalizedJid === jidNormalizedUser(me.id) || (me.lid && normalizedJid === jidNormalizedUser(me.lid)));
577
- let content = baseContent;
578
- if (shouldIncludeTcToken && serverProps.profilePicPrivacyToken && isUserJid && !isSelf) {
579
- content = await buildTcTokenFromJid({
580
- authState,
581
- jid: normalizedJid,
582
- baseContent,
583
- getLIDForPN
584
- });
585
- }
509
+ const profilePictureUrl = async (jid, type = 'image', timeoutMs) => {
510
+ // Lia@Changes 06-02-26 --- Refactor profilePictureUrl() to use tctoken and adjust error handling
586
511
  jid = jidNormalizedUser(jid);
512
+ const baseContent = {
513
+ tag: 'picture',
514
+ attrs: {
515
+ type,
516
+ query: 'url'
517
+ }
518
+ };
519
+ const tcTokenData = await authState.keys.get('tctoken', [jid]);
520
+ const tcTokenBuffer = tcTokenData?.[jid]?.token
521
+ if (tcTokenBuffer) {
522
+ baseContent.content = [{
523
+ tag: 'tctoken',
524
+ attrs: {},
525
+ content: tcTokenBuffer
526
+ }];
527
+ }
587
528
  const result = await query({
588
529
  tag: 'iq',
589
530
  attrs: {
@@ -592,9 +533,16 @@ export const makeChatsSocket = (config) => {
592
533
  type: 'get',
593
534
  xmlns: 'w:profile:picture'
594
535
  },
595
- content
536
+ content: [baseContent]
596
537
  }, timeoutMs);
597
538
  const child = getBinaryNodeChild(result, 'picture');
539
+ if (!child) {
540
+ throw new Boom('Picture node missing', { statusCode: 404 });
541
+ }
542
+ const status = child.attrs?.status;
543
+ if (status === '404' || status === '204') {
544
+ throw new Boom('Profile picture not set', { statusCode: 404 });
545
+ }
598
546
  return child?.attrs?.url;
599
547
  };
600
548
  const createCallLink = async (type, event, timeoutMs) => {
@@ -658,12 +606,7 @@ export const makeChatsSocket = (config) => {
658
606
  * @param tcToken token for subscription, use if present
659
607
  */
660
608
  const presenceSubscribe = async (toJid) => {
661
- // Only include tctoken for user JIDs groups/newsletters don't use tctokens
662
- const normalizedToJid = jidNormalizedUser(toJid);
663
- const isUserJid = isPnUser(normalizedToJid) || isLidUser(normalizedToJid);
664
- const tcTokenContent = isUserJid
665
- ? await buildTcTokenFromJid({ authState, jid: normalizedToJid, getLIDForPN })
666
- : undefined;
609
+ const tcTokenContent = await buildTcTokenFromJid({ authState, jid: toJid });
667
610
  return sendNode({
668
611
  tag: 'presence',
669
612
  attrs: {
@@ -684,8 +627,7 @@ export const makeChatsSocket = (config) => {
684
627
  if (tag === 'presence') {
685
628
  presence = {
686
629
  lastKnownPresence: attrs.type === 'unavailable' ? 'unavailable' : 'available',
687
- lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined,
688
- groupOnlineCount: attrs.count ? +attrs.count : undefined
630
+ lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined
689
631
  };
690
632
  }
691
633
  else if (Array.isArray(content)) {
@@ -719,7 +661,7 @@ export const makeChatsSocket = (config) => {
719
661
  logger.debug({ patch: patchCreate }, 'applying app patch');
720
662
  await resyncAppState([name], false);
721
663
  const { [name]: currentSyncVersion } = await authState.keys.get('app-state-sync-version', [name]);
722
- initial = currentSyncVersion ? ensureLTHashStateVersion(currentSyncVersion) : newLTHashState();
664
+ initial = currentSyncVersion || newLTHashState();
723
665
  encodeResult = await encodeSyncdPatch(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey);
724
666
  const { patch, state } = encodeResult;
725
667
  const node = {
@@ -765,21 +707,22 @@ export const makeChatsSocket = (config) => {
765
707
  }
766
708
  }
767
709
  };
768
- /** fetch AB props */
710
+ /** sending non-abt props may fix QR scan fail if server expects */
769
711
  const fetchProps = async () => {
712
+ //TODO: implement both protocol 1 and protocol 2 prop fetching, specially for abKey for WM
770
713
  const resultNode = await query({
771
714
  tag: 'iq',
772
715
  attrs: {
773
716
  to: S_WHATSAPP_NET,
774
- xmlns: 'abt',
717
+ xmlns: 'w',
775
718
  type: 'get'
776
719
  },
777
720
  content: [
778
721
  {
779
722
  tag: 'props',
780
723
  attrs: {
781
- protocol: '1',
782
- ...(authState?.creds?.lastPropHash ? { hash: authState.creds.lastPropHash } : {})
724
+ protocol: '2',
725
+ hash: authState?.creds?.lastPropHash || ''
783
726
  }
784
727
  }
785
728
  ]
@@ -794,20 +737,7 @@ export const makeChatsSocket = (config) => {
794
737
  }
795
738
  props = reduceBinaryNodeToDictionary(propsNode, 'prop');
796
739
  }
797
- // Extract protocol-relevant AB props (only the ones we need)
798
- const privacyTokenProp = props['10518'] ?? props['privacy_token_sending_on_all_1_on_1_messages'];
799
- if (privacyTokenProp !== undefined) {
800
- serverProps.privacyTokenOn1to1 = privacyTokenProp === 'true' || privacyTokenProp === '1';
801
- }
802
- const profilePicProp = props['9666'] ?? props['profile_scraping_privacy_token_in_photo_iq'];
803
- if (profilePicProp !== undefined) {
804
- serverProps.profilePicPrivacyToken = profilePicProp === 'true' || profilePicProp === '1';
805
- }
806
- const lidIssueProp = props['14303'] ?? props['lid_trusted_token_issue_to_lid'];
807
- if (lidIssueProp !== undefined) {
808
- serverProps.lidTrustedTokenIssueToLid = lidIssueProp === 'true' || lidIssueProp === '1';
809
- }
810
- logger.debug({ serverProps }, 'fetched props');
740
+ logger.debug('fetched props');
811
741
  return props;
812
742
  };
813
743
  /**
@@ -947,47 +877,6 @@ export const makeChatsSocket = (config) => {
947
877
  ? shouldSyncHistoryMessage(historyMsg) &&
948
878
  PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType)
949
879
  : false;
950
- if (historyMsg && shouldProcessHistoryMsg) {
951
- const syncType = historyMsg.syncType;
952
- // INITIAL_BOOTSTRAP — fire immediately, no progress check (same as WA Web K function)
953
- if (syncType === proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP &&
954
- !historySyncStatus.initialBootstrapComplete) {
955
- historySyncStatus.initialBootstrapComplete = true;
956
- ev.emit('messaging-history.status', {
957
- syncType,
958
- status: 'complete',
959
- explicit: true
960
- });
961
- }
962
- // RECENT with progress === 100 — explicit completion
963
- if (syncType === proto.HistorySync.HistorySyncType.RECENT &&
964
- historyMsg.progress === 100 &&
965
- !historySyncStatus.recentSyncComplete) {
966
- historySyncStatus.recentSyncComplete = true;
967
- clearTimeout(historySyncPausedTimeout);
968
- historySyncPausedTimeout = undefined;
969
- ev.emit('messaging-history.status', {
970
- syncType,
971
- status: 'complete',
972
- explicit: true
973
- });
974
- }
975
- // Reset 120s paused timeout on any RECENT chunk (like WA Web's handleChunkProgress)
976
- if (syncType === proto.HistorySync.HistorySyncType.RECENT && !historySyncStatus.recentSyncComplete) {
977
- clearTimeout(historySyncPausedTimeout);
978
- historySyncPausedTimeout = setTimeout(() => {
979
- if (!historySyncStatus.recentSyncComplete) {
980
- historySyncStatus.recentSyncComplete = true;
981
- ev.emit('messaging-history.status', {
982
- syncType: proto.HistorySync.HistorySyncType.RECENT,
983
- status: 'paused',
984
- explicit: false
985
- });
986
- }
987
- historySyncPausedTimeout = undefined;
988
- }, HISTORY_SYNC_PAUSED_TIMEOUT_MS);
989
- }
990
- }
991
880
  // State machine: decide on sync and flush
992
881
  if (historyMsg && syncState === SyncState.AwaitingInitialSync) {
993
882
  if (awaitingSyncTimeout) {
@@ -1007,8 +896,6 @@ export const makeChatsSocket = (config) => {
1007
896
  }
1008
897
  const doAppStateSync = async () => {
1009
898
  if (syncState === SyncState.Syncing) {
1010
- // All collections will be synced, so clear any blocked ones
1011
- blockedCollections.clear();
1012
899
  logger.info('Doing app state sync');
1013
900
  await resyncAppState(ALL_WA_PATCH_NAMES, true);
1014
901
  // Sync is complete, go online and flush everything
@@ -1068,11 +955,6 @@ export const makeChatsSocket = (config) => {
1068
955
  }
1069
956
  });
1070
957
  ev.on('connection.update', ({ connection, receivedPendingNotifications }) => {
1071
- if (connection === 'close') {
1072
- blockedCollections.clear();
1073
- clearTimeout(historySyncPausedTimeout);
1074
- historySyncPausedTimeout = undefined;
1075
- }
1076
958
  if (connection === 'open') {
1077
959
  if (fireInitQueries) {
1078
960
  executeInitQueries().catch(error => onUnexpectedError(error, 'init queries'));
@@ -1082,10 +964,6 @@ export const makeChatsSocket = (config) => {
1082
964
  if (!receivedPendingNotifications || syncState !== SyncState.Connecting) {
1083
965
  return;
1084
966
  }
1085
- historySyncStatus.initialBootstrapComplete = false;
1086
- historySyncStatus.recentSyncComplete = false;
1087
- clearTimeout(historySyncPausedTimeout);
1088
- historySyncPausedTimeout = undefined;
1089
967
  syncState = SyncState.AwaitingInitialSync;
1090
968
  logger.info('Connection is now AwaitingInitialSync, buffering events');
1091
969
  ev.buffer();
@@ -1098,49 +976,19 @@ export const makeChatsSocket = (config) => {
1098
976
  setTimeout(() => ev.flush(), 0);
1099
977
  return;
1100
978
  }
1101
- // On reconnection (accountSyncCounter > 0), the server does not push
1102
- // history sync notifications — the device already has its data.
1103
- // Skip the 20s wait and go online immediately.
1104
- if (authState.creds.accountSyncCounter > 0) {
1105
- logger.info('Reconnection with existing sync data, skipping history sync wait. Transitioning to Online.');
1106
- syncState = SyncState.Online;
1107
- setTimeout(() => ev.flush(), 0);
1108
- return;
1109
- }
1110
- logger.info('First connection, awaiting history sync notification with a 20s timeout.');
979
+ logger.info('History sync is enabled, awaiting notification with a 20s timeout.');
1111
980
  if (awaitingSyncTimeout) {
1112
981
  clearTimeout(awaitingSyncTimeout);
1113
982
  }
1114
983
  awaitingSyncTimeout = setTimeout(() => {
1115
984
  if (syncState === SyncState.AwaitingInitialSync) {
985
+ // TODO: investigate
1116
986
  logger.warn('Timeout in AwaitingInitialSync, forcing state to Online and flushing buffer');
1117
987
  syncState = SyncState.Online;
1118
988
  ev.flush();
1119
- // Increment so subsequent reconnections skip the 20s wait.
1120
- // Late-arriving history is still processed via processMessage
1121
- // regardless of the state machine phase.
1122
- const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1;
1123
- ev.emit('creds.update', { accountSyncCounter });
1124
989
  }
1125
990
  }, 20000);
1126
991
  });
1127
- // When an app state sync key arrives (myAppStateKeyId is set) and there are
1128
- // collections blocked on a missing key, trigger a re-sync for just those collections.
1129
- // This mirrors WA Web's Blocked → retry-on-key-arrival behavior.
1130
- ev.on('creds.update', ({ myAppStateKeyId }) => {
1131
- if (!myAppStateKeyId || blockedCollections.size === 0) {
1132
- return;
1133
- }
1134
- // If we're in the middle of a full sync, doAppStateSync handles all collections
1135
- if (syncState === SyncState.Syncing) {
1136
- blockedCollections.clear();
1137
- return;
1138
- }
1139
- const collections = [...blockedCollections];
1140
- blockedCollections.clear();
1141
- logger.info({ collections }, 'app state sync key arrived, re-syncing blocked collections');
1142
- resyncAppState(collections, false).catch(error => onUnexpectedError(error, 'blocked collections resync'));
1143
- });
1144
992
  ev.on('lid-mapping.update', async ({ lid, pn }) => {
1145
993
  try {
1146
994
  await signalRepository.lidMapping.storeLIDPNMappings([{ lid, pn }]);
@@ -1162,8 +1010,6 @@ export const makeChatsSocket = (config) => {
1162
1010
  });
1163
1011
  return {
1164
1012
  ...sock,
1165
- findUserId,
1166
- serverProps,
1167
1013
  createCallLink,
1168
1014
  getBotListV2,
1169
1015
  messageMutex,
@@ -1179,6 +1025,7 @@ export const makeChatsSocket = (config) => {
1179
1025
  fetchBlocklist,
1180
1026
  fetchStatus,
1181
1027
  fetchDisappearingDuration,
1028
+ findUserId,
1182
1029
  updateProfilePicture,
1183
1030
  removeProfilePicture,
1184
1031
  updateProfileStatus,
@@ -1200,7 +1047,6 @@ export const makeChatsSocket = (config) => {
1200
1047
  cleanDirtyBits,
1201
1048
  addOrEditContact,
1202
1049
  removeContact,
1203
- placeholderResendCache,
1204
1050
  addLabel,
1205
1051
  addChatLabel,
1206
1052
  removeChatLabel,
@@ -1210,5 +1056,4 @@ export const makeChatsSocket = (config) => {
1210
1056
  addOrEditQuickReply,
1211
1057
  removeQuickReply
1212
1058
  };
1213
- };
1214
- //# sourceMappingURL=chats.js.map
1059
+ };