@neelegirl/baileys 1.5.5 → 1.5.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 (203) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +183 -10
  3. package/WAProto/WAProto.proto +5007 -0
  4. package/WAProto/index.d.ts +57712 -0
  5. package/WAProto/index.js +178969 -0
  6. package/lib/Defaults/baileys-version.json +3 -0
  7. package/lib/Defaults/index.d.ts +68 -0
  8. package/lib/Defaults/index.js +137 -0
  9. package/lib/Defaults/phonenumber-mcc.json +223 -0
  10. package/lib/Signal/WASignalGroup/GroupProtocol.js +1909 -0
  11. package/lib/Signal/WASignalGroup/ciphertext_message.js +16 -0
  12. package/lib/Signal/WASignalGroup/generate-proto.sh +1 -0
  13. package/lib/Signal/WASignalGroup/group.proto +42 -0
  14. package/lib/Signal/WASignalGroup/group_cipher.js +120 -0
  15. package/lib/Signal/WASignalGroup/group_session_builder.js +46 -0
  16. package/lib/Signal/WASignalGroup/index.js +6 -0
  17. package/lib/Signal/WASignalGroup/keyhelper.js +21 -0
  18. package/lib/Signal/WASignalGroup/protobufs.js +3 -0
  19. package/lib/Signal/WASignalGroup/queue_job.js +69 -0
  20. package/lib/Signal/WASignalGroup/readme.md +6 -0
  21. package/lib/Signal/WASignalGroup/sender_chain_key.js +50 -0
  22. package/lib/Signal/WASignalGroup/sender_key_distribution_message.js +78 -0
  23. package/lib/Signal/WASignalGroup/sender_key_message.js +92 -0
  24. package/lib/Signal/WASignalGroup/sender_key_name.js +70 -0
  25. package/lib/Signal/WASignalGroup/sender_key_record.js +56 -0
  26. package/lib/Signal/WASignalGroup/sender_key_state.js +129 -0
  27. package/lib/Signal/WASignalGroup/sender_message_key.js +39 -0
  28. package/lib/Signal/libsignal.d.ts +4 -0
  29. package/lib/Signal/libsignal.js +162 -0
  30. package/lib/Socket/Client/abstract-socket-client.d.ts +15 -0
  31. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  32. package/lib/Socket/Client/index.d.ts +2 -0
  33. package/lib/Socket/Client/index.js +22 -0
  34. package/lib/Socket/Client/mobile-socket-client.d.ts +12 -0
  35. package/lib/Socket/Client/mobile-socket-client.js +65 -0
  36. package/lib/Socket/Client/types.d.ts +16 -0
  37. package/lib/Socket/Client/types.js +18 -0
  38. package/lib/Socket/Client/websocket.d.ts +13 -0
  39. package/lib/Socket/Client/websocket.js +62 -0
  40. package/lib/Socket/business.d.ts +187 -0
  41. package/lib/Socket/business.js +268 -0
  42. package/lib/Socket/chats.d.ts +98 -0
  43. package/lib/Socket/chats.js +1113 -0
  44. package/lib/Socket/communities.d.ts +223 -0
  45. package/lib/Socket/communities.js +433 -0
  46. package/lib/Socket/groups.d.ts +131 -0
  47. package/lib/Socket/groups.js +352 -0
  48. package/lib/Socket/index.d.ts +191 -0
  49. package/lib/Socket/index.js +23 -0
  50. package/lib/Socket/messages-recv.d.ts +177 -0
  51. package/lib/Socket/messages-recv.js +1764 -0
  52. package/lib/Socket/messages-send.d.ts +168 -0
  53. package/lib/Socket/messages-send.js +1303 -0
  54. package/lib/Socket/mex.d.ts +2 -0
  55. package/lib/Socket/mex.js +47 -0
  56. package/lib/Socket/newsletter.d.ts +147 -0
  57. package/lib/Socket/newsletter.js +286 -0
  58. package/lib/Socket/registration.d.ts +266 -0
  59. package/lib/Socket/registration.js +166 -0
  60. package/lib/Socket/socket.d.ts +45 -0
  61. package/lib/Socket/socket.js +766 -0
  62. package/lib/Socket/usync.d.ts +37 -0
  63. package/lib/Socket/usync.js +83 -0
  64. package/lib/Store/index.d.ts +4 -0
  65. package/lib/Store/index.js +24 -0
  66. package/lib/Store/make-cache-manager-store.d.ts +14 -0
  67. package/lib/Store/make-cache-manager-store.js +90 -0
  68. package/lib/Store/make-in-memory-store.d.ts +123 -0
  69. package/lib/Store/make-in-memory-store.js +429 -0
  70. package/lib/Store/make-ordered-dictionary.d.ts +12 -0
  71. package/lib/Store/make-ordered-dictionary.js +86 -0
  72. package/lib/Store/object-repository.d.ts +10 -0
  73. package/lib/Store/object-repository.js +31 -0
  74. package/lib/Types/Auth.d.ts +120 -0
  75. package/lib/Types/Auth.js +3 -0
  76. package/lib/Types/Call.d.ts +14 -0
  77. package/lib/Types/Call.js +3 -0
  78. package/lib/Types/Chat.d.ts +138 -0
  79. package/lib/Types/Chat.js +9 -0
  80. package/lib/Types/Contact.d.ts +20 -0
  81. package/lib/Types/Contact.js +3 -0
  82. package/lib/Types/Events.d.ts +229 -0
  83. package/lib/Types/Events.js +3 -0
  84. package/lib/Types/GroupMetadata.d.ts +66 -0
  85. package/lib/Types/GroupMetadata.js +3 -0
  86. package/lib/Types/Label.d.ts +48 -0
  87. package/lib/Types/Label.js +31 -0
  88. package/lib/Types/LabelAssociation.d.ts +35 -0
  89. package/lib/Types/LabelAssociation.js +13 -0
  90. package/lib/Types/Message.d.ts +473 -0
  91. package/lib/Types/Message.js +13 -0
  92. package/lib/Types/MexUpdates.d.ts +9 -0
  93. package/lib/Types/MexUpdates.js +18 -0
  94. package/lib/Types/Newsletter.d.ts +109 -0
  95. package/lib/Types/Newsletter.js +40 -0
  96. package/lib/Types/Product.d.ts +92 -0
  97. package/lib/Types/Product.js +3 -0
  98. package/lib/Types/Signal.d.ts +68 -0
  99. package/lib/Types/Signal.js +3 -0
  100. package/lib/Types/Socket.d.ts +122 -0
  101. package/lib/Types/Socket.js +3 -0
  102. package/lib/Types/State.d.ts +41 -0
  103. package/lib/Types/State.js +14 -0
  104. package/lib/Types/USync.d.ts +26 -0
  105. package/lib/Types/USync.js +3 -0
  106. package/lib/Types/index.d.ts +79 -0
  107. package/lib/Types/index.js +48 -0
  108. package/lib/Utils/auth-utils.d.ts +21 -0
  109. package/lib/Utils/auth-utils.js +205 -0
  110. package/lib/Utils/baileys-event-stream.d.ts +18 -0
  111. package/lib/Utils/baileys-event-stream.js +70 -0
  112. package/lib/Utils/business.d.ts +29 -0
  113. package/lib/Utils/business.js +255 -0
  114. package/lib/Utils/chat-utils.d.ts +82 -0
  115. package/lib/Utils/chat-utils.js +781 -0
  116. package/lib/Utils/check-npm-version.d.ts +15 -0
  117. package/lib/Utils/check-npm-version.js +52 -0
  118. package/lib/Utils/crypto.d.ts +56 -0
  119. package/lib/Utils/crypto.js +179 -0
  120. package/lib/Utils/decode-wa-message.d.ts +41 -0
  121. package/lib/Utils/decode-wa-message.js +253 -0
  122. package/lib/Utils/event-buffer.d.ts +39 -0
  123. package/lib/Utils/event-buffer.js +565 -0
  124. package/lib/Utils/generics.d.ts +129 -0
  125. package/lib/Utils/generics.js +618 -0
  126. package/lib/Utils/history.d.ts +23 -0
  127. package/lib/Utils/history.js +110 -0
  128. package/lib/Utils/index.d.ts +19 -0
  129. package/lib/Utils/index.js +41 -0
  130. package/lib/Utils/link-preview.d.ts +23 -0
  131. package/lib/Utils/link-preview.js +120 -0
  132. package/lib/Utils/logger.d.ts +13 -0
  133. package/lib/Utils/logger.js +7 -0
  134. package/lib/Utils/lt-hash.d.ts +14 -0
  135. package/lib/Utils/lt-hash.js +58 -0
  136. package/lib/Utils/make-mutex.d.ts +9 -0
  137. package/lib/Utils/make-mutex.js +49 -0
  138. package/lib/Utils/message-retry-manager.d.ts +82 -0
  139. package/lib/Utils/message-retry-manager.js +177 -0
  140. package/lib/Utils/messages-media.d.ts +129 -0
  141. package/lib/Utils/messages-media.js +806 -0
  142. package/lib/Utils/messages.d.ts +103 -0
  143. package/lib/Utils/messages.js +1579 -0
  144. package/lib/Utils/noise-handler.d.ts +20 -0
  145. package/lib/Utils/noise-handler.js +155 -0
  146. package/lib/Utils/process-message.d.ts +49 -0
  147. package/lib/Utils/process-message.js +428 -0
  148. package/lib/Utils/signal.d.ts +42 -0
  149. package/lib/Utils/signal.js +166 -0
  150. package/lib/Utils/use-mongo-file-auth-state.d.ts +6 -0
  151. package/lib/Utils/use-mongo-file-auth-state.js +84 -0
  152. package/lib/Utils/use-multi-file-auth-state.d.ts +18 -0
  153. package/lib/Utils/use-multi-file-auth-state.js +238 -0
  154. package/lib/Utils/use-single-file-auth-state.d.ts +13 -0
  155. package/lib/Utils/use-single-file-auth-state.js +80 -0
  156. package/lib/Utils/validate-connection.d.ts +13 -0
  157. package/lib/Utils/validate-connection.js +187 -0
  158. package/lib/WABinary/constants.d.ts +30 -0
  159. package/lib/WABinary/constants.js +1316 -0
  160. package/lib/WABinary/decode.d.ts +9 -0
  161. package/lib/WABinary/decode.js +288 -0
  162. package/lib/WABinary/encode.d.ts +3 -0
  163. package/lib/WABinary/encode.js +265 -0
  164. package/lib/WABinary/generic-utils.d.ts +28 -0
  165. package/lib/WABinary/generic-utils.js +142 -0
  166. package/lib/WABinary/index.d.ts +5 -0
  167. package/lib/WABinary/index.js +25 -0
  168. package/lib/WABinary/jid-utils.d.ts +53 -0
  169. package/lib/WABinary/jid-utils.js +92 -0
  170. package/lib/WABinary/types.d.ts +22 -0
  171. package/lib/WABinary/types.js +3 -0
  172. package/lib/WAM/BinaryInfo.d.ts +16 -0
  173. package/lib/WAM/BinaryInfo.js +17 -0
  174. package/lib/WAM/constants.d.ts +47 -0
  175. package/lib/WAM/constants.js +15371 -0
  176. package/lib/WAM/encode.d.ts +3 -0
  177. package/lib/WAM/encode.js +165 -0
  178. package/lib/WAM/index.d.ts +3 -0
  179. package/lib/WAM/index.js +23 -0
  180. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.d.ts +28 -0
  181. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +69 -0
  182. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +10 -0
  183. package/lib/WAUSync/Protocols/USyncContactProtocol.js +36 -0
  184. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +26 -0
  185. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +62 -0
  186. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +14 -0
  187. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +35 -0
  188. package/lib/WAUSync/Protocols/USyncLIDProtocol.d.ts +9 -0
  189. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +30 -0
  190. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +14 -0
  191. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +46 -0
  192. package/lib/WAUSync/Protocols/index.d.ts +6 -0
  193. package/lib/WAUSync/Protocols/index.js +26 -0
  194. package/lib/WAUSync/USyncQuery.d.ts +31 -0
  195. package/lib/WAUSync/USyncQuery.js +92 -0
  196. package/lib/WAUSync/USyncUser.d.ts +12 -0
  197. package/lib/WAUSync/USyncUser.js +30 -0
  198. package/lib/WAUSync/index.d.ts +3 -0
  199. package/lib/WAUSync/index.js +23 -0
  200. package/lib/index.d.ts +13 -0
  201. package/lib/index.js +33 -0
  202. package/package.json +88 -10
  203. package/index.js +0 -38
@@ -0,0 +1,1303 @@
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 crypto_1 = require("crypto")
12
+ const WAProto_1 = require("../../WAProto")
13
+ const Defaults_1 = require("../Defaults")
14
+ const Utils_1 = require("../Utils")
15
+ const Types_1 = require("../Types")
16
+ const WABinary_1 = require("../WABinary")
17
+ const WAUSync_1 = require("../WAUSync")
18
+ const newsletter_1 = require("./newsletter")
19
+ const link_preview_1 = require("../Utils/link-preview")
20
+
21
+ const makeMessagesSocket = (config) => {
22
+ const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: axiosOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config
23
+ const baron = newsletter_1.makeNewsletterSocket(config)
24
+ const { ev, authState, processingMutex, signalRepository, upsertMessage, createCallLink, query, fetchPrivacySettings, sendNode, groupQuery, groupMetadata, groupToggleEphemeral, newsletterWMexQuery, executeUSyncQuery } = baron
25
+
26
+ const userDevicesCache = config.userDevicesCache || new node_cache_1.default({
27
+ stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES,
28
+ useClones: false
29
+ })
30
+
31
+ // Initialize message retry manager if enabled
32
+ const messageRetryManager = enableRecentMessageCache ? new Utils_1.MessageRetryManager(logger, maxMsgRetryCount) : null
33
+
34
+ let mediaConn
35
+
36
+ const refreshMediaConn = async (forceGet = false) => {
37
+ const media = await mediaConn
38
+
39
+ if (!media || forceGet || (new Date().getTime() - media.fetchDate.getTime()) > media.ttl * 1000) {
40
+ mediaConn = (async () => {
41
+
42
+ const result = await query({
43
+ tag: 'iq',
44
+ attrs: {
45
+ type: 'set',
46
+ xmlns: 'w:m',
47
+ to: WABinary_1.S_WHATSAPP_NET,
48
+ },
49
+ content: [{ tag: 'media_conn', attrs: {} }]
50
+ })
51
+
52
+ const mediaConnNode = WABinary_1.getBinaryNodeChild(result, 'media_conn')
53
+
54
+ const node = {
55
+ hosts: WABinary_1.getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
56
+ hostname: attrs.hostname,
57
+ maxContentLengthBytes: +attrs.maxContentLengthBytes,
58
+ })),
59
+ auth: mediaConnNode.attrs.auth,
60
+ ttl: +mediaConnNode.attrs.ttl,
61
+ fetchDate: new Date()
62
+ }
63
+
64
+ logger.debug('fetched media conn')
65
+
66
+ return node
67
+ })()
68
+ }
69
+
70
+ return mediaConn
71
+ }
72
+
73
+ /**
74
+ * generic send receipt function
75
+ * used for receipts of phone call, read, delivery etc.
76
+ * */
77
+ const sendReceipt = async (jid, participant, messageIds, type) => {
78
+ const node = {
79
+ tag: 'receipt',
80
+ attrs: {
81
+ id: messageIds[0],
82
+ },
83
+ }
84
+
85
+ const isReadReceipt = type === 'read' || type === 'read-self'
86
+
87
+ if (isReadReceipt) {
88
+ node.attrs.t = Utils_1.unixTimestampSeconds().toString()
89
+ }
90
+
91
+ if (type === 'sender' && WABinary_1.isJidUser(jid)) {
92
+ node.attrs.recipient = jid
93
+ node.attrs.to = participant
94
+ }
95
+
96
+ else {
97
+ node.attrs.to = jid
98
+ if (participant) {
99
+ node.attrs.participant = participant
100
+ }
101
+ }
102
+
103
+ if (type) {
104
+ node.attrs.type = WABinary_1.isJidNewsletter(jid) ? 'read-self' : type
105
+ }
106
+
107
+ const remainingMessageIds = messageIds.slice(1)
108
+
109
+ if (remainingMessageIds.length) {
110
+ node.content = [
111
+ {
112
+ tag: 'list',
113
+ attrs: {},
114
+ content: remainingMessageIds.map(id => ({
115
+ tag: 'item',
116
+ attrs: { id }
117
+ }))
118
+ }
119
+ ]
120
+ }
121
+
122
+ logger.debug({ attrs: node.attrs, messageIds }, 'sending receipt for messages')
123
+
124
+ await sendNode(node)
125
+ }
126
+
127
+ /** Correctly bulk send receipts to multiple chats, participants */
128
+ const sendReceipts = async (keys, type) => {
129
+ const recps = Utils_1.aggregateMessageKeysNotFromMe(keys)
130
+
131
+ for (const { jid, participant, messageIds } of recps) {
132
+ await sendReceipt(jid, participant, messageIds, type)
133
+ }
134
+ }
135
+
136
+ /** Bulk read messages. Keys can be from different chats & participants */
137
+ const readMessages = async (keys) => {
138
+ const privacySettings = await fetchPrivacySettings()
139
+
140
+ // based on privacy settings, we have to change the read type
141
+ const readType = privacySettings.readreceipts === 'all' ? 'read' : 'read-self'
142
+
143
+ await sendReceipts(keys, readType)
144
+ }
145
+
146
+ /** Fetch image for groups, user, and newsletter **/
147
+ const profilePictureUrl = async (jid) => {
148
+ if (WABinary_1.isJidNewsletter(jid)) {
149
+
150
+ let node = await newsletterWMexQuery(undefined, Types_1.QueryIds.METADATA, {
151
+ input: {
152
+ key: jid,
153
+ type: 'JID',
154
+ view_role: 'GUEST'
155
+ },
156
+ fetch_viewer_metadata: true,
157
+ fetch_full_image: true,
158
+ fetch_creation_time: true
159
+ })
160
+
161
+ let result = WABinary_1.getBinaryNodeChild(node, 'result')?.content?.toString()
162
+
163
+ let metadata = JSON.parse(result).data[Types_1.XWAPaths.NEWSLETTER]
164
+
165
+ return Utils_1.getUrlFromDirectPath(metadata.thread_metadata.picture?.direct_path || '')
166
+
167
+ }
168
+
169
+ else {
170
+ const result = await query({
171
+ tag: 'iq',
172
+ attrs: {
173
+ target: WABinary_1.jidNormalizedUser(jid),
174
+ to: WABinary_1.S_WHATSAPP_NET,
175
+ type: 'get',
176
+ xmlns: 'w:profile:picture'
177
+ },
178
+ content: [{
179
+ tag: 'picture',
180
+ attrs: {
181
+ type: 'image',
182
+ query: 'url'
183
+ }
184
+ }]
185
+ })
186
+
187
+ const child = WABinary_1.getBinaryNodeChild(result, 'picture')
188
+
189
+ return child?.attrs?.url || null
190
+ }
191
+ }
192
+
193
+ /** Fetch all the devices we've to send a message to */
194
+ const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
195
+ const deviceResults = []
196
+
197
+ if (!useCache) {
198
+ logger.debug('not using cache for devices')
199
+ }
200
+
201
+ const toFetch = []
202
+
203
+ jids = Array.from(new Set(jids))
204
+
205
+ for (let jid of jids) {
206
+ const user = WABinary_1.jidDecode(jid)?.user
207
+
208
+ jid = WABinary_1.jidNormalizedUser(jid)
209
+
210
+ if (useCache) {
211
+ const devices = userDevicesCache.get(user)
212
+
213
+ if (devices) {
214
+ deviceResults.push(...devices)
215
+ logger.trace({ user }, 'using cache for devices')
216
+ }
217
+
218
+ else {
219
+ toFetch.push(jid)
220
+ }
221
+ }
222
+
223
+ else {
224
+ toFetch.push(jid)
225
+ }
226
+ }
227
+
228
+ if (!toFetch.length) {
229
+ return deviceResults
230
+ }
231
+
232
+ const query = new WAUSync_1.USyncQuery()
233
+ .withContext('message')
234
+ .withDeviceProtocol()
235
+
236
+ for (const jid of toFetch) {
237
+ query.withUser(new WAUSync_1.USyncUser().withId(jid))
238
+ }
239
+
240
+ const result = await executeUSyncQuery(query)
241
+
242
+ if (result) {
243
+ const extracted = Utils_1.extractDeviceJids(result?.list, authState.creds.me.id, ignoreZeroDevices)
244
+ const deviceMap = {}
245
+
246
+ for (const item of extracted) {
247
+ deviceMap[item.user] = deviceMap[item.user] || []
248
+ deviceMap[item.user].push(item)
249
+ deviceResults.push(item)
250
+ }
251
+
252
+ for (const key in deviceMap) {
253
+ userDevicesCache.set(key, deviceMap[key])
254
+ }
255
+ }
256
+
257
+ return deviceResults
258
+ }
259
+
260
+ /** Assert Sessions */
261
+ const assertSessions = async (jids, force) => {
262
+ let didFetchNewSession = false
263
+ let jidsRequiringFetch = []
264
+
265
+ if (force) {
266
+ jidsRequiringFetch = jids
267
+ }
268
+
269
+ else {
270
+ const addrs = jids.map(jid => (signalRepository.jidToSignalProtocolAddress(jid)))
271
+
272
+ const sessions = await authState.keys.get('session', addrs)
273
+
274
+ for (const jid of jids) {
275
+ const signalId = signalRepository
276
+ .jidToSignalProtocolAddress(jid)
277
+
278
+ if (!sessions[signalId]) {
279
+ jidsRequiringFetch.push(jid)
280
+ }
281
+ }
282
+ }
283
+
284
+ if (jidsRequiringFetch.length) {
285
+ logger.debug({ jidsRequiringFetch }, 'fetching sessions')
286
+
287
+ const result = await query({
288
+ tag: 'iq',
289
+ attrs: {
290
+ xmlns: 'encrypt',
291
+ type: 'get',
292
+ to: WABinary_1.S_WHATSAPP_NET,
293
+ },
294
+ content: [
295
+ {
296
+ tag: 'key',
297
+ attrs: {},
298
+ content: jidsRequiringFetch.map(jid => ({
299
+ tag: 'user',
300
+ attrs: { jid },
301
+ }))
302
+ }
303
+ ]
304
+ })
305
+
306
+ await Utils_1.parseAndInjectE2ESessions(result, signalRepository)
307
+
308
+ didFetchNewSession = true
309
+ }
310
+
311
+ return didFetchNewSession
312
+ }
313
+
314
+ /** Send Peer Operation */
315
+ const sendPeerDataOperationMessage = async (pdoMessage) => {
316
+ //TODO: for later, abstract the logic to send a Peer Message instead of just PDO - useful for App State Key Resync with phone
317
+ if (!authState.creds.me?.id) {
318
+ throw new boom_1.Boom('Not authenticated')
319
+ }
320
+
321
+ const protocolMessage = {
322
+ protocolMessage: {
323
+ peerDataOperationRequestMessage: pdoMessage,
324
+ type: WAProto_1.proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
325
+ }
326
+ }
327
+
328
+ const meJid = WABinary_1.jidNormalizedUser(authState.creds.me.id)
329
+
330
+ const msgId = await relayMessage(meJid, protocolMessage, {
331
+ additionalAttributes: {
332
+ category: 'peer',
333
+ // eslint-disable-next-line camelcase
334
+ push_priority: 'high_force',
335
+ },
336
+ })
337
+
338
+ return msgId
339
+ }
340
+
341
+ const createParticipantNodes = async (jids, message, extraAttrs) => {
342
+ const patched = await patchMessageBeforeSending(message, jids)
343
+ const bytes = Utils_1.encodeWAMessage(patched)
344
+
345
+ let shouldIncludeDeviceIdentity = false
346
+
347
+ const nodes = await Promise.all(jids.map(async (jid) => {
348
+ const { type, ciphertext } = await signalRepository.encryptMessage({ jid, data: bytes })
349
+
350
+ if (type === 'pkmsg') {
351
+ shouldIncludeDeviceIdentity = true
352
+ }
353
+
354
+ const node = {
355
+ tag: 'to',
356
+ attrs: { jid },
357
+ content: [{
358
+ tag: 'enc',
359
+ attrs: {
360
+ v: '2',
361
+ type,
362
+ ...extraAttrs || {}
363
+ },
364
+ content: ciphertext
365
+ }]
366
+ }
367
+
368
+ return node
369
+ }))
370
+
371
+ return {
372
+ nodes,
373
+ shouldIncludeDeviceIdentity
374
+ }
375
+ }
376
+
377
+ const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, additionalNodes, AI = true }) => {
378
+ const meId = authState.creds.me.id
379
+
380
+ let didPushAdditional = false
381
+ let shouldIncludeDeviceIdentity = false
382
+
383
+ const { user, server } = WABinary_1.jidDecode(jid)
384
+
385
+ const statusJid = 'status@broadcast'
386
+ const isGroup = server === 'g.us'
387
+ const isPrivate = server === 's.whatsapp.net'
388
+ const isNewsletter = server == 'newsletter'
389
+ const isStatus = jid === statusJid
390
+ const isLid = server === 'lid'
391
+
392
+ msgId = msgId || Utils_1.generateMessageID(authState.creds.me.id)
393
+ useUserDevicesCache = useUserDevicesCache !== false
394
+ useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus
395
+
396
+ const participants = []
397
+ const destinationJid = (!isStatus) ? WABinary_1.jidEncode(user, isLid ? 'lid' : isGroup ? 'g.us' : isNewsletter ? 'newsletter' : 's.whatsapp.net') : statusJid
398
+ const binaryNodeContent = []
399
+ const devices = []
400
+
401
+ const meMsg = {
402
+ deviceSentMessage: {
403
+ destinationJid,
404
+ message
405
+ },
406
+ messageContextInfo: message.messageContextInfo || {}
407
+ }
408
+
409
+ const extraAttrs = {}
410
+
411
+ const regexGroupOld = /^(\d{1,15})-(\d+)@g\.us$/
412
+
413
+ const messages = Utils_1.normalizeMessageContent(message)
414
+
415
+ const buttonType = getButtonType(messages)
416
+ const pollMessage = messages.pollCreationMessage || messages.pollCreationMessageV2 || messages.pollCreationMessageV3
417
+
418
+
419
+ if (participant) {
420
+ // when the retry request is not for a group
421
+ // only send to the specific device that asked for a retry
422
+ // otherwise the message is sent out to every device that should be a recipient
423
+ if (!isGroup && !isStatus) {
424
+ additionalAttributes = { ...additionalAttributes, 'device_fanout': 'false' }
425
+ }
426
+
427
+ const { user, device } = WABinary_1.jidDecode(participant.jid)
428
+
429
+ devices.push({ user, device })
430
+ }
431
+
432
+ await authState.keys.transaction(async () => {
433
+ const mediaType = getMediaType(message)
434
+
435
+ if (mediaType) {
436
+ extraAttrs['mediatype'] = mediaType
437
+ }
438
+
439
+ if (messages.pinInChatMessage || messages.keepInChatMessage || message.reactionMessage || message.protocolMessage?.editedMessage) {
440
+ extraAttrs['decrypt-fail'] = 'hide'
441
+ }
442
+
443
+ if (messages.interactiveResponseMessage?.nativeFlowResponseMessage) {
444
+ extraAttrs['native_flow_name'] = messages.interactiveResponseMessage.nativeFlowResponseMessage?.name || 'menu_options'
445
+ }
446
+
447
+ if (isGroup || isStatus) {
448
+ const [groupData, senderKeyMap] = await Promise.all([
449
+ (async () => {
450
+ let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined
451
+
452
+ if (groupData && Array.isArray(groupData?.participants)) {
453
+ logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata')
454
+ }
455
+
456
+ else if (!isStatus) {
457
+ groupData = await groupMetadata(jid)
458
+ }
459
+
460
+ return groupData
461
+ })(),
462
+
463
+ (async () => {
464
+ if (!participant && !isStatus) {
465
+ const result = await authState.keys.get('sender-key-memory', [jid])
466
+ return result[jid] || {}
467
+ }
468
+
469
+ return {}
470
+
471
+ })()
472
+ ])
473
+
474
+ if (!participant) {
475
+ const participantsList = (groupData && !isStatus) ? groupData.participants.map(p => p.id) : []
476
+
477
+ if (isStatus && statusJidList) {
478
+ participantsList.push(...statusJidList)
479
+ }
480
+
481
+ if (!isStatus) {
482
+ additionalAttributes = {
483
+ ...additionalAttributes,
484
+ addressing_mode: groupData.addressingMode
485
+ }
486
+ }
487
+
488
+ const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false)
489
+ devices.push(...additionalDevices)
490
+ }
491
+
492
+ const patched = await patchMessageBeforeSending(message, devices.map(d => WABinary_1.jidEncode(d.user, isLid ? 'lid' : 's.whatsapp.net', d.device)))
493
+ const bytes = Utils_1.encodeWAMessage(patched)
494
+
495
+ const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
496
+ group: destinationJid,
497
+ data: bytes,
498
+ meId,
499
+ })
500
+
501
+ const senderKeyJids = []
502
+
503
+ // ensure a connection is established with every device
504
+ for (const { user, device } of devices) {
505
+ const jid = WABinary_1.jidEncode(user, 's.whatsapp.net', device)
506
+ if (!senderKeyMap[jid] || !!participant) {
507
+ senderKeyJids.push(jid)
508
+ // store that this person has had the sender keys sent to them
509
+ senderKeyMap[jid] = true
510
+ }
511
+ }
512
+
513
+ // if there are some participants with whom the session has not been established
514
+ // if there are, we re-send the senderkey
515
+ if (senderKeyJids.length) {
516
+ logger.debug({ senderKeyJids }, 'sending new sender key')
517
+ const senderKeyMsg = {
518
+ senderKeyDistributionMessage: {
519
+ axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
520
+ groupId: destinationJid
521
+ }
522
+ }
523
+
524
+ await assertSessions(senderKeyJids, false)
525
+
526
+ const result = await createParticipantNodes(senderKeyJids, senderKeyMsg, extraAttrs)
527
+
528
+ shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity
529
+
530
+ participants.push(...result.nodes)
531
+ }
532
+
533
+ binaryNodeContent.push({
534
+ tag: 'enc',
535
+ attrs: { v: '2', type: 'skmsg', ...extraAttrs },
536
+ content: ciphertext
537
+ })
538
+
539
+ await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } })
540
+ }
541
+
542
+ else if (isNewsletter) {
543
+ // Message edit
544
+ if (message.protocolMessage?.editedMessage) {
545
+ msgId = message.protocolMessage.key?.id
546
+ message = message.protocolMessage.editedMessage
547
+ }
548
+
549
+ // Message delete
550
+ if (message.protocolMessage?.type === WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE) {
551
+ msgId = message.protocolMessage.key?.id
552
+ message = {}
553
+ }
554
+
555
+ const patched = await patchMessageBeforeSending(message, [])
556
+ const bytes = Utils_1.encodeNewsletterMessage(patched)
557
+
558
+ binaryNodeContent.push({
559
+ tag: 'plaintext',
560
+ attrs: extraAttrs ? extraAttrs : {},
561
+ content: bytes
562
+ })
563
+ }
564
+
565
+ else {
566
+ const { user: meUser } = WABinary_1.jidDecode(meId)
567
+
568
+ if (!participant) {
569
+ devices.push({ user })
570
+ if (user !== meUser) {
571
+ devices.push({ user: meUser })
572
+ }
573
+
574
+ if (additionalAttributes?.['category'] !== 'peer') {
575
+ const additionalDevices = await getUSyncDevices([meId, jid], !!useUserDevicesCache, true)
576
+
577
+ devices.push(...additionalDevices)
578
+ }
579
+ }
580
+
581
+ const allJids = []
582
+ const meJids = []
583
+ const otherJids = []
584
+
585
+ for (const { user, device } of devices) {
586
+ const isMe = user === meUser
587
+ const jid = WABinary_1.jidEncode(isMe && isLid ? authState.creds?.me?.lid?.split(':')[0] || user : user, isLid ? 'lid' : 's.whatsapp.net', device)
588
+
589
+ if (isMe) {
590
+ meJids.push(jid)
591
+ }
592
+
593
+ else {
594
+ otherJids.push(jid)
595
+ }
596
+
597
+ allJids.push(jid)
598
+ }
599
+
600
+ await assertSessions(allJids, false)
601
+
602
+ const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
603
+ createParticipantNodes(meJids, meMsg, extraAttrs),
604
+ createParticipantNodes(otherJids, message, extraAttrs)
605
+ ])
606
+
607
+ participants.push(...meNodes)
608
+
609
+ participants.push(...otherNodes)
610
+
611
+ shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2
612
+ }
613
+
614
+ if (participants.length) {
615
+ if (additionalAttributes?.['category'] === 'peer') {
616
+ const peerNode = participants[0]?.content?.[0]
617
+
618
+ if (peerNode) {
619
+ binaryNodeContent.push(peerNode) // push only enc
620
+ }
621
+ }
622
+
623
+ else {
624
+ binaryNodeContent.push({
625
+ tag: 'participants',
626
+ attrs: {},
627
+ content: participants
628
+ })
629
+ }
630
+ }
631
+
632
+ const stanza = {
633
+ tag: 'message',
634
+ attrs: {
635
+ id: msgId,
636
+ type: getTypeMessage(message),
637
+ ...(additionalAttributes || {})
638
+ },
639
+ content: binaryNodeContent
640
+ }
641
+
642
+ // if the participant to send to is explicitly specified (generally retry recp)
643
+ // ensure the message is only sent to that person
644
+ // if a retry receipt is sent to everyone -- it'll fail decryption for everyone else who received the msg
645
+ if (participant) {
646
+ if (WABinary_1.isJidGroup(destinationJid)) {
647
+ stanza.attrs.to = destinationJid
648
+ stanza.attrs.participant = participant.jid
649
+ }
650
+
651
+ else if (WABinary_1.areJidsSameUser(participant.jid, meId)) {
652
+ stanza.attrs.to = participant.jid
653
+ stanza.attrs.recipient = destinationJid
654
+ }
655
+
656
+ else {
657
+ stanza.attrs.to = participant.jid
658
+ }
659
+ }
660
+
661
+ else {
662
+ stanza.attrs.to = destinationJid
663
+ }
664
+
665
+ if (shouldIncludeDeviceIdentity) {
666
+ stanza.content.push({
667
+ tag: 'device-identity',
668
+ attrs: {},
669
+ content: Utils_1.encodeSignedDeviceIdentity(authState.creds.account, true)
670
+ })
671
+
672
+ logger.debug({ jid }, 'adding device identity')
673
+ }
674
+
675
+ if (isGroup && regexGroupOld.test(jid) && !message.reactionMessage) {
676
+ stanza.content.push({
677
+ tag: 'multicast',
678
+ attrs: {}
679
+ })
680
+ }
681
+
682
+ if (pollMessage || messages.eventMessage) {
683
+ stanza.content.push({
684
+ tag: 'meta',
685
+ attrs: messages.eventMessage ? {
686
+ event_type: 'creation'
687
+ } : isNewsletter ? {
688
+ polltype: 'creation',
689
+ contenttype: pollMessage?.pollContentType === 2 ? 'image' : 'text'
690
+ } : {
691
+ polltype: 'creation'
692
+ }
693
+ })
694
+ }
695
+
696
+ if (!isNewsletter && buttonType) {
697
+ const buttonsNode = getButtonArgs(messages)
698
+ const filteredButtons = WABinary_1.getBinaryFilteredButtons(additionalNodes ? additionalNodes : [])
699
+
700
+ if (filteredButtons) {
701
+ stanza.content.push(...additionalNodes)
702
+ didPushAdditional = true
703
+ }
704
+
705
+ else {
706
+ stanza.content.push(buttonsNode)
707
+ }
708
+ }
709
+
710
+ if (AI && isPrivate) {
711
+ const botNode = {
712
+ tag: 'bot',
713
+ attrs: {
714
+ biz_bot: '1'
715
+ }
716
+ }
717
+
718
+ const filteredBizBot = WABinary_1.getBinaryFilteredBizBot(additionalNodes ? additionalNodes : [])
719
+
720
+ if (filteredBizBot) {
721
+ stanza.content.push(...additionalNodes)
722
+ didPushAdditional = true
723
+ }
724
+
725
+ else {
726
+ stanza.content.push(botNode)
727
+ }
728
+ }
729
+
730
+ if (!didPushAdditional && additionalNodes && additionalNodes.length > 0) {
731
+ stanza.content.push(...additionalNodes)
732
+ }
733
+
734
+ logger.debug({ msgId }, `sending message to ${participants.length} devices`)
735
+
736
+ await sendNode(stanza)
737
+
738
+ // Add message to retry cache if enabled
739
+ if (messageRetryManager && !participant) {
740
+ messageRetryManager.addRecentMessage(destinationJid, msgId, message)
741
+ }
742
+ })
743
+
744
+ return msgId
745
+ }
746
+
747
+ const getTypeMessage = (msg) => {
748
+ const message = Utils_1.normalizeMessageContent(msg)
749
+ if (message.pollCreationMessage || message.pollCreationMessageV2 || message.pollCreationMessageV3) {
750
+ return 'poll'
751
+ }
752
+ else if (message.reactionMessage) {
753
+ return 'reaction'
754
+ }
755
+ else if (message.eventMessage) {
756
+ return 'event'
757
+ }
758
+ else if (getMediaType(message)) {
759
+ return 'media'
760
+ }
761
+ else {
762
+ return 'text'
763
+ }
764
+ }
765
+
766
+ const getMediaType = (message) => {
767
+ if (message.imageMessage) {
768
+ return 'image'
769
+ }
770
+ else if (message.stickerMessage) {
771
+ return message.stickerMessage.isLottie ? '1p_sticker' : message.stickerMessage.isAvatar ? 'avatar_sticker' : 'sticker'
772
+ }
773
+ else if (message.videoMessage) {
774
+ return message.videoMessage.gifPlayback ? 'gif' : 'video'
775
+ }
776
+ else if (message.audioMessage) {
777
+ return message.audioMessage.ptt ? 'ptt' : 'audio'
778
+ }
779
+ else if (message.ptvMessage) {
780
+ return 'ptv'
781
+ }
782
+ else if (message.contactMessage) {
783
+ return 'vcard'
784
+ }
785
+ else if (message.documentMessage) {
786
+ return 'document'
787
+ }
788
+ else if (message.stickerPackMessage) {
789
+ return 'sticker_pack'
790
+ }
791
+ else if (message.contactsArrayMessage) {
792
+ return 'contact_array'
793
+ }
794
+ else if (message.locationMessage) {
795
+ return 'location'
796
+ }
797
+ else if (message.liveLocationMessage) {
798
+ return 'livelocation'
799
+ }
800
+ else if (message.listMessage) {
801
+ return 'list'
802
+ }
803
+ else if (message.listResponseMessage) {
804
+ return 'list_response'
805
+ }
806
+ else if (message.buttonsResponseMessage) {
807
+ return 'buttons_response'
808
+ }
809
+ else if (message.orderMessage) {
810
+ return 'order'
811
+ }
812
+ else if (message.productMessage) {
813
+ return 'product'
814
+ }
815
+ else if (message.interactiveResponseMessage) {
816
+ return 'native_flow_response'
817
+ }
818
+ else if (/https:\/\/wa\.me\/c\/\d+/.test(message.extendedTextMessage?.text)) {
819
+ return 'cataloglink'
820
+ }
821
+ else if (/https:\/\/wa\.me\/p\/\d+\/\d+/.test(message.extendedTextMessage?.text)) {
822
+ return 'productlink'
823
+ }
824
+ else if (message.extendedTextMessage?.matchedText || message.groupInviteMessage) {
825
+ return 'url'
826
+ }
827
+ }
828
+
829
+ const getButtonType = (message) => {
830
+ if (message.listMessage) {
831
+ return 'list'
832
+ }
833
+ else if (message.buttonsMessage) {
834
+ return 'buttons'
835
+ }
836
+ else if(message.interactiveMessage?.nativeFlowMessage) {
837
+ return 'native_flow'
838
+ }
839
+ }
840
+
841
+ const getButtonArgs = (message) => {
842
+ const nativeFlow = message.interactiveMessage?.nativeFlowMessage
843
+ const firstButtonName = nativeFlow?.buttons?.[0]?.name
844
+ const nativeFlowSpecials = [
845
+ 'mpm', 'cta_catalog', 'send_location',
846
+ 'call_permission_request', 'wa_payment_transaction_details',
847
+ 'automated_greeting_message_view_catalog'
848
+ ]
849
+
850
+ if (nativeFlow && (firstButtonName === 'review_and_pay' || firstButtonName === 'payment_info')) {
851
+ return {
852
+ tag: 'biz',
853
+ attrs: {
854
+ native_flow_name: firstButtonName === 'review_and_pay' ? 'order_details' : firstButtonName
855
+ }
856
+ }
857
+ } else if (nativeFlow && nativeFlowSpecials.includes(firstButtonName)) {
858
+ // Only works for WhatsApp Original, not WhatsApp Business
859
+ return {
860
+ tag: 'biz',
861
+ attrs: {},
862
+ content: [{
863
+ tag: 'interactive',
864
+ attrs: {
865
+ type: 'native_flow',
866
+ v: '1'
867
+ },
868
+ content: [{
869
+ tag: 'native_flow',
870
+ attrs: {
871
+ v: '2',
872
+ name: firstButtonName
873
+ }
874
+ }]
875
+ }]
876
+ }
877
+ } else if (nativeFlow || message.buttonsMessage) {
878
+ // It works for whatsapp original and whatsapp business
879
+ return {
880
+ tag: 'biz',
881
+ attrs: {},
882
+ content: [{
883
+ tag: 'interactive',
884
+ attrs: {
885
+ type: 'native_flow',
886
+ v: '1'
887
+ },
888
+ content: [{
889
+ tag: 'native_flow',
890
+ attrs: {
891
+ v: '9',
892
+ name: 'mixed'
893
+ }
894
+ }]
895
+ }]
896
+ }
897
+ } else if (message.listMessage) {
898
+ return {
899
+ tag: 'biz',
900
+ attrs: {},
901
+ content: [{
902
+ tag: 'list',
903
+ attrs: {
904
+ v: '2',
905
+ type: 'product_list'
906
+ }
907
+ }]
908
+ }
909
+ } else {
910
+ return {
911
+ tag: 'biz',
912
+ attrs: {}
913
+ }
914
+ }
915
+ }
916
+
917
+ const getPrivacyTokens = async (jids) => {
918
+ const t = Utils_1.unixTimestampSeconds().toString()
919
+
920
+ const result = await query({
921
+ tag: 'iq',
922
+ attrs: {
923
+ to: WABinary_1.S_WHATSAPP_NET,
924
+ type: 'set',
925
+ xmlns: 'privacy'
926
+ },
927
+ content: [
928
+ {
929
+ tag: 'tokens',
930
+ attrs: {},
931
+ content: jids.map(jid => ({
932
+ tag: 'token',
933
+ attrs: {
934
+ jid: WABinary_1.jidNormalizedUser(jid),
935
+ t,
936
+ type: 'trusted_contact'
937
+ }
938
+ }))
939
+ }
940
+ ]
941
+ })
942
+
943
+ return result
944
+ }
945
+
946
+ const getEphemeralGroup = (jid) => {
947
+ if (!WABinary_1.isJidGroup(jid)) throw new TypeError("Jid should originate from a group!")
948
+
949
+ return groupQuery(jid, 'get', [{
950
+ tag: 'query',
951
+ attrs: {
952
+ request: 'interactive'
953
+ }
954
+ }])
955
+ .then((groups) => WABinary_1.getBinaryNodeChild(groups, 'group'))
956
+ .then((metadata) => WABinary_1.getBinaryNodeChild(metadata, 'ephemeral')?.attrs?.expiration || 0)
957
+ }
958
+
959
+ const waUploadToServer = Utils_1.getWAUploadToServer(config, refreshMediaConn)
960
+
961
+ const waitForMsgMediaUpdate = Utils_1.bindWaitForEvent(ev, 'messages.media-update')
962
+
963
+ return {
964
+ ...baron,
965
+ getPrivacyTokens,
966
+ assertSessions,
967
+ relayMessage,
968
+ sendReceipt,
969
+ sendReceipts,
970
+ readMessages,
971
+ profilePictureUrl,
972
+ getUSyncDevices,
973
+ refreshMediaConn,
974
+ waUploadToServer,
975
+ getEphemeralGroup,
976
+ fetchPrivacySettings,
977
+ createParticipantNodes,
978
+ sendPeerDataOperationMessage,
979
+ messageRetryManager,
980
+ updateMediaMessage: async (message) => {
981
+ const content = Utils_1.assertMediaContent(message.message)
982
+ const mediaKey = content.mediaKey
983
+ const meId = authState.creds.me.id
984
+ const node = await Utils_1.encryptMediaRetryRequest(message.key, mediaKey, meId)
985
+ let error = undefined
986
+
987
+ await Promise.all([
988
+ sendNode(node),
989
+ waitForMsgMediaUpdate(async (update) => {
990
+ const result = update.find(c => c.key.id === message.key.id)
991
+ if (result) {
992
+ if (result.error) {
993
+ error = result.error
994
+ }
995
+
996
+ else {
997
+ try {
998
+ const media = await Utils_1.decryptMediaRetryData(result.media, mediaKey, result.key.id)
999
+
1000
+ if (media.result !== WAProto_1.proto.MediaRetryNotification.ResultType.SUCCESS) {
1001
+ const resultStr = WAProto_1.proto.MediaRetryNotification.ResultType[media.result]
1002
+
1003
+ throw new boom_1.Boom(`Media re-upload failed by device (${resultStr})`, { data: media, statusCode: Utils_1.getStatusCodeForMediaRetry(media.result) || 404 })
1004
+ }
1005
+
1006
+ content.directPath = media.directPath
1007
+
1008
+ content.url = Utils_1.getUrlFromDirectPath(content.directPath)
1009
+
1010
+ logger.debug({ directPath: media.directPath, key: result.key }, 'media update successful')
1011
+ }
1012
+
1013
+ catch (err) {
1014
+ error = err
1015
+ }
1016
+ }
1017
+
1018
+ return true
1019
+ }
1020
+ })
1021
+ ])
1022
+
1023
+ if (error) {
1024
+ throw error
1025
+ }
1026
+
1027
+ ev.emit('messages.update', [
1028
+ { key: message.key, update: { message: message.message } }
1029
+ ])
1030
+
1031
+ return message
1032
+ },
1033
+ sendStatusMentions: async (content, jids = []) => {
1034
+ const userJid = WABinary_1.jidNormalizedUser(authState.creds.me.id)
1035
+ let allUsers = new Set()
1036
+ allUsers.add(userJid)
1037
+
1038
+ for (const id of jids) {
1039
+ const isGroup = WABinary_1.isJidGroup(id)
1040
+ const isPrivate = WABinary_1.isJidUser(id)
1041
+
1042
+ if (isGroup) {
1043
+ try {
1044
+ const metadata = await cachedGroupMetadata(id) || await groupMetadata(id)
1045
+ const participants = metadata.participants.map(p => WABinary_1.jidNormalizedUser(p.id))
1046
+ participants.forEach(jid => allUsers.add(jid))
1047
+ } catch (error) {
1048
+ logger.error(`Error getting metadata for group ${id}: ${error}`)
1049
+ }
1050
+ } else if (isPrivate) {
1051
+ allUsers.add(WABinary_1.jidNormalizedUser(id))
1052
+ }
1053
+ }
1054
+
1055
+ const uniqueUsers = Array.from(allUsers)
1056
+ const getRandomHexColor = () => "#" + Math.floor(Math.random() * 16777215).toString(16).padStart(6, "0")
1057
+
1058
+ const isMedia = content.image || content.video || content.audio
1059
+ const isAudio = !!content.audio
1060
+
1061
+ const messageContent = { ...content }
1062
+
1063
+ if (isMedia && !isAudio) {
1064
+ if (messageContent.text) {
1065
+ messageContent.caption = messageContent.text
1066
+
1067
+ delete messageContent.text
1068
+ }
1069
+
1070
+ delete messageContent.ptt
1071
+ delete messageContent.font
1072
+ delete messageContent.backgroundColor
1073
+ delete messageContent.textColor
1074
+ }
1075
+
1076
+ if (isAudio) {
1077
+ delete messageContent.text
1078
+ delete messageContent.caption
1079
+ delete messageContent.font
1080
+ delete messageContent.textColor
1081
+ }
1082
+
1083
+ const font = !isMedia ? (content.font || Math.floor(Math.random() * 9)) : undefined
1084
+ const textColor = !isMedia ? (content.textColor || getRandomHexColor()) : undefined
1085
+ const backgroundColor = (!isMedia || isAudio) ? (content.backgroundColor || getRandomHexColor()) : undefined
1086
+ const ptt = isAudio ? (typeof content.ptt === 'boolean' ? content.ptt : true) : undefined
1087
+
1088
+ let msg
1089
+ let mediaHandle
1090
+ try {
1091
+ msg = await Utils_1.generateWAMessage(WABinary_1.STORIES_JID, messageContent, {
1092
+ logger,
1093
+ userJid,
1094
+ getUrlInfo: text => link_preview_1.getUrlInfo(text, {
1095
+ thumbnailWidth: linkPreviewImageThumbnailWidth,
1096
+ fetchOpts: { timeout: 3000, ...axiosOptions || {} },
1097
+ logger,
1098
+ uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
1099
+ }),
1100
+ upload: async (encFilePath, opts) => {
1101
+ const up = await waUploadToServer(encFilePath, { ...opts })
1102
+ mediaHandle = up.handle
1103
+ return up
1104
+ },
1105
+ mediaCache: config.mediaCache,
1106
+ options: config.options,
1107
+ font,
1108
+ textColor,
1109
+ backgroundColor,
1110
+ ptt
1111
+ })
1112
+ } catch (error) {
1113
+ logger.error(`Error generating message: ${error}`)
1114
+ throw error
1115
+ }
1116
+
1117
+ await relayMessage(WABinary_1.STORIES_JID, msg.message, {
1118
+ messageId: msg.key.id,
1119
+ statusJidList: uniqueUsers,
1120
+ additionalNodes: [
1121
+ {
1122
+ tag: 'meta',
1123
+ attrs: {},
1124
+ content: [
1125
+ {
1126
+ tag: 'mentioned_users',
1127
+ attrs: {},
1128
+ content: jids.map(jid => ({
1129
+ tag: 'to',
1130
+ attrs: { jid: WABinary_1.jidNormalizedUser(jid) }
1131
+ }))
1132
+ }]
1133
+ }]
1134
+ })
1135
+
1136
+ for (const id of jids) {
1137
+ try {
1138
+ const normalizedId = WABinary_1.jidNormalizedUser(id)
1139
+ const isPrivate = WABinary_1.isJidUser(normalizedId)
1140
+ const type = isPrivate ? 'statusMentionMessage' : 'groupStatusMentionMessage'
1141
+
1142
+ const protocolMessage = {
1143
+ [type]: {
1144
+ message: {
1145
+ protocolMessage: {
1146
+ key: msg.key,
1147
+ type: 25
1148
+ }
1149
+ }
1150
+ },
1151
+ messageContextInfo: {
1152
+ messageSecret: crypto_1.randomBytes(32)
1153
+ }
1154
+ }
1155
+
1156
+ const statusMsg = await Utils_1.generateWAMessageFromContent(normalizedId,
1157
+ protocolMessage,
1158
+ {}
1159
+ )
1160
+
1161
+ await relayMessage(
1162
+ normalizedId,
1163
+ statusMsg.message,
1164
+ {
1165
+ additionalNodes: [{
1166
+ tag: 'meta',
1167
+ attrs: isPrivate ?
1168
+ { is_status_mention: 'true' } :
1169
+ { is_group_status_mention: 'true' }
1170
+ }]
1171
+ }
1172
+ )
1173
+
1174
+ await Utils_1.delay(2000)
1175
+ } catch (error) {
1176
+ logger.error(`Error sending to ${id}: ${error}`)
1177
+ }
1178
+ }
1179
+
1180
+ return msg
1181
+ },
1182
+ sendMessage: async (jid, content, options = {}) => {
1183
+ const userJid = authState.creds.me.id
1184
+ const additionalAttributes = {}
1185
+
1186
+ if (!options.ephemeralExpiration) {
1187
+ if (WABinary_1.isJidGroup(jid)) {
1188
+ const expiration = await getEphemeralGroup(jid)
1189
+ options.ephemeralExpiration = expiration
1190
+ }
1191
+ }
1192
+
1193
+ if (typeof content === 'object' &&
1194
+ 'disappearingMessagesInChat' in content &&
1195
+ typeof content['disappearingMessagesInChat'] !== 'undefined' &&
1196
+ WABinary_1.isJidGroup(jid)) {
1197
+
1198
+ const { disappearingMessagesInChat } = content
1199
+
1200
+ const value = typeof disappearingMessagesInChat === 'boolean' ?
1201
+ (disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
1202
+ disappearingMessagesInChat
1203
+
1204
+ await groupToggleEphemeral(jid, value)
1205
+ }
1206
+
1207
+ else if (typeof content === 'object' && 'album' in content && content.album) {
1208
+ const albumMsg = await Utils_1.prepareAlbumMessageContent(jid, content.album, {
1209
+ baron: {
1210
+ relayMessage,
1211
+ waUploadToServer
1212
+ },
1213
+ userJid: userJid,
1214
+ ...options
1215
+ })
1216
+
1217
+ for (const media of albumMsg) {
1218
+ await Utils_1.delay(options.delay || 500)
1219
+ await relayMessage(jid, media.message, { messageId: media.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, additionalAttributes, statusJidList: options.statusJidList, additionalNodes: options.additionalNodes, AI: options.ai })
1220
+ }
1221
+
1222
+ return albumMsg
1223
+ }
1224
+
1225
+ else {
1226
+ let mediaHandle
1227
+
1228
+ const fullMsg = await Utils_1.generateWAMessage(jid, content, {
1229
+ logger,
1230
+ userJid,
1231
+ getUrlInfo: text => link_preview_1.getUrlInfo(text, {
1232
+ thumbnailWidth: linkPreviewImageThumbnailWidth,
1233
+ fetchOpts: {
1234
+ timeout: 3000,
1235
+ ...axiosOptions || {}
1236
+ },
1237
+ logger,
1238
+ uploadImage: generateHighQualityLinkPreview
1239
+ ? waUploadToServer
1240
+ : undefined
1241
+ }),
1242
+ getProfilePicUrl: profilePictureUrl,
1243
+ getCallLink: createCallLink,
1244
+ upload: async (encFilePath, opts) => {
1245
+ const up = await waUploadToServer(encFilePath, { ...opts, newsletter: WABinary_1.isJidNewsletter(jid) })
1246
+ mediaHandle = up.handle
1247
+ return up
1248
+ },
1249
+ mediaCache: config.mediaCache,
1250
+ options: config.options,
1251
+ messageId: Utils_1.generateMessageID(userJid),
1252
+ ...options,
1253
+ })
1254
+
1255
+ const isPin = 'pin' in content && !!content.pin
1256
+ const isEdit = 'edit' in content && !!content.edit
1257
+ const isDelete = 'delete' in content && !!content.delete
1258
+ const isKeep = 'keep' in content && !!content.keep && content.keep?.type === 2
1259
+
1260
+ if (isDelete || isKeep) {
1261
+ // if the chat is a group, and I am not the author, then delete the message as an admin
1262
+ if (WABinary_1.isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe || WABinary_1.isJidNewsletter(jid)) {
1263
+ additionalAttributes.edit = '8'
1264
+ }
1265
+
1266
+ else {
1267
+ additionalAttributes.edit = '7'
1268
+ }
1269
+ }
1270
+
1271
+ else if (isEdit) {
1272
+ additionalAttributes.edit = WABinary_1.isJidNewsletter(jid) ? '3' : '1'
1273
+ }
1274
+
1275
+ else if (isPin) {
1276
+ additionalAttributes.edit = '2'
1277
+ }
1278
+
1279
+ if (mediaHandle) {
1280
+ additionalAttributes['media_id'] = mediaHandle
1281
+ }
1282
+
1283
+ if ('cachedGroupMetadata' in options) {
1284
+ console.warn('cachedGroupMetadata in sendMessage are deprecated, now cachedGroupMetadata is part of the socket config.')
1285
+ }
1286
+
1287
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, additionalAttributes, statusJidList: options.statusJidList, additionalNodes: options.additionalNodes, AI: options.ai })
1288
+
1289
+ if (config.emitOwnEvents) {
1290
+ process.nextTick(() => {
1291
+ processingMutex.mutex(() => (upsertMessage(fullMsg, 'append')))
1292
+ })
1293
+ }
1294
+
1295
+ return fullMsg
1296
+ }
1297
+ }
1298
+ }
1299
+ }
1300
+
1301
+ module.exports = {
1302
+ makeMessagesSocket
1303
+ }