@badzz88/baileys 8.5.6 → 8.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/README.md +337 -1055
  2. package/WAProto/WAProto.proto +28 -1189
  3. package/WAProto/fix-imports.js +79 -69
  4. package/WAProto/index.d.ts +71491 -15254
  5. package/WAProto/index.js +126436 -19814
  6. package/engine-requirements.js +8 -15
  7. package/lib/Defaults/index.js +130 -0
  8. package/{src → lib}/Signal/Group/ciphertext-message.js +2 -5
  9. package/lib/Signal/Group/group-session-builder.js +30 -0
  10. package/{src → lib}/Signal/Group/group_cipher.js +11 -11
  11. package/lib/Signal/Group/index.js +12 -0
  12. package/lib/Signal/Group/keyhelper.js +18 -0
  13. package/{src → lib}/Signal/Group/sender-chain-key.js +6 -9
  14. package/{src → lib}/Signal/Group/sender-key-distribution-message.js +6 -9
  15. package/{src → lib}/Signal/Group/sender-key-message.js +9 -12
  16. package/{src → lib}/Signal/Group/sender-key-name.js +2 -5
  17. package/{src → lib}/Signal/Group/sender-key-record.js +8 -11
  18. package/{src → lib}/Signal/Group/sender-key-state.js +6 -9
  19. package/lib/Signal/Group/sender-message-key.js +26 -0
  20. package/{src → lib}/Signal/libsignal.js +131 -155
  21. package/{src → lib}/Signal/lid-mapping.js +27 -23
  22. package/lib/Socket/Client/index.js +3 -0
  23. package/lib/Socket/Client/types.js +11 -0
  24. package/{src → lib}/Socket/Client/websocket.js +11 -18
  25. package/{src → lib}/Socket/business.js +35 -67
  26. package/{src → lib}/Socket/chats.js +294 -550
  27. package/{src → lib}/Socket/communities.js +82 -114
  28. package/lib/Socket/graphql.js +716 -0
  29. package/lib/Socket/groups.js +374 -0
  30. package/lib/Socket/index.js +18 -0
  31. package/lib/Socket/interop.js +463 -0
  32. package/{src → lib}/Socket/luxu.js +120 -82
  33. package/lib/Socket/messages-recv.js +1916 -0
  34. package/lib/Socket/messages-send.js +1436 -0
  35. package/lib/Socket/mex.js +54 -0
  36. package/lib/Socket/newsletter.js +757 -0
  37. package/lib/Socket/privacy.js +318 -0
  38. package/{src → lib}/Socket/socket.js +356 -244
  39. package/lib/Socket/username.js +236 -0
  40. package/lib/Store/index.js +10 -0
  41. package/{src → lib}/Store/keyed-db.js +11 -21
  42. package/lib/Store/make-cache-manager-store.js +85 -0
  43. package/lib/Store/make-in-memory-store.js +244 -0
  44. package/{src → lib}/Store/make-ordered-dictionary.js +19 -25
  45. package/{src → lib}/Store/object-repository.js +11 -5
  46. package/lib/Types/Auth.js +2 -0
  47. package/lib/Types/Bussines.js +2 -0
  48. package/lib/Types/Call.js +2 -0
  49. package/lib/Types/Chat.js +8 -0
  50. package/lib/Types/Contact.js +2 -0
  51. package/lib/Types/Events.js +2 -0
  52. package/lib/Types/GroupMetadata.js +2 -0
  53. package/lib/Types/Label.js +25 -0
  54. package/lib/Types/LabelAssociation.js +7 -0
  55. package/lib/Types/Message.js +11 -0
  56. package/lib/Types/Mex.js +111 -0
  57. package/lib/Types/Product.js +2 -0
  58. package/lib/Types/Signal.js +2 -0
  59. package/lib/Types/Socket.js +3 -0
  60. package/lib/Types/State.js +56 -0
  61. package/lib/Types/USync.js +2 -0
  62. package/lib/Types/index.js +26 -0
  63. package/{src → lib}/Utils/auth-utils.js +91 -43
  64. package/lib/Utils/browser-utils.js +48 -0
  65. package/lib/Utils/business.js +231 -0
  66. package/lib/Utils/chat-utils.js +872 -0
  67. package/lib/Utils/companion-reg-client-utils.js +35 -0
  68. package/lib/Utils/crypto.js +118 -0
  69. package/lib/Utils/decode-wa-message.js +350 -0
  70. package/{src → lib}/Utils/event-buffer.js +81 -39
  71. package/lib/Utils/generics.js +403 -0
  72. package/lib/Utils/history.js +134 -0
  73. package/{src → lib}/Utils/identity-change-handler.js +9 -11
  74. package/lib/Utils/index.js +23 -0
  75. package/lib/Utils/link-preview.js +85 -0
  76. package/lib/Utils/logger.js +3 -0
  77. package/lib/Utils/lt-hash.js +8 -0
  78. package/{src → lib}/Utils/make-mutex.js +7 -10
  79. package/lib/Utils/message-composer.js +273 -0
  80. package/{src → lib}/Utils/message-retry-manager.js +76 -28
  81. package/lib/Utils/messages-media.js +870 -0
  82. package/lib/Utils/messages.js +1337 -0
  83. package/lib/Utils/noise-handler.js +201 -0
  84. package/{src → lib}/Utils/offline-node-processor.js +10 -4
  85. package/{src → lib}/Utils/pre-key-manager.js +27 -11
  86. package/lib/Utils/process-message.js +630 -0
  87. package/{src → lib}/Utils/reporting-utils.js +12 -15
  88. package/lib/Utils/signal.js +201 -0
  89. package/{src → lib}/Utils/stanza-ack.js +12 -4
  90. package/lib/Utils/sticker.js +110 -0
  91. package/{src → lib}/Utils/sync-action-utils.js +14 -10
  92. package/{src → lib}/Utils/tc-token-utils.js +48 -43
  93. package/{src → lib}/Utils/use-multi-file-auth-state.js +35 -25
  94. package/lib/Utils/validate-connection.js +203 -0
  95. package/{src → lib}/WABinary/constants.js +9 -12
  96. package/{src → lib}/WABinary/decode.js +38 -118
  97. package/{src → lib}/WABinary/encode.js +6 -11
  98. package/lib/WABinary/generic-utils.js +204 -0
  99. package/lib/WABinary/index.js +6 -0
  100. package/lib/WABinary/jid-utils.js +98 -0
  101. package/lib/WABinary/types.js +2 -0
  102. package/{src → lib}/WAM/BinaryInfo.js +2 -5
  103. package/{src → lib}/WAM/constants.js +4 -16635
  104. package/{src → lib}/WAM/encode.js +18 -17
  105. package/lib/WAM/index.js +4 -0
  106. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +53 -0
  107. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +43 -0
  108. package/lib/WAUSync/Protocols/USyncContactProtocol.js +54 -0
  109. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
  110. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
  111. package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +58 -0
  112. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +30 -0
  113. package/lib/WAUSync/Protocols/USyncPictureProtocol.js +32 -0
  114. package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +28 -0
  115. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +39 -0
  116. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +38 -0
  117. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +27 -0
  118. package/lib/WAUSync/Protocols/index.js +12 -0
  119. package/lib/WAUSync/USyncQuery.js +151 -0
  120. package/lib/WAUSync/USyncUser.js +56 -0
  121. package/lib/WAUSync/index.js +3 -0
  122. package/{src → lib}/index.js +16 -51
  123. package/package.json +129 -99
  124. package/LICENSE +0 -21
  125. package/src/Defaults/index.js +0 -186
  126. package/src/Defaults/phonenumber-mcc.json +0 -223
  127. package/src/Signal/Group/group-session-builder.js +0 -86
  128. package/src/Signal/Group/index.js +0 -140
  129. package/src/Signal/Group/keyhelper.js +0 -77
  130. package/src/Signal/Group/sender-message-key.js +0 -29
  131. package/src/Socket/Client/index.js +0 -31
  132. package/src/Socket/Client/types.js +0 -13
  133. package/src/Socket/aigroups.js +0 -221
  134. package/src/Socket/graphql.js +0 -523
  135. package/src/Socket/groups.js +0 -516
  136. package/src/Socket/index.js +0 -31
  137. package/src/Socket/interactive-handler.js +0 -527
  138. package/src/Socket/interop.js +0 -339
  139. package/src/Socket/managed-account.js +0 -98
  140. package/src/Socket/messages-recv.js +0 -2685
  141. package/src/Socket/messages-send.js +0 -2047
  142. package/src/Socket/mex.js +0 -57
  143. package/src/Socket/newsletter.js +0 -455
  144. package/src/Socket/privacy.js +0 -125
  145. package/src/Socket/registration.js +0 -236
  146. package/src/Socket/text-router.js +0 -65
  147. package/src/Socket/username.js +0 -130
  148. package/src/Store/index.js +0 -33
  149. package/src/Store/make-cache-manager-store.js +0 -84
  150. package/src/Store/make-in-memory-store.js +0 -551
  151. package/src/Types/Auth.js +0 -31
  152. package/src/Types/Bussines.js +0 -2
  153. package/src/Types/Call.js +0 -2
  154. package/src/Types/Chat.js +0 -4
  155. package/src/Types/Contact.js +0 -2
  156. package/src/Types/Events.js +0 -2
  157. package/src/Types/GroupMetadata.js +0 -2
  158. package/src/Types/Label.js +0 -26
  159. package/src/Types/LabelAssociation.js +0 -8
  160. package/src/Types/Message.js +0 -93
  161. package/src/Types/Mex.js +0 -112
  162. package/src/Types/Newsletter.js +0 -109
  163. package/src/Types/Product.js +0 -2
  164. package/src/Types/Signal.js +0 -2
  165. package/src/Types/Socket.js +0 -2
  166. package/src/Types/State.js +0 -62
  167. package/src/Types/USync.js +0 -2
  168. package/src/Types/index.js +0 -56
  169. package/src/Utils/browser-utils.js +0 -112
  170. package/src/Utils/business.js +0 -240
  171. package/src/Utils/chat-utils.js +0 -1230
  172. package/src/Utils/command-loader.d.ts +0 -27
  173. package/src/Utils/command-loader.js +0 -89
  174. package/src/Utils/companion-reg-client-utils.js +0 -40
  175. package/src/Utils/consumer-application.js +0 -105
  176. package/src/Utils/crypto.js +0 -118
  177. package/src/Utils/curve25519-js.js +0 -242
  178. package/src/Utils/decode-wa-message.js +0 -529
  179. package/src/Utils/generics.js +0 -483
  180. package/src/Utils/group-history.js +0 -44
  181. package/src/Utils/history.js +0 -232
  182. package/src/Utils/index.js +0 -58
  183. package/src/Utils/jid-display-normalization.js +0 -195
  184. package/src/Utils/link-preview.js +0 -135
  185. package/src/Utils/logger.js +0 -8
  186. package/src/Utils/lt-hash.js +0 -25
  187. package/src/Utils/message-composer.js +0 -471
  188. package/src/Utils/messages-media.js +0 -843
  189. package/src/Utils/messages.js +0 -2817
  190. package/src/Utils/meta-ai-msmsg.js +0 -222
  191. package/src/Utils/native-bridge.js +0 -68
  192. package/src/Utils/noise-handler.js +0 -169
  193. package/src/Utils/process-message.js +0 -950
  194. package/src/Utils/session-pool.d.ts +0 -14
  195. package/src/Utils/session-pool.js +0 -70
  196. package/src/Utils/signal.js +0 -217
  197. package/src/Utils/sticker.d.ts +0 -13
  198. package/src/Utils/sticker.js +0 -123
  199. package/src/Utils/validate-connection.js +0 -209
  200. package/src/Utils/view-once-cache.d.ts +0 -12
  201. package/src/Utils/view-once-cache.js +0 -63
  202. package/src/Utils/voip-rekey.js +0 -22
  203. package/src/WABinary/generic-utils.js +0 -238
  204. package/src/WABinary/index.js +0 -34
  205. package/src/WABinary/jid-utils.js +0 -351
  206. package/src/WABinary/types.js +0 -2
  207. package/src/WAM/index.js +0 -32
  208. package/src/WAUSync/Protocols/USyncBotProfileProtocol.js +0 -53
  209. package/src/WAUSync/Protocols/USyncBusinessProtocol.js +0 -44
  210. package/src/WAUSync/Protocols/USyncContactProtocol.js +0 -55
  211. package/src/WAUSync/Protocols/USyncDeviceProtocol.js +0 -55
  212. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.js +0 -31
  213. package/src/WAUSync/Protocols/USyncFeatureProtocol.js +0 -54
  214. package/src/WAUSync/Protocols/USyncLIDProtocol.js +0 -32
  215. package/src/WAUSync/Protocols/USyncNewsletterProtocol.js +0 -473
  216. package/src/WAUSync/Protocols/USyncPictureProtocol.js +0 -34
  217. package/src/WAUSync/Protocols/USyncSidelistProtocol.js +0 -29
  218. package/src/WAUSync/Protocols/USyncStatusProtocol.js +0 -42
  219. package/src/WAUSync/Protocols/USyncTextStatusProtocol.js +0 -38
  220. package/src/WAUSync/Protocols/USyncUsernameProtocol.js +0 -28
  221. package/src/WAUSync/Protocols/index.js +0 -40
  222. package/src/WAUSync/USyncQuery.js +0 -126
  223. package/src/WAUSync/USyncUser.js +0 -50
  224. package/src/WAUSync/index.js +0 -32
  225. package/src/antiban.js +0 -4152
@@ -1,55 +1,57 @@
1
- 'use strict';
2
- var __importDefault = (this && this.__importDefault) ||
3
- function (mod) {
4
- return mod && mod.__esModule ? mod : { default: mod };
5
- };
6
- Object.defineProperty(exports, '__esModule', { value: true });
7
- exports.makeChatsSocket = void 0;
8
- const node_cache_1 = __importDefault(require('@cacheable/node-cache'));
9
- const boom_1 = require('@hapi/boom');
10
- const index_js_1 = require('../../WAProto/index.js');
11
- const Defaults_1 = require('../Defaults');
12
- const Types_1 = require('../Types');
13
- const State_1 = require('../Types/State');
14
- const Utils_1 = require('../Utils');
15
- const make_mutex_1 = require('../Utils/make-mutex');
16
- const process_message_1 = __importDefault(require('../Utils/process-message'));
17
- const tc_token_utils_1 = require('../Utils/tc-token-utils');
18
- const WABinary_1 = require('../WABinary');
19
- const WAUSync_1 = require('../WAUSync');
20
- const socket_js_1 = require('./socket.js');
21
- const interop_js_1 = require('./interop.js');
22
- const makeChatsSocket = config => {
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) => {
23
15
  const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, getMessage } = config;
24
- const sock = (0, interop_js_1.makeInteropSocket)((0, socket_js_1.makeSocket)(config));
25
- const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError, sendUnifiedSession, initInterop, fetchIntegrators, acceptInteropTOS, optInIntegrators, optOutIntegrators, resolveInteropUser, resolveInteropUsers, getReachabilitySettings, setReachabilitySettings, blockInteropUser, unblockInteropUser, reportInteropSpam, trustInteropContact, createInteropGroup, leaveInteropGroup, getInteropGroupAddPrivacy, INTEGRATOR_BIRDYCHAT, INTEGRATOR_HAIKET } = sock;
16
+ const sock = makeSocket(config);
17
+ const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError, sendUnifiedSession, registerSocketEndHandler } = sock;
26
18
  const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
27
19
  let privacySettings;
20
+ /** Server-assigned AB props for protocol behavior. */
28
21
  const serverProps = {
22
+ /** AB prop 10518: gate tctoken on 1:1 messages. Default true (safe: avoids 463). */
29
23
  privacyTokenOn1to1: true,
24
+ /** AB prop 9666: gate tctoken on profile picture IQs. WA Web default: true. */
30
25
  profilePicPrivacyToken: true,
26
+ /** AB prop 14303: issue tctokens to LID instead of PN. WA Web default: false. */
31
27
  lidTrustedTokenIssueToLid: false
32
28
  };
33
- let syncState = State_1.SyncState.Connecting;
34
- const messageMutex = (0, make_mutex_1.makeMutex)();
35
- const receiptMutex = (0, make_mutex_1.makeMutex)();
36
- const appStatePatchMutex = (0, make_mutex_1.makeMutex)();
37
- const notificationMutex = (0, make_mutex_1.makeMutex)();
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
38
39
  let awaitingSyncTimeout;
40
+ // In-memory history sync completion tracking (resets on reconnection)
39
41
  const historySyncStatus = {
40
42
  initialBootstrapComplete: false,
41
43
  recentSyncComplete: false
42
44
  };
43
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.
44
48
  const blockedCollections = new Set();
45
49
  const placeholderResendCache = config.placeholderResendCache ||
46
- new node_cache_1.default({
47
- stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.MSG_RETRY,
50
+ new NodeCache({
51
+ stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
48
52
  useClones: false
49
53
  });
50
- if (!config.placeholderResendCache) {
51
- config.placeholderResendCache = placeholderResendCache;
52
- }
54
+ /** helper function to fetch the given app state sync key */
53
55
  const getAppStateSyncKey = async (keyId) => {
54
56
  const { [keyId]: key } = await authState.keys.get('app-state-sync-key', [keyId]);
55
57
  return key;
@@ -60,21 +62,22 @@ const makeChatsSocket = config => {
60
62
  tag: 'iq',
61
63
  attrs: {
62
64
  xmlns: 'privacy',
63
- to: WABinary_1.S_WHATSAPP_NET,
65
+ to: S_WHATSAPP_NET,
64
66
  type: 'get'
65
67
  },
66
68
  content: [{ tag: 'privacy', attrs: {} }]
67
69
  });
68
- privacySettings = (0, WABinary_1.reduceBinaryNodeToDictionary)(content?.[0], 'category');
70
+ privacySettings = reduceBinaryNodeToDictionary(content?.[0], 'category');
69
71
  }
70
72
  return privacySettings;
71
73
  };
74
+ /** helper function to run a privacy IQ query */
72
75
  const privacyQuery = async (name, value) => {
73
76
  await query({
74
77
  tag: 'iq',
75
78
  attrs: {
76
79
  xmlns: 'privacy',
77
- to: WABinary_1.S_WHATSAPP_NET,
80
+ to: S_WHATSAPP_NET,
78
81
  type: 'set'
79
82
  },
80
83
  content: [
@@ -109,59 +112,6 @@ const makeChatsSocket = config => {
109
112
  const updateStatusPrivacy = async (value) => {
110
113
  await privacyQuery('status', value);
111
114
  };
112
- const getStatusPrivacy = async () => {
113
- const result = await query({
114
- tag: 'iq',
115
- attrs: {
116
- xmlns: 'status',
117
- to: WABinary_1.S_WHATSAPP_NET,
118
- type: 'get'
119
- },
120
- content: [{ tag: 'privacy', attrs: {} }]
121
- });
122
- const privacyNode = result?.content?.[0];
123
- if (!privacyNode)
124
- return null;
125
- const lists = [];
126
- for (const listNode of (privacyNode.content || [])) {
127
- const { type, id, listname, emoji, selected, deleted } = listNode.attrs || {};
128
- const members = (listNode.content || []).map(u => u.attrs?.jid).filter(Boolean);
129
- lists.push({ type, id, listname, emoji, selected: selected === 'true', deleted: deleted === 'true', members });
130
- }
131
- return lists;
132
- };
133
- const setStatusPrivacy = async (type, jids = [], customLists = []) => {
134
- const content = [];
135
- const mainList = {
136
- tag: 'list',
137
- attrs: { type },
138
- content: jids.map(jid => ({ tag: 'user', attrs: { jid }, content: [] }))
139
- };
140
- content.push(mainList);
141
- for (const cl of customLists) {
142
- const attrs = { type: 'customlist', id: cl.id, listname: cl.listname };
143
- if (cl.emoji)
144
- attrs.emoji = cl.emoji;
145
- if (cl.selected)
146
- attrs.selected = 'true';
147
- if (cl.deleted)
148
- attrs.deleted = 'true';
149
- content.push({
150
- tag: 'list',
151
- attrs,
152
- content: (cl.members || []).map(jid => ({ tag: 'user', attrs: { jid }, content: [] }))
153
- });
154
- }
155
- await query({
156
- tag: 'iq',
157
- attrs: {
158
- xmlns: 'status',
159
- to: WABinary_1.S_WHATSAPP_NET,
160
- type: 'set'
161
- },
162
- content: [{ tag: 'privacy', attrs: {}, content }]
163
- });
164
- };
165
115
  const updateReadReceiptsPrivacy = async (value) => {
166
116
  await privacyQuery('readreceipts', value);
167
117
  };
@@ -173,7 +123,7 @@ const makeChatsSocket = config => {
173
123
  tag: 'iq',
174
124
  attrs: {
175
125
  xmlns: 'disappearing_mode',
176
- to: WABinary_1.S_WHATSAPP_NET,
126
+ to: S_WHATSAPP_NET,
177
127
  type: 'set'
178
128
  },
179
129
  content: [
@@ -186,35 +136,12 @@ const makeChatsSocket = config => {
186
136
  ]
187
137
  });
188
138
  };
189
- const fetchBroadcastListQuota = async () => {
190
- const result = await query({
191
- tag: 'iq',
192
- attrs: {
193
- xmlns: 'w:biz',
194
- to: WABinary_1.S_WHATSAPP_NET,
195
- type: 'get'
196
- },
197
- content: [{ tag: 'broadcast_list_quota', attrs: {}, content: [] }]
198
- }, 32000);
199
- const limitsNode = (0, WABinary_1.getBinaryNodeChild)(result, 'limits');
200
- const timeframeNode = (0, WABinary_1.getBinaryNodeChild)(result, 'timeframe');
201
- if (!limitsNode)
202
- return null;
203
- return {
204
- messagesLeft: parseInt(limitsNode.attrs?.messages_left ?? (0, WABinary_1.getBinaryNodeChild)(limitsNode, 'messages_left')?.content ?? '0'),
205
- totalLimit: parseInt(limitsNode.attrs?.total_limit ?? (0, WABinary_1.getBinaryNodeChild)(limitsNode, 'total_limit')?.content ?? '0'),
206
- isHeavySender: (limitsNode.attrs?.is_heavy_sender ?? (0, WABinary_1.getBinaryNodeChild)(limitsNode, 'is_heavy_sender')?.content) === 'true',
207
- startTs: parseInt(timeframeNode?.attrs?.start_ts_s ?? (0, WABinary_1.getBinaryNodeChild)(timeframeNode, 'start_ts_s')?.content ?? '0'),
208
- endTs: parseInt(timeframeNode?.attrs?.end_ts_s ?? (0, WABinary_1.getBinaryNodeChild)(timeframeNode, 'end_ts_s')?.content ?? '0'),
209
- resetTs: parseInt(timeframeNode?.attrs?.reset_ts_s ?? (0, WABinary_1.getBinaryNodeChild)(timeframeNode, 'reset_ts_s')?.content ?? '0')
210
- };
211
- };
212
139
  const getBotListV2 = async () => {
213
140
  const resp = await query({
214
141
  tag: 'iq',
215
142
  attrs: {
216
143
  xmlns: 'bot',
217
- to: WABinary_1.S_WHATSAPP_NET,
144
+ to: S_WHATSAPP_NET,
218
145
  type: 'get'
219
146
  },
220
147
  content: [
@@ -226,11 +153,11 @@ const makeChatsSocket = config => {
226
153
  }
227
154
  ]
228
155
  });
229
- const botNode = (0, WABinary_1.getBinaryNodeChild)(resp, 'bot');
156
+ const botNode = getBinaryNodeChild(resp, 'bot');
230
157
  const botList = [];
231
- for (const section of (0, WABinary_1.getBinaryNodeChildren)(botNode, 'section')) {
158
+ for (const section of getBinaryNodeChildren(botNode, 'section')) {
232
159
  if (section.attrs.type === 'all') {
233
- for (const bot of (0, WABinary_1.getBinaryNodeChildren)(section, 'bot')) {
160
+ for (const bot of getBinaryNodeChildren(section, 'bot')) {
234
161
  botList.push({
235
162
  jid: bot.attrs.jid,
236
163
  personaId: bot.attrs['persona_id']
@@ -240,66 +167,10 @@ const makeChatsSocket = config => {
240
167
  }
241
168
  return botList;
242
169
  };
243
- const getChatBlockingStatus = async () => {
244
- const result = await query({
245
- tag: 'iq',
246
- attrs: {
247
- to: WABinary_1.S_WHATSAPP_NET,
248
- xmlns: 'w:comms:chat',
249
- type: 'get'
250
- },
251
- content: [{ tag: 'query', attrs: {}, content: [{ tag: 'blocking_status', attrs: {} }] }]
252
- });
253
- const blocking = (0, WABinary_1.getBinaryNodeChild)(result, 'blocking') ||
254
- (0, WABinary_1.getBinaryNodeChild)((0, WABinary_1.getBinaryNodeChild)(result, 'query'), 'blocking');
255
- return blocking?.attrs?.status;
256
- };
257
- const updateChatBlockingStatus = async (action) => {
258
- const result = await query({
259
- tag: 'iq',
260
- attrs: {
261
- to: WABinary_1.S_WHATSAPP_NET,
262
- xmlns: 'w:comms:chat',
263
- type: 'set'
264
- },
265
- content: [{ tag: 'blocking', attrs: { action } }]
266
- });
267
- const blocking = (0, WABinary_1.getBinaryNodeChild)(result, 'blocking');
268
- return blocking?.attrs?.status;
269
- };
270
- const getUserDisclosures = async (t = 0) => {
271
- const result = await query({
272
- tag: 'iq',
273
- attrs: { to: WABinary_1.S_WHATSAPP_NET, xmlns: 'tos', type: 'get' },
274
- content: [{ tag: 'get_user_disclosures', attrs: { t: String(t) } }]
275
- });
276
- return (0, WABinary_1.getBinaryNodeChildren)(result, 'notice').map(n => ({ ...n.attrs }));
277
- };
278
- const getOptOutList = async () => {
279
- return query({
280
- tag: 'iq',
281
- attrs: { to: WABinary_1.S_WHATSAPP_NET, xmlns: 'optoutlist', type: 'get' }
282
- });
283
- };
284
- const getPushConfig = async () => {
285
- const result = await query({
286
- tag: 'iq',
287
- attrs: { to: WABinary_1.S_WHATSAPP_NET, xmlns: 'urn:xmpp:whatsapp:push', type: 'get' },
288
- content: [{ tag: 'settings', attrs: {} }]
289
- });
290
- return (0, WABinary_1.getBinaryNodeChild)(result, 'settings');
291
- };
292
- const setPushConfig = async (config) => {
293
- await query({
294
- tag: 'iq',
295
- attrs: { to: WABinary_1.S_WHATSAPP_NET, xmlns: 'urn:xmpp:whatsapp:push', type: 'set' },
296
- content: [{ tag: 'config', attrs: config }]
297
- });
298
- };
299
170
  const fetchStatus = async (...jids) => {
300
- const usyncQuery = new WAUSync_1.USyncQuery().withStatusProtocol();
171
+ const usyncQuery = new USyncQuery().withStatusProtocol();
301
172
  for (const jid of jids) {
302
- usyncQuery.withUser(new WAUSync_1.USyncUser().withId(jid));
173
+ usyncQuery.withUser(new USyncUser().withId(jid));
303
174
  }
304
175
  const result = await sock.executeUSyncQuery(usyncQuery);
305
176
  if (result) {
@@ -307,31 +178,32 @@ const makeChatsSocket = config => {
307
178
  }
308
179
  };
309
180
  const fetchDisappearingDuration = async (...jids) => {
310
- const usyncQuery = new WAUSync_1.USyncQuery().withDisappearingModeProtocol();
181
+ const usyncQuery = new USyncQuery().withDisappearingModeProtocol();
311
182
  for (const jid of jids) {
312
- usyncQuery.withUser(new WAUSync_1.USyncUser().withId(jid));
183
+ usyncQuery.withUser(new USyncUser().withId(jid));
313
184
  }
314
185
  const result = await sock.executeUSyncQuery(usyncQuery);
315
186
  if (result) {
316
187
  return result.list;
317
188
  }
318
189
  };
190
+ /** update the profile picture for yourself or a group */
319
191
  const updateProfilePicture = async (jid, content, dimensions) => {
320
192
  let targetJid;
321
193
  if (!jid) {
322
- 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');
194
+ throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update');
323
195
  }
324
- if ((0, WABinary_1.jidNormalizedUser)(jid) !== (0, WABinary_1.jidNormalizedUser)(authState.creds.me.id)) {
325
- targetJid = (0, WABinary_1.jidNormalizedUser)(jid);
196
+ if (jidNormalizedUser(jid) !== jidNormalizedUser(authState.creds.me.id)) {
197
+ targetJid = jidNormalizedUser(jid); // in case it is someone other than us
326
198
  }
327
199
  else {
328
200
  targetJid = undefined;
329
201
  }
330
- const { img } = await (0, Utils_1.generateProfilePicture)(content, dimensions);
202
+ const { img } = await generateProfilePicture(content, dimensions);
331
203
  await query({
332
204
  tag: 'iq',
333
205
  attrs: {
334
- to: WABinary_1.S_WHATSAPP_NET,
206
+ to: S_WHATSAPP_NET,
335
207
  type: 'set',
336
208
  xmlns: 'w:profile:picture',
337
209
  ...(targetJid ? { target: targetJid } : {})
@@ -345,13 +217,14 @@ const makeChatsSocket = config => {
345
217
  ]
346
218
  });
347
219
  };
220
+ /** remove the profile picture for yourself or a group */
348
221
  const removeProfilePicture = async (jid) => {
349
222
  let targetJid;
350
223
  if (!jid) {
351
- 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');
224
+ throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update');
352
225
  }
353
- if ((0, WABinary_1.jidNormalizedUser)(jid) !== (0, WABinary_1.jidNormalizedUser)(authState.creds.me.id)) {
354
- targetJid = (0, WABinary_1.jidNormalizedUser)(jid);
226
+ if (jidNormalizedUser(jid) !== jidNormalizedUser(authState.creds.me.id)) {
227
+ targetJid = jidNormalizedUser(jid); // in case it is someone other than us
355
228
  }
356
229
  else {
357
230
  targetJid = undefined;
@@ -359,18 +232,19 @@ const makeChatsSocket = config => {
359
232
  await query({
360
233
  tag: 'iq',
361
234
  attrs: {
362
- to: WABinary_1.S_WHATSAPP_NET,
235
+ to: S_WHATSAPP_NET,
363
236
  type: 'set',
364
237
  xmlns: 'w:profile:picture',
365
238
  ...(targetJid ? { target: targetJid } : {})
366
239
  }
367
240
  });
368
241
  };
242
+ /** update the profile status for yourself */
369
243
  const updateProfileStatus = async (status) => {
370
244
  await query({
371
245
  tag: 'iq',
372
246
  attrs: {
373
- to: WABinary_1.S_WHATSAPP_NET,
247
+ to: S_WHATSAPP_NET,
374
248
  type: 'set',
375
249
  xmlns: 'status'
376
250
  },
@@ -391,28 +265,61 @@ const makeChatsSocket = config => {
391
265
  tag: 'iq',
392
266
  attrs: {
393
267
  xmlns: 'blocklist',
394
- to: WABinary_1.S_WHATSAPP_NET,
268
+ to: S_WHATSAPP_NET,
395
269
  type: 'get'
396
270
  }
397
271
  });
398
- const listNode = (0, WABinary_1.getBinaryNodeChild)(result, 'list');
399
- return (0, WABinary_1.getBinaryNodeChildren)(listNode, 'item').map(n => n.attrs.jid);
272
+ const listNode = getBinaryNodeChild(result, 'list');
273
+ return getBinaryNodeChildren(listNode, 'item').map(n => n.attrs.jid);
400
274
  };
401
275
  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
+ }
402
312
  await query({
403
313
  tag: 'iq',
404
314
  attrs: {
405
315
  xmlns: 'blocklist',
406
- to: WABinary_1.S_WHATSAPP_NET,
316
+ to: S_WHATSAPP_NET,
407
317
  type: 'set'
408
318
  },
409
319
  content: [
410
320
  {
411
321
  tag: 'item',
412
- attrs: {
413
- action,
414
- jid
415
- }
322
+ attrs: itemAttrs
416
323
  }
417
324
  ]
418
325
  });
@@ -438,17 +345,17 @@ const makeChatsSocket = config => {
438
345
  }
439
346
  ]
440
347
  });
441
- const profileNode = (0, WABinary_1.getBinaryNodeChild)(results, 'business_profile');
442
- const profiles = (0, WABinary_1.getBinaryNodeChild)(profileNode, 'profile');
348
+ const profileNode = getBinaryNodeChild(results, 'business_profile');
349
+ const profiles = getBinaryNodeChild(profileNode, 'profile');
443
350
  if (profiles) {
444
- const address = (0, WABinary_1.getBinaryNodeChild)(profiles, 'address');
445
- const description = (0, WABinary_1.getBinaryNodeChild)(profiles, 'description');
446
- const website = (0, WABinary_1.getBinaryNodeChild)(profiles, 'website');
447
- const email = (0, WABinary_1.getBinaryNodeChild)(profiles, 'email');
448
- const category = (0, WABinary_1.getBinaryNodeChild)((0, WABinary_1.getBinaryNodeChild)(profiles, 'categories'), 'category');
449
- const businessHours = (0, WABinary_1.getBinaryNodeChild)(profiles, 'business_hours');
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');
450
357
  const businessHoursConfig = businessHours
451
- ? (0, WABinary_1.getBinaryNodeChildren)(businessHours, 'business_hours_config')
358
+ ? getBinaryNodeChildren(businessHours, 'business_hours_config')
452
359
  : undefined;
453
360
  const websiteStr = website?.content?.toString();
454
361
  return {
@@ -470,7 +377,7 @@ const makeChatsSocket = config => {
470
377
  await sendNode({
471
378
  tag: 'iq',
472
379
  attrs: {
473
- to: WABinary_1.S_WHATSAPP_NET,
380
+ to: S_WHATSAPP_NET,
474
381
  type: 'set',
475
382
  xmlns: 'urn:xmpp:whatsapp:dirty',
476
383
  id: generateMessageTag()
@@ -486,11 +393,10 @@ const makeChatsSocket = config => {
486
393
  ]
487
394
  });
488
395
  };
489
- const newAppStateChunkHandler = isInitialSync => {
396
+ const newAppStateChunkHandler = (isInitialSync) => {
490
397
  return {
491
398
  onMutation(mutation) {
492
- ;
493
- (0, Utils_1.processSyncAction)(mutation, ev, authState.creds.me, isInitialSync ? { accountSettings: authState.creds.accountSettings } : undefined, logger);
399
+ processSyncAction(mutation, ev, authState.creds.me, isInitialSync ? { accountSettings: authState.creds.accountSettings } : undefined, logger);
494
400
  }
495
401
  };
496
402
  };
@@ -504,12 +410,20 @@ const makeChatsSocket = config => {
504
410
  appStateSyncKeyCache.set(keyId, key ?? null);
505
411
  return key;
506
412
  };
413
+ // we use this to determine which events to fire
414
+ // otherwise when we resync from scratch -- all notifications will fire
507
415
  const initialVersionMap = {};
508
416
  const globalMutationMap = {};
509
417
  await authState.keys.transaction(async () => {
510
418
  const collectionsToHandle = new Set(collections);
419
+ // in case something goes wrong -- ensure we don't enter a loop that cannot be exited from
511
420
  const attemptsMap = {};
421
+ // collections that failed and need a full snapshot on retry
422
+ // mirrors WA Web's ErrorFatal -> force snapshot behavior
512
423
  const forceSnapshotCollections = new Set();
424
+ // keep executing till all collections are done
425
+ // sometimes a single patch request will not return all the patches (God knows why)
426
+ // so we fetch till they're all done (this is determined by the "has_more_patches" flag)
513
427
  while (collectionsToHandle.size) {
514
428
  const states = {};
515
429
  const nodes = [];
@@ -517,12 +431,13 @@ const makeChatsSocket = config => {
517
431
  const result = await authState.keys.get('app-state-sync-version', [name]);
518
432
  let state = result[name];
519
433
  if (state) {
434
+ state = ensureLTHashStateVersion(state);
520
435
  if (typeof initialVersionMap[name] === 'undefined') {
521
436
  initialVersionMap[name] = state.version;
522
437
  }
523
438
  }
524
439
  else {
525
- state = (0, Utils_1.newLTHashState)();
440
+ state = newLTHashState();
526
441
  }
527
442
  states[name] = state;
528
443
  const shouldForceSnapshot = forceSnapshotCollections.has(name);
@@ -535,6 +450,7 @@ const makeChatsSocket = config => {
535
450
  attrs: {
536
451
  name,
537
452
  version: state.version.toString(),
453
+ // return snapshot if syncing from scratch or forcing after a failed attempt
538
454
  return_snapshot: (shouldForceSnapshot || !state.version).toString()
539
455
  }
540
456
  });
@@ -542,7 +458,7 @@ const makeChatsSocket = config => {
542
458
  const result = await query({
543
459
  tag: 'iq',
544
460
  attrs: {
545
- to: WABinary_1.S_WHATSAPP_NET,
461
+ to: S_WHATSAPP_NET,
546
462
  xmlns: 'w:sync:app:state',
547
463
  type: 'set'
548
464
  },
@@ -554,20 +470,22 @@ const makeChatsSocket = config => {
554
470
  }
555
471
  ]
556
472
  });
557
- const decoded = await (0, Utils_1.extractSyncdPatches)(result, config?.options);
473
+ // extract from binary node
474
+ const decoded = await extractSyncdPatches(result, config?.options);
558
475
  for (const key in decoded) {
559
476
  const name = key;
560
477
  const { patches, hasMorePatches, snapshot } = decoded[name];
561
478
  try {
562
479
  if (snapshot) {
563
- const { state: newState, mutationMap } = await (0, Utils_1.decodeSyncdSnapshot)(name, snapshot, getCachedAppStateSyncKey, initialVersionMap[name], appStateMacVerification.snapshot);
480
+ const { state: newState, mutationMap } = await decodeSyncdSnapshot(name, snapshot, getCachedAppStateSyncKey, initialVersionMap[name], appStateMacVerification.snapshot, logger);
564
481
  states[name] = newState;
565
482
  Object.assign(globalMutationMap, mutationMap);
566
483
  logger.info(`restored state of ${name} from snapshot to v${newState.version} with mutations`);
567
484
  await authState.keys.set({ 'app-state-sync-version': { [name]: newState } });
568
485
  }
486
+ // only process if there are syncd patches
569
487
  if (patches.length) {
570
- const { state: newState, mutationMap } = await (0, Utils_1.decodePatches)(name, patches, states[name], getCachedAppStateSyncKey, config.options, initialVersionMap[name], logger, appStateMacVerification.patch);
488
+ const { state: newState, mutationMap } = await decodePatches(name, patches, states[name], getCachedAppStateSyncKey, config.options, initialVersionMap[name], logger, appStateMacVerification.patch);
571
489
  await authState.keys.set({ 'app-state-sync-version': { [name]: newState } });
572
490
  logger.info(`synced ${name} to v${newState.version}`);
573
491
  initialVersionMap[name] = newState.version;
@@ -577,6 +495,7 @@ const makeChatsSocket = config => {
577
495
  logger.info(`${name} has more patches...`);
578
496
  }
579
497
  else {
498
+ // collection is done with sync
580
499
  collectionsToHandle.delete(name);
581
500
  }
582
501
  }
@@ -590,21 +509,26 @@ const makeChatsSocket = config => {
590
509
  errorType: error.name,
591
510
  error: error.stack
592
511
  };
593
- if ((0, Utils_1.isMissingKeyError)(error) && attemptsMap[name] >= Utils_1.MAX_SYNC_ATTEMPTS) {
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.
594
515
  logger.warn(logData, `${name} blocked on missing key from v${states[name].version}, parking after ${attemptsMap[name]} attempts`);
595
516
  blockedCollections.add(name);
596
517
  collectionsToHandle.delete(name);
597
518
  }
598
- else if ((0, Utils_1.isMissingKeyError)(error)) {
519
+ else if (isMissingKeyError(error)) {
520
+ // Retry with a snapshot which may use a different key.
599
521
  logger.info(logData, `${name} blocked on missing key from v${states[name].version}, retrying with snapshot`);
600
522
  forceSnapshotCollections.add(name);
601
523
  }
602
- else if ((0, Utils_1.isAppStateSyncIrrecoverable)(error, attemptsMap[name])) {
524
+ else if (isAppStateSyncIrrecoverable(error, attemptsMap[name])) {
603
525
  logger.warn(logData, `failed to sync ${name} from v${states[name].version}, giving up`);
604
526
  collectionsToHandle.delete(name);
605
527
  }
606
528
  else {
607
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)
608
532
  forceSnapshotCollections.add(name);
609
533
  }
610
534
  }
@@ -616,36 +540,41 @@ const makeChatsSocket = config => {
616
540
  onMutation(globalMutationMap[key]);
617
541
  }
618
542
  });
543
+ /**
544
+ * fetch the profile picture of a user/group
545
+ * type = "preview" for a low res picture
546
+ * type = "image for the high res picture"
547
+ */
619
548
  const profilePictureUrl = async (jid, type = 'preview', timeoutMs) => {
620
- const picAttrs = type === 'image' ? { type, query: 'url' } : { type };
621
- const baseContent = [{ tag: 'picture', attrs: picAttrs }];
622
- const normalizedJid = (0, WABinary_1.jidNormalizedUser)(jid);
623
- const isUserJid = (0, WABinary_1.isPnUser)(normalizedJid) || (0, WABinary_1.isLidUser)(normalizedJid);
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);
624
555
  const me = authState.creds.me;
625
- const isSelf = me &&
626
- (normalizedJid === (0, WABinary_1.jidNormalizedUser)(me.id) ||
627
- (me.lid && normalizedJid === (0, WABinary_1.jidNormalizedUser)(me.lid)));
556
+ const isSelf = me && (normalizedJid === jidNormalizedUser(me.id) || (me.lid && normalizedJid === jidNormalizedUser(me.lid)));
628
557
  let content = baseContent;
629
558
  if (serverProps.profilePicPrivacyToken && isUserJid && !isSelf) {
630
- content = await (0, tc_token_utils_1.buildTcTokenFromJid)({
559
+ content = await buildTcTokenFromJid({
631
560
  authState,
632
561
  jid: normalizedJid,
633
562
  baseContent,
634
563
  getLIDForPN
635
564
  });
636
565
  }
637
- jid = (0, WABinary_1.jidNormalizedUser)(jid);
566
+ jid = jidNormalizedUser(jid);
638
567
  const result = await query({
639
568
  tag: 'iq',
640
569
  attrs: {
641
570
  target: jid,
642
- to: WABinary_1.S_WHATSAPP_NET,
571
+ to: S_WHATSAPP_NET,
643
572
  type: 'get',
644
573
  xmlns: 'w:profile:picture'
645
574
  },
646
575
  content
647
576
  }, timeoutMs);
648
- const child = (0, WABinary_1.getBinaryNodeChild)(result, 'picture');
577
+ const child = getBinaryNodeChild(result, 'picture');
649
578
  return child?.attrs?.url;
650
579
  };
651
580
  const createCallLink = async (type, event, timeoutMs) => {
@@ -663,23 +592,9 @@ const makeChatsSocket = config => {
663
592
  }
664
593
  ]
665
594
  }, timeoutMs);
666
- const child = (0, WABinary_1.getBinaryNodeChild)(result, 'link_create');
595
+ const child = getBinaryNodeChild(result, 'link_create');
667
596
  return child?.attrs?.token;
668
597
  };
669
- const toggleCallLinkWaitingRoom = async (linkToken, enabled, media = 'audio') => {
670
- const result = await query({
671
- tag: 'call',
672
- attrs: { id: generateMessageTag(), to: '@call' },
673
- content: [
674
- {
675
- tag: 'waiting_room_toggle',
676
- attrs: { enabled: enabled ? '1' : '0', 'link-token': linkToken, media }
677
- }
678
- ]
679
- });
680
- const child = (0, WABinary_1.getBinaryNodeChild)(result, 'waiting_room_toggle');
681
- return child?.attrs;
682
- };
683
598
  const sendPresenceUpdate = async (type, toJid) => {
684
599
  const me = authState.creds.me;
685
600
  const isAvailableType = type === 'available';
@@ -701,7 +616,7 @@ const makeChatsSocket = config => {
701
616
  });
702
617
  }
703
618
  else {
704
- const { server } = (0, WABinary_1.jidDecode)(toJid);
619
+ const { server } = jidDecode(toJid);
705
620
  const isLid = server === 'lid';
706
621
  await sendNode({
707
622
  tag: 'chatstate',
@@ -718,11 +633,16 @@ const makeChatsSocket = config => {
718
633
  });
719
634
  }
720
635
  };
636
+ /**
637
+ * @param toJid the jid to subscribe to
638
+ * @param tcToken token for subscription, use if present
639
+ */
721
640
  const presenceSubscribe = async (toJid) => {
722
- const normalizedToJid = (0, WABinary_1.jidNormalizedUser)(toJid);
723
- const isUserJid = (0, WABinary_1.isPnUser)(normalizedToJid) || (0, WABinary_1.isLidUser)(normalizedToJid);
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);
724
644
  const tcTokenContent = isUserJid
725
- ? await (0, tc_token_utils_1.buildTcTokenFromJid)({ authState, jid: normalizedToJid, getLIDForPN })
645
+ ? await buildTcTokenFromJid({ authState, jid: normalizedToJid, getLIDForPN })
726
646
  : undefined;
727
647
  return sendNode({
728
648
  tag: 'presence',
@@ -738,13 +658,14 @@ const makeChatsSocket = config => {
738
658
  let presence;
739
659
  const jid = attrs.from;
740
660
  const participant = attrs.participant || attrs.from;
741
- if (shouldIgnoreJid(jid) && jid !== WABinary_1.S_WHATSAPP_NET) {
661
+ if (shouldIgnoreJid(jid) && jid !== S_WHATSAPP_NET) {
742
662
  return;
743
663
  }
744
664
  if (tag === 'presence') {
745
665
  presence = {
746
666
  lastKnownPresence: attrs.type === 'unavailable' ? 'unavailable' : 'available',
747
- lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined
667
+ lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined,
668
+ groupOnlineCount: attrs.count ? +attrs.count : undefined
748
669
  };
749
670
  }
750
671
  else if (Array.isArray(content)) {
@@ -769,7 +690,7 @@ const makeChatsSocket = config => {
769
690
  const name = patchCreate.type;
770
691
  const myAppStateKeyId = authState.creds.myAppStateKeyId;
771
692
  if (!myAppStateKeyId) {
772
- throw new boom_1.Boom('App state key not present!', { statusCode: 400 });
693
+ throw new Boom('App state key not present!', { statusCode: 400 });
773
694
  }
774
695
  let initial;
775
696
  let encodeResult;
@@ -778,13 +699,13 @@ const makeChatsSocket = config => {
778
699
  logger.debug({ patch: patchCreate }, 'applying app patch');
779
700
  await resyncAppState([name], false);
780
701
  const { [name]: currentSyncVersion } = await authState.keys.get('app-state-sync-version', [name]);
781
- initial = currentSyncVersion || (0, Utils_1.newLTHashState)();
782
- encodeResult = await (0, Utils_1.encodeSyncdPatch)(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey);
702
+ initial = currentSyncVersion ? ensureLTHashStateVersion(currentSyncVersion) : newLTHashState();
703
+ encodeResult = await encodeSyncdPatch(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey);
783
704
  const { patch, state } = encodeResult;
784
705
  const node = {
785
706
  tag: 'iq',
786
707
  attrs: {
787
- to: WABinary_1.S_WHATSAPP_NET,
708
+ to: S_WHATSAPP_NET,
788
709
  type: 'set',
789
710
  xmlns: 'w:sync:app:state'
790
711
  },
@@ -804,7 +725,7 @@ const makeChatsSocket = config => {
804
725
  {
805
726
  tag: 'patch',
806
727
  attrs: {},
807
- content: index_js_1.proto.SyncdPatch.encode(patch).finish()
728
+ content: proto.SyncdPatch.encode(patch).finish()
808
729
  }
809
730
  ]
810
731
  }
@@ -818,39 +739,42 @@ const makeChatsSocket = config => {
818
739
  });
819
740
  if (config.emitOwnEvents) {
820
741
  const { onMutation } = newAppStateChunkHandler(false);
821
- const { mutationMap } = await (0, Utils_1.decodePatches)(name, [{ ...encodeResult.patch, version: { version: encodeResult.state.version } }], initial, getAppStateSyncKey, config.options, undefined, logger);
742
+ const { mutationMap } = await decodePatches(name, [{ ...encodeResult.patch, version: { version: encodeResult.state.version } }], initial, getAppStateSyncKey, config.options, undefined, logger);
822
743
  for (const key in mutationMap) {
823
744
  onMutation(mutationMap[key]);
824
745
  }
825
746
  }
826
747
  };
748
+ /** fetch AB props */
827
749
  const fetchProps = async () => {
828
750
  const resultNode = await query({
829
751
  tag: 'iq',
830
752
  attrs: {
831
- to: WABinary_1.S_WHATSAPP_NET,
832
- xmlns: 'w',
753
+ to: S_WHATSAPP_NET,
754
+ xmlns: 'abt',
833
755
  type: 'get'
834
756
  },
835
757
  content: [
836
758
  {
837
759
  tag: 'props',
838
760
  attrs: {
839
- protocol: '2',
840
- hash: authState?.creds?.lastPropHash || ''
761
+ protocol: '1',
762
+ ...(authState?.creds?.lastPropHash ? { hash: authState.creds.lastPropHash } : {})
841
763
  }
842
764
  }
843
765
  ]
844
766
  });
845
- const propsNode = (0, WABinary_1.getBinaryNodeChild)(resultNode, 'props');
767
+ const propsNode = getBinaryNodeChild(resultNode, 'props');
846
768
  let props = {};
847
769
  if (propsNode) {
848
770
  if (propsNode.attrs?.hash) {
771
+ // on some clients, the hash is returning as undefined
849
772
  authState.creds.lastPropHash = propsNode?.attrs?.hash;
850
773
  ev.emit('creds.update', authState.creds);
851
774
  }
852
- props = (0, WABinary_1.reduceBinaryNodeToDictionary)(propsNode, 'prop');
775
+ props = reduceBinaryNodeToDictionary(propsNode, 'prop');
853
776
  }
777
+ // Extract protocol-relevant AB props (only the ones we need)
854
778
  const privacyTokenProp = props['10518'] ?? props['privacy_token_sending_on_all_1_on_1_messages'];
855
779
  if (privacyTokenProp !== undefined) {
856
780
  serverProps.privacyTokenOn1to1 = privacyTokenProp === 'true' || privacyTokenProp === '1';
@@ -866,15 +790,26 @@ const makeChatsSocket = config => {
866
790
  logger.debug({ serverProps }, 'fetched props');
867
791
  return props;
868
792
  };
793
+ /**
794
+ * modify a chat -- mark unread, read etc.
795
+ * lastMessages must be sorted in reverse chronologically
796
+ * requires the last messages till the last message received; required for archive & unread
797
+ */
869
798
  const chatModify = (mod, jid) => {
870
- const patch = (0, Utils_1.chatModificationToAppPatch)(mod, jid);
799
+ const patch = chatModificationToAppPatch(mod, jid);
871
800
  return appPatch(patch);
872
801
  };
873
- const updateDisableLinkPreviewsPrivacy = isPreviewsDisabled => {
802
+ /**
803
+ * Enable/Disable link preview privacy, not related to baileys link preview generation
804
+ */
805
+ const updateDisableLinkPreviewsPrivacy = (isPreviewsDisabled) => {
874
806
  return chatModify({
875
807
  disableLinkPreviews: { isPreviewsDisabled }
876
808
  }, '');
877
809
  };
810
+ /**
811
+ * Star or Unstar a message
812
+ */
878
813
  const star = (jid, messages, star) => {
879
814
  return chatModify({
880
815
  star: {
@@ -883,16 +818,25 @@ const makeChatsSocket = config => {
883
818
  }
884
819
  }, jid);
885
820
  };
821
+ /**
822
+ * Add or Edit Contact
823
+ */
886
824
  const addOrEditContact = (jid, contact) => {
887
825
  return chatModify({
888
826
  contact
889
827
  }, jid);
890
828
  };
891
- const removeContact = jid => {
829
+ /**
830
+ * Remove Contact
831
+ */
832
+ const removeContact = (jid) => {
892
833
  return chatModify({
893
834
  contact: null
894
835
  }, jid);
895
836
  };
837
+ /**
838
+ * Adds label
839
+ */
896
840
  const addLabel = (jid, labels) => {
897
841
  return chatModify({
898
842
  addLabel: {
@@ -900,6 +844,9 @@ const makeChatsSocket = config => {
900
844
  }
901
845
  }, jid);
902
846
  };
847
+ /**
848
+ * Adds label for the chats
849
+ */
903
850
  const addChatLabel = (jid, labelId) => {
904
851
  return chatModify({
905
852
  addChatLabel: {
@@ -907,6 +854,9 @@ const makeChatsSocket = config => {
907
854
  }
908
855
  }, jid);
909
856
  };
857
+ /**
858
+ * Removes label for the chat
859
+ */
910
860
  const removeChatLabel = (jid, labelId) => {
911
861
  return chatModify({
912
862
  removeChatLabel: {
@@ -914,6 +864,9 @@ const makeChatsSocket = config => {
914
864
  }
915
865
  }, jid);
916
866
  };
867
+ /**
868
+ * Adds label for the message
869
+ */
917
870
  const addMessageLabel = (jid, messageId, labelId) => {
918
871
  return chatModify({
919
872
  addMessageLabel: {
@@ -922,6 +875,9 @@ const makeChatsSocket = config => {
922
875
  }
923
876
  }, jid);
924
877
  };
878
+ /**
879
+ * Removes label for the message
880
+ */
925
881
  const removeMessageLabel = (jid, messageId, labelId) => {
926
882
  return chatModify({
927
883
  removeMessageLabel: {
@@ -930,238 +886,51 @@ const makeChatsSocket = config => {
930
886
  }
931
887
  }, jid);
932
888
  };
933
- const addOrEditQuickReply = quickReply => {
889
+ /**
890
+ * Add or Edit Quick Reply
891
+ */
892
+ const addOrEditQuickReply = (quickReply) => {
934
893
  return chatModify({
935
894
  quickReply
936
895
  }, '');
937
896
  };
938
- const removeQuickReply = timestamp => {
897
+ /**
898
+ * Remove Quick Reply
899
+ */
900
+ const removeQuickReply = (timestamp) => {
939
901
  return chatModify({
940
902
  quickReply: { timestamp, deleted: true }
941
903
  }, '');
942
904
  };
943
- const renameAIThread = (jid, title) => {
944
- return chatModify({ aiThreadRename: { title } }, jid);
945
- };
946
- const pinThreadMessage = (jid, messageId, pinned = true) => {
947
- return chatModify({ threadPin: { pinned, messageId } }, jid);
948
- };
949
- const updatePrivateProcessingSetting = enabled => {
950
- return chatModify({ privateProcessingSetting: enabled ? 'enabled' : 'disabled' }, '');
951
- };
952
- const updateBioPrivacy = async (value) => {
953
- await privacyQuery('about', value);
954
- };
955
- const blockBot = async (botJid) => {
956
- await query({
957
- tag: 'iq',
958
- attrs: {
959
- xmlns: 'disappearing_mode',
960
- to: WABinary_1.S_WHATSAPP_NET,
961
- type: 'set'
962
- },
963
- content: [
964
- {
965
- tag: 'block',
966
- attrs: { jid: botJid }
967
- }
968
- ]
969
- });
970
- };
971
- const unblockBot = async (botJid) => {
972
- await updateBlockStatus(botJid, 'unblock');
973
- };
974
- const muteContactStatus = (jid, muted = true) => {
975
- return chatModify({ muteStatus: { muted } }, jid);
976
- };
977
- const toggleFavorite = (jid, isFavorite = true) => {
978
- return chatModify({ favorite: { isFavorite } }, jid);
979
- };
980
- const reorderLabels = sortedLabelIds => {
981
- return chatModify({ reorderLabel: { sortedLabelIds } }, '');
982
- };
983
- const deleteCallLog = (callId, jid = '') => {
984
- return chatModify({ deleteCallLog: { callId } }, jid);
985
- };
986
- const setChatNote = (jid, note) => {
987
- return chatModify({ noteEdit: { note } }, jid);
988
- };
989
- const deleteChatNote = jid => {
990
- return chatModify({ noteEdit: { note: '', deleted: true } }, jid);
991
- };
992
- const markChatAsUnread = (jid, lastMessages) => {
993
- return chatModify({ markAsUnread: true, lastMessages }, jid);
994
- };
995
- const setChatEphemeral = (jid, duration) => {
996
- return chatModify({ setChatEphemeral: duration }, jid);
997
- };
998
- const silenceChat = (jid, silent = true, until = null) => {
999
- return chatModify({ silenceChat: { silent, until } }, jid);
1000
- };
1001
- const fetchBotProfiles = async (jids) => {
1002
- const { USyncQuery, USyncUser, USyncBotProfileProtocol } = require('../WAUSync');
1003
- const q = new USyncQuery();
1004
- q.protocols.push(new USyncBotProfileProtocol());
1005
- for (const jid of jids) {
1006
- q.withUser(new USyncUser().withId(jid));
1007
- }
1008
- const result = await sock.executeUSyncQuery(q);
1009
- return result?.list || [];
1010
- };
1011
- const updateChatLock = (jid, locked) => {
1012
- return chatModify({ chatLock: { locked } }, jid);
1013
- };
1014
- const updateChatWallpaper = (jid, wallpaper) => {
1015
- if (!wallpaper) {
1016
- return chatModify({ wallpaper: { remove: true } }, jid);
1017
- }
1018
- return chatModify({ wallpaper }, jid);
1019
- };
1020
- const updateChatMediaVisibility = (jid, visibility) => {
1021
- return chatModify({ mediaVisibility: visibility }, jid);
1022
- };
1023
- const getBotProfile = async (botJid) => {
1024
- const resp = await query({
1025
- tag: 'iq',
1026
- attrs: {
1027
- xmlns: 'bot',
1028
- to: WABinary_1.S_WHATSAPP_NET,
1029
- type: 'get'
1030
- },
1031
- content: [
1032
- {
1033
- tag: 'bot',
1034
- attrs: { v: '2', jid: botJid }
1035
- }
1036
- ]
1037
- });
1038
- const botNode = (0, WABinary_1.getBinaryNodeChild)(resp, 'bot');
1039
- if (!botNode)
1040
- return null;
1041
- return {
1042
- jid: botNode.attrs.jid,
1043
- personaId: botNode.attrs['persona_id'],
1044
- name: botNode.attrs.name,
1045
- description: botNode.attrs.description
1046
- };
1047
- };
1048
- const fetchABProps = async (protocol = '2', hash = '', refreshId = null, group = null) => {
1049
- const propAttrs = { protocol };
1050
- if (hash)
1051
- propAttrs.hash = hash;
1052
- if (refreshId != null)
1053
- propAttrs.refresh_id = String(refreshId);
1054
- if (group != null)
1055
- propAttrs.group = String(group);
1056
- const result = await query({
1057
- tag: 'iq',
1058
- attrs: { to: WABinary_1.S_WHATSAPP_NET, xmlns: 'abt', type: 'get' },
1059
- content: [{ tag: 'props', attrs: propAttrs }]
1060
- });
1061
- const propsNode = (0, WABinary_1.getBinaryNodeChild)(result, 'props');
1062
- if (!propsNode)
1063
- return {};
1064
- return (0, WABinary_1.reduceBinaryNodeToDictionary)(propsNode, 'prop');
1065
- };
1066
- const removeCompanionDevice = async (keyIndex, reason = 'user_initiated') => {
1067
- await query({
1068
- tag: 'iq',
1069
- attrs: { to: WABinary_1.S_WHATSAPP_NET, xmlns: 'md', type: 'set' },
1070
- content: [
1071
- {
1072
- tag: 'remove-companion-device',
1073
- attrs: { platform: 'true', reason, id: String(keyIndex) }
1074
- }
1075
- ]
1076
- });
1077
- };
1078
- const updateKeyIndexList = async (ts, content) => {
1079
- await query({
1080
- tag: 'iq',
1081
- attrs: { to: WABinary_1.S_WHATSAPP_NET, xmlns: 'md', type: 'set' },
1082
- content: [
1083
- {
1084
- tag: 'key-index-list',
1085
- attrs: { ts: String(ts) },
1086
- content
1087
- }
1088
- ]
1089
- });
1090
- };
1091
- const fetchMediaConn = async (lastId = null) => {
1092
- const attrs = {};
1093
- if (lastId != null)
1094
- attrs.last_id = String(lastId);
1095
- const result = await query({
1096
- tag: 'iq',
1097
- attrs: { to: WABinary_1.S_WHATSAPP_NET, xmlns: 'w:m', type: 'set' },
1098
- content: [{ tag: 'media_conn', attrs }]
1099
- });
1100
- return (0, WABinary_1.getBinaryNodeChild)(result, 'media_conn') || null;
1101
- };
1102
- const deleteBroadcastList = async (listId) => {
1103
- await query({
1104
- tag: 'iq',
1105
- attrs: { to: WABinary_1.S_WHATSAPP_NET, xmlns: 'w:b', type: 'set' },
1106
- content: [
1107
- {
1108
- tag: 'delete',
1109
- attrs: {},
1110
- content: [{ tag: 'list', attrs: { id: String(listId) } }]
1111
- }
1112
- ]
1113
- });
1114
- };
1115
- const fetchQRCode = async (code, addressingMode = null) => {
1116
- const attrs = { code };
1117
- if (addressingMode)
1118
- attrs.addressing_mode = addressingMode;
1119
- const result = await query({
1120
- tag: 'iq',
1121
- attrs: { to: WABinary_1.S_WHATSAPP_NET, xmlns: 'w:qr', type: 'get' },
1122
- content: [{ tag: 'qr', attrs }]
1123
- });
1124
- return (0, WABinary_1.getBinaryNodeChild)(result, 'qr') || null;
1125
- };
1126
- const confirmDeviceLogout = async (id, approve = true) => {
1127
- await query({
1128
- tag: 'iq',
1129
- attrs: {
1130
- to: WABinary_1.S_WHATSAPP_NET,
1131
- xmlns: 'w:account_defence',
1132
- type: 'set',
1133
- smax_id: '87'
1134
- },
1135
- content: [
1136
- {
1137
- tag: 'device_logout',
1138
- attrs: { approve: approve ? 'true' : 'false', id: String(id) }
1139
- }
1140
- ]
1141
- });
1142
- };
905
+ /**
906
+ * queries need to be fired on connection open
907
+ * help ensure parity with WA Web
908
+ * */
1143
909
  const executeInitQueries = async () => {
1144
- await Promise.all([fetchProps(), fetchBlocklist(), fetchPrivacySettings(), initInterop()]);
910
+ await Promise.all([fetchProps(), fetchBlocklist(), fetchPrivacySettings()]);
1145
911
  };
1146
912
  const upsertMessage = ev.createBufferedFunction(async (msg, type) => {
1147
913
  ev.emit('messages.upsert', { messages: [msg], type });
1148
914
  if (!!msg.pushName) {
1149
915
  let jid = msg.key.fromMe ? authState.creds.me.id : msg.key.participant || msg.key.remoteJid;
1150
- jid = (0, WABinary_1.jidNormalizedUser)(jid);
916
+ jid = jidNormalizedUser(jid);
1151
917
  if (!msg.key.fromMe) {
1152
918
  ev.emit('contacts.update', [{ id: jid, notify: msg.pushName, verifiedName: msg.verifiedBizName }]);
1153
919
  }
920
+ // update our pushname too
1154
921
  if (msg.key.fromMe && msg.pushName && authState.creds.me?.name !== msg.pushName) {
1155
922
  ev.emit('creds.update', { me: { ...authState.creds.me, name: msg.pushName } });
1156
923
  }
1157
924
  }
1158
- const historyMsg = (0, Utils_1.getHistoryMsg)(msg.message);
925
+ const historyMsg = getHistoryMsg(msg.message);
1159
926
  const shouldProcessHistoryMsg = historyMsg
1160
- ? shouldSyncHistoryMessage(historyMsg) && Defaults_1.PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType)
927
+ ? shouldSyncHistoryMessage(historyMsg) &&
928
+ PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType)
1161
929
  : false;
1162
930
  if (historyMsg && shouldProcessHistoryMsg) {
1163
931
  const syncType = historyMsg.syncType;
1164
- if (syncType === index_js_1.proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP &&
932
+ // INITIAL_BOOTSTRAP — fire immediately, no progress check (same as WA Web K function)
933
+ if (syncType === proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP &&
1165
934
  !historySyncStatus.initialBootstrapComplete) {
1166
935
  historySyncStatus.initialBootstrapComplete = true;
1167
936
  ev.emit('messaging-history.status', {
@@ -1170,7 +939,8 @@ const makeChatsSocket = config => {
1170
939
  explicit: true
1171
940
  });
1172
941
  }
1173
- if (syncType === index_js_1.proto.HistorySync.HistorySyncType.RECENT &&
942
+ // RECENT with progress === 100 — explicit completion
943
+ if (syncType === proto.HistorySync.HistorySyncType.RECENT &&
1174
944
  historyMsg.progress === 100 &&
1175
945
  !historySyncStatus.recentSyncComplete) {
1176
946
  historySyncStatus.recentSyncComplete = true;
@@ -1182,42 +952,47 @@ const makeChatsSocket = config => {
1182
952
  explicit: true
1183
953
  });
1184
954
  }
1185
- if (syncType === index_js_1.proto.HistorySync.HistorySyncType.RECENT && !historySyncStatus.recentSyncComplete) {
955
+ // Reset 120s paused timeout on any RECENT chunk (like WA Web's handleChunkProgress)
956
+ if (syncType === proto.HistorySync.HistorySyncType.RECENT && !historySyncStatus.recentSyncComplete) {
1186
957
  clearTimeout(historySyncPausedTimeout);
1187
958
  historySyncPausedTimeout = setTimeout(() => {
1188
959
  if (!historySyncStatus.recentSyncComplete) {
1189
960
  historySyncStatus.recentSyncComplete = true;
1190
961
  ev.emit('messaging-history.status', {
1191
- syncType: index_js_1.proto.HistorySync.HistorySyncType.RECENT,
962
+ syncType: proto.HistorySync.HistorySyncType.RECENT,
1192
963
  status: 'paused',
1193
964
  explicit: false
1194
965
  });
1195
966
  }
1196
967
  historySyncPausedTimeout = undefined;
1197
- }, Defaults_1.HISTORY_SYNC_PAUSED_TIMEOUT_MS);
968
+ }, HISTORY_SYNC_PAUSED_TIMEOUT_MS);
1198
969
  }
1199
970
  }
1200
- if (historyMsg && syncState === State_1.SyncState.AwaitingInitialSync) {
971
+ // State machine: decide on sync and flush
972
+ if (historyMsg && syncState === SyncState.AwaitingInitialSync) {
1201
973
  if (awaitingSyncTimeout) {
1202
974
  clearTimeout(awaitingSyncTimeout);
1203
975
  awaitingSyncTimeout = undefined;
1204
976
  }
1205
977
  if (shouldProcessHistoryMsg) {
1206
- syncState = State_1.SyncState.Syncing;
978
+ syncState = SyncState.Syncing;
1207
979
  logger.info('Transitioned to Syncing state');
980
+ // Let doAppStateSync handle the final flush after it's done
1208
981
  }
1209
982
  else {
1210
- syncState = State_1.SyncState.Online;
983
+ syncState = SyncState.Online;
1211
984
  logger.info('History sync skipped, transitioning to Online state and flushing buffer');
1212
985
  ev.flush();
1213
986
  }
1214
987
  }
1215
988
  const doAppStateSync = async () => {
1216
- if (syncState === State_1.SyncState.Syncing) {
989
+ if (syncState === SyncState.Syncing) {
990
+ // All collections will be synced, so clear any blocked ones
1217
991
  blockedCollections.clear();
1218
992
  logger.info('Doing app state sync');
1219
- await resyncAppState(Types_1.ALL_WA_PATCH_NAMES, true);
1220
- syncState = State_1.SyncState.Online;
993
+ await resyncAppState(ALL_WA_PATCH_NAMES, true);
994
+ // Sync is complete, go online and flush everything
995
+ syncState = SyncState.Online;
1221
996
  logger.info('App state sync complete, transitioning to Online state and flushing buffer');
1222
997
  ev.flush();
1223
998
  const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1;
@@ -1230,7 +1005,7 @@ const makeChatsSocket = config => {
1230
1005
  await doAppStateSync();
1231
1006
  }
1232
1007
  })(),
1233
- (0, process_message_1.default)(msg, {
1008
+ processMessage(msg, {
1234
1009
  signalRepository,
1235
1010
  shouldProcessHistoryMsg,
1236
1011
  placeholderResendCache,
@@ -1242,7 +1017,8 @@ const makeChatsSocket = config => {
1242
1017
  getMessage
1243
1018
  })
1244
1019
  ]);
1245
- if (msg.message?.protocolMessage?.appStateSyncKeyShare && syncState === State_1.SyncState.Syncing) {
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) {
1246
1022
  logger.info('App state sync key arrived, triggering app state sync');
1247
1023
  await doAppStateSync();
1248
1024
  }
@@ -1250,7 +1026,7 @@ const makeChatsSocket = config => {
1250
1026
  ws.on('CB:presence', handlePresenceUpdate);
1251
1027
  ws.on('CB:chatstate', handlePresenceUpdate);
1252
1028
  ws.on('CB:ib,,dirty', async (node) => {
1253
- const { attrs } = (0, WABinary_1.getBinaryNodeChild)(node, 'dirty');
1029
+ const { attrs } = getBinaryNodeChild(node, 'dirty');
1254
1030
  const type = attrs.type;
1255
1031
  switch (type) {
1256
1032
  case 'account_sync':
@@ -1264,6 +1040,7 @@ const makeChatsSocket = config => {
1264
1040
  }
1265
1041
  break;
1266
1042
  case 'groups':
1043
+ // handled in groups.ts
1267
1044
  break;
1268
1045
  default:
1269
1046
  logger.info({ node }, 'received unknown sync');
@@ -1282,28 +1059,31 @@ const makeChatsSocket = config => {
1282
1059
  }
1283
1060
  sendPresenceUpdate(markOnlineOnConnect ? 'available' : 'unavailable').catch(error => onUnexpectedError(error, 'presence update requests'));
1284
1061
  }
1285
- if (!receivedPendingNotifications || syncState !== State_1.SyncState.Connecting) {
1062
+ if (!receivedPendingNotifications || syncState !== SyncState.Connecting) {
1286
1063
  return;
1287
1064
  }
1288
1065
  historySyncStatus.initialBootstrapComplete = false;
1289
1066
  historySyncStatus.recentSyncComplete = false;
1290
1067
  clearTimeout(historySyncPausedTimeout);
1291
1068
  historySyncPausedTimeout = undefined;
1292
- syncState = State_1.SyncState.AwaitingInitialSync;
1069
+ syncState = SyncState.AwaitingInitialSync;
1293
1070
  logger.info('Connection is now AwaitingInitialSync, buffering events');
1294
1071
  ev.buffer();
1295
- const willSyncHistory = shouldSyncHistoryMessage(index_js_1.proto.Message.HistorySyncNotification.create({
1296
- syncType: index_js_1.proto.HistorySync.HistorySyncType.RECENT
1072
+ const willSyncHistory = shouldSyncHistoryMessage(proto.Message.HistorySyncNotification.create({
1073
+ syncType: proto.HistorySync.HistorySyncType.RECENT
1297
1074
  }));
1298
1075
  if (!willSyncHistory) {
1299
1076
  logger.info('History sync is disabled by config, not waiting for notification. Transitioning to Online.');
1300
- syncState = State_1.SyncState.Online;
1077
+ syncState = SyncState.Online;
1301
1078
  setTimeout(() => ev.flush(), 0);
1302
1079
  return;
1303
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.
1304
1084
  if (authState.creds.accountSyncCounter > 0) {
1305
1085
  logger.info('Reconnection with existing sync data, skipping history sync wait. Transitioning to Online.');
1306
- syncState = State_1.SyncState.Online;
1086
+ syncState = SyncState.Online;
1307
1087
  setTimeout(() => ev.flush(), 0);
1308
1088
  return;
1309
1089
  }
@@ -1312,20 +1092,27 @@ const makeChatsSocket = config => {
1312
1092
  clearTimeout(awaitingSyncTimeout);
1313
1093
  }
1314
1094
  awaitingSyncTimeout = setTimeout(() => {
1315
- if (syncState === State_1.SyncState.AwaitingInitialSync) {
1095
+ if (syncState === SyncState.AwaitingInitialSync) {
1316
1096
  logger.warn('Timeout in AwaitingInitialSync, forcing state to Online and flushing buffer');
1317
- syncState = State_1.SyncState.Online;
1097
+ syncState = SyncState.Online;
1318
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.
1319
1102
  const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1;
1320
1103
  ev.emit('creds.update', { accountSyncCounter });
1321
1104
  }
1322
1105
  }, 20000);
1323
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.
1324
1110
  ev.on('creds.update', ({ myAppStateKeyId }) => {
1325
1111
  if (!myAppStateKeyId || blockedCollections.size === 0) {
1326
1112
  return;
1327
1113
  }
1328
- if (syncState === State_1.SyncState.Syncing) {
1114
+ // If we're in the middle of a full sync, doAppStateSync handles all collections
1115
+ if (syncState === SyncState.Syncing) {
1329
1116
  blockedCollections.clear();
1330
1117
  return;
1331
1118
  }
@@ -1342,18 +1129,22 @@ const makeChatsSocket = config => {
1342
1129
  logger.warn({ lid, pn, error }, 'Failed to store LID-PN mapping');
1343
1130
  }
1344
1131
  });
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
+ });
1345
1143
  return {
1346
1144
  ...sock,
1347
1145
  serverProps,
1348
1146
  createCallLink,
1349
- toggleCallLinkWaitingRoom,
1350
1147
  getBotListV2,
1351
- getChatBlockingStatus,
1352
- updateChatBlockingStatus,
1353
- getUserDisclosures,
1354
- getOptOutList,
1355
- getPushConfig,
1356
- setPushConfig,
1357
1148
  messageMutex,
1358
1149
  receiptMutex,
1359
1150
  appStatePatchMutex,
@@ -1379,18 +1170,16 @@ const makeChatsSocket = config => {
1379
1170
  updateOnlinePrivacy,
1380
1171
  updateProfilePicturePrivacy,
1381
1172
  updateStatusPrivacy,
1382
- getStatusPrivacy,
1383
- setStatusPrivacy,
1384
1173
  updateReadReceiptsPrivacy,
1385
1174
  updateGroupsAddPrivacy,
1386
1175
  updateDefaultDisappearingMode,
1387
- fetchBroadcastListQuota,
1388
1176
  getBusinessProfile,
1389
1177
  resyncAppState,
1390
1178
  chatModify,
1391
1179
  cleanDirtyBits,
1392
1180
  addOrEditContact,
1393
1181
  removeContact,
1182
+ placeholderResendCache,
1394
1183
  addLabel,
1395
1184
  addChatLabel,
1396
1185
  removeChatLabel,
@@ -1398,52 +1187,7 @@ const makeChatsSocket = config => {
1398
1187
  removeMessageLabel,
1399
1188
  star,
1400
1189
  addOrEditQuickReply,
1401
- removeQuickReply,
1402
- renameAIThread,
1403
- pinThreadMessage,
1404
- updatePrivateProcessingSetting,
1405
- updateBioPrivacy,
1406
- blockBot,
1407
- unblockBot,
1408
- getBotProfile,
1409
- muteContactStatus,
1410
- toggleFavorite,
1411
- reorderLabels,
1412
- deleteCallLog,
1413
- setChatNote,
1414
- deleteChatNote,
1415
- markChatAsUnread,
1416
- setChatEphemeral,
1417
- silenceChat,
1418
- fetchBotProfiles,
1419
- updateChatLock,
1420
- updateChatWallpaper,
1421
- updateChatMediaVisibility,
1422
- fetchIntegrators,
1423
- acceptInteropTOS,
1424
- optInIntegrators,
1425
- optOutIntegrators,
1426
- resolveInteropUser,
1427
- resolveInteropUsers,
1428
- getReachabilitySettings,
1429
- setReachabilitySettings,
1430
- blockInteropUser,
1431
- unblockInteropUser,
1432
- reportInteropSpam,
1433
- trustInteropContact,
1434
- initInterop,
1435
- createInteropGroup,
1436
- leaveInteropGroup,
1437
- getInteropGroupAddPrivacy,
1438
- INTEGRATOR_BIRDYCHAT,
1439
- INTEGRATOR_HAIKET,
1440
- fetchABProps,
1441
- removeCompanionDevice,
1442
- updateKeyIndexList,
1443
- fetchMediaConn,
1444
- deleteBroadcastList,
1445
- fetchQRCode,
1446
- confirmDeviceLogout
1190
+ removeQuickReply
1447
1191
  };
1448
1192
  };
1449
- exports.makeChatsSocket = makeChatsSocket;
1193
+ //# sourceMappingURL=chats.js.map