@ubedsockets/baileys 1.6.6 → 1.6.7

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.
Files changed (87) hide show
  1. package/WAProto/GenerateStatics.sh +4 -3
  2. package/WAProto/WAProto.proto +511 -1215
  3. package/WAProto/index.js +131318 -59331
  4. package/lib/Defaults/index.js +92 -76
  5. package/lib/Signal/Group/ciphertext-message.js +5 -2
  6. package/lib/Signal/Group/group-session-builder.js +41 -7
  7. package/lib/Signal/Group/group_cipher.js +51 -37
  8. package/lib/Signal/Group/index.js +57 -12
  9. package/lib/Signal/Group/keyhelper.js +44 -7
  10. package/lib/Signal/Group/sender-chain-key.js +15 -7
  11. package/lib/Signal/Group/sender-key-distribution-message.js +11 -8
  12. package/lib/Signal/Group/sender-key-message.js +12 -9
  13. package/lib/Signal/Group/sender-key-name.js +5 -2
  14. package/lib/Signal/Group/sender-key-record.js +21 -9
  15. package/lib/Signal/Group/sender-key-state.js +42 -27
  16. package/lib/Signal/Group/sender-message-key.js +7 -4
  17. package/lib/Signal/libsignal.js +90 -347
  18. package/lib/Socket/Client/index.js +18 -3
  19. package/lib/Socket/Client/types.js +6 -4
  20. package/lib/Socket/Client/websocket.js +78 -21
  21. package/lib/Socket/business.js +43 -162
  22. package/lib/Socket/chats.js +249 -571
  23. package/lib/Socket/groups.js +99 -114
  24. package/lib/Socket/index.js +9 -11
  25. package/lib/Socket/messages-recv.js +559 -1277
  26. package/lib/Socket/messages-send.js +669 -674
  27. package/lib/Socket/newsletter.js +286 -149
  28. package/lib/Socket/socket.js +235 -548
  29. package/lib/Types/Auth.js +2 -2
  30. package/lib/Types/Call.js +2 -2
  31. package/lib/Types/Chat.js +4 -8
  32. package/lib/Types/Contact.js +2 -2
  33. package/lib/Types/Events.js +2 -2
  34. package/lib/Types/GroupMetadata.js +2 -2
  35. package/lib/Types/Label.js +5 -3
  36. package/lib/Types/LabelAssociation.js +5 -3
  37. package/lib/Types/Message.js +7 -11
  38. package/lib/Types/Product.js +2 -2
  39. package/lib/Types/Signal.js +2 -2
  40. package/lib/Types/Socket.js +2 -3
  41. package/lib/Types/State.js +2 -56
  42. package/lib/Types/USync.js +2 -2
  43. package/lib/Types/index.js +31 -15
  44. package/lib/Utils/auth-utils.js +136 -239
  45. package/lib/Utils/business.js +69 -66
  46. package/lib/Utils/chat-utils.js +238 -380
  47. package/lib/Utils/crypto.js +127 -56
  48. package/lib/Utils/decode-wa-message.js +63 -173
  49. package/lib/Utils/event-buffer.js +70 -174
  50. package/lib/Utils/generics.js +207 -159
  51. package/lib/Utils/history.js +53 -93
  52. package/lib/Utils/index.js +33 -22
  53. package/lib/Utils/link-preview.js +58 -17
  54. package/lib/Utils/logger.js +7 -3
  55. package/lib/Utils/lt-hash.js +46 -3
  56. package/lib/Utils/make-mutex.js +34 -24
  57. package/lib/Utils/messages-media.js +744 -483
  58. package/lib/Utils/messages.js +621 -411
  59. package/lib/Utils/noise-handler.js +99 -149
  60. package/lib/Utils/process-message.js +150 -459
  61. package/lib/Utils/signal.js +73 -112
  62. package/lib/Utils/use-multi-file-auth-state.js +27 -23
  63. package/lib/Utils/validate-connection.js +104 -74
  64. package/lib/WABinary/constants.js +11 -9
  65. package/lib/WABinary/decode.js +52 -49
  66. package/lib/WABinary/encode.js +49 -19
  67. package/lib/WABinary/generic-utils.js +43 -46
  68. package/lib/WABinary/index.js +21 -6
  69. package/lib/WABinary/jid-utils.js +45 -72
  70. package/lib/WABinary/types.js +2 -2
  71. package/lib/WAM/BinaryInfo.js +5 -2
  72. package/lib/WAM/constants.js +11958 -19461
  73. package/lib/WAM/encode.js +22 -17
  74. package/lib/WAM/index.js +19 -4
  75. package/lib/WAUSync/Protocols/USyncContactProtocol.js +13 -33
  76. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +14 -11
  77. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +11 -8
  78. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +13 -9
  79. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +22 -20
  80. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +8 -13
  81. package/lib/WAUSync/Protocols/index.js +20 -6
  82. package/lib/WAUSync/USyncQuery.js +35 -44
  83. package/lib/WAUSync/USyncUser.js +5 -10
  84. package/lib/WAUSync/index.js +19 -4
  85. package/lib/index.js +70 -11
  86. package/package.json +60 -100
  87. package/engine-requirements.js +0 -10
@@ -1,56 +1,37 @@
1
- import NodeCache from '@cacheable/node-cache';
2
- import { Boom } from '@hapi/boom';
3
- import { proto } from '../../WAProto/index.js';
4
- import { DEFAULT_CACHE_TTLS, HISTORY_SYNC_PAUSED_TIMEOUT_MS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
5
- import { ALL_WA_PATCH_NAMES } from '../Types/index.js';
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';
8
- import { makeMutex } from '../Utils/make-mutex.js';
9
- import processMessage from '../Utils/process-message.js';
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';
12
- import { USyncQuery, USyncUser } from '../WAUSync/index.js';
13
- import { makeSocket } from './socket.js';
14
- export const makeChatsSocket = (config) => {
15
- const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, getMessage } = config;
16
- const sock = makeSocket(config);
17
- const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError, sendUnifiedSession, registerSocketEndHandler } = sock;
18
- const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.makeChatsSocket = void 0;
7
+ const boom_1 = require("@hapi/boom");
8
+ const node_cache_1 = __importDefault(require("@cacheable/node-cache"));
9
+ const WAProto_1 = require("../../WAProto");
10
+ const Defaults_1 = require("../Defaults");
11
+ const Types_1 = require("../Types");
12
+ const Utils_1 = require("../Utils");
13
+ const make_mutex_1 = require("../Utils/make-mutex");
14
+ const process_message_1 = __importDefault(require("../Utils/process-message"));
15
+ const WABinary_1 = require("../WABinary");
16
+ const WAUSync_1 = require("../WAUSync");
17
+ const usync_1 = require("./usync");
18
+ const MAX_SYNC_ATTEMPTS = 2;
19
+ const makeChatsSocket = (config) => {
20
+ const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, } = config;
21
+ const sock = (0, usync_1.makeUSyncSocket)(config);
22
+ const { ev, ws, authState, generateMessageTag, sendNode, query, onUnexpectedError, } = sock;
19
23
  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
- let syncState = SyncState.Connecting;
30
- /** this mutex ensures that messages are processed in order */
31
- const messageMutex = makeMutex();
32
- /** this mutex ensures that receipts are processed in order */
33
- const receiptMutex = makeMutex();
34
- /** this mutex ensures that app state patches are processed in order */
35
- const appStatePatchMutex = makeMutex();
36
- /** this mutex ensures that notifications are processed in order */
37
- const notificationMutex = makeMutex();
38
- // Timeout for AwaitingInitialSync state
39
- 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
- const placeholderResendCache = config.placeholderResendCache ||
50
- new NodeCache({
51
- stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
52
- useClones: false
53
- });
24
+ let needToFlushWithAppStateSync = false;
25
+ let pendingAppStateSync = false;
26
+ /** this mutex ensures that the notifications (receipts, messages etc.) are processed in order */
27
+ const processingMutex = (0, make_mutex_1.makeMutex)();
28
+ const placeholderResendCache = config.placeholderResendCache || new node_cache_1.default({
29
+ stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
30
+ useClones: false
31
+ });
32
+ if (!config.placeholderResendCache) {
33
+ config.placeholderResendCache = placeholderResendCache;
34
+ }
54
35
  /** helper function to fetch the given app state sync key */
55
36
  const getAppStateSyncKey = async (keyId) => {
56
37
  const { [keyId]: key } = await authState.keys.get('app-state-sync-key', [keyId]);
@@ -62,12 +43,14 @@ export const makeChatsSocket = (config) => {
62
43
  tag: 'iq',
63
44
  attrs: {
64
45
  xmlns: 'privacy',
65
- to: S_WHATSAPP_NET,
46
+ to: WABinary_1.S_WHATSAPP_NET,
66
47
  type: 'get'
67
48
  },
68
- content: [{ tag: 'privacy', attrs: {} }]
49
+ content: [
50
+ { tag: 'privacy', attrs: {} }
51
+ ]
69
52
  });
70
- privacySettings = reduceBinaryNodeToDictionary(content?.[0], 'category');
53
+ privacySettings = (0, WABinary_1.reduceBinaryNodeToDictionary)(content === null || content === void 0 ? void 0 : content[0], 'category');
71
54
  }
72
55
  return privacySettings;
73
56
  };
@@ -77,11 +60,10 @@ export const makeChatsSocket = (config) => {
77
60
  tag: 'iq',
78
61
  attrs: {
79
62
  xmlns: 'privacy',
80
- to: S_WHATSAPP_NET,
63
+ to: WABinary_1.S_WHATSAPP_NET,
81
64
  type: 'set'
82
65
  },
83
- content: [
84
- {
66
+ content: [{
85
67
  tag: 'privacy',
86
68
  attrs: {},
87
69
  content: [
@@ -90,8 +72,7 @@ export const makeChatsSocket = (config) => {
90
72
  attrs: { name, value }
91
73
  }
92
74
  ]
93
- }
94
- ]
75
+ }]
95
76
  });
96
77
  };
97
78
  const updateMessagesPrivacy = async (value) => {
@@ -123,17 +104,15 @@ export const makeChatsSocket = (config) => {
123
104
  tag: 'iq',
124
105
  attrs: {
125
106
  xmlns: 'disappearing_mode',
126
- to: S_WHATSAPP_NET,
107
+ to: WABinary_1.S_WHATSAPP_NET,
127
108
  type: 'set'
128
109
  },
129
- content: [
130
- {
110
+ content: [{
131
111
  tag: 'disappearing_mode',
132
112
  attrs: {
133
113
  duration: duration.toString()
134
114
  }
135
- }
136
- ]
115
+ }]
137
116
  });
138
117
  };
139
118
  const getBotListV2 = async () => {
@@ -141,23 +120,21 @@ export const makeChatsSocket = (config) => {
141
120
  tag: 'iq',
142
121
  attrs: {
143
122
  xmlns: 'bot',
144
- to: S_WHATSAPP_NET,
123
+ to: WABinary_1.S_WHATSAPP_NET,
145
124
  type: 'get'
146
125
  },
147
- content: [
148
- {
126
+ content: [{
149
127
  tag: 'bot',
150
128
  attrs: {
151
129
  v: '2'
152
130
  }
153
- }
154
- ]
131
+ }]
155
132
  });
156
- const botNode = getBinaryNodeChild(resp, 'bot');
133
+ const botNode = (0, WABinary_1.getBinaryNodeChild)(resp, 'bot');
157
134
  const botList = [];
158
- for (const section of getBinaryNodeChildren(botNode, 'section')) {
135
+ for (const section of (0, WABinary_1.getBinaryNodeChildren)(botNode, 'section')) {
159
136
  if (section.attrs.type === 'all') {
160
- for (const bot of getBinaryNodeChildren(section, 'bot')) {
137
+ for (const bot of (0, WABinary_1.getBinaryNodeChildren)(section, 'bot')) {
161
138
  botList.push({
162
139
  jid: bot.attrs.jid,
163
140
  personaId: bot.attrs['persona_id']
@@ -167,10 +144,24 @@ export const makeChatsSocket = (config) => {
167
144
  }
168
145
  return botList;
169
146
  };
147
+ const onWhatsApp = async (...jids) => {
148
+ const usyncQuery = new WAUSync_1.USyncQuery()
149
+ .withContactProtocol()
150
+ .withLIDProtocol();
151
+ for (const jid of jids) {
152
+ const phone = `+${jid.replace('+', '').split('@')[0].split(':')[0]}`;
153
+ usyncQuery.withUser(new WAUSync_1.USyncUser().withPhone(phone));
154
+ }
155
+ const results = await sock.executeUSyncQuery(usyncQuery);
156
+ if (results) {
157
+ return results.list.filter((a) => !!a.contact).map(({ contact, id, lid }) => ({ jid: id, exists: contact, lid }));
158
+ }
159
+ };
170
160
  const fetchStatus = async (...jids) => {
171
- const usyncQuery = new USyncQuery().withStatusProtocol();
161
+ const usyncQuery = new WAUSync_1.USyncQuery()
162
+ .withStatusProtocol();
172
163
  for (const jid of jids) {
173
- usyncQuery.withUser(new USyncUser().withId(jid));
164
+ usyncQuery.withUser(new WAUSync_1.USyncUser().withId(jid));
174
165
  }
175
166
  const result = await sock.executeUSyncQuery(usyncQuery);
176
167
  if (result) {
@@ -178,9 +169,10 @@ export const makeChatsSocket = (config) => {
178
169
  }
179
170
  };
180
171
  const fetchDisappearingDuration = async (...jids) => {
181
- const usyncQuery = new USyncQuery().withDisappearingModeProtocol();
172
+ const usyncQuery = new WAUSync_1.USyncQuery()
173
+ .withDisappearingModeProtocol();
182
174
  for (const jid of jids) {
183
- usyncQuery.withUser(new USyncUser().withId(jid));
175
+ usyncQuery.withUser(new WAUSync_1.USyncUser().withId(jid));
184
176
  }
185
177
  const result = await sock.executeUSyncQuery(usyncQuery);
186
178
  if (result) {
@@ -188,25 +180,22 @@ export const makeChatsSocket = (config) => {
188
180
  }
189
181
  };
190
182
  /** update the profile picture for yourself or a group */
191
- const updateProfilePicture = async (jid, content, dimensions) => {
183
+ const updateProfilePicture = async (jid, content) => {
192
184
  let targetJid;
193
185
  if (!jid) {
194
- throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update');
186
+ throw new boom_1.Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update');
195
187
  }
196
- if (jidNormalizedUser(jid) !== jidNormalizedUser(authState.creds.me.id)) {
197
- targetJid = jidNormalizedUser(jid); // in case it is someone other than us
188
+ if ((0, WABinary_1.jidNormalizedUser)(jid) !== (0, WABinary_1.jidNormalizedUser)(authState.creds.me.id)) {
189
+ targetJid = (0, WABinary_1.jidNormalizedUser)(jid); // in case it is someone other than us
198
190
  }
199
- else {
200
- targetJid = undefined;
201
- }
202
- const { img } = await generateProfilePicture(content, dimensions);
191
+ const { img } = await (0, Utils_1.generateProfilePicture)(content);
203
192
  await query({
204
193
  tag: 'iq',
205
194
  attrs: {
206
- to: S_WHATSAPP_NET,
195
+ target: targetJid,
196
+ to: WABinary_1.S_WHATSAPP_NET,
207
197
  type: 'set',
208
- xmlns: 'w:profile:picture',
209
- ...(targetJid ? { target: targetJid } : {})
198
+ xmlns: 'w:profile:picture'
210
199
  },
211
200
  content: [
212
201
  {
@@ -221,21 +210,18 @@ export const makeChatsSocket = (config) => {
221
210
  const removeProfilePicture = async (jid) => {
222
211
  let targetJid;
223
212
  if (!jid) {
224
- throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update');
213
+ throw new boom_1.Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update');
225
214
  }
226
- if (jidNormalizedUser(jid) !== jidNormalizedUser(authState.creds.me.id)) {
227
- targetJid = jidNormalizedUser(jid); // in case it is someone other than us
228
- }
229
- else {
230
- targetJid = undefined;
215
+ if ((0, WABinary_1.jidNormalizedUser)(jid) !== (0, WABinary_1.jidNormalizedUser)(authState.creds.me.id)) {
216
+ targetJid = (0, WABinary_1.jidNormalizedUser)(jid); // in case it is someone other than us
231
217
  }
232
218
  await query({
233
219
  tag: 'iq',
234
220
  attrs: {
235
- to: S_WHATSAPP_NET,
221
+ target: targetJid,
222
+ to: WABinary_1.S_WHATSAPP_NET,
236
223
  type: 'set',
237
- xmlns: 'w:profile:picture',
238
- ...(targetJid ? { target: targetJid } : {})
224
+ xmlns: 'w:profile:picture'
239
225
  }
240
226
  });
241
227
  };
@@ -244,7 +230,7 @@ export const makeChatsSocket = (config) => {
244
230
  await query({
245
231
  tag: 'iq',
246
232
  attrs: {
247
- to: S_WHATSAPP_NET,
233
+ to: WABinary_1.S_WHATSAPP_NET,
248
234
  type: 'set',
249
235
  xmlns: 'status'
250
236
  },
@@ -265,66 +251,35 @@ export const makeChatsSocket = (config) => {
265
251
  tag: 'iq',
266
252
  attrs: {
267
253
  xmlns: 'blocklist',
268
- to: S_WHATSAPP_NET,
254
+ to: WABinary_1.S_WHATSAPP_NET,
269
255
  type: 'get'
270
256
  }
271
257
  });
272
- const listNode = getBinaryNodeChild(result, 'list');
273
- return getBinaryNodeChildren(listNode, 'item').map(n => n.attrs.jid);
258
+ const listNode = (0, WABinary_1.getBinaryNodeChild)(result, 'list');
259
+ return (0, WABinary_1.getBinaryNodeChildren)(listNode, 'item')
260
+ .map(n => n.attrs.jid);
274
261
  };
275
262
  const updateBlockStatus = async (jid, action) => {
276
- const normalizedJid = jidNormalizedUser(jid);
277
- let lid;
278
- let pn_jid;
279
- if (isLidUser(normalizedJid) || isHostedLidUser(normalizedJid)) {
280
- lid = normalizedJid;
281
- if (action === 'block') {
282
- const pn = await signalRepository.lidMapping.getPNForLID(normalizedJid);
283
- if (!pn) {
284
- throw new Boom(`Unable to resolve PN JID for LID: ${jid}`, { statusCode: 400 });
285
- }
286
- pn_jid = jidNormalizedUser(pn);
287
- }
288
- }
289
- else if (isPnUser(normalizedJid) || isHostedPnUser(normalizedJid)) {
290
- const mapped = await signalRepository.lidMapping.getLIDForPN(normalizedJid);
291
- if (!mapped) {
292
- throw new Boom(`Unable to resolve LID for PN JID: ${jid}`, { statusCode: 400 });
293
- }
294
- lid = mapped;
295
- if (action === 'block') {
296
- pn_jid = jidNormalizedUser(normalizedJid);
297
- }
298
- }
299
- else {
300
- throw new Boom(`Invalid jid: ${jid}`, { statusCode: 400 });
301
- }
302
- const itemAttrs = {
303
- action,
304
- jid: lid
305
- };
306
- if (action === 'block') {
307
- if (!pn_jid) {
308
- throw new Boom(`pn_jid required for block: ${jid}`, { statusCode: 400 });
309
- }
310
- itemAttrs.pn_jid = pn_jid;
311
- }
312
263
  await query({
313
264
  tag: 'iq',
314
265
  attrs: {
315
266
  xmlns: 'blocklist',
316
- to: S_WHATSAPP_NET,
267
+ to: WABinary_1.S_WHATSAPP_NET,
317
268
  type: 'set'
318
269
  },
319
270
  content: [
320
271
  {
321
272
  tag: 'item',
322
- attrs: itemAttrs
273
+ attrs: {
274
+ action,
275
+ jid
276
+ }
323
277
  }
324
278
  ]
325
279
  });
326
280
  };
327
281
  const getBusinessProfile = async (jid) => {
282
+ var _a, _b, _c, _d, _e, _f, _g;
328
283
  const results = await query({
329
284
  tag: 'iq',
330
285
  attrs: {
@@ -332,42 +287,38 @@ export const makeChatsSocket = (config) => {
332
287
  xmlns: 'w:biz',
333
288
  type: 'get'
334
289
  },
335
- content: [
336
- {
290
+ content: [{
337
291
  tag: 'business_profile',
338
292
  attrs: { v: '244' },
339
- content: [
340
- {
293
+ content: [{
341
294
  tag: 'profile',
342
295
  attrs: { jid }
343
- }
344
- ]
345
- }
346
- ]
296
+ }]
297
+ }]
347
298
  });
348
- const profileNode = getBinaryNodeChild(results, 'business_profile');
349
- const profiles = getBinaryNodeChild(profileNode, 'profile');
299
+ const profileNode = (0, WABinary_1.getBinaryNodeChild)(results, 'business_profile');
300
+ const profiles = (0, WABinary_1.getBinaryNodeChild)(profileNode, 'profile');
350
301
  if (profiles) {
351
- const address = getBinaryNodeChild(profiles, 'address');
352
- const description = getBinaryNodeChild(profiles, 'description');
353
- const website = getBinaryNodeChild(profiles, 'website');
354
- const email = getBinaryNodeChild(profiles, 'email');
355
- const category = getBinaryNodeChild(getBinaryNodeChild(profiles, 'categories'), 'category');
356
- const businessHours = getBinaryNodeChild(profiles, 'business_hours');
302
+ const address = (0, WABinary_1.getBinaryNodeChild)(profiles, 'address');
303
+ const description = (0, WABinary_1.getBinaryNodeChild)(profiles, 'description');
304
+ const website = (0, WABinary_1.getBinaryNodeChild)(profiles, 'website');
305
+ const email = (0, WABinary_1.getBinaryNodeChild)(profiles, 'email');
306
+ const category = (0, WABinary_1.getBinaryNodeChild)((0, WABinary_1.getBinaryNodeChild)(profiles, 'categories'), 'category');
307
+ const businessHours = (0, WABinary_1.getBinaryNodeChild)(profiles, 'business_hours');
357
308
  const businessHoursConfig = businessHours
358
- ? getBinaryNodeChildren(businessHours, 'business_hours_config')
309
+ ? (0, WABinary_1.getBinaryNodeChildren)(businessHours, 'business_hours_config')
359
310
  : undefined;
360
- const websiteStr = website?.content?.toString();
311
+ const websiteStr = (_a = website === null || website === void 0 ? void 0 : website.content) === null || _a === void 0 ? void 0 : _a.toString();
361
312
  return {
362
- wid: profiles.attrs?.jid,
363
- address: address?.content?.toString(),
364
- description: description?.content?.toString() || '',
313
+ wid: (_b = profiles.attrs) === null || _b === void 0 ? void 0 : _b.jid,
314
+ address: (_c = address === null || address === void 0 ? void 0 : address.content) === null || _c === void 0 ? void 0 : _c.toString(),
315
+ description: ((_d = description === null || description === void 0 ? void 0 : description.content) === null || _d === void 0 ? void 0 : _d.toString()) || '',
365
316
  website: websiteStr ? [websiteStr] : [],
366
- email: email?.content?.toString(),
367
- category: category?.content?.toString(),
368
- business_hours: {
369
- timezone: businessHours?.attrs?.timezone,
370
- business_config: businessHoursConfig?.map(({ attrs }) => attrs)
317
+ email: (_e = email === null || email === void 0 ? void 0 : email.content) === null || _e === void 0 ? void 0 : _e.toString(),
318
+ category: (_f = category === null || category === void 0 ? void 0 : category.content) === null || _f === void 0 ? void 0 : _f.toString(),
319
+ 'business_hours': {
320
+ timezone: (_g = businessHours === null || businessHours === void 0 ? void 0 : businessHours.attrs) === null || _g === void 0 ? void 0 : _g.timezone,
321
+ 'business_config': businessHoursConfig === null || businessHoursConfig === void 0 ? void 0 : businessHoursConfig.map(({ attrs }) => attrs)
371
322
  }
372
323
  };
373
324
  }
@@ -377,17 +328,17 @@ export const makeChatsSocket = (config) => {
377
328
  await sendNode({
378
329
  tag: 'iq',
379
330
  attrs: {
380
- to: S_WHATSAPP_NET,
331
+ to: WABinary_1.S_WHATSAPP_NET,
381
332
  type: 'set',
382
333
  xmlns: 'urn:xmpp:whatsapp:dirty',
383
- id: generateMessageTag()
334
+ id: generateMessageTag(),
384
335
  },
385
336
  content: [
386
337
  {
387
338
  tag: 'clean',
388
339
  attrs: {
389
340
  type,
390
- ...(fromTimestamp ? { timestamp: fromTimestamp.toString() } : null)
341
+ ...(fromTimestamp ? { timestamp: fromTimestamp.toString() } : null),
391
342
  }
392
343
  }
393
344
  ]
@@ -396,31 +347,20 @@ export const makeChatsSocket = (config) => {
396
347
  const newAppStateChunkHandler = (isInitialSync) => {
397
348
  return {
398
349
  onMutation(mutation) {
399
- processSyncAction(mutation, ev, authState.creds.me, isInitialSync ? { accountSettings: authState.creds.accountSettings } : undefined, logger);
350
+ (0, Utils_1.processSyncAction)(mutation, ev, authState.creds.me, isInitialSync ? { accountSettings: authState.creds.accountSettings } : undefined, logger);
400
351
  }
401
352
  };
402
353
  };
403
354
  const resyncAppState = ev.createBufferedFunction(async (collections, isInitialSync) => {
404
- const appStateSyncKeyCache = new Map();
405
- const getCachedAppStateSyncKey = async (keyId) => {
406
- if (appStateSyncKeyCache.has(keyId)) {
407
- return appStateSyncKeyCache.get(keyId) ?? undefined;
408
- }
409
- const key = await getAppStateSyncKey(keyId);
410
- appStateSyncKeyCache.set(keyId, key ?? null);
411
- return key;
412
- };
413
355
  // we use this to determine which events to fire
414
356
  // otherwise when we resync from scratch -- all notifications will fire
415
357
  const initialVersionMap = {};
416
358
  const globalMutationMap = {};
417
359
  await authState.keys.transaction(async () => {
360
+ var _a;
418
361
  const collectionsToHandle = new Set(collections);
419
362
  // in case something goes wrong -- ensure we don't enter a loop that cannot be exited from
420
363
  const attemptsMap = {};
421
- // collections that failed and need a full snapshot on retry
422
- // mirrors WA Web's ErrorFatal -> force snapshot behavior
423
- const forceSnapshotCollections = new Set();
424
364
  // keep executing till all collections are done
425
365
  // sometimes a single patch request will not return all the patches (God knows why)
426
366
  // so we fetch till they're all done (this is determined by the "has_more_patches" flag)
@@ -431,34 +371,29 @@ export const makeChatsSocket = (config) => {
431
371
  const result = await authState.keys.get('app-state-sync-version', [name]);
432
372
  let state = result[name];
433
373
  if (state) {
434
- state = ensureLTHashStateVersion(state);
435
374
  if (typeof initialVersionMap[name] === 'undefined') {
436
375
  initialVersionMap[name] = state.version;
437
376
  }
438
377
  }
439
378
  else {
440
- state = newLTHashState();
379
+ state = (0, Utils_1.newLTHashState)();
441
380
  }
442
381
  states[name] = state;
443
- const shouldForceSnapshot = forceSnapshotCollections.has(name);
444
- if (shouldForceSnapshot) {
445
- forceSnapshotCollections.delete(name);
446
- }
447
- logger.info(`resyncing ${name} from v${state.version}${shouldForceSnapshot ? ' (forcing snapshot)' : ''}`);
382
+ logger.info(`resyncing ${name} from v${state.version}`);
448
383
  nodes.push({
449
384
  tag: 'collection',
450
385
  attrs: {
451
386
  name,
452
387
  version: state.version.toString(),
453
- // return snapshot if syncing from scratch or forcing after a failed attempt
454
- return_snapshot: (shouldForceSnapshot || !state.version).toString()
388
+ // return snapshot if being synced from scratch
389
+ 'return_snapshot': (!state.version).toString()
455
390
  }
456
391
  });
457
392
  }
458
393
  const result = await query({
459
394
  tag: 'iq',
460
395
  attrs: {
461
- to: S_WHATSAPP_NET,
396
+ to: WABinary_1.S_WHATSAPP_NET,
462
397
  xmlns: 'w:sync:app:state',
463
398
  type: 'set'
464
399
  },
@@ -471,13 +406,13 @@ export const makeChatsSocket = (config) => {
471
406
  ]
472
407
  });
473
408
  // extract from binary node
474
- const decoded = await extractSyncdPatches(result, config?.options);
409
+ const decoded = await (0, Utils_1.extractSyncdPatches)(result, config === null || config === void 0 ? void 0 : config.options);
475
410
  for (const key in decoded) {
476
411
  const name = key;
477
412
  const { patches, hasMorePatches, snapshot } = decoded[name];
478
413
  try {
479
414
  if (snapshot) {
480
- const { state: newState, mutationMap } = await decodeSyncdSnapshot(name, snapshot, getCachedAppStateSyncKey, initialVersionMap[name], appStateMacVerification.snapshot, logger);
415
+ const { state: newState, mutationMap } = await (0, Utils_1.decodeSyncdSnapshot)(name, snapshot, getAppStateSyncKey, initialVersionMap[name], appStateMacVerification.snapshot);
481
416
  states[name] = newState;
482
417
  Object.assign(globalMutationMap, mutationMap);
483
418
  logger.info(`restored state of ${name} from snapshot to v${newState.version} with mutations`);
@@ -485,7 +420,7 @@ export const makeChatsSocket = (config) => {
485
420
  }
486
421
  // only process if there are syncd patches
487
422
  if (patches.length) {
488
- const { state: newState, mutationMap } = await decodePatches(name, patches, states[name], getCachedAppStateSyncKey, config.options, initialVersionMap[name], logger, appStateMacVerification.patch);
423
+ const { state: newState, mutationMap } = await (0, Utils_1.decodePatches)(name, patches, states[name], getAppStateSyncKey, config.options, initialVersionMap[name], logger, appStateMacVerification.patch);
489
424
  await authState.keys.set({ 'app-state-sync-version': { [name]: newState } });
490
425
  logger.info(`synced ${name} to v${newState.version}`);
491
426
  initialVersionMap[name] = newState.version;
@@ -494,47 +429,28 @@ export const makeChatsSocket = (config) => {
494
429
  if (hasMorePatches) {
495
430
  logger.info(`${name} has more patches...`);
496
431
  }
497
- else {
498
- // collection is done with sync
432
+ else { // collection is done with sync
499
433
  collectionsToHandle.delete(name);
500
434
  }
501
435
  }
502
436
  catch (error) {
437
+ // if retry attempts overshoot
438
+ // or key not found
439
+ const isIrrecoverableError = attemptsMap[name] >= MAX_SYNC_ATTEMPTS
440
+ || ((_a = error.output) === null || _a === void 0 ? void 0 : _a.statusCode) === 404
441
+ || error.name === 'TypeError';
442
+ logger.info({ name, error: error.stack }, `failed to sync state from version${isIrrecoverableError ? '' : ', removing and trying from scratch'}`);
443
+ await authState.keys.set({ 'app-state-sync-version': { [name]: null } });
444
+ // increment number of retries
503
445
  attemptsMap[name] = (attemptsMap[name] || 0) + 1;
504
- const logData = {
505
- name,
506
- attempt: attemptsMap[name],
507
- version: states[name].version,
508
- statusCode: error.output?.statusCode,
509
- errorType: error.name,
510
- error: error.stack
511
- };
512
- if (isMissingKeyError(error) && attemptsMap[name] >= MAX_SYNC_ATTEMPTS) {
513
- // WA Web treats missing keys as "Blocked" — park the collection
514
- // until the key arrives via APP_STATE_SYNC_KEY_SHARE.
515
- logger.warn(logData, `${name} blocked on missing key from v${states[name].version}, parking after ${attemptsMap[name]} attempts`);
516
- blockedCollections.add(name);
517
- collectionsToHandle.delete(name);
518
- }
519
- else if (isMissingKeyError(error)) {
520
- // Retry with a snapshot which may use a different key.
521
- logger.info(logData, `${name} blocked on missing key from v${states[name].version}, retrying with snapshot`);
522
- forceSnapshotCollections.add(name);
523
- }
524
- else if (isAppStateSyncIrrecoverable(error, attemptsMap[name])) {
525
- logger.warn(logData, `failed to sync ${name} from v${states[name].version}, giving up`);
446
+ if (isIrrecoverableError) {
447
+ // stop retrying
526
448
  collectionsToHandle.delete(name);
527
449
  }
528
- else {
529
- logger.info(logData, `failed to sync ${name} from v${states[name].version}, forcing snapshot retry`);
530
- // force a full snapshot on retry to recover from
531
- // corrupted local state (e.g. LTHash MAC mismatch)
532
- forceSnapshotCollections.add(name);
533
- }
534
450
  }
535
451
  }
536
452
  }
537
- }, authState?.creds?.me?.id || 'resync-app-state');
453
+ });
538
454
  const { onMutation } = newAppStateChunkHandler(isInitialSync);
539
455
  for (const key in globalMutationMap) {
540
456
  onMutation(globalMutationMap[key]);
@@ -546,67 +462,31 @@ export const makeChatsSocket = (config) => {
546
462
  * type = "image for the high res picture"
547
463
  */
548
464
  const profilePictureUrl = async (jid, type = 'preview', timeoutMs) => {
549
- const baseContent = [{ tag: 'picture', attrs: { type, query: 'url' } }];
550
- // WA Web only includes tctoken for user JIDs (not groups/newsletters)
551
- // and never for own profile pic (Chat model for self has no tcToken).
552
- // Including tctoken for own JID causes the server to never respond.
553
- const normalizedJid = jidNormalizedUser(jid);
554
- const isUserJid = isPnUser(normalizedJid) || isLidUser(normalizedJid);
555
- const me = authState.creds.me;
556
- const isSelf = me && (normalizedJid === jidNormalizedUser(me.id) || (me.lid && normalizedJid === jidNormalizedUser(me.lid)));
557
- let content = baseContent;
558
- if (serverProps.profilePicPrivacyToken && isUserJid && !isSelf) {
559
- content = await buildTcTokenFromJid({
560
- authState,
561
- jid: normalizedJid,
562
- baseContent,
563
- getLIDForPN
564
- });
565
- }
566
- jid = jidNormalizedUser(jid);
465
+ var _a;
466
+ jid = (0, WABinary_1.jidNormalizedUser)(jid);
567
467
  const result = await query({
568
468
  tag: 'iq',
569
469
  attrs: {
570
470
  target: jid,
571
- to: S_WHATSAPP_NET,
471
+ to: WABinary_1.S_WHATSAPP_NET,
572
472
  type: 'get',
573
473
  xmlns: 'w:profile:picture'
574
474
  },
575
- content
576
- }, timeoutMs);
577
- const child = getBinaryNodeChild(result, 'picture');
578
- return child?.attrs?.url;
579
- };
580
- const createCallLink = async (type, event, timeoutMs) => {
581
- const result = await query({
582
- tag: 'call',
583
- attrs: {
584
- id: generateMessageTag(),
585
- to: '@call'
586
- },
587
475
  content: [
588
- {
589
- tag: 'link_create',
590
- attrs: { media: type },
591
- content: event ? [{ tag: 'event', attrs: { start_time: String(event.startTime) } }] : undefined
592
- }
476
+ { tag: 'picture', attrs: { type, query: 'url' } }
593
477
  ]
594
478
  }, timeoutMs);
595
- const child = getBinaryNodeChild(result, 'link_create');
596
- return child?.attrs?.token;
479
+ const child = (0, WABinary_1.getBinaryNodeChild)(result, 'picture');
480
+ return (_a = child === null || child === void 0 ? void 0 : child.attrs) === null || _a === void 0 ? void 0 : _a.url;
597
481
  };
598
482
  const sendPresenceUpdate = async (type, toJid) => {
599
483
  const me = authState.creds.me;
600
- const isAvailableType = type === 'available';
601
- if (isAvailableType || type === 'unavailable') {
484
+ if (type === 'available' || type === 'unavailable') {
602
485
  if (!me.name) {
603
486
  logger.warn('no name present, ignoring presence update request...');
604
487
  return;
605
488
  }
606
- ev.emit('connection.update', { isOnline: isAvailableType });
607
- if (isAvailableType) {
608
- void sendUnifiedSession();
609
- }
489
+ ev.emit('connection.update', { isOnline: type === 'available' });
610
490
  await sendNode({
611
491
  tag: 'presence',
612
492
  attrs: {
@@ -616,13 +496,13 @@ export const makeChatsSocket = (config) => {
616
496
  });
617
497
  }
618
498
  else {
619
- const { server } = jidDecode(toJid);
499
+ const { server } = (0, WABinary_1.jidDecode)(toJid);
620
500
  const isLid = server === 'lid';
621
501
  await sendNode({
622
502
  tag: 'chatstate',
623
503
  attrs: {
624
504
  from: isLid ? me.lid : me.id,
625
- to: toJid
505
+ to: toJid,
626
506
  },
627
507
  content: [
628
508
  {
@@ -637,35 +517,35 @@ export const makeChatsSocket = (config) => {
637
517
  * @param toJid the jid to subscribe to
638
518
  * @param tcToken token for subscription, use if present
639
519
  */
640
- const presenceSubscribe = async (toJid) => {
641
- // Only include tctoken for user JIDs — groups/newsletters don't use tctokens
642
- const normalizedToJid = jidNormalizedUser(toJid);
643
- const isUserJid = isPnUser(normalizedToJid) || isLidUser(normalizedToJid);
644
- const tcTokenContent = isUserJid
645
- ? await buildTcTokenFromJid({ authState, jid: normalizedToJid, getLIDForPN })
646
- : undefined;
647
- return sendNode({
648
- tag: 'presence',
649
- attrs: {
650
- to: toJid,
651
- id: generateMessageTag(),
652
- type: 'subscribe'
653
- },
654
- content: tcTokenContent
655
- });
656
- };
520
+ const presenceSubscribe = (toJid, tcToken) => (sendNode({
521
+ tag: 'presence',
522
+ attrs: {
523
+ to: toJid,
524
+ id: generateMessageTag(),
525
+ type: 'subscribe'
526
+ },
527
+ content: tcToken
528
+ ? [
529
+ {
530
+ tag: 'tctoken',
531
+ attrs: {},
532
+ content: tcToken
533
+ }
534
+ ]
535
+ : undefined
536
+ }));
657
537
  const handlePresenceUpdate = ({ tag, attrs, content }) => {
538
+ var _a;
658
539
  let presence;
659
540
  const jid = attrs.from;
660
541
  const participant = attrs.participant || attrs.from;
661
- if (shouldIgnoreJid(jid) && jid !== S_WHATSAPP_NET) {
542
+ if (shouldIgnoreJid(jid) && jid != '@s.whatsapp.net') {
662
543
  return;
663
544
  }
664
545
  if (tag === 'presence') {
665
546
  presence = {
666
547
  lastKnownPresence: attrs.type === 'unavailable' ? 'unavailable' : 'available',
667
- lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined,
668
- groupOnlineCount: attrs.count ? +attrs.count : undefined
548
+ lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined
669
549
  };
670
550
  }
671
551
  else if (Array.isArray(content)) {
@@ -674,7 +554,7 @@ export const makeChatsSocket = (config) => {
674
554
  if (type === 'paused') {
675
555
  type = 'available';
676
556
  }
677
- if (firstChild.attrs?.media === 'audio') {
557
+ if (((_a = firstChild.attrs) === null || _a === void 0 ? void 0 : _a.media) === 'audio') {
678
558
  type = 'recording';
679
559
  }
680
560
  presence = { lastKnownPresence: type };
@@ -690,22 +570,22 @@ export const makeChatsSocket = (config) => {
690
570
  const name = patchCreate.type;
691
571
  const myAppStateKeyId = authState.creds.myAppStateKeyId;
692
572
  if (!myAppStateKeyId) {
693
- throw new Boom('App state key not present!', { statusCode: 400 });
573
+ throw new boom_1.Boom('App state key not present!', { statusCode: 400 });
694
574
  }
695
575
  let initial;
696
576
  let encodeResult;
697
- await appStatePatchMutex.mutex(async () => {
577
+ await processingMutex.mutex(async () => {
698
578
  await authState.keys.transaction(async () => {
699
579
  logger.debug({ patch: patchCreate }, 'applying app patch');
700
580
  await resyncAppState([name], false);
701
581
  const { [name]: currentSyncVersion } = await authState.keys.get('app-state-sync-version', [name]);
702
- initial = currentSyncVersion ? ensureLTHashStateVersion(currentSyncVersion) : newLTHashState();
703
- encodeResult = await encodeSyncdPatch(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey);
582
+ initial = currentSyncVersion || (0, Utils_1.newLTHashState)();
583
+ encodeResult = await (0, Utils_1.encodeSyncdPatch)(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey);
704
584
  const { patch, state } = encodeResult;
705
585
  const node = {
706
586
  tag: 'iq',
707
587
  attrs: {
708
- to: S_WHATSAPP_NET,
588
+ to: WABinary_1.S_WHATSAPP_NET,
709
589
  type: 'set',
710
590
  xmlns: 'w:sync:app:state'
711
591
  },
@@ -719,13 +599,13 @@ export const makeChatsSocket = (config) => {
719
599
  attrs: {
720
600
  name,
721
601
  version: (state.version - 1).toString(),
722
- return_snapshot: 'false'
602
+ 'return_snapshot': 'false'
723
603
  },
724
604
  content: [
725
605
  {
726
606
  tag: 'patch',
727
607
  attrs: {},
728
- content: proto.SyncdPatch.encode(patch).finish()
608
+ content: WAProto_1.proto.SyncdPatch.encode(patch).finish()
729
609
  }
730
610
  ]
731
611
  }
@@ -735,78 +615,54 @@ export const makeChatsSocket = (config) => {
735
615
  };
736
616
  await query(node);
737
617
  await authState.keys.set({ 'app-state-sync-version': { [name]: state } });
738
- }, authState?.creds?.me?.id || 'app-patch');
618
+ });
739
619
  });
740
620
  if (config.emitOwnEvents) {
741
621
  const { onMutation } = newAppStateChunkHandler(false);
742
- const { mutationMap } = await decodePatches(name, [{ ...encodeResult.patch, version: { version: encodeResult.state.version } }], initial, getAppStateSyncKey, config.options, undefined, logger);
622
+ const { mutationMap } = await (0, Utils_1.decodePatches)(name, [{ ...encodeResult.patch, version: { version: encodeResult.state.version }, }], initial, getAppStateSyncKey, config.options, undefined, logger);
743
623
  for (const key in mutationMap) {
744
624
  onMutation(mutationMap[key]);
745
625
  }
746
626
  }
747
627
  };
748
- /** fetch AB props */
628
+ /** sending non-abt props may fix QR scan fail if server expects */
749
629
  const fetchProps = async () => {
630
+ var _a, _b, _c;
750
631
  const resultNode = await query({
751
632
  tag: 'iq',
752
633
  attrs: {
753
- to: S_WHATSAPP_NET,
754
- xmlns: 'abt',
755
- type: 'get'
634
+ to: WABinary_1.S_WHATSAPP_NET,
635
+ xmlns: 'w',
636
+ type: 'get',
756
637
  },
757
638
  content: [
758
- {
759
- tag: 'props',
760
- attrs: {
761
- protocol: '1',
762
- ...(authState?.creds?.lastPropHash ? { hash: authState.creds.lastPropHash } : {})
763
- }
764
- }
639
+ { tag: 'props', attrs: {
640
+ protocol: '2',
641
+ hash: ((_a = authState === null || authState === void 0 ? void 0 : authState.creds) === null || _a === void 0 ? void 0 : _a.lastPropHash) || ''
642
+ } }
765
643
  ]
766
644
  });
767
- const propsNode = getBinaryNodeChild(resultNode, 'props');
645
+ const propsNode = (0, WABinary_1.getBinaryNodeChild)(resultNode, 'props');
768
646
  let props = {};
769
647
  if (propsNode) {
770
- if (propsNode.attrs?.hash) {
771
- // on some clients, the hash is returning as undefined
772
- authState.creds.lastPropHash = propsNode?.attrs?.hash;
648
+ if ((_b = propsNode.attrs) === null || _b === void 0 ? void 0 : _b.hash) { // on some clients, the hash is returning as undefined
649
+ authState.creds.lastPropHash = (_c = propsNode === null || propsNode === void 0 ? void 0 : propsNode.attrs) === null || _c === void 0 ? void 0 : _c.hash;
773
650
  ev.emit('creds.update', authState.creds);
774
651
  }
775
- props = reduceBinaryNodeToDictionary(propsNode, 'prop');
652
+ props = (0, WABinary_1.reduceBinaryNodeToDictionary)(propsNode, 'prop');
776
653
  }
777
- // Extract protocol-relevant AB props (only the ones we need)
778
- const privacyTokenProp = props['10518'] ?? props['privacy_token_sending_on_all_1_on_1_messages'];
779
- if (privacyTokenProp !== undefined) {
780
- serverProps.privacyTokenOn1to1 = privacyTokenProp === 'true' || privacyTokenProp === '1';
781
- }
782
- const profilePicProp = props['9666'] ?? props['profile_scraping_privacy_token_in_photo_iq'];
783
- if (profilePicProp !== undefined) {
784
- serverProps.profilePicPrivacyToken = profilePicProp === 'true' || profilePicProp === '1';
785
- }
786
- const lidIssueProp = props['14303'] ?? props['lid_trusted_token_issue_to_lid'];
787
- if (lidIssueProp !== undefined) {
788
- serverProps.lidTrustedTokenIssueToLid = lidIssueProp === 'true' || lidIssueProp === '1';
789
- }
790
- logger.debug({ serverProps }, 'fetched props');
654
+ logger.debug('fetched props');
791
655
  return props;
792
656
  };
793
657
  /**
794
658
  * modify a chat -- mark unread, read etc.
795
659
  * lastMessages must be sorted in reverse chronologically
796
660
  * requires the last messages till the last message received; required for archive & unread
797
- */
661
+ */
798
662
  const chatModify = (mod, jid) => {
799
- const patch = chatModificationToAppPatch(mod, jid);
663
+ const patch = (0, Utils_1.chatModificationToAppPatch)(mod, jid);
800
664
  return appPatch(patch);
801
665
  };
802
- /**
803
- * Enable/Disable link preview privacy, not related to baileys link preview generation
804
- */
805
- const updateDisableLinkPreviewsPrivacy = (isPreviewsDisabled) => {
806
- return chatModify({
807
- disableLinkPreviews: { isPreviewsDisabled }
808
- }, '');
809
- };
810
666
  /**
811
667
  * Star or Unstar a message
812
668
  */
@@ -818,32 +674,6 @@ export const makeChatsSocket = (config) => {
818
674
  }
819
675
  }, jid);
820
676
  };
821
- /**
822
- * Add or Edit Contact
823
- */
824
- const addOrEditContact = (jid, contact) => {
825
- return chatModify({
826
- contact
827
- }, jid);
828
- };
829
- /**
830
- * Remove Contact
831
- */
832
- const removeContact = (jid) => {
833
- return chatModify({
834
- contact: null
835
- }, jid);
836
- };
837
- /**
838
- * Adds label
839
- */
840
- const addLabel = (jid, labels) => {
841
- return chatModify({
842
- addLabel: {
843
- ...labels
844
- }
845
- }, jid);
846
- };
847
677
  /**
848
678
  * Adds label for the chats
849
679
  */
@@ -886,127 +716,49 @@ export const makeChatsSocket = (config) => {
886
716
  }
887
717
  }, jid);
888
718
  };
889
- /**
890
- * Add or Edit Quick Reply
891
- */
892
- const addOrEditQuickReply = (quickReply) => {
893
- return chatModify({
894
- quickReply
895
- }, '');
896
- };
897
- /**
898
- * Remove Quick Reply
899
- */
900
- const removeQuickReply = (timestamp) => {
901
- return chatModify({
902
- quickReply: { timestamp, deleted: true }
903
- }, '');
904
- };
905
719
  /**
906
720
  * queries need to be fired on connection open
907
721
  * help ensure parity with WA Web
908
722
  * */
909
723
  const executeInitQueries = async () => {
910
- await Promise.all([fetchProps(), fetchBlocklist(), fetchPrivacySettings()]);
724
+ await Promise.all([
725
+ fetchProps(),
726
+ fetchBlocklist(),
727
+ fetchPrivacySettings(),
728
+ ]);
911
729
  };
912
730
  const upsertMessage = ev.createBufferedFunction(async (msg, type) => {
731
+ var _a, _b, _c;
913
732
  ev.emit('messages.upsert', { messages: [msg], type });
914
733
  if (!!msg.pushName) {
915
- let jid = msg.key.fromMe ? authState.creds.me.id : msg.key.participant || msg.key.remoteJid;
916
- jid = jidNormalizedUser(jid);
734
+ let jid = msg.key.fromMe ? authState.creds.me.id : (msg.key.participant || msg.key.remoteJid);
735
+ jid = (0, WABinary_1.jidNormalizedUser)(jid);
917
736
  if (!msg.key.fromMe) {
918
737
  ev.emit('contacts.update', [{ id: jid, notify: msg.pushName, verifiedName: msg.verifiedBizName }]);
919
738
  }
920
739
  // update our pushname too
921
- if (msg.key.fromMe && msg.pushName && authState.creds.me?.name !== msg.pushName) {
740
+ if (msg.key.fromMe && msg.pushName && ((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.name) !== msg.pushName) {
922
741
  ev.emit('creds.update', { me: { ...authState.creds.me, name: msg.pushName } });
923
742
  }
924
743
  }
925
- const historyMsg = getHistoryMsg(msg.message);
744
+ const historyMsg = (0, Utils_1.getHistoryMsg)(msg.message);
926
745
  const shouldProcessHistoryMsg = historyMsg
927
- ? shouldSyncHistoryMessage(historyMsg) &&
928
- PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType)
746
+ ? (shouldSyncHistoryMessage(historyMsg)
747
+ && Defaults_1.PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType))
929
748
  : false;
930
- if (historyMsg && shouldProcessHistoryMsg) {
931
- const syncType = historyMsg.syncType;
932
- // INITIAL_BOOTSTRAP — fire immediately, no progress check (same as WA Web K function)
933
- if (syncType === proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP &&
934
- !historySyncStatus.initialBootstrapComplete) {
935
- historySyncStatus.initialBootstrapComplete = true;
936
- ev.emit('messaging-history.status', {
937
- syncType,
938
- status: 'complete',
939
- explicit: true
940
- });
941
- }
942
- // RECENT with progress === 100 — explicit completion
943
- if (syncType === proto.HistorySync.HistorySyncType.RECENT &&
944
- historyMsg.progress === 100 &&
945
- !historySyncStatus.recentSyncComplete) {
946
- historySyncStatus.recentSyncComplete = true;
947
- clearTimeout(historySyncPausedTimeout);
948
- historySyncPausedTimeout = undefined;
949
- ev.emit('messaging-history.status', {
950
- syncType,
951
- status: 'complete',
952
- explicit: true
953
- });
954
- }
955
- // Reset 120s paused timeout on any RECENT chunk (like WA Web's handleChunkProgress)
956
- if (syncType === proto.HistorySync.HistorySyncType.RECENT && !historySyncStatus.recentSyncComplete) {
957
- clearTimeout(historySyncPausedTimeout);
958
- historySyncPausedTimeout = setTimeout(() => {
959
- if (!historySyncStatus.recentSyncComplete) {
960
- historySyncStatus.recentSyncComplete = true;
961
- ev.emit('messaging-history.status', {
962
- syncType: proto.HistorySync.HistorySyncType.RECENT,
963
- status: 'paused',
964
- explicit: false
965
- });
966
- }
967
- historySyncPausedTimeout = undefined;
968
- }, HISTORY_SYNC_PAUSED_TIMEOUT_MS);
969
- }
749
+ if (historyMsg && !authState.creds.myAppStateKeyId) {
750
+ logger.warn('skipping app state sync, as myAppStateKeyId is not set');
751
+ pendingAppStateSync = true;
970
752
  }
971
- // State machine: decide on sync and flush
972
- if (historyMsg && syncState === SyncState.AwaitingInitialSync) {
973
- if (awaitingSyncTimeout) {
974
- clearTimeout(awaitingSyncTimeout);
975
- awaitingSyncTimeout = undefined;
976
- }
977
- if (shouldProcessHistoryMsg) {
978
- syncState = SyncState.Syncing;
979
- logger.info('Transitioned to Syncing state');
980
- // Let doAppStateSync handle the final flush after it's done
981
- }
982
- else {
983
- syncState = SyncState.Online;
984
- logger.info('History sync skipped, transitioning to Online state and flushing buffer');
985
- ev.flush();
986
- }
987
- }
988
- const doAppStateSync = async () => {
989
- if (syncState === SyncState.Syncing) {
990
- // All collections will be synced, so clear any blocked ones
991
- blockedCollections.clear();
992
- logger.info('Doing app state sync');
993
- await resyncAppState(ALL_WA_PATCH_NAMES, true);
994
- // Sync is complete, go online and flush everything
995
- syncState = SyncState.Online;
996
- logger.info('App state sync complete, transitioning to Online state and flushing buffer');
997
- ev.flush();
998
- const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1;
999
- ev.emit('creds.update', { accountSyncCounter });
1000
- }
1001
- };
1002
753
  await Promise.all([
1003
754
  (async () => {
1004
- if (shouldProcessHistoryMsg) {
755
+ if (historyMsg
756
+ && authState.creds.myAppStateKeyId) {
757
+ pendingAppStateSync = false;
1005
758
  await doAppStateSync();
1006
759
  }
1007
760
  })(),
1008
- processMessage(msg, {
1009
- signalRepository,
761
+ (0, process_message_1.default)(msg, {
1010
762
  shouldProcessHistoryMsg,
1011
763
  placeholderResendCache,
1012
764
  ev,
@@ -1014,19 +766,31 @@ export const makeChatsSocket = (config) => {
1014
766
  keyStore: authState.keys,
1015
767
  logger,
1016
768
  options: config.options,
1017
- getMessage
769
+ getMessage: config.getMessage,
1018
770
  })
1019
771
  ]);
1020
- // If the app state key arrives and we are waiting to sync, trigger the sync now.
1021
- if (msg.message?.protocolMessage?.appStateSyncKeyShare && syncState === SyncState.Syncing) {
1022
- logger.info('App state sync key arrived, triggering app state sync');
772
+ if (((_c = (_b = msg.message) === null || _b === void 0 ? void 0 : _b.protocolMessage) === null || _c === void 0 ? void 0 : _c.appStateSyncKeyShare)
773
+ && pendingAppStateSync) {
1023
774
  await doAppStateSync();
775
+ pendingAppStateSync = false;
776
+ }
777
+ async function doAppStateSync() {
778
+ if (!authState.creds.accountSyncCounter) {
779
+ logger.info('doing initial app state sync');
780
+ await resyncAppState(Types_1.ALL_WA_PATCH_NAMES, true);
781
+ const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1;
782
+ ev.emit('creds.update', { accountSyncCounter });
783
+ if (needToFlushWithAppStateSync) {
784
+ logger.debug('flushing with app state sync');
785
+ ev.flush();
786
+ }
787
+ }
1024
788
  }
1025
789
  });
1026
790
  ws.on('CB:presence', handlePresenceUpdate);
1027
791
  ws.on('CB:chatstate', handlePresenceUpdate);
1028
792
  ws.on('CB:ib,,dirty', async (node) => {
1029
- const { attrs } = getBinaryNodeChild(node, 'dirty');
793
+ const { attrs } = (0, WABinary_1.getBinaryNodeChild)(node, 'dirty');
1030
794
  const type = attrs.type;
1031
795
  switch (type) {
1032
796
  case 'account_sync':
@@ -1048,122 +812,42 @@ export const makeChatsSocket = (config) => {
1048
812
  }
1049
813
  });
1050
814
  ev.on('connection.update', ({ connection, receivedPendingNotifications }) => {
1051
- if (connection === 'close') {
1052
- blockedCollections.clear();
1053
- clearTimeout(historySyncPausedTimeout);
1054
- historySyncPausedTimeout = undefined;
1055
- }
815
+ var _a;
1056
816
  if (connection === 'open') {
1057
817
  if (fireInitQueries) {
1058
- executeInitQueries().catch(error => onUnexpectedError(error, 'init queries'));
818
+ executeInitQueries()
819
+ .catch(error => onUnexpectedError(error, 'init queries'));
1059
820
  }
1060
- sendPresenceUpdate(markOnlineOnConnect ? 'available' : 'unavailable').catch(error => onUnexpectedError(error, 'presence update requests'));
821
+ sendPresenceUpdate(markOnlineOnConnect ? 'available' : 'unavailable')
822
+ .catch(error => onUnexpectedError(error, 'presence update requests'));
1061
823
  }
1062
- if (!receivedPendingNotifications || syncState !== SyncState.Connecting) {
1063
- return;
1064
- }
1065
- historySyncStatus.initialBootstrapComplete = false;
1066
- historySyncStatus.recentSyncComplete = false;
1067
- clearTimeout(historySyncPausedTimeout);
1068
- historySyncPausedTimeout = undefined;
1069
- syncState = SyncState.AwaitingInitialSync;
1070
- logger.info('Connection is now AwaitingInitialSync, buffering events');
1071
- ev.buffer();
1072
- const willSyncHistory = shouldSyncHistoryMessage(proto.Message.HistorySyncNotification.create({
1073
- syncType: proto.HistorySync.HistorySyncType.RECENT
1074
- }));
1075
- if (!willSyncHistory) {
1076
- logger.info('History sync is disabled by config, not waiting for notification. Transitioning to Online.');
1077
- syncState = SyncState.Online;
1078
- setTimeout(() => ev.flush(), 0);
1079
- return;
1080
- }
1081
- // On reconnection (accountSyncCounter > 0), the server does not push
1082
- // history sync notifications — the device already has its data.
1083
- // Skip the 20s wait and go online immediately.
1084
- if (authState.creds.accountSyncCounter > 0) {
1085
- logger.info('Reconnection with existing sync data, skipping history sync wait. Transitioning to Online.');
1086
- syncState = SyncState.Online;
1087
- setTimeout(() => ev.flush(), 0);
1088
- return;
1089
- }
1090
- logger.info('First connection, awaiting history sync notification with a 20s timeout.');
1091
- if (awaitingSyncTimeout) {
1092
- clearTimeout(awaitingSyncTimeout);
1093
- }
1094
- awaitingSyncTimeout = setTimeout(() => {
1095
- if (syncState === SyncState.AwaitingInitialSync) {
1096
- logger.warn('Timeout in AwaitingInitialSync, forcing state to Online and flushing buffer');
1097
- syncState = SyncState.Online;
1098
- ev.flush();
1099
- // Increment so subsequent reconnections skip the 20s wait.
1100
- // Late-arriving history is still processed via processMessage
1101
- // regardless of the state machine phase.
1102
- const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1;
1103
- ev.emit('creds.update', { accountSyncCounter });
1104
- }
1105
- }, 20000);
1106
- });
1107
- // When an app state sync key arrives (myAppStateKeyId is set) and there are
1108
- // collections blocked on a missing key, trigger a re-sync for just those collections.
1109
- // This mirrors WA Web's Blocked → retry-on-key-arrival behavior.
1110
- ev.on('creds.update', ({ myAppStateKeyId }) => {
1111
- if (!myAppStateKeyId || blockedCollections.size === 0) {
1112
- return;
1113
- }
1114
- // If we're in the middle of a full sync, doAppStateSync handles all collections
1115
- if (syncState === SyncState.Syncing) {
1116
- blockedCollections.clear();
1117
- return;
1118
- }
1119
- const collections = [...blockedCollections];
1120
- blockedCollections.clear();
1121
- logger.info({ collections }, 'app state sync key arrived, re-syncing blocked collections');
1122
- resyncAppState(collections, false).catch(error => onUnexpectedError(error, 'blocked collections resync'));
1123
- });
1124
- ev.on('lid-mapping.update', async ({ lid, pn }) => {
1125
- try {
1126
- await signalRepository.lidMapping.storeLIDPNMappings([{ lid, pn }]);
1127
- }
1128
- catch (error) {
1129
- logger.warn({ lid, pn, error }, 'Failed to store LID-PN mapping');
824
+ if (receivedPendingNotifications && // if we don't have the app state key
825
+ // we keep buffering events until we finally have
826
+ // the key and can sync the messages
827
+ !((_a = authState.creds) === null || _a === void 0 ? void 0 : _a.myAppStateKeyId)) {
828
+ ev.buffer();
829
+ needToFlushWithAppStateSync = true;
1130
830
  }
1131
831
  });
1132
- registerSocketEndHandler(() => {
1133
- if (awaitingSyncTimeout) {
1134
- clearTimeout(awaitingSyncTimeout);
1135
- awaitingSyncTimeout = undefined;
1136
- }
1137
- if (!config.placeholderResendCache && placeholderResendCache.close) {
1138
- placeholderResendCache.close();
1139
- }
1140
- syncState = SyncState.Connecting;
1141
- privacySettings = undefined;
1142
- });
1143
832
  return {
1144
833
  ...sock,
1145
- serverProps,
1146
- createCallLink,
1147
834
  getBotListV2,
1148
- messageMutex,
1149
- receiptMutex,
1150
- appStatePatchMutex,
1151
- notificationMutex,
835
+ processingMutex,
1152
836
  fetchPrivacySettings,
1153
837
  upsertMessage,
1154
838
  appPatch,
1155
839
  sendPresenceUpdate,
1156
840
  presenceSubscribe,
1157
841
  profilePictureUrl,
842
+ onWhatsApp,
1158
843
  fetchBlocklist,
1159
- fetchStatus,
1160
844
  fetchDisappearingDuration,
845
+ fetchStatus,
1161
846
  updateProfilePicture,
1162
847
  removeProfilePicture,
1163
848
  updateProfileStatus,
1164
849
  updateProfileName,
1165
850
  updateBlockStatus,
1166
- updateDisableLinkPreviewsPrivacy,
1167
851
  updateCallPrivacy,
1168
852
  updateMessagesPrivacy,
1169
853
  updateLastSeenPrivacy,
@@ -1177,17 +861,11 @@ export const makeChatsSocket = (config) => {
1177
861
  resyncAppState,
1178
862
  chatModify,
1179
863
  cleanDirtyBits,
1180
- addOrEditContact,
1181
- removeContact,
1182
- placeholderResendCache,
1183
- addLabel,
1184
864
  addChatLabel,
1185
865
  removeChatLabel,
1186
866
  addMessageLabel,
1187
867
  removeMessageLabel,
1188
- star,
1189
- addOrEditQuickReply,
1190
- removeQuickReply
868
+ star
1191
869
  };
1192
870
  };
1193
- //# sourceMappingURL=chats.js.map
871
+ exports.makeChatsSocket = makeChatsSocket;