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