@badzz88/baileys 8.4.7 → 8.4.9

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 (240) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1055 -337
  3. package/WAProto/WAProto.proto +347 -6
  4. package/WAProto/fix-import.js +38 -0
  5. package/WAProto/fix-imports.js +86 -85
  6. package/WAProto/index.d.ts +4913 -25
  7. package/WAProto/index.js +14074 -98
  8. package/package.json +50 -90
  9. package/src/Defaults/index.js +201 -0
  10. package/src/Defaults/phonenumber-mcc.json +223 -0
  11. package/src/Signal/Group/ciphertext-message.js +15 -0
  12. package/src/Signal/Group/group-session-builder.js +92 -0
  13. package/src/Signal/Group/group_cipher.js +89 -0
  14. package/src/Signal/Group/index.js +136 -0
  15. package/src/Signal/Group/keyhelper.js +73 -0
  16. package/src/Signal/Group/sender-chain-key.js +32 -0
  17. package/src/Signal/Group/sender-key-distribution-message.js +66 -0
  18. package/src/Signal/Group/sender-key-message.js +69 -0
  19. package/src/Signal/Group/sender-key-name.js +50 -0
  20. package/src/Signal/Group/sender-key-record.js +44 -0
  21. package/src/Signal/Group/sender-key-state.js +97 -0
  22. package/src/Signal/Group/sender-message-key.js +30 -0
  23. package/src/Signal/libsignal.js +470 -0
  24. package/src/Signal/lid-mapping.js +262 -0
  25. package/src/Socket/Client/index.js +30 -0
  26. package/src/Socket/Client/types.js +13 -0
  27. package/src/Socket/Client/websocket.js +62 -0
  28. package/src/Socket/aigroups.js +240 -0
  29. package/src/Socket/business.js +422 -0
  30. package/src/Socket/chats.js +2374 -0
  31. package/src/Socket/communities.js +580 -0
  32. package/src/Socket/graphql.js +915 -0
  33. package/src/Socket/groups.js +812 -0
  34. package/src/Socket/index.js +37 -0
  35. package/src/Socket/interactive-handler.js +579 -0
  36. package/src/Socket/interop.js +566 -0
  37. package/src/Socket/managed-account.js +214 -0
  38. package/src/Socket/messages-recv.js +3012 -0
  39. package/src/Socket/messages-send.js +2163 -0
  40. package/{lib → src}/Socket/mex.js +11 -5
  41. package/src/Socket/newsletter.js +1057 -0
  42. package/src/Socket/privacy.js +452 -0
  43. package/src/Socket/registration.js +434 -0
  44. package/src/Socket/socket.js +1079 -0
  45. package/src/Socket/text-router.js +67 -0
  46. package/src/Socket/username.js +234 -0
  47. package/src/Store/index.js +36 -0
  48. package/src/Store/make-cache-manager-store.js +90 -0
  49. package/src/Store/make-in-memory-store.js +506 -0
  50. package/src/Store/make-ordered-dictionary.js +81 -0
  51. package/src/Store/object-repository.js +29 -0
  52. package/src/Types/Auth.js +38 -0
  53. package/src/Types/Bussines.js +2 -0
  54. package/src/Types/Call.js +2 -0
  55. package/src/Types/Chat.js +4 -0
  56. package/src/Types/Contact.js +2 -0
  57. package/src/Types/Events.js +2 -0
  58. package/src/Types/GroupMetadata.js +2 -0
  59. package/src/Types/Label.js +27 -0
  60. package/src/Types/LabelAssociation.js +9 -0
  61. package/src/Types/Message.js +95 -0
  62. package/src/Types/Newsletter.js +152 -0
  63. package/src/Types/Product.js +2 -0
  64. package/src/Types/Signal.js +2 -0
  65. package/src/Types/Socket.js +2 -0
  66. package/src/Types/State.js +70 -0
  67. package/src/Types/USync.js +2 -0
  68. package/src/Types/index.js +54 -0
  69. package/src/Utils/auth-utils.js +306 -0
  70. package/src/Utils/browser-utils.js +114 -0
  71. package/src/Utils/business.js +247 -0
  72. package/src/Utils/chat-utils.js +1272 -0
  73. package/src/Utils/consumer-application.js +107 -0
  74. package/src/Utils/crypto.js +125 -0
  75. package/src/Utils/decode-wa-message.js +808 -0
  76. package/src/Utils/event-buffer.js +586 -0
  77. package/src/Utils/generics.js +640 -0
  78. package/src/Utils/group-history.js +60 -0
  79. package/src/Utils/history.js +244 -0
  80. package/src/Utils/identity-change-handler.js +52 -0
  81. package/src/Utils/index.js +53 -0
  82. package/src/Utils/jid-display-normalization.js +218 -0
  83. package/src/Utils/link-preview.js +143 -0
  84. package/src/Utils/logger.js +9 -0
  85. package/src/Utils/lt-hash.js +10 -0
  86. package/src/Utils/make-mutex.js +36 -0
  87. package/src/Utils/message-composer.js +479 -0
  88. package/src/Utils/message-inspect.js +400 -0
  89. package/src/Utils/message-retry-manager.js +231 -0
  90. package/src/Utils/messages-media.js +943 -0
  91. package/src/Utils/messages.js +2490 -0
  92. package/src/Utils/meta-ai-msmsg.js +133 -0
  93. package/src/Utils/noise-handler.js +194 -0
  94. package/src/Utils/offline-node-processor.js +42 -0
  95. package/src/Utils/pre-key-manager.js +107 -0
  96. package/src/Utils/process-message.js +1047 -0
  97. package/src/Utils/reporting-utils.js +262 -0
  98. package/src/Utils/signal.js +192 -0
  99. package/src/Utils/stanza-ack.js +74 -0
  100. package/src/Utils/sync-action-utils.js +54 -0
  101. package/src/Utils/tc-token-utils.js +161 -0
  102. package/src/Utils/use-multi-file-auth-state.js +121 -0
  103. package/src/Utils/validate-connection.js +248 -0
  104. package/src/Utils/voip-rekey.js +22 -0
  105. package/src/WABinary/constants.js +1304 -0
  106. package/src/WABinary/decode.js +377 -0
  107. package/src/WABinary/encode.js +58 -0
  108. package/src/WABinary/generic-utils.js +148 -0
  109. package/src/WABinary/index.js +33 -0
  110. package/src/WABinary/jid-utils.js +374 -0
  111. package/src/WABinary/types.js +2 -0
  112. package/src/WAM/BinaryInfo.js +13 -0
  113. package/src/WAM/constants.js +39486 -0
  114. package/src/WAM/encode.js +142 -0
  115. package/src/WAM/index.js +31 -0
  116. package/src/WAUSync/Protocols/USyncBotProfileProtocol.js +55 -0
  117. package/src/WAUSync/Protocols/USyncBusinessProtocol.js +100 -0
  118. package/src/WAUSync/Protocols/USyncContactProtocol.js +60 -0
  119. package/src/WAUSync/Protocols/USyncDeviceProtocol.js +65 -0
  120. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -0
  121. package/src/WAUSync/Protocols/USyncFeatureProtocol.js +74 -0
  122. package/src/WAUSync/Protocols/USyncLIDProtocol.js +31 -0
  123. package/src/WAUSync/Protocols/USyncPictureProtocol.js +32 -0
  124. package/src/WAUSync/Protocols/USyncSidelistProtocol.js +29 -0
  125. package/src/WAUSync/Protocols/USyncStatusProtocol.js +44 -0
  126. package/src/WAUSync/Protocols/USyncTextStatusProtocol.js +38 -0
  127. package/src/WAUSync/Protocols/USyncUsernameProtocol.js +28 -0
  128. package/src/WAUSync/Protocols/index.js +40 -0
  129. package/src/WAUSync/USyncBackoff.js +31 -0
  130. package/src/WAUSync/USyncQuery.js +204 -0
  131. package/src/WAUSync/USyncUser.js +58 -0
  132. package/src/WAUSync/index.js +32 -0
  133. package/src/antiban.js +4726 -0
  134. package/{lib → src}/index.js +48 -15
  135. package/lib/Defaults/index.js +0 -130
  136. package/lib/Signal/Group/ciphertext-message.js +0 -12
  137. package/lib/Signal/Group/group-session-builder.js +0 -30
  138. package/lib/Signal/Group/group_cipher.js +0 -82
  139. package/lib/Signal/Group/index.js +0 -12
  140. package/lib/Signal/Group/keyhelper.js +0 -18
  141. package/lib/Signal/Group/sender-chain-key.js +0 -26
  142. package/lib/Signal/Group/sender-key-distribution-message.js +0 -63
  143. package/lib/Signal/Group/sender-key-message.js +0 -66
  144. package/lib/Signal/Group/sender-key-name.js +0 -48
  145. package/lib/Signal/Group/sender-key-record.js +0 -41
  146. package/lib/Signal/Group/sender-key-state.js +0 -84
  147. package/lib/Signal/Group/sender-message-key.js +0 -26
  148. package/lib/Signal/libsignal.js +0 -431
  149. package/lib/Signal/lid-mapping.js +0 -277
  150. package/lib/Socket/Client/index.js +0 -3
  151. package/lib/Socket/Client/types.js +0 -11
  152. package/lib/Socket/Client/websocket.js +0 -54
  153. package/lib/Socket/business.js +0 -379
  154. package/lib/Socket/chats.js +0 -1193
  155. package/lib/Socket/communities.js +0 -431
  156. package/lib/Socket/groups.js +0 -374
  157. package/lib/Socket/index.js +0 -12
  158. package/lib/Socket/luxu.js +0 -386
  159. package/lib/Socket/messages-recv.js +0 -1916
  160. package/lib/Socket/messages-send.js +0 -1453
  161. package/lib/Socket/newsletter.js +0 -251
  162. package/lib/Socket/socket.js +0 -980
  163. package/lib/Socket/username.js +0 -146
  164. package/lib/Store/index.js +0 -10
  165. package/lib/Store/keyed-db.js +0 -108
  166. package/lib/Store/make-cache-manager-store.js +0 -85
  167. package/lib/Store/make-in-memory-store.js +0 -198
  168. package/lib/Store/make-ordered-dictionary.js +0 -75
  169. package/lib/Store/object-repository.js +0 -32
  170. package/lib/Types/Auth.js +0 -2
  171. package/lib/Types/Bussines.js +0 -2
  172. package/lib/Types/Call.js +0 -2
  173. package/lib/Types/Chat.js +0 -8
  174. package/lib/Types/Contact.js +0 -2
  175. package/lib/Types/Events.js +0 -2
  176. package/lib/Types/GroupMetadata.js +0 -2
  177. package/lib/Types/Label.js +0 -25
  178. package/lib/Types/LabelAssociation.js +0 -7
  179. package/lib/Types/Message.js +0 -11
  180. package/lib/Types/Mex.js +0 -37
  181. package/lib/Types/Product.js +0 -2
  182. package/lib/Types/Signal.js +0 -2
  183. package/lib/Types/Socket.js +0 -3
  184. package/lib/Types/State.js +0 -56
  185. package/lib/Types/USync.js +0 -2
  186. package/lib/Types/index.js +0 -26
  187. package/lib/Utils/auth-utils.js +0 -302
  188. package/lib/Utils/browser-utils.js +0 -49
  189. package/lib/Utils/business.js +0 -231
  190. package/lib/Utils/chat-utils.js +0 -872
  191. package/lib/Utils/companion-reg-client-utils.js +0 -35
  192. package/lib/Utils/crypto.js +0 -118
  193. package/lib/Utils/decode-wa-message.js +0 -350
  194. package/lib/Utils/event-buffer.js +0 -622
  195. package/lib/Utils/generics.js +0 -403
  196. package/lib/Utils/history.js +0 -134
  197. package/lib/Utils/identity-change-handler.js +0 -50
  198. package/lib/Utils/index.js +0 -23
  199. package/lib/Utils/link-preview.js +0 -85
  200. package/lib/Utils/logger.js +0 -3
  201. package/lib/Utils/lt-hash.js +0 -8
  202. package/lib/Utils/make-mutex.js +0 -33
  203. package/lib/Utils/message-composer.js +0 -273
  204. package/lib/Utils/message-retry-manager.js +0 -265
  205. package/lib/Utils/messages-media.js +0 -788
  206. package/lib/Utils/messages.js +0 -1260
  207. package/lib/Utils/noise-handler.js +0 -201
  208. package/lib/Utils/offline-node-processor.js +0 -40
  209. package/lib/Utils/pre-key-manager.js +0 -106
  210. package/lib/Utils/process-message.js +0 -630
  211. package/lib/Utils/reporting-utils.js +0 -258
  212. package/lib/Utils/signal.js +0 -201
  213. package/lib/Utils/stanza-ack.js +0 -38
  214. package/lib/Utils/sync-action-utils.js +0 -49
  215. package/lib/Utils/tc-token-utils.js +0 -163
  216. package/lib/Utils/use-multi-file-auth-state.js +0 -121
  217. package/lib/Utils/validate-connection.js +0 -203
  218. package/lib/WABinary/constants.js +0 -1301
  219. package/lib/WABinary/decode.js +0 -262
  220. package/lib/WABinary/encode.js +0 -220
  221. package/lib/WABinary/generic-utils.js +0 -204
  222. package/lib/WABinary/index.js +0 -6
  223. package/lib/WABinary/jid-utils.js +0 -98
  224. package/lib/WABinary/types.js +0 -2
  225. package/lib/WAM/BinaryInfo.js +0 -10
  226. package/lib/WAM/constants.js +0 -22853
  227. package/lib/WAM/encode.js +0 -150
  228. package/lib/WAM/index.js +0 -4
  229. package/lib/WAUSync/Protocols/USyncContactProtocol.js +0 -52
  230. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +0 -54
  231. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +0 -27
  232. package/lib/WAUSync/Protocols/USyncNewsletterProtocol.js +0 -263
  233. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +0 -38
  234. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +0 -25
  235. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +0 -51
  236. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +0 -29
  237. package/lib/WAUSync/Protocols/index.js +0 -6
  238. package/lib/WAUSync/USyncQuery.js +0 -98
  239. package/lib/WAUSync/USyncUser.js +0 -31
  240. package/lib/WAUSync/index.js +0 -4
@@ -0,0 +1,586 @@
1
+ 'use strict'
2
+ var __importDefault =
3
+ (this && this.__importDefault) ||
4
+ function (mod) {
5
+ return mod && mod.__esModule ? mod : { default: mod }
6
+ }
7
+ Object.defineProperty(exports, '__esModule', { value: true })
8
+ exports.makeEventBuffer = void 0
9
+ const events_1 = __importDefault(require('events'))
10
+ const Types_1 = require('../Types')
11
+ const generics_1 = require('./generics')
12
+ const messages_1 = require('./messages')
13
+ const process_message_1 = require('./process-message')
14
+ const BUFFERABLE_EVENT = [
15
+ 'messaging-history.set',
16
+ 'chats.upsert',
17
+ 'chats.update',
18
+ 'chats.delete',
19
+ 'contacts.upsert',
20
+ 'contacts.update',
21
+ 'messages.upsert',
22
+ 'messages.update',
23
+ 'messages.delete',
24
+ 'messages.reaction',
25
+ 'message-receipt.update',
26
+ 'groups.update'
27
+ ]
28
+ const BUFFERABLE_EVENT_SET = new Set(BUFFERABLE_EVENT)
29
+ /**
30
+ * The event buffer logically consolidates different events into a single event
31
+ * making the data processing more efficient.
32
+ */
33
+ const makeEventBuffer = logger => {
34
+ const ev = new events_1.default()
35
+ const historyCache = new Set()
36
+ let data = makeBufferData()
37
+ let isBuffering = false
38
+ let bufferTimeout = null
39
+ let flushPendingTimeout = null // Add a specific timer for the debounced flush to prevent leak
40
+ let bufferCount = 0
41
+ const MAX_HISTORY_CACHE_SIZE = 10000 // Limit the history cache size to prevent memory bloat
42
+ const BUFFER_TIMEOUT_MS = 30000 // 30 seconds
43
+ // take the generic event and fire it as a baileys event
44
+ ev.on('event', map => {
45
+ for (const event in map) {
46
+ ev.emit(event, map[event])
47
+ }
48
+ })
49
+ function buffer() {
50
+ if (!isBuffering) {
51
+ logger.debug('Event buffer activated')
52
+ isBuffering = true
53
+ bufferCount = 0
54
+ if (bufferTimeout) {
55
+ clearTimeout(bufferTimeout)
56
+ }
57
+ bufferTimeout = setTimeout(() => {
58
+ if (isBuffering) {
59
+ logger.warn('Buffer timeout reached, auto-flushing')
60
+ flush()
61
+ }
62
+ }, BUFFER_TIMEOUT_MS)
63
+ }
64
+ // Always increment count when requested
65
+ bufferCount++
66
+ }
67
+ function flush() {
68
+ if (!isBuffering) {
69
+ return false
70
+ }
71
+ logger.debug({ bufferCount }, 'Flushing event buffer')
72
+ isBuffering = false
73
+ bufferCount = 0
74
+ // Clear timeout
75
+ if (bufferTimeout) {
76
+ clearTimeout(bufferTimeout)
77
+ bufferTimeout = null
78
+ }
79
+ if (flushPendingTimeout) {
80
+ clearTimeout(flushPendingTimeout)
81
+ flushPendingTimeout = null
82
+ }
83
+ // Clear history cache if it exceeds the max size
84
+ if (historyCache.size > MAX_HISTORY_CACHE_SIZE) {
85
+ logger.debug({ cacheSize: historyCache.size }, 'Clearing history cache')
86
+ historyCache.clear()
87
+ }
88
+ const newData = makeBufferData()
89
+ const chatUpdates = Object.values(data.chatUpdates)
90
+ let conditionalChatUpdatesLeft = 0
91
+ for (const update of chatUpdates) {
92
+ if (update.conditional) {
93
+ conditionalChatUpdatesLeft += 1
94
+ newData.chatUpdates[update.id] = update
95
+ delete data.chatUpdates[update.id]
96
+ }
97
+ }
98
+ const consolidatedData = consolidateEvents(data)
99
+ if (Object.keys(consolidatedData).length) {
100
+ ev.emit('event', consolidatedData)
101
+ }
102
+ data = newData
103
+ logger.trace({ conditionalChatUpdatesLeft }, 'released buffered events')
104
+ return true
105
+ }
106
+ return {
107
+ process(handler) {
108
+ const listener = async map => {
109
+ await handler(map)
110
+ }
111
+ ev.on('event', listener)
112
+ return () => {
113
+ ev.off('event', listener)
114
+ }
115
+ },
116
+ emit(event, evData) {
117
+ // Check if this is a messages.upsert with a different type than what's buffered
118
+ // If so, flush the buffered messages first to avoid type overshadowing
119
+ if (event === 'messages.upsert') {
120
+ const { type } = evData
121
+ const existingUpserts = Object.values(data.messageUpserts)
122
+ if (existingUpserts.length > 0) {
123
+ const bufferedType = existingUpserts[0].type
124
+ if (bufferedType !== type) {
125
+ logger.debug({ bufferedType, newType: type }, 'messages.upsert type mismatch, emitting buffered messages')
126
+ // Emit the buffered messages with their correct type
127
+ ev.emit('event', {
128
+ 'messages.upsert': {
129
+ messages: existingUpserts.map(m => m.message),
130
+ type: bufferedType
131
+ }
132
+ })
133
+ // Clear the message upserts from the buffer
134
+ data.messageUpserts = {}
135
+ }
136
+ }
137
+ }
138
+ if (isBuffering && BUFFERABLE_EVENT_SET.has(event)) {
139
+ append(data, historyCache, event, evData, logger)
140
+ return true
141
+ }
142
+ return ev.emit('event', { [event]: evData })
143
+ },
144
+ isBuffering() {
145
+ return isBuffering
146
+ },
147
+ buffer,
148
+ flush,
149
+ createBufferedFunction(work) {
150
+ return async (...args) => {
151
+ buffer()
152
+ try {
153
+ const result = await work(...args)
154
+ // If this is the only buffer, flush after a small delay
155
+ if (bufferCount === 1) {
156
+ setTimeout(() => {
157
+ if (isBuffering && bufferCount === 1) {
158
+ flush()
159
+ }
160
+ }, 100) // Small delay to allow nested buffers
161
+ }
162
+ return result
163
+ } catch (error) {
164
+ throw error
165
+ } finally {
166
+ bufferCount = Math.max(0, bufferCount - 1)
167
+ if (bufferCount === 0) {
168
+ // Only schedule ONE timeout, not 10,000
169
+ if (!flushPendingTimeout) {
170
+ flushPendingTimeout = setTimeout(flush, 100)
171
+ }
172
+ }
173
+ }
174
+ }
175
+ },
176
+ on: (...args) => ev.on(...args),
177
+ off: (...args) => ev.off(...args),
178
+ once: (...args) => ev.once(...args),
179
+ removeAllListeners: (...args) => ev.removeAllListeners(...args)
180
+ }
181
+ }
182
+ exports.makeEventBuffer = makeEventBuffer
183
+ const makeBufferData = () => {
184
+ return {
185
+ historySets: {
186
+ chats: {},
187
+ messages: {},
188
+ contacts: {},
189
+ isLatest: false,
190
+ empty: true
191
+ },
192
+ chatUpserts: {},
193
+ chatUpdates: {},
194
+ chatDeletes: new Set(),
195
+ contactUpserts: {},
196
+ contactUpdates: {},
197
+ messageUpserts: {},
198
+ messageUpdates: {},
199
+ messageReactions: {},
200
+ messageDeletes: {},
201
+ messageReceipts: {},
202
+ groupUpdates: {}
203
+ }
204
+ }
205
+ function append(
206
+ data,
207
+ historyCache,
208
+ event,
209
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
210
+ eventData,
211
+ logger
212
+ ) {
213
+ switch (event) {
214
+ case 'messaging-history.set':
215
+ for (const chat of eventData.chats) {
216
+ const id = chat.id || ''
217
+ const existingChat = data.historySets.chats[id]
218
+ if (existingChat) {
219
+ existingChat.endOfHistoryTransferType = chat.endOfHistoryTransferType
220
+ }
221
+ if (!existingChat && !historyCache.has(id)) {
222
+ data.historySets.chats[id] = chat
223
+ historyCache.add(id)
224
+ absorbingChatUpdate(chat)
225
+ }
226
+ }
227
+ for (const contact of eventData.contacts) {
228
+ const existingContact = data.historySets.contacts[contact.id]
229
+ if (existingContact) {
230
+ Object.assign(existingContact, (0, generics_1.trimUndefined)(contact))
231
+ } else {
232
+ const historyContactId = `c:${contact.id}`
233
+ const hasAnyName = contact.notify || contact.name || contact.verifiedName
234
+ if (!historyCache.has(historyContactId) || hasAnyName) {
235
+ data.historySets.contacts[contact.id] = contact
236
+ historyCache.add(historyContactId)
237
+ }
238
+ }
239
+ }
240
+ for (const message of eventData.messages) {
241
+ const key = stringifyMessageKey(message.key)
242
+ const existingMsg = data.historySets.messages[key]
243
+ if (!existingMsg && !historyCache.has(key)) {
244
+ data.historySets.messages[key] = message
245
+ historyCache.add(key)
246
+ }
247
+ }
248
+ data.historySets.empty = false
249
+ data.historySets.syncType = eventData.syncType
250
+ data.historySets.progress = eventData.progress
251
+ data.historySets.peerDataRequestSessionId = eventData.peerDataRequestSessionId
252
+ data.historySets.isLatest = eventData.isLatest || data.historySets.isLatest
253
+ break
254
+ case 'chats.upsert':
255
+ for (const chat of eventData) {
256
+ const id = chat.id || ''
257
+ let upsert = data.chatUpserts[id]
258
+ if (id && !upsert) {
259
+ upsert = data.historySets.chats[id]
260
+ if (upsert) {
261
+ logger.debug({ chatId: id }, 'absorbed chat upsert in chat set')
262
+ }
263
+ }
264
+ if (upsert) {
265
+ upsert = concatChats(upsert, chat)
266
+ } else {
267
+ upsert = chat
268
+ data.chatUpserts[id] = upsert
269
+ }
270
+ absorbingChatUpdate(upsert)
271
+ if (data.chatDeletes.has(id)) {
272
+ data.chatDeletes.delete(id)
273
+ }
274
+ }
275
+ break
276
+ case 'chats.update':
277
+ for (const update of eventData) {
278
+ const chatId = update.id
279
+ const conditionMatches = update.conditional ? update.conditional(data) : true
280
+ if (conditionMatches) {
281
+ delete update.conditional
282
+ // if there is an existing upsert, merge the update into it
283
+ const upsert = data.historySets.chats[chatId] || data.chatUpserts[chatId]
284
+ if (upsert) {
285
+ concatChats(upsert, update)
286
+ } else {
287
+ // merge the update into the existing update
288
+ const chatUpdate = data.chatUpdates[chatId] || {}
289
+ data.chatUpdates[chatId] = concatChats(chatUpdate, update)
290
+ }
291
+ } else if (conditionMatches === undefined) {
292
+ // condition yet to be fulfilled
293
+ data.chatUpdates[chatId] = update
294
+ }
295
+ // otherwise -- condition not met, update is invalid
296
+ // if the chat has been updated
297
+ // ignore any existing chat delete
298
+ if (data.chatDeletes.has(chatId)) {
299
+ data.chatDeletes.delete(chatId)
300
+ }
301
+ }
302
+ break
303
+ case 'chats.delete':
304
+ for (const chatId of eventData) {
305
+ if (!data.chatDeletes.has(chatId)) {
306
+ data.chatDeletes.add(chatId)
307
+ }
308
+ // remove any prior updates & upserts
309
+ if (data.chatUpdates[chatId]) {
310
+ delete data.chatUpdates[chatId]
311
+ }
312
+ if (data.chatUpserts[chatId]) {
313
+ delete data.chatUpserts[chatId]
314
+ }
315
+ if (data.historySets.chats[chatId]) {
316
+ delete data.historySets.chats[chatId]
317
+ }
318
+ }
319
+ break
320
+ case 'contacts.upsert':
321
+ for (const contact of eventData) {
322
+ let upsert = data.contactUpserts[contact.id]
323
+ if (!upsert) {
324
+ upsert = data.historySets.contacts[contact.id]
325
+ if (upsert) {
326
+ logger.debug({ contactId: contact.id }, 'absorbed contact upsert in contact set')
327
+ }
328
+ }
329
+ if (upsert) {
330
+ upsert = Object.assign(upsert, (0, generics_1.trimUndefined)(contact))
331
+ } else {
332
+ upsert = contact
333
+ data.contactUpserts[contact.id] = upsert
334
+ }
335
+ if (data.contactUpdates[contact.id]) {
336
+ upsert = Object.assign(data.contactUpdates[contact.id], (0, generics_1.trimUndefined)(contact))
337
+ delete data.contactUpdates[contact.id]
338
+ }
339
+ }
340
+ break
341
+ case 'contacts.update':
342
+ const contactUpdates = eventData
343
+ for (const update of contactUpdates) {
344
+ const id = update.id
345
+ // merge into prior upsert
346
+ const upsert = data.historySets.contacts[id] || data.contactUpserts[id]
347
+ if (upsert) {
348
+ Object.assign(upsert, update)
349
+ } else {
350
+ // merge into prior update
351
+ const contactUpdate = data.contactUpdates[id] || {}
352
+ data.contactUpdates[id] = Object.assign(contactUpdate, update)
353
+ }
354
+ }
355
+ break
356
+ case 'messages.upsert':
357
+ const { messages, type } = eventData
358
+ for (const message of messages) {
359
+ const key = stringifyMessageKey(message.key)
360
+ let existing = data.messageUpserts[key]?.message
361
+ if (!existing) {
362
+ existing = data.historySets.messages[key]
363
+ if (existing) {
364
+ logger.debug({ messageId: key }, 'absorbed message upsert in message set')
365
+ }
366
+ }
367
+ if (existing) {
368
+ message.messageTimestamp = existing.messageTimestamp
369
+ }
370
+ if (data.messageUpdates[key]) {
371
+ logger.debug('absorbed prior message update in message upsert')
372
+ Object.assign(message, data.messageUpdates[key].update)
373
+ delete data.messageUpdates[key]
374
+ }
375
+ if (data.historySets.messages[key]) {
376
+ data.historySets.messages[key] = message
377
+ } else {
378
+ data.messageUpserts[key] = {
379
+ message,
380
+ type: type === 'notify' || data.messageUpserts[key]?.type === 'notify' ? 'notify' : type
381
+ }
382
+ }
383
+ }
384
+ break
385
+ case 'messages.update':
386
+ const msgUpdates = eventData
387
+ for (const { key, update } of msgUpdates) {
388
+ const keyStr = stringifyMessageKey(key)
389
+ const existing = data.historySets.messages[keyStr] || data.messageUpserts[keyStr]?.message
390
+ if (existing) {
391
+ Object.assign(existing, update)
392
+ // if the message was received & read by us
393
+ // the chat counter must have been incremented
394
+ // so we need to decrement it
395
+ if (update.status === Types_1.WAMessageStatus.READ && !key.fromMe) {
396
+ decrementChatReadCounterIfMsgDidUnread(existing)
397
+ }
398
+ } else {
399
+ const msgUpdate = data.messageUpdates[keyStr] || { key, update: {} }
400
+ Object.assign(msgUpdate.update, update)
401
+ data.messageUpdates[keyStr] = msgUpdate
402
+ }
403
+ }
404
+ break
405
+ case 'messages.delete':
406
+ const deleteData = eventData
407
+ if ('keys' in deleteData) {
408
+ const { keys } = deleteData
409
+ for (const key of keys) {
410
+ const keyStr = stringifyMessageKey(key)
411
+ if (!data.messageDeletes[keyStr]) {
412
+ data.messageDeletes[keyStr] = key
413
+ }
414
+ if (data.messageUpserts[keyStr]) {
415
+ delete data.messageUpserts[keyStr]
416
+ }
417
+ if (data.messageUpdates[keyStr]) {
418
+ delete data.messageUpdates[keyStr]
419
+ }
420
+ }
421
+ } else {
422
+ // Reserved for a whole-chat-clear variant ({ jid, all: true }); nothing in
423
+ // this codebase emits that shape today (the only emitter is chat-utils.js,
424
+ // always with `keys`), and the flush loop below only supports one payload
425
+ // per event name, so consolidating it properly needs that loop reworked
426
+ // first — not adding untested handling for a shape with no current caller.
427
+ }
428
+ break
429
+ case 'messages.reaction':
430
+ const reactions = eventData
431
+ for (const { key, reaction } of reactions) {
432
+ const keyStr = stringifyMessageKey(key)
433
+ const existing = data.messageUpserts[keyStr]
434
+ if (existing) {
435
+ ;(0, messages_1.updateMessageWithReaction)(existing.message, reaction)
436
+ } else {
437
+ data.messageReactions[keyStr] = data.messageReactions[keyStr] || { key, reactions: [] }
438
+ ;(0, messages_1.updateMessageWithReaction)(data.messageReactions[keyStr], reaction)
439
+ }
440
+ }
441
+ break
442
+ case 'message-receipt.update':
443
+ const receipts = eventData
444
+ for (const { key, receipt } of receipts) {
445
+ const keyStr = stringifyMessageKey(key)
446
+ const existing = data.messageUpserts[keyStr]
447
+ if (existing) {
448
+ ;(0, messages_1.updateMessageWithReceipt)(existing.message, receipt)
449
+ } else {
450
+ data.messageReceipts[keyStr] = data.messageReceipts[keyStr] || { key, userReceipt: [] }
451
+ ;(0, messages_1.updateMessageWithReceipt)(data.messageReceipts[keyStr], receipt)
452
+ }
453
+ }
454
+ break
455
+ case 'groups.update':
456
+ const groupUpdates = eventData
457
+ for (const update of groupUpdates) {
458
+ const id = update.id
459
+ const groupUpdate = data.groupUpdates[id] || {}
460
+ if (!data.groupUpdates[id]) {
461
+ data.groupUpdates[id] = Object.assign(groupUpdate, update)
462
+ }
463
+ }
464
+ break
465
+ default:
466
+ throw new Error(`"${event}" cannot be buffered`)
467
+ }
468
+ function absorbingChatUpdate(existing) {
469
+ const chatId = existing.id || ''
470
+ const update = data.chatUpdates[chatId]
471
+ if (update) {
472
+ const conditionMatches = update.conditional ? update.conditional(data) : true
473
+ if (conditionMatches) {
474
+ delete update.conditional
475
+ logger.debug({ chatId }, 'absorbed chat update in existing chat')
476
+ Object.assign(existing, concatChats(update, existing))
477
+ delete data.chatUpdates[chatId]
478
+ } else if (conditionMatches === false) {
479
+ logger.debug({ chatId }, 'chat update condition fail, removing')
480
+ delete data.chatUpdates[chatId]
481
+ }
482
+ }
483
+ }
484
+ function decrementChatReadCounterIfMsgDidUnread(message) {
485
+ // decrement chat unread counter
486
+ // if the message has already been marked read by us
487
+ const chatId = message.key.remoteJid
488
+ const chat = data.chatUpdates[chatId] || data.chatUpserts[chatId]
489
+ if (
490
+ (0, process_message_1.isRealMessage)(message) &&
491
+ (0, process_message_1.shouldIncrementChatUnread)(message) &&
492
+ typeof chat?.unreadCount === 'number' &&
493
+ chat.unreadCount > 0
494
+ ) {
495
+ logger.debug({ chatId: chat.id }, 'decrementing chat counter')
496
+ chat.unreadCount -= 1
497
+ if (chat.unreadCount === 0) {
498
+ delete chat.unreadCount
499
+ }
500
+ }
501
+ }
502
+ }
503
+ function consolidateEvents(data) {
504
+ const map = {}
505
+ if (!data.historySets.empty) {
506
+ map['messaging-history.set'] = {
507
+ chats: Object.values(data.historySets.chats),
508
+ messages: Object.values(data.historySets.messages),
509
+ contacts: Object.values(data.historySets.contacts),
510
+ syncType: data.historySets.syncType,
511
+ progress: data.historySets.progress,
512
+ isLatest: data.historySets.isLatest,
513
+ peerDataRequestSessionId: data.historySets.peerDataRequestSessionId
514
+ }
515
+ }
516
+ const chatUpsertList = Object.values(data.chatUpserts)
517
+ if (chatUpsertList.length) {
518
+ map['chats.upsert'] = chatUpsertList
519
+ }
520
+ const chatUpdateList = Object.values(data.chatUpdates)
521
+ if (chatUpdateList.length) {
522
+ map['chats.update'] = chatUpdateList
523
+ }
524
+ const chatDeleteList = Array.from(data.chatDeletes)
525
+ if (chatDeleteList.length) {
526
+ map['chats.delete'] = chatDeleteList
527
+ }
528
+ const messageUpsertList = Object.values(data.messageUpserts)
529
+ if (messageUpsertList.length) {
530
+ const type = messageUpsertList[0].type
531
+ map['messages.upsert'] = {
532
+ messages: messageUpsertList.map(m => m.message),
533
+ type
534
+ }
535
+ }
536
+ const messageUpdateList = Object.values(data.messageUpdates)
537
+ if (messageUpdateList.length) {
538
+ map['messages.update'] = messageUpdateList
539
+ }
540
+ const messageDeleteList = Object.values(data.messageDeletes)
541
+ if (messageDeleteList.length) {
542
+ map['messages.delete'] = { keys: messageDeleteList }
543
+ }
544
+ const messageReactionList = Object.values(data.messageReactions).flatMap(({ key, reactions }) =>
545
+ reactions.flatMap(reaction => ({ key, reaction }))
546
+ )
547
+ if (messageReactionList.length) {
548
+ map['messages.reaction'] = messageReactionList
549
+ }
550
+ const messageReceiptList = Object.values(data.messageReceipts).flatMap(({ key, userReceipt }) =>
551
+ userReceipt.flatMap(receipt => ({ key, receipt }))
552
+ )
553
+ if (messageReceiptList.length) {
554
+ map['message-receipt.update'] = messageReceiptList
555
+ }
556
+ const contactUpsertList = Object.values(data.contactUpserts)
557
+ if (contactUpsertList.length) {
558
+ map['contacts.upsert'] = contactUpsertList
559
+ }
560
+ const contactUpdateList = Object.values(data.contactUpdates)
561
+ if (contactUpdateList.length) {
562
+ map['contacts.update'] = contactUpdateList
563
+ }
564
+ const groupUpdateList = Object.values(data.groupUpdates)
565
+ if (groupUpdateList.length) {
566
+ map['groups.update'] = groupUpdateList
567
+ }
568
+ return map
569
+ }
570
+ function concatChats(a, b) {
571
+ if (
572
+ b.unreadCount === null && // neutralize unread counter
573
+ a.unreadCount < 0
574
+ ) {
575
+ a.unreadCount = undefined
576
+ b.unreadCount = undefined
577
+ }
578
+ if (typeof a.unreadCount === 'number' && typeof b.unreadCount === 'number') {
579
+ b = { ...b }
580
+ if (b.unreadCount >= 0) {
581
+ b.unreadCount = Math.max(b.unreadCount, 0) + Math.max(a.unreadCount, 0)
582
+ }
583
+ }
584
+ return Object.assign(a, b)
585
+ }
586
+ const stringifyMessageKey = key => `${key.remoteJid},${key.id},${key.fromMe ? '1' : '0'}`