@celestial-community/baileys 0.0.1-security → 1.0.0

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.

Potentially problematic release.


This version of @celestial-community/baileys might be problematic. Click here for more details.

Files changed (175) hide show
  1. package/WAProto/index.js +138933 -0
  2. package/engine-requirements.js +10 -0
  3. package/lib/Defaults/baileys-version.json +7 -0
  4. package/lib/Defaults/index.js +157 -0
  5. package/lib/Defaults/phonenumber-mcc.json +223 -0
  6. package/lib/Signal/Group/ciphertext-message.js +15 -0
  7. package/lib/Signal/Group/group-session-builder.js +94 -0
  8. package/lib/Signal/Group/group_cipher.js +118 -0
  9. package/lib/Signal/Group/index.js +138 -0
  10. package/lib/Signal/Group/keyhelper.js +75 -0
  11. package/lib/Signal/Group/queue-job.js +54 -0
  12. package/lib/Signal/Group/sender-chain-key.js +39 -0
  13. package/lib/Signal/Group/sender-key-distribution-message.js +71 -0
  14. package/lib/Signal/Group/sender-key-message.js +76 -0
  15. package/lib/Signal/Group/sender-key-name.js +50 -0
  16. package/lib/Signal/Group/sender-key-record.js +65 -0
  17. package/lib/Signal/Group/sender-key-state.js +114 -0
  18. package/lib/Signal/Group/sender-message-key.js +33 -0
  19. package/lib/Signal/libsignal.js +204 -0
  20. package/lib/Signal/lid-mapping.js +267 -0
  21. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  22. package/lib/Socket/Client/index.js +32 -0
  23. package/lib/Socket/Client/mobile-socket-client.js +82 -0
  24. package/lib/Socket/Client/web-socket-client.js +89 -0
  25. package/lib/Socket/Denzy-ZeroDay.js +805 -0
  26. package/lib/Socket/business.js +279 -0
  27. package/lib/Socket/chats.js +1169 -0
  28. package/lib/Socket/community.d.ts +120 -0
  29. package/lib/Socket/community.js +388 -0
  30. package/lib/Socket/graphql.js +1122 -0
  31. package/lib/Socket/groups.js +345 -0
  32. package/lib/Socket/index.js +22 -0
  33. package/lib/Socket/interop.js +265 -0
  34. package/lib/Socket/lid-mapping.js +111 -0
  35. package/lib/Socket/messages-recv.js +1385 -0
  36. package/lib/Socket/messages-send.js +956 -0
  37. package/lib/Socket/mex.js +69 -0
  38. package/lib/Socket/newsletter.js +424 -0
  39. package/lib/Socket/privacy.js +229 -0
  40. package/lib/Socket/registration.js +190 -0
  41. package/lib/Socket/socket.js +783 -0
  42. package/lib/Socket/username.d.ts +185 -0
  43. package/lib/Socket/username.js +168 -0
  44. package/lib/Socket/usync.js +80 -0
  45. package/lib/Store/index.js +14 -0
  46. package/lib/Store/keyed-db.js +158 -0
  47. package/lib/Store/make-cache-manager-store.js +88 -0
  48. package/lib/Store/make-in-memory-store.js +484 -0
  49. package/lib/Store/make-ordered-dictionary.js +78 -0
  50. package/lib/Store/object-repository.js +27 -0
  51. package/lib/Types/Auth.js +2 -0
  52. package/lib/Types/Call.js +2 -0
  53. package/lib/Types/Chat.js +10 -0
  54. package/lib/Types/Contact.js +2 -0
  55. package/lib/Types/Events.js +2 -0
  56. package/lib/Types/GroupMetadata.js +2 -0
  57. package/lib/Types/Label.js +27 -0
  58. package/lib/Types/LabelAssociation.js +9 -0
  59. package/lib/Types/Message.js +14 -0
  60. package/lib/Types/MexUpdates.js +19 -0
  61. package/lib/Types/Newsletter.js +38 -0
  62. package/lib/Types/Product.js +2 -0
  63. package/lib/Types/RichType.js +30 -0
  64. package/lib/Types/Signal.js +2 -0
  65. package/lib/Types/Socket.js +2 -0
  66. package/lib/Types/State.js +2 -0
  67. package/lib/Types/USync.js +2 -0
  68. package/lib/Types/index.js +58 -0
  69. package/lib/Utils/anti-ban.js +339 -0
  70. package/lib/Utils/anti-delete.d.ts +158 -0
  71. package/lib/Utils/anti-delete.js +293 -0
  72. package/lib/Utils/antiban-presets.js +91 -0
  73. package/lib/Utils/antiban-profiles.js +43 -0
  74. package/lib/Utils/auth-utils.js +210 -0
  75. package/lib/Utils/baileys-event-stream.js +66 -0
  76. package/lib/Utils/browser-utils.js +52 -0
  77. package/lib/Utils/business.js +261 -0
  78. package/lib/Utils/chat-control.d.ts +113 -0
  79. package/lib/Utils/chat-control.js +230 -0
  80. package/lib/Utils/chat-utils.js +922 -0
  81. package/lib/Utils/companion-reg-client-utils.js +37 -0
  82. package/lib/Utils/contact-graph-warmer.js +208 -0
  83. package/lib/Utils/crypto.js +196 -0
  84. package/lib/Utils/decode-wa-message.js +208 -0
  85. package/lib/Utils/delivery-tracker.js +110 -0
  86. package/lib/Utils/device-fingerprint.js +135 -0
  87. package/lib/Utils/event-buffer.js +531 -0
  88. package/lib/Utils/generics.js +571 -0
  89. package/lib/Utils/group-operation-guard.js +147 -0
  90. package/lib/Utils/health-monitor.js +207 -0
  91. package/lib/Utils/history.js +122 -0
  92. package/lib/Utils/human-entropy.js +226 -0
  93. package/lib/Utils/identity-change-handler.js +72 -0
  94. package/lib/Utils/index.js +83 -0
  95. package/lib/Utils/interactive-message.d.ts +139 -0
  96. package/lib/Utils/interactive-message.js +273 -0
  97. package/lib/Utils/legitimacy-signal-injector.js +180 -0
  98. package/lib/Utils/link-preview.js +106 -0
  99. package/lib/Utils/logger.d.ts +13 -0
  100. package/lib/Utils/logger.js +9 -0
  101. package/lib/Utils/lt-hash.js +54 -0
  102. package/lib/Utils/make-mutex.js +41 -0
  103. package/lib/Utils/message-composer.d.ts +106 -0
  104. package/lib/Utils/message-composer.js +721 -0
  105. package/lib/Utils/message-retry-manager.d.ts +88 -0
  106. package/lib/Utils/message-retry-manager.js +160 -0
  107. package/lib/Utils/message-search.d.ts +52 -0
  108. package/lib/Utils/message-search.js +226 -0
  109. package/lib/Utils/messages-media.js +899 -0
  110. package/lib/Utils/messages.js +2698 -0
  111. package/lib/Utils/noise-handler.js +175 -0
  112. package/lib/Utils/offline-node-processor.js +45 -0
  113. package/lib/Utils/pre-key-manager.js +131 -0
  114. package/lib/Utils/presence-choreographer.js +438 -0
  115. package/lib/Utils/process-message.js +423 -0
  116. package/lib/Utils/rate-limiter.js +232 -0
  117. package/lib/Utils/reconnect-throttle.js +157 -0
  118. package/lib/Utils/reply-ratio-guard.js +137 -0
  119. package/lib/Utils/reporting-utils.js +307 -0
  120. package/lib/Utils/retry-reason-tracker.js +140 -0
  121. package/lib/Utils/rich-message-utils.d.ts +48 -0
  122. package/lib/Utils/rich-message-utils.js +400 -0
  123. package/lib/Utils/rich-response-utils.js +461 -0
  124. package/lib/Utils/scheduling.d.ts +135 -0
  125. package/lib/Utils/scheduling.js +246 -0
  126. package/lib/Utils/session-fingerprint.js +226 -0
  127. package/lib/Utils/session-stability.js +224 -0
  128. package/lib/Utils/signal.js +188 -0
  129. package/lib/Utils/stanza-ack.js +38 -0
  130. package/lib/Utils/state-manager.js +91 -0
  131. package/lib/Utils/status-posting.d.ts +81 -0
  132. package/lib/Utils/status-posting.js +187 -0
  133. package/lib/Utils/stealth-connect.js +124 -0
  134. package/lib/Utils/sync-action-utils.js +55 -0
  135. package/lib/Utils/tc-token-utils.js +171 -0
  136. package/lib/Utils/templates.d.ts +54 -0
  137. package/lib/Utils/templates.js +244 -0
  138. package/lib/Utils/timelock-guard.js +162 -0
  139. package/lib/Utils/use-mongo-file-auth-state.d.ts +6 -0
  140. package/lib/Utils/use-mongo-file-auth-state.js +81 -0
  141. package/lib/Utils/use-multi-file-auth-state.js +125 -0
  142. package/lib/Utils/use-single-file-auth-state.d.ts +13 -0
  143. package/lib/Utils/use-single-file-auth-state.js +86 -0
  144. package/lib/Utils/use-sqlite-auth-state.js +187 -0
  145. package/lib/Utils/vCard.d.ts +71 -0
  146. package/lib/Utils/vCard.js +196 -0
  147. package/lib/Utils/validate-connection.js +253 -0
  148. package/lib/Utils/warmup.js +154 -0
  149. package/lib/WABinary/constants.js +1303 -0
  150. package/lib/WABinary/decode.js +270 -0
  151. package/lib/WABinary/encode.js +279 -0
  152. package/lib/WABinary/generic-utils.js +223 -0
  153. package/lib/WABinary/index.js +34 -0
  154. package/lib/WABinary/jid-utils.js +84 -0
  155. package/lib/WABinary/types.js +2 -0
  156. package/lib/WAM/BinaryInfo.js +13 -0
  157. package/lib/WAM/constants.js +15254 -0
  158. package/lib/WAM/encode.js +149 -0
  159. package/lib/WAM/index.js +32 -0
  160. package/lib/WAUSync/Protocols/USyncContactProtocol.js +37 -0
  161. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +71 -0
  162. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +32 -0
  163. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +49 -0
  164. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +23 -0
  165. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +58 -0
  166. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  167. package/lib/WAUSync/Protocols/index.js +34 -0
  168. package/lib/WAUSync/USyncQuery.js +99 -0
  169. package/lib/WAUSync/USyncUser.js +26 -0
  170. package/lib/WAUSync/USyncUsernameProtocol.d.ts +9 -0
  171. package/lib/WAUSync/USyncUsernameProtocol.js +37 -0
  172. package/lib/WAUSync/index.js +32 -0
  173. package/lib/index.js +59 -0
  174. package/package.json +105 -5
  175. package/README.md +0 -5
@@ -0,0 +1,423 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.decryptPollVote =
4
+ exports.getChatId =
5
+ exports.shouldIncrementChatUnread =
6
+ exports.isRealMessage =
7
+ exports.cleanMessage =
8
+ void 0
9
+ const WAProto_1 = require('../../WAProto')
10
+ const Types_1 = require('../Types')
11
+ const messages_1 = require('../Utils/messages')
12
+ const WABinary_1 = require('../WABinary')
13
+ const crypto_1 = require('./crypto')
14
+ const generics_1 = require('./generics')
15
+ const history_1 = require('./history')
16
+ const REAL_MSG_STUB_TYPES = new Set([
17
+ Types_1.WAMessageStubType.CALL_MISSED_GROUP_VIDEO,
18
+ Types_1.WAMessageStubType.CALL_MISSED_GROUP_VOICE,
19
+ Types_1.WAMessageStubType.CALL_MISSED_VIDEO,
20
+ Types_1.WAMessageStubType.CALL_MISSED_VOICE
21
+ ])
22
+ const REAL_MSG_REQ_ME_STUB_TYPES = new Set([Types_1.WAMessageStubType.GROUP_PARTICIPANT_ADD])
23
+ /** Cleans a received message to further processing */
24
+ const cleanMessage = (message, meId) => {
25
+ // ensure remoteJid and participant doesn't have device or agent in it
26
+ message.key.remoteJid = (0, WABinary_1.jidNormalizedUser)(message.key.remoteJid)
27
+ message.key.participant = message.key.participant
28
+ ? (0, WABinary_1.jidNormalizedUser)(message.key.participant)
29
+ : undefined
30
+ const content = (0, messages_1.normalizeMessageContent)(message.message)
31
+ // if the message has a reaction, ensure fromMe & remoteJid are from our perspective
32
+ if (content === null || content === void 0 ? void 0 : content.reactionMessage) {
33
+ normaliseKey(content.reactionMessage.key)
34
+ }
35
+ if (content === null || content === void 0 ? void 0 : content.pollUpdateMessage) {
36
+ normaliseKey(content.pollUpdateMessage.pollCreationMessageKey)
37
+ }
38
+ function normaliseKey(msgKey) {
39
+ // if the reaction is from another user
40
+ // we've to correctly map the key to this user's perspective
41
+ if (!message.key.fromMe) {
42
+ // if the sender believed the message being reacted to is not from them
43
+ // we've to correct the key to be from them, or some other participant
44
+ msgKey.fromMe = !msgKey.fromMe
45
+ ? (0, WABinary_1.areJidsSameUser)(msgKey.participant || msgKey.remoteJid, meId)
46
+ : // if the message being reacted to, was from them
47
+ // fromMe automatically becomes false
48
+ false
49
+ // set the remoteJid to being the same as the chat the message came from
50
+ msgKey.remoteJid = message.key.remoteJid
51
+ // set participant of the message
52
+ msgKey.participant = msgKey.participant || message.key.participant
53
+ }
54
+ }
55
+ }
56
+ exports.cleanMessage = cleanMessage
57
+ const isRealMessage = (message, meId) => {
58
+ var _a
59
+ const normalizedContent = (0, messages_1.normalizeMessageContent)(message.message)
60
+ const hasSomeContent = !!(0, messages_1.getContentType)(normalizedContent)
61
+ return (
62
+ (!!normalizedContent ||
63
+ REAL_MSG_STUB_TYPES.has(message.messageStubType) ||
64
+ (REAL_MSG_REQ_ME_STUB_TYPES.has(message.messageStubType) &&
65
+ ((_a = message.messageStubParameters) === null || _a === void 0
66
+ ? void 0
67
+ : _a.some((p) => (0, WABinary_1.areJidsSameUser)(meId, p))))) &&
68
+ hasSomeContent &&
69
+ !(normalizedContent === null || normalizedContent === void 0
70
+ ? void 0
71
+ : normalizedContent.protocolMessage) &&
72
+ !(normalizedContent === null || normalizedContent === void 0
73
+ ? void 0
74
+ : normalizedContent.reactionMessage) &&
75
+ !(normalizedContent === null || normalizedContent === void 0
76
+ ? void 0
77
+ : normalizedContent.pollUpdateMessage)
78
+ )
79
+ }
80
+ exports.isRealMessage = isRealMessage
81
+ const shouldIncrementChatUnread = (message) => !message.key.fromMe && !message.messageStubType
82
+ exports.shouldIncrementChatUnread = shouldIncrementChatUnread
83
+ /**
84
+ * Get the ID of the chat from the given key.
85
+ * Typically -- that'll be the remoteJid, but for broadcasts, it'll be the participant
86
+ */
87
+ const getChatId = ({ remoteJid, participant, fromMe }) => {
88
+ if (
89
+ (0, WABinary_1.isJidBroadcast)(remoteJid) &&
90
+ !(0, WABinary_1.isJidStatusBroadcast)(remoteJid) &&
91
+ !fromMe
92
+ ) {
93
+ return participant
94
+ }
95
+ return remoteJid
96
+ }
97
+ exports.getChatId = getChatId
98
+ /**
99
+ * Decrypt a poll vote
100
+ * @param vote encrypted vote
101
+ * @param ctx additional info about the poll required for decryption
102
+ * @returns list of SHA256 options
103
+ */
104
+ function decryptPollVote(
105
+ { encPayload, encIv },
106
+ { pollCreatorJid, pollMsgId, pollEncKey, voterJid }
107
+ ) {
108
+ const sign = Buffer.concat([
109
+ toBinary(pollMsgId),
110
+ toBinary(pollCreatorJid),
111
+ toBinary(voterJid),
112
+ toBinary('Poll Vote'),
113
+ new Uint8Array([1])
114
+ ])
115
+ const key0 = (0, crypto_1.hmacSign)(pollEncKey, new Uint8Array(32), 'sha256')
116
+ const decKey = (0, crypto_1.hmacSign)(sign, key0, 'sha256')
117
+ const aad = toBinary(`${pollMsgId}\u0000${voterJid}`)
118
+ const decrypted = (0, crypto_1.aesDecryptGCM)(encPayload, decKey, encIv, aad)
119
+ return WAProto_1.proto.Message.PollVoteMessage.decode(decrypted)
120
+ function toBinary(txt) {
121
+ return Buffer.from(txt)
122
+ }
123
+ }
124
+ exports.decryptPollVote = decryptPollVote
125
+ const processMessage = async (
126
+ message,
127
+ { shouldProcessHistoryMsg, ev, creds, keyStore, logger, options, getMessage }
128
+ ) => {
129
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k
130
+ const meId = creds.me.id
131
+ const { accountSettings } = creds
132
+ const chat = { id: (0, WABinary_1.jidNormalizedUser)((0, exports.getChatId)(message.key)) }
133
+ const isRealMsg = (0, exports.isRealMessage)(message, meId)
134
+ if (isRealMsg) {
135
+ chat.conversationTimestamp = (0, generics_1.toNumber)(message.messageTimestamp)
136
+ // only increment unread count if not CIPHERTEXT and from another person
137
+ if ((0, exports.shouldIncrementChatUnread)(message)) {
138
+ chat.unreadCount = (chat.unreadCount || 0) + 1
139
+ }
140
+ }
141
+ const content = (0, messages_1.normalizeMessageContent)(message.message)
142
+ // unarchive chat if it's a real message, or someone reacted to our message
143
+ // and we've the unarchive chats setting on
144
+ if (
145
+ (isRealMsg ||
146
+ ((_b =
147
+ (_a = content === null || content === void 0 ? void 0 : content.reactionMessage) ===
148
+ null || _a === void 0
149
+ ? void 0
150
+ : _a.key) === null || _b === void 0
151
+ ? void 0
152
+ : _b.fromMe)) &&
153
+ (accountSettings === null || accountSettings === void 0
154
+ ? void 0
155
+ : accountSettings.unarchiveChats)
156
+ ) {
157
+ chat.archived = false
158
+ chat.readOnly = false
159
+ }
160
+ const protocolMsg = content === null || content === void 0 ? void 0 : content.protocolMessage
161
+ if (protocolMsg) {
162
+ switch (protocolMsg.type) {
163
+ case WAProto_1.proto.Message.ProtocolMessage.Type.HISTORY_SYNC_NOTIFICATION:
164
+ const histNotification = protocolMsg.historySyncNotification
165
+ const process = shouldProcessHistoryMsg
166
+ const isLatest = !((_c = creds.processedHistoryMessages) === null || _c === void 0
167
+ ? void 0
168
+ : _c.length)
169
+ logger === null || logger === void 0
170
+ ? void 0
171
+ : logger.info(
172
+ {
173
+ histNotification,
174
+ process,
175
+ id: message.key.id,
176
+ isLatest
177
+ },
178
+ 'got history notification'
179
+ )
180
+ if (process) {
181
+ // ON_DEMAND (peer data request) must not count as a processed history batch
182
+ if (
183
+ histNotification.syncType !==
184
+ WAProto_1.proto.HistorySync.HistorySyncType.ON_DEMAND
185
+ ) {
186
+ ev.emit('creds.update', {
187
+ processedHistoryMessages: [
188
+ ...(creds.processedHistoryMessages || []),
189
+ { key: message.key, messageTimestamp: message.messageTimestamp }
190
+ ]
191
+ })
192
+ }
193
+ const data = await (0, history_1.downloadAndProcessHistorySyncNotification)(
194
+ histNotification,
195
+ options
196
+ )
197
+ ev.emit('messaging-history.set', {
198
+ ...data,
199
+ isLatest:
200
+ histNotification.syncType !==
201
+ WAProto_1.proto.HistorySync.HistorySyncType.ON_DEMAND
202
+ ? isLatest
203
+ : undefined,
204
+ chunkOrder: histNotification.chunkOrder,
205
+ peerDataRequestSessionId: histNotification.peerDataRequestSessionId
206
+ })
207
+ }
208
+ break
209
+ case WAProto_1.proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_SHARE:
210
+ const keys = protocolMsg.appStateSyncKeyShare.keys
211
+ if (keys === null || keys === void 0 ? void 0 : keys.length) {
212
+ let newAppStateSyncKeyId = ''
213
+ await keyStore.transaction(async () => {
214
+ const newKeys = []
215
+ for (const { keyData, keyId } of keys) {
216
+ const strKeyId = Buffer.from(keyId.keyId).toString('base64')
217
+ newKeys.push(strKeyId)
218
+ await keyStore.set({ 'app-state-sync-key': { [strKeyId]: keyData } })
219
+ newAppStateSyncKeyId = strKeyId
220
+ }
221
+ logger === null || logger === void 0
222
+ ? void 0
223
+ : logger.info(
224
+ { newAppStateSyncKeyId, newKeys },
225
+ 'injecting new app state sync keys'
226
+ )
227
+ })
228
+ ev.emit('creds.update', { myAppStateKeyId: newAppStateSyncKeyId })
229
+ } else {
230
+ logger === null || logger === void 0
231
+ ? void 0
232
+ : logger.info({ protocolMsg }, 'recv app state sync with 0 keys')
233
+ }
234
+ break
235
+ case WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE:
236
+ ev.emit('messages.update', [
237
+ {
238
+ key: {
239
+ ...message.key,
240
+ id: protocolMsg.key.id
241
+ },
242
+ update: {
243
+ message: null,
244
+ messageStubType: Types_1.WAMessageStubType.REVOKE,
245
+ key: message.key
246
+ }
247
+ }
248
+ ])
249
+ break
250
+ case WAProto_1.proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING:
251
+ Object.assign(chat, {
252
+ ephemeralSettingTimestamp: (0, generics_1.toNumber)(message.messageTimestamp),
253
+ ephemeralExpiration: protocolMsg.ephemeralExpiration || null
254
+ })
255
+ break
256
+ case WAProto_1.proto.Message.ProtocolMessage.Type
257
+ .PEER_DATA_OPERATION_REQUEST_RESPONSE_MESSAGE:
258
+ const response = protocolMsg.peerDataOperationRequestResponseMessage
259
+ if (response) {
260
+ const { peerDataOperationResult } = response
261
+ for (const result of peerDataOperationResult) {
262
+ const { placeholderMessageResendResponse: retryResponse } = result
263
+ if (retryResponse) {
264
+ const webMessageInfo = WAProto_1.proto.WebMessageInfo.decode(
265
+ retryResponse.webMessageInfoBytes
266
+ )
267
+ ev.emit('messages.update', [
268
+ {
269
+ key: webMessageInfo.key,
270
+ update: { message: webMessageInfo.message }
271
+ }
272
+ ])
273
+ }
274
+ }
275
+ }
276
+ break
277
+ }
278
+ } else if (content === null || content === void 0 ? void 0 : content.reactionMessage) {
279
+ const reaction = {
280
+ ...content.reactionMessage,
281
+ key: message.key
282
+ }
283
+ ev.emit('messages.reaction', [
284
+ {
285
+ reaction,
286
+ key: content.reactionMessage.key
287
+ }
288
+ ])
289
+ } else if (message.messageStubType) {
290
+ const jid = message.key.remoteJid
291
+ //let actor = whatsappID (message.participant)
292
+ let participants
293
+ const emitParticipantsUpdate = (action) =>
294
+ ev.emit('group-participants.update', {
295
+ id: jid,
296
+ author: message.participant,
297
+ participants,
298
+ action
299
+ })
300
+ const emitGroupUpdate = (update) => {
301
+ var _a
302
+ ev.emit('groups.update', [
303
+ {
304
+ id: jid,
305
+ ...update,
306
+ author: (_a = message.participant) !== null && _a !== void 0 ? _a : undefined
307
+ }
308
+ ])
309
+ }
310
+ const participantsIncludesMe = () =>
311
+ participants.find((jid) => (0, WABinary_1.areJidsSameUser)(meId, jid))
312
+ switch (message.messageStubType) {
313
+ case Types_1.WAMessageStubType.GROUP_PARTICIPANT_LEAVE:
314
+ case Types_1.WAMessageStubType.GROUP_PARTICIPANT_REMOVE:
315
+ participants = message.messageStubParameters || []
316
+ emitParticipantsUpdate('remove')
317
+ // mark the chat read only if you left the group
318
+ if (participantsIncludesMe()) {
319
+ chat.readOnly = true
320
+ }
321
+ break
322
+ case Types_1.WAMessageStubType.GROUP_PARTICIPANT_ADD:
323
+ case Types_1.WAMessageStubType.GROUP_PARTICIPANT_INVITE:
324
+ case Types_1.WAMessageStubType.GROUP_PARTICIPANT_ADD_REQUEST_JOIN:
325
+ participants = message.messageStubParameters || []
326
+ if (participantsIncludesMe()) {
327
+ chat.readOnly = false
328
+ }
329
+ emitParticipantsUpdate('add')
330
+ break
331
+ case Types_1.WAMessageStubType.GROUP_PARTICIPANT_DEMOTE:
332
+ participants = message.messageStubParameters || []
333
+ emitParticipantsUpdate('demote')
334
+ break
335
+ case Types_1.WAMessageStubType.GROUP_PARTICIPANT_PROMOTE:
336
+ participants = message.messageStubParameters || []
337
+ emitParticipantsUpdate('promote')
338
+ break
339
+ case Types_1.WAMessageStubType.GROUP_CHANGE_ANNOUNCE:
340
+ const announceValue =
341
+ (_d = message.messageStubParameters) === null || _d === void 0 ? void 0 : _d[0]
342
+ emitGroupUpdate({ announce: announceValue === 'true' || announceValue === 'on' })
343
+ break
344
+ case Types_1.WAMessageStubType.GROUP_CHANGE_RESTRICT:
345
+ const restrictValue =
346
+ (_e = message.messageStubParameters) === null || _e === void 0 ? void 0 : _e[0]
347
+ emitGroupUpdate({ restrict: restrictValue === 'true' || restrictValue === 'on' })
348
+ break
349
+ case Types_1.WAMessageStubType.GROUP_CHANGE_SUBJECT:
350
+ const name =
351
+ (_f = message.messageStubParameters) === null || _f === void 0 ? void 0 : _f[0]
352
+ chat.name = name
353
+ emitGroupUpdate({ subject: name })
354
+ break
355
+ case Types_1.WAMessageStubType.GROUP_CHANGE_INVITE_LINK:
356
+ const code =
357
+ (_g = message.messageStubParameters) === null || _g === void 0 ? void 0 : _g[0]
358
+ emitGroupUpdate({ inviteCode: code })
359
+ break
360
+ case Types_1.WAMessageStubType.GROUP_MEMBER_ADD_MODE:
361
+ const memberAddValue =
362
+ (_h = message.messageStubParameters) === null || _h === void 0 ? void 0 : _h[0]
363
+ emitGroupUpdate({ memberAddMode: memberAddValue === 'all_member_add' })
364
+ break
365
+ case Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE:
366
+ const approvalMode =
367
+ (_j = message.messageStubParameters) === null || _j === void 0 ? void 0 : _j[0]
368
+ emitGroupUpdate({ joinApprovalMode: approvalMode === 'on' })
369
+ break
370
+ }
371
+ } else if (content === null || content === void 0 ? void 0 : content.pollUpdateMessage) {
372
+ const creationMsgKey = content.pollUpdateMessage.pollCreationMessageKey
373
+ // we need to fetch the poll creation message to get the poll enc key
374
+ const pollMsg = await getMessage(creationMsgKey)
375
+ if (pollMsg) {
376
+ const meIdNormalised = (0, WABinary_1.jidNormalizedUser)(meId)
377
+ const pollCreatorJid = (0, generics_1.getKeyAuthor)(creationMsgKey, meIdNormalised)
378
+ const voterJid = (0, generics_1.getKeyAuthor)(message.key, meIdNormalised)
379
+ const pollEncKey =
380
+ (_k = pollMsg.messageContextInfo) === null || _k === void 0
381
+ ? void 0
382
+ : _k.messageSecret
383
+ try {
384
+ const voteMsg = decryptPollVote(content.pollUpdateMessage.vote, {
385
+ pollEncKey,
386
+ pollCreatorJid,
387
+ pollMsgId: creationMsgKey.id,
388
+ voterJid
389
+ })
390
+ ev.emit('messages.update', [
391
+ {
392
+ key: creationMsgKey,
393
+ update: {
394
+ pollUpdates: [
395
+ {
396
+ pollUpdateMessageKey: message.key,
397
+ vote: voteMsg,
398
+ senderTimestampMs:
399
+ content.pollUpdateMessage.senderTimestampMs.toNumber()
400
+ }
401
+ ]
402
+ }
403
+ }
404
+ ])
405
+ } catch (err) {
406
+ logger === null || logger === void 0
407
+ ? void 0
408
+ : logger.warn({ err, creationMsgKey }, 'failed to decrypt poll vote')
409
+ }
410
+ } else {
411
+ logger === null || logger === void 0
412
+ ? void 0
413
+ : logger.warn(
414
+ { creationMsgKey },
415
+ 'poll creation message not found, cannot decrypt update'
416
+ )
417
+ }
418
+ }
419
+ if (Object.keys(chat).length > 1) {
420
+ ev.emit('chats.update', [chat])
421
+ }
422
+ }
423
+ exports.default = processMessage
@@ -0,0 +1,232 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.RateLimiter = void 0
4
+
5
+ /**
6
+ * @file rate-limiter.js
7
+ * @description Human-like rate limiting for WhatsApp message sending.
8
+ * Prevents ban by enforcing per-minute/hour/day limits with gaussian jitter.
9
+ * Ported from baileys-antiban to CJS for bilis.
10
+ * @author Denzy ZeroDay (port), Kobus Wentzel (original)
11
+ */
12
+
13
+ const MS_PER_MINUTE = 60000
14
+ const MS_PER_HOUR = 3600000
15
+ const MS_PER_DAY = 86400000
16
+ const BURST_RESET_MS = 30000
17
+ const IDENTICAL_WINDOW_MS = 3600000
18
+
19
+ const DEFAULT_CONFIG = {
20
+ maxPerMinute: 8,
21
+ maxPerHour: 200,
22
+ maxPerDay: 1500,
23
+ minDelayMs: 1500,
24
+ maxDelayMs: 5000,
25
+ newChatDelayMs: 3000,
26
+ maxIdenticalMessages: 3,
27
+ burstAllowance: 3,
28
+ identicalMessageWindowMs: IDENTICAL_WINDOW_MS
29
+ }
30
+
31
+ class RateLimiter {
32
+ constructor(config = {}) {
33
+ this.config = { ...DEFAULT_CONFIG, ...config }
34
+ this.originalConfig = { ...this.config }
35
+ this.messages = []
36
+ this.identicalCount = new Map()
37
+ this.knownChats = new Set()
38
+ this.burstCount = 0
39
+ this.lastMessageTime = 0
40
+ }
41
+
42
+ /**
43
+ * Calculate delay before next message can be sent.
44
+ * Returns 0 if ok, -1 if blocked (daily/identical limit).
45
+ */
46
+ async getDelay(recipient, content) {
47
+ const now = Date.now()
48
+ this._cleanup(now)
49
+ const contentHash = this._hash(content)
50
+
51
+ // Daily limit
52
+ const dayMessages = this.messages.filter((m) => now - m.timestamp < MS_PER_DAY)
53
+ if (dayMessages.length >= this.config.maxPerDay) return -1
54
+
55
+ // Hourly limit
56
+ const hourMessages = this.messages.filter((m) => now - m.timestamp < MS_PER_HOUR)
57
+ if (hourMessages.length >= this.config.maxPerHour) {
58
+ hourMessages.sort((a, b) => a.timestamp - b.timestamp)
59
+ const oldest = hourMessages[0]
60
+ return Math.max(oldest.timestamp + MS_PER_HOUR - now, MS_PER_MINUTE)
61
+ }
62
+
63
+ // Per-minute limit
64
+ const minuteMessages = this.messages.filter((m) => now - m.timestamp < MS_PER_MINUTE)
65
+ if (minuteMessages.length >= this.config.maxPerMinute) {
66
+ minuteMessages.sort((a, b) => a.timestamp - b.timestamp)
67
+ const oldest = minuteMessages[0]
68
+ return Math.max(oldest.timestamp + MS_PER_MINUTE - now, 1000)
69
+ }
70
+
71
+ // Identical message spam check
72
+ const tracker = this.identicalCount.get(contentHash)
73
+ if (tracker && now - tracker.firstSeen < this.config.identicalMessageWindowMs) {
74
+ if (tracker.count >= this.config.maxIdenticalMessages) return -1
75
+ }
76
+
77
+ // Human-like delay calculation
78
+ let delay = 0
79
+ if (this.burstCount < this.config.burstAllowance) {
80
+ this.burstCount++
81
+ delay = this._jitter(this.config.minDelayMs * 0.5, this.config.minDelayMs)
82
+ } else {
83
+ delay = this._jitter(this.config.minDelayMs, this.config.maxDelayMs)
84
+ }
85
+
86
+ // Extra delay for new chats
87
+ if (!this.knownChats.has(recipient)) {
88
+ delay += this._jitter(this.config.newChatDelayMs * 0.5, this.config.newChatDelayMs)
89
+ }
90
+
91
+ // Minimum time since last message
92
+ const timeSinceLast = now - this.lastMessageTime
93
+ if (timeSinceLast < this.config.minDelayMs) {
94
+ delay = Math.max(delay, this.config.minDelayMs - timeSinceLast)
95
+ }
96
+
97
+ // Typing simulation delay based on content length
98
+ const typingDelay = Math.min(content.length * 30, 3000)
99
+ delay += this._jitter(typingDelay * 0.5, typingDelay)
100
+
101
+ return Math.round(delay)
102
+ }
103
+
104
+ /**
105
+ * Record a sent message
106
+ */
107
+ record(recipient, content) {
108
+ const now = Date.now()
109
+ const contentHash = this._hash(content)
110
+
111
+ if (now - this.lastMessageTime > BURST_RESET_MS) this.burstCount = 0
112
+
113
+ this.messages.push({ timestamp: now, recipient, contentHash })
114
+ this.knownChats.add(recipient)
115
+ this.lastMessageTime = now
116
+
117
+ const tracker = this.identicalCount.get(contentHash)
118
+ if (tracker) {
119
+ if (now - tracker.firstSeen < this.config.identicalMessageWindowMs) {
120
+ tracker.count++
121
+ tracker.lastSeen = now
122
+ } else {
123
+ this.identicalCount.set(contentHash, { count: 1, firstSeen: now, lastSeen: now })
124
+ }
125
+ } else {
126
+ this.identicalCount.set(contentHash, { count: 1, firstSeen: now, lastSeen: now })
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Get current stats
132
+ */
133
+ getStats() {
134
+ const now = Date.now()
135
+ this._cleanup(now)
136
+ return {
137
+ lastMinute: this.messages.filter((m) => now - m.timestamp < MS_PER_MINUTE).length,
138
+ lastHour: this.messages.filter((m) => now - m.timestamp < MS_PER_HOUR).length,
139
+ lastDay: this.messages.filter((m) => now - m.timestamp < MS_PER_DAY).length,
140
+ limits: {
141
+ perMinute: this.config.maxPerMinute,
142
+ perHour: this.config.maxPerHour,
143
+ perDay: this.config.maxPerDay
144
+ },
145
+ knownChats: this.knownChats.size,
146
+ currentFactor: this.getCurrentFactor()
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Scale rate limits by factor (0.1–1.0)
152
+ */
153
+ adaptLimits(factor) {
154
+ const f = Math.max(0.1, Math.min(1.0, factor))
155
+ this.config.maxPerMinute = Math.max(1, Math.floor(this.originalConfig.maxPerMinute * f))
156
+ this.config.maxPerHour = Math.max(5, Math.floor(this.originalConfig.maxPerHour * f))
157
+ this.config.maxPerDay = Math.max(20, Math.floor(this.originalConfig.maxPerDay * f))
158
+ const delayScale = 1 + (1 - f) * 2
159
+ this.config.minDelayMs = Math.floor(this.originalConfig.minDelayMs * delayScale)
160
+ this.config.maxDelayMs = Math.floor(this.originalConfig.maxDelayMs * delayScale)
161
+ }
162
+
163
+ getCurrentFactor() {
164
+ return this.config.maxPerMinute / this.originalConfig.maxPerMinute
165
+ }
166
+
167
+ getKnownChats() {
168
+ return this.knownChats
169
+ }
170
+
171
+ restoreKnownChats(chats) {
172
+ for (const jid of chats) this.knownChats.add(jid)
173
+ }
174
+
175
+ injectTimestamps(timestamps) {
176
+ const now = Date.now()
177
+ const recent = timestamps.filter((ts) => now - ts < MS_PER_DAY)
178
+ const existing = new Set(this.messages.map((m) => m.timestamp))
179
+ for (const ts of recent) {
180
+ if (!existing.has(ts)) {
181
+ this.messages.push({
182
+ timestamp: ts,
183
+ recipient: '__injected__',
184
+ contentHash: '__injected__'
185
+ })
186
+ }
187
+ }
188
+ const max = Math.max(...recent, 0)
189
+ if (max > this.lastMessageTime) this.lastMessageTime = max
190
+ this.messages.sort((a, b) => a.timestamp - b.timestamp)
191
+ }
192
+
193
+ _cleanup(now) {
194
+ this.messages = this.messages.filter((m) => now - m.timestamp < MS_PER_DAY)
195
+ for (const [hash, tracker] of this.identicalCount.entries()) {
196
+ if (now - tracker.lastSeen > this.config.identicalMessageWindowMs) {
197
+ this.identicalCount.delete(hash)
198
+ }
199
+ }
200
+ if (this.identicalCount.size > 10000) {
201
+ const sorted = [...this.identicalCount.entries()].sort(
202
+ ([, a], [, b]) => a.lastSeen - b.lastSeen
203
+ )
204
+ const excess = this.identicalCount.size - 10000
205
+ for (let i = 0; i < excess; i++) this.identicalCount.delete(sorted[i][0])
206
+ }
207
+ }
208
+
209
+ /** Gaussian-ish jitter for human-like timing */
210
+ _jitter(min, max) {
211
+ const u1 = Math.random()
212
+ const u2 = Math.random()
213
+ const normal = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2)
214
+ const normalized = (normal + 3) / 6
215
+ const clamped = Math.max(0, Math.min(1, normalized))
216
+ return Math.round(min + clamped * (max - min))
217
+ }
218
+
219
+ /** Simple hash for content dedup */
220
+ _hash(content) {
221
+ let hash = 0
222
+ for (let i = 0; i < content.length; i++) {
223
+ const char = content.charCodeAt(i)
224
+ hash = (hash << 5) - hash + char
225
+ hash |= 0
226
+ }
227
+ return hash.toString(36)
228
+ }
229
+ }
230
+
231
+ exports.RateLimiter = RateLimiter
232
+ module.exports = { RateLimiter }