@neelegirl/baileys 1.5.3 → 1.5.5

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 (224) hide show
  1. package/README.md +16 -195
  2. package/index.js +38 -0
  3. package/package.json +16 -96
  4. package/LICENSE +0 -21
  5. package/WAProto/WAProto.proto +0 -5308
  6. package/WAProto/index.d.ts +0 -61295
  7. package/WAProto/index.js +0 -189754
  8. package/lib/Defaults/baileys-version.json +0 -3
  9. package/lib/Defaults/index.d.ts +0 -78
  10. package/lib/Defaults/index.js +0 -149
  11. package/lib/Defaults/phonenumber-mcc.json +0 -223
  12. package/lib/Signal/WASignalGroup/GroupProtocol.js +0 -1909
  13. package/lib/Signal/WASignalGroup/ciphertext-message.d.ts +0 -9
  14. package/lib/Signal/WASignalGroup/ciphertext-message.js +0 -19
  15. package/lib/Signal/WASignalGroup/ciphertext_message.js +0 -16
  16. package/lib/Signal/WASignalGroup/generate-proto.sh +0 -1
  17. package/lib/Signal/WASignalGroup/group-session-builder.d.ts +0 -17
  18. package/lib/Signal/WASignalGroup/group-session-builder.js +0 -72
  19. package/lib/Signal/WASignalGroup/group.proto +0 -42
  20. package/lib/Signal/WASignalGroup/group_cipher.d.ts +0 -19
  21. package/lib/Signal/WASignalGroup/group_cipher.js +0 -111
  22. package/lib/Signal/WASignalGroup/group_session_builder.js +0 -46
  23. package/lib/Signal/WASignalGroup/index.d.ts +0 -11
  24. package/lib/Signal/WASignalGroup/index.js +0 -61
  25. package/lib/Signal/WASignalGroup/keyhelper.d.ts +0 -16
  26. package/lib/Signal/WASignalGroup/keyhelper.js +0 -66
  27. package/lib/Signal/WASignalGroup/protobufs.js +0 -3
  28. package/lib/Signal/WASignalGroup/queue_job.js +0 -69
  29. package/lib/Signal/WASignalGroup/readme.md +0 -6
  30. package/lib/Signal/WASignalGroup/sender-chain-key.d.ts +0 -14
  31. package/lib/Signal/WASignalGroup/sender-chain-key.js +0 -47
  32. package/lib/Signal/WASignalGroup/sender-key-distribution-message.d.ts +0 -17
  33. package/lib/Signal/WASignalGroup/sender-key-distribution-message.js +0 -71
  34. package/lib/Signal/WASignalGroup/sender-key-message.d.ts +0 -19
  35. package/lib/Signal/WASignalGroup/sender-key-message.js +0 -73
  36. package/lib/Signal/WASignalGroup/sender-key-name.d.ts +0 -19
  37. package/lib/Signal/WASignalGroup/sender-key-name.js +0 -59
  38. package/lib/Signal/WASignalGroup/sender-key-record.d.ts +0 -32
  39. package/lib/Signal/WASignalGroup/sender-key-record.js +0 -58
  40. package/lib/Signal/WASignalGroup/sender-key-state.d.ts +0 -44
  41. package/lib/Signal/WASignalGroup/sender-key-state.js +0 -147
  42. package/lib/Signal/WASignalGroup/sender-message-key.d.ts +0 -11
  43. package/lib/Signal/WASignalGroup/sender-message-key.js +0 -33
  44. package/lib/Signal/WASignalGroup/sender_chain_key.js +0 -50
  45. package/lib/Signal/WASignalGroup/sender_key_distribution_message.js +0 -78
  46. package/lib/Signal/WASignalGroup/sender_key_message.js +0 -92
  47. package/lib/Signal/WASignalGroup/sender_key_name.js +0 -70
  48. package/lib/Signal/WASignalGroup/sender_key_record.js +0 -56
  49. package/lib/Signal/WASignalGroup/sender_key_state.js +0 -129
  50. package/lib/Signal/WASignalGroup/sender_message_key.js +0 -39
  51. package/lib/Signal/libsignal.d.ts +0 -8
  52. package/lib/Signal/libsignal.js +0 -391
  53. package/lib/Signal/lid-mapping.d.ts +0 -28
  54. package/lib/Signal/lid-mapping.js +0 -184
  55. package/lib/Socket/Client/abstract-socket-client.d.ts +0 -15
  56. package/lib/Socket/Client/abstract-socket-client.js +0 -13
  57. package/lib/Socket/Client/index.d.ts +0 -2
  58. package/lib/Socket/Client/index.js +0 -22
  59. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -12
  60. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  61. package/lib/Socket/Client/types.d.ts +0 -16
  62. package/lib/Socket/Client/types.js +0 -18
  63. package/lib/Socket/Client/websocket.d.ts +0 -13
  64. package/lib/Socket/Client/websocket.js +0 -62
  65. package/lib/Socket/business.d.ts +0 -187
  66. package/lib/Socket/business.js +0 -415
  67. package/lib/Socket/chats.d.ts +0 -97
  68. package/lib/Socket/chats.js +0 -1118
  69. package/lib/Socket/communities.d.ts +0 -223
  70. package/lib/Socket/communities.js +0 -433
  71. package/lib/Socket/groups.d.ts +0 -129
  72. package/lib/Socket/groups.js +0 -360
  73. package/lib/Socket/index.d.ts +0 -191
  74. package/lib/Socket/index.js +0 -24
  75. package/lib/Socket/messages-recv.d.ts +0 -174
  76. package/lib/Socket/messages-recv.js +0 -1506
  77. package/lib/Socket/messages-send.d.ts +0 -165
  78. package/lib/Socket/messages-send.js +0 -1785
  79. package/lib/Socket/mex.d.ts +0 -2
  80. package/lib/Socket/mex.js +0 -47
  81. package/lib/Socket/newsletter.d.ts +0 -145
  82. package/lib/Socket/newsletter.js +0 -295
  83. package/lib/Socket/socket.d.ts +0 -45
  84. package/lib/Socket/socket.js +0 -934
  85. package/lib/Socket/usync.d.ts +0 -37
  86. package/lib/Socket/usync.js +0 -83
  87. package/lib/Store/index.d.ts +0 -4
  88. package/lib/Store/index.js +0 -24
  89. package/lib/Store/make-cache-manager-store.d.ts +0 -14
  90. package/lib/Store/make-cache-manager-store.js +0 -90
  91. package/lib/Store/make-in-memory-store.d.ts +0 -123
  92. package/lib/Store/make-in-memory-store.js +0 -429
  93. package/lib/Store/make-ordered-dictionary.d.ts +0 -12
  94. package/lib/Store/make-ordered-dictionary.js +0 -86
  95. package/lib/Store/object-repository.d.ts +0 -10
  96. package/lib/Store/object-repository.js +0 -31
  97. package/lib/Types/Auth.d.ts +0 -121
  98. package/lib/Types/Auth.js +0 -3
  99. package/lib/Types/Bussines.js +0 -3
  100. package/lib/Types/Bussiness.d.ts +0 -28
  101. package/lib/Types/Call.d.ts +0 -14
  102. package/lib/Types/Call.js +0 -3
  103. package/lib/Types/Chat.d.ts +0 -143
  104. package/lib/Types/Chat.js +0 -9
  105. package/lib/Types/Contact.d.ts +0 -23
  106. package/lib/Types/Contact.js +0 -3
  107. package/lib/Types/Events.d.ts +0 -226
  108. package/lib/Types/Events.js +0 -3
  109. package/lib/Types/GroupMetadata.d.ts +0 -66
  110. package/lib/Types/GroupMetadata.js +0 -3
  111. package/lib/Types/Label.d.ts +0 -48
  112. package/lib/Types/Label.js +0 -31
  113. package/lib/Types/LabelAssociation.d.ts +0 -35
  114. package/lib/Types/LabelAssociation.js +0 -13
  115. package/lib/Types/Message.d.ts +0 -484
  116. package/lib/Types/Message.js +0 -19
  117. package/lib/Types/MexUpdates.d.ts +0 -9
  118. package/lib/Types/MexUpdates.js +0 -18
  119. package/lib/Types/Newsletter.d.ts +0 -109
  120. package/lib/Types/Newsletter.js +0 -40
  121. package/lib/Types/Product.d.ts +0 -92
  122. package/lib/Types/Product.js +0 -3
  123. package/lib/Types/Signal.d.ts +0 -98
  124. package/lib/Types/Signal.js +0 -3
  125. package/lib/Types/Socket.d.ts +0 -141
  126. package/lib/Types/Socket.js +0 -3
  127. package/lib/Types/State.d.ts +0 -41
  128. package/lib/Types/State.js +0 -14
  129. package/lib/Types/USync.d.ts +0 -26
  130. package/lib/Types/USync.js +0 -3
  131. package/lib/Types/index.d.ts +0 -80
  132. package/lib/Types/index.js +0 -50
  133. package/lib/Utils/auth-utils.d.ts +0 -21
  134. package/lib/Utils/auth-utils.js +0 -528
  135. package/lib/Utils/baileys-event-stream.d.ts +0 -18
  136. package/lib/Utils/baileys-event-stream.js +0 -70
  137. package/lib/Utils/business.d.ts +0 -29
  138. package/lib/Utils/business.js +0 -255
  139. package/lib/Utils/chat-utils.d.ts +0 -82
  140. package/lib/Utils/chat-utils.js +0 -809
  141. package/lib/Utils/crypto.d.ts +0 -56
  142. package/lib/Utils/crypto.js +0 -189
  143. package/lib/Utils/decode-wa-message.d.ts +0 -53
  144. package/lib/Utils/decode-wa-message.js +0 -323
  145. package/lib/Utils/event-buffer.d.ts +0 -39
  146. package/lib/Utils/event-buffer.js +0 -595
  147. package/lib/Utils/generics.d.ts +0 -131
  148. package/lib/Utils/generics.js +0 -630
  149. package/lib/Utils/history.d.ts +0 -23
  150. package/lib/Utils/history.js +0 -104
  151. package/lib/Utils/index.d.ts +0 -20
  152. package/lib/Utils/index.js +0 -40
  153. package/lib/Utils/link-preview.d.ts +0 -23
  154. package/lib/Utils/link-preview.js +0 -120
  155. package/lib/Utils/logger.d.ts +0 -13
  156. package/lib/Utils/logger.js +0 -7
  157. package/lib/Utils/lt-hash.d.ts +0 -14
  158. package/lib/Utils/lt-hash.js +0 -58
  159. package/lib/Utils/make-mutex.d.ts +0 -9
  160. package/lib/Utils/make-mutex.js +0 -49
  161. package/lib/Utils/message-retry-manager.d.ts +0 -88
  162. package/lib/Utils/message-retry-manager.js +0 -160
  163. package/lib/Utils/messages-media.d.ts +0 -135
  164. package/lib/Utils/messages-media.js +0 -869
  165. package/lib/Utils/messages.d.ts +0 -105
  166. package/lib/Utils/messages.js +0 -1745
  167. package/lib/Utils/noise-handler.d.ts +0 -21
  168. package/lib/Utils/noise-handler.js +0 -165
  169. package/lib/Utils/process-message.d.ts +0 -49
  170. package/lib/Utils/process-message.js +0 -427
  171. package/lib/Utils/signal.d.ts +0 -42
  172. package/lib/Utils/signal.js +0 -166
  173. package/lib/Utils/use-mongo-file-auth-state.d.ts +0 -6
  174. package/lib/Utils/use-mongo-file-auth-state.js +0 -84
  175. package/lib/Utils/use-multi-file-auth-state.d.ts +0 -18
  176. package/lib/Utils/use-multi-file-auth-state.js +0 -238
  177. package/lib/Utils/use-single-file-auth-state.d.ts +0 -13
  178. package/lib/Utils/use-single-file-auth-state.js +0 -80
  179. package/lib/Utils/validate-connection.d.ts +0 -13
  180. package/lib/Utils/validate-connection.js +0 -220
  181. package/lib/WABinary/constants.d.ts +0 -30
  182. package/lib/WABinary/constants.js +0 -1316
  183. package/lib/WABinary/decode.d.ts +0 -9
  184. package/lib/WABinary/decode.js +0 -288
  185. package/lib/WABinary/encode.d.ts +0 -3
  186. package/lib/WABinary/encode.js +0 -265
  187. package/lib/WABinary/generic-utils.d.ts +0 -28
  188. package/lib/WABinary/generic-utils.js +0 -142
  189. package/lib/WABinary/index.d.ts +0 -5
  190. package/lib/WABinary/index.js +0 -25
  191. package/lib/WABinary/jid-utils.d.ts +0 -58
  192. package/lib/WABinary/jid-utils.js +0 -104
  193. package/lib/WABinary/types.d.ts +0 -22
  194. package/lib/WABinary/types.js +0 -3
  195. package/lib/WAM/BinaryInfo.d.ts +0 -16
  196. package/lib/WAM/BinaryInfo.js +0 -17
  197. package/lib/WAM/constants.d.ts +0 -47
  198. package/lib/WAM/constants.js +0 -15371
  199. package/lib/WAM/encode.d.ts +0 -3
  200. package/lib/WAM/encode.js +0 -164
  201. package/lib/WAM/index.d.ts +0 -3
  202. package/lib/WAM/index.js +0 -23
  203. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.d.ts +0 -28
  204. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +0 -69
  205. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +0 -10
  206. package/lib/WAUSync/Protocols/USyncContactProtocol.js +0 -36
  207. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +0 -26
  208. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +0 -62
  209. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +0 -14
  210. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +0 -35
  211. package/lib/WAUSync/Protocols/USyncLIDProtocol.d.ts +0 -10
  212. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +0 -38
  213. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +0 -14
  214. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +0 -46
  215. package/lib/WAUSync/Protocols/index.d.ts +0 -6
  216. package/lib/WAUSync/Protocols/index.js +0 -26
  217. package/lib/WAUSync/USyncQuery.d.ts +0 -31
  218. package/lib/WAUSync/USyncQuery.js +0 -92
  219. package/lib/WAUSync/USyncUser.d.ts +0 -12
  220. package/lib/WAUSync/USyncUser.js +0 -30
  221. package/lib/WAUSync/index.d.ts +0 -3
  222. package/lib/WAUSync/index.js +0 -23
  223. package/lib/index.d.ts +0 -13
  224. package/lib/index.js +0 -33
@@ -1,1785 +0,0 @@
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
- const make_keyed_mutex_1 = require("../Utils/make-mutex")
21
-
22
- const makeMessagesSocket = (config) => {
23
- const { logger, maxMsgRetryCount, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: axiosOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache } = config
24
- const baron = newsletter_1.makeNewsletterSocket(config)
25
- const { ev, authState, processingMutex, signalRepository, upsertMessage, createCallLink, query, fetchPrivacySettings, sendNode, groupQuery, groupMetadata, groupToggleEphemeral, newsletterWMexQuery, executeUSyncQuery } = baron
26
-
27
- const userDevicesCache = config.userDevicesCache || new node_cache_1.default({
28
- stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES,
29
- useClones: false
30
- })
31
-
32
- // Initialize message retry manager if enabled
33
- const messageRetryManager = enableRecentMessageCache ? new Utils_1.MessageRetryManager(logger, maxMsgRetryCount) : null
34
-
35
- // Prevent race conditions in Signal session encryption by user
36
- const encryptionMutex = make_keyed_mutex_1.makeKeyedMutex()
37
-
38
- let mediaConn
39
-
40
- const refreshMediaConn = async (forceGet = false) => {
41
- const media = await mediaConn
42
-
43
- if (!media || forceGet || (new Date().getTime() - media.fetchDate.getTime()) > media.ttl * 1000) {
44
- mediaConn = (async () => {
45
-
46
- const result = await query({
47
- tag: 'iq',
48
- attrs: {
49
- type: 'set',
50
- xmlns: 'w:m',
51
- to: WABinary_1.S_WHATSAPP_NET,
52
- },
53
- content: [{ tag: 'media_conn', attrs: {} }]
54
- })
55
-
56
- const mediaConnNode = WABinary_1.getBinaryNodeChild(result, 'media_conn')
57
-
58
- const node = {
59
- hosts: WABinary_1.getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
60
- hostname: attrs.hostname,
61
- maxContentLengthBytes: +attrs.maxContentLengthBytes,
62
- })),
63
- auth: mediaConnNode.attrs.auth,
64
- ttl: +mediaConnNode.attrs.ttl,
65
- fetchDate: new Date()
66
- }
67
-
68
- logger.debug('fetched media conn')
69
-
70
- return node
71
- })()
72
- }
73
-
74
- return mediaConn
75
- }
76
-
77
- /**
78
- * generic send receipt function
79
- * used for receipts of phone call, read, delivery etc.
80
- * */
81
- const sendReceipt = async (jid, participant, messageIds, type) => {
82
- const node = {
83
- tag: 'receipt',
84
- attrs: {
85
- id: messageIds[0],
86
- },
87
- }
88
-
89
- const isReadReceipt = type === 'read' || type === 'read-self'
90
-
91
- if (isReadReceipt) {
92
- node.attrs.t = Utils_1.unixTimestampSeconds().toString()
93
- }
94
-
95
- if (type === 'sender' && WABinary_1.isJidUser(jid)) {
96
- node.attrs.recipient = jid
97
- node.attrs.to = participant
98
- }
99
-
100
- else {
101
- node.attrs.to = jid
102
- if (participant) {
103
- node.attrs.participant = participant
104
- }
105
- }
106
-
107
- if (type) {
108
- node.attrs.type = WABinary_1.isJidNewsletter(jid) ? 'read-self' : type
109
- }
110
-
111
- const remainingMessageIds = messageIds.slice(1)
112
-
113
- if (remainingMessageIds.length) {
114
- node.content = [
115
- {
116
- tag: 'list',
117
- attrs: {},
118
- content: remainingMessageIds.map(id => ({
119
- tag: 'item',
120
- attrs: { id }
121
- }))
122
- }
123
- ]
124
- }
125
-
126
- logger.debug({ attrs: node.attrs, messageIds }, 'sending receipt for messages')
127
-
128
- await sendNode(node)
129
- }
130
-
131
- /** Correctly bulk send receipts to multiple chats, participants */
132
- const sendReceipts = async (keys, type) => {
133
- const recps = Utils_1.aggregateMessageKeysNotFromMe(keys)
134
-
135
- for (const { jid, participant, messageIds } of recps) {
136
- await sendReceipt(jid, participant, messageIds, type)
137
- }
138
- }
139
-
140
- /** Bulk read messages. Keys can be from different chats & participants */
141
- const readMessages = async (keys) => {
142
- const privacySettings = await fetchPrivacySettings()
143
-
144
- // based on privacy settings, we have to change the read type
145
- const readType = privacySettings.readreceipts === 'all' ? 'read' : 'read-self'
146
-
147
- await sendReceipts(keys, readType)
148
- }
149
-
150
- /**
151
- * Deduplicate JIDs when both LID and PN versions exist for same user
152
- * Prefers LID over PN to maintain single encryption layer
153
- */
154
- const deduplicateLidPnJids = (jids) => {
155
- const lidUsers = new Set()
156
- const filteredJids = []
157
-
158
- // Collect all LID users
159
- for (const jid of jids) {
160
- if (WABinary_1.isLidUser(jid)) {
161
- const user = WABinary_1.jidDecode(jid)?.user
162
- if (user)
163
- lidUsers.add(user)
164
- }
165
- }
166
-
167
- // Filter out PN versions when LID exists
168
- for (const jid of jids) {
169
- if (WABinary_1.isJidUser(jid)) {
170
- const user = WABinary_1.jidDecode(jid)?.user
171
- if (user && lidUsers.has(user)) {
172
- logger.debug({ jid }, 'Skipping PN - LID version exists')
173
- continue
174
- }
175
- }
176
- filteredJids.push(jid)
177
- }
178
- return filteredJids
179
- }
180
-
181
- /** Fetch image for groups, user, and newsletter **/
182
- const profilePictureUrl = async (jid) => {
183
- if (WABinary_1.isJidNewsletter(jid)) {
184
-
185
- let node = await newsletterWMexQuery(undefined, Types_1.QueryIds.METADATA, {
186
- input: {
187
- key: jid,
188
- type: 'JID',
189
- view_role: 'GUEST'
190
- },
191
- fetch_viewer_metadata: true,
192
- fetch_full_image: true,
193
- fetch_creation_time: true
194
- })
195
-
196
- let result = WABinary_1.getBinaryNodeChild(node, 'result')?.content?.toString()
197
-
198
- let metadata = JSON.parse(result).data[Types_1.XWAPaths.NEWSLETTER]
199
-
200
- return Utils_1.getUrlFromDirectPath(metadata.thread_metadata.picture?.direct_path || '')
201
-
202
- }
203
-
204
- else {
205
- const result = await query({
206
- tag: 'iq',
207
- attrs: {
208
- target: WABinary_1.jidNormalizedUser(jid),
209
- to: WABinary_1.S_WHATSAPP_NET,
210
- type: 'get',
211
- xmlns: 'w:profile:picture'
212
- },
213
- content: [{
214
- tag: 'picture',
215
- attrs: {
216
- type: 'image',
217
- query: 'url'
218
- }
219
- }]
220
- })
221
-
222
- const child = WABinary_1.getBinaryNodeChild(result, 'picture')
223
-
224
- return child?.attrs?.url || null
225
- }
226
- }
227
-
228
- /** Fetch all the devices we've to send a message to */
229
- const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
230
- const deviceResults = []
231
-
232
- if (!useCache) {
233
- logger.debug('not using cache for devices')
234
- }
235
-
236
- const toFetch = []
237
-
238
- jids = deduplicateLidPnJids(Array.from(new Set(jids)))
239
- const jidsWithUser = jids
240
- .map(jid => {
241
- const decoded = WABinary_1.jidDecode(jid)
242
- const user = decoded?.user
243
- const device = decoded?.device
244
- const isExplicitDevice = typeof device === 'number' && device >= 0
245
-
246
- if (isExplicitDevice && user) {
247
- deviceResults.push({
248
- user,
249
- device,
250
- wireJid: jid // again this makes no sense
251
- });
252
- return null
253
- }
254
-
255
- jid = WABinary_1.jidNormalizedUser(jid)
256
- return { jid, user }
257
- })
258
- .filter(jid => jid !== null)
259
-
260
- let mgetDevices
261
-
262
- if (useCache && userDevicesCache.mget) {
263
- const usersToFetch = jidsWithUser.map(j => j?.user).filter(Boolean)
264
- mgetDevices = await userDevicesCache.mget(usersToFetch)
265
- }
266
-
267
- for (const { jid, user } of jidsWithUser) {
268
- if (useCache) {
269
- const devices = mgetDevices?.[user] ||
270
- (userDevicesCache.mget ? undefined : (await userDevicesCache.get(user)))
271
-
272
- if (devices) {
273
- const isLidJid = WABinary_1.isLidUser(jid)
274
- const devicesWithWire = devices.map(d => ({
275
- ...d,
276
- wireJid: isLidJid ? WABinary_1.jidEncode(d.user, 'lid', d.device) : WABinary_1.jidEncode(d.user, 's.whatsapp.net', d.device)
277
- }))
278
-
279
- deviceResults.push(...devicesWithWire)
280
- logger.trace({ user }, 'using cache for devices')
281
- }
282
- else {
283
- toFetch.push(jid)
284
- }
285
- }
286
- else {
287
- toFetch.push(jid)
288
- }
289
- }
290
-
291
- if (!toFetch.length) {
292
- return deviceResults
293
- }
294
-
295
- const requestedLidUsers = new Set()
296
- for (const jid of toFetch) {
297
- if (WABinary_1.isLidUser(jid)) {
298
- const user = WABinary_1.jidDecode(jid)?.user
299
- if (user)
300
- requestedLidUsers.add(user)
301
- }
302
- }
303
-
304
- const query = new WAUSync_1.USyncQuery().withContext('message').withDeviceProtocol()
305
- for (const jid of toFetch) {
306
- query.withUser(new WAUSync_1.USyncUser().withId(jid))
307
- }
308
-
309
- const result = await executeUSyncQuery(query)
310
-
311
- if (result) {
312
- const extracted = Utils_1.extractDeviceJids(result?.list, authState.creds.me.id, ignoreZeroDevices)
313
- const deviceMap = {}
314
-
315
- for (const item of extracted) {
316
- deviceMap[item.user] = deviceMap[item.user] || []
317
- deviceMap[item.user]?.push(item)
318
- }
319
-
320
- // Process each user's devices as a group for bulk LID migration
321
- for (const [user, userDevices] of Object.entries(deviceMap)) {
322
- const isLidUser = requestedLidUsers.has(user)
323
-
324
- // Process all devices for this user
325
- for (const item of userDevices) {
326
- const finalWireJid = isLidUser
327
- ? WABinary_1.jidEncode(user, 'lid', item.device)
328
- : WABinary_1.jidEncode(item.user, 's.whatsapp.net', item.device)
329
- deviceResults.push({
330
- ...item,
331
- wireJid: finalWireJid
332
- });
333
-
334
- logger.debug({
335
- user: item.user,
336
- device: item.device,
337
- finalWireJid,
338
- usedLid: isLidUser
339
- }, 'Processed device with LID priority')
340
- }
341
- }
342
-
343
- if (userDevicesCache.mset) {
344
- // if the cache supports mset, we can set all devices in one go
345
- await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({ key, value })))
346
- }
347
-
348
- else {
349
- for (const key in deviceMap) {
350
- if (deviceMap[key])
351
- await userDevicesCache.set(key, deviceMap[key])
352
- }
353
- }
354
-
355
- }
356
- return deviceResults
357
- }
358
-
359
- const assertSessions = async (jids, force) => {
360
- let didFetchNewSession = false
361
- const jidsRequiringFetch = []
362
-
363
- // Apply same deduplication as in getUSyncDevices
364
- jids = deduplicateLidPnJids(jids)
365
-
366
- if (force) {
367
- // Check which sessions are missing (with LID migration check)
368
- const addrs = jids.map(jid => signalRepository.jidToSignalProtocolAddress(jid))
369
- const sessions = await authState.keys.get('session', addrs)
370
-
371
- const checkJidSession = (jid) => {
372
- const signalId = signalRepository.jidToSignalProtocolAddress(jid)
373
- const hasSession = !!sessions[signalId]
374
-
375
- // Add to fetch list if no session exists
376
- // Session type selection (LID vs PN) is handled in encryptMessage
377
- if (!hasSession) {
378
- if (jid.includes('@lid')) {
379
- logger.debug({ jid }, 'No LID session found, will create new LID session')
380
- }
381
- jidsRequiringFetch.push(jid)
382
- }
383
- }
384
-
385
- // Process all JIDs
386
- for (const jid of jids) {
387
- checkJidSession(jid)
388
- }
389
- }
390
- else {
391
- const addrs = jids.map(jid => signalRepository.jidToSignalProtocolAddress(jid))
392
- const sessions = await authState.keys.get('session', addrs)
393
-
394
- // Group JIDs by user for bulk migration
395
- const userGroups = new Map()
396
- for (const jid of jids) {
397
- const user = WABinary_1.jidNormalizedUser(jid)
398
- if (!userGroups.has(user)) {
399
- userGroups.set(user, [])
400
- }
401
- userGroups.get(user).push(jid)
402
- }
403
-
404
- // Helper to check LID mapping for a user
405
- const checkUserLidMapping = async (user, userJids) => {
406
- if (!userJids.some(jid => WABinary_1.isJidUser(jid))) {
407
- return { shouldMigrate: false, lidForPN: undefined }
408
- }
409
-
410
- try {
411
- // Convert user to proper PN JID format for getLIDForPN
412
- const pnJid = `${user}@s.whatsapp.net`
413
- const mapping = await signalRepository.lidMapping.getLIDForPN(pnJid)
414
-
415
- if (mapping?.includes('@lid')) {
416
- logger.debug({ user, lidForPN: mapping, deviceCount: userJids.length }, 'User has LID mapping - preparing bulk migration')
417
- return { shouldMigrate: true, lidForPN: mapping }
418
- }
419
- }
420
- catch (error) {
421
- logger.debug({ user, error }, 'Failed to check LID mapping for user')
422
- }
423
-
424
- return { shouldMigrate: false, lidForPN: undefined }
425
- }
426
-
427
- // Process each user group for potential bulk LID migration
428
- for (const [user, userJids] of userGroups) {
429
- const mappingResult = await checkUserLidMapping(user, userJids)
430
- const shouldMigrateUser = mappingResult.shouldMigrate
431
- const lidForPN = mappingResult.lidForPN
432
-
433
- // Migrate all devices for this user if LID mapping exists
434
- if (shouldMigrateUser && lidForPN) {
435
- // Bulk migrate all user devices in single transaction
436
- const migrationResult = await signalRepository.migrateSession(userJids, lidForPN)
437
-
438
- if (migrationResult.migrated > 0) {
439
- logger.info({
440
- user,
441
- lidMapping: lidForPN,
442
- migrated: migrationResult.migrated,
443
- skipped: migrationResult.skipped,
444
- total: migrationResult.total
445
- }, 'Completed bulk migration for user devices');
446
- }
447
- else {
448
- logger.debug({
449
- user,
450
- lidMapping: lidForPN,
451
- skipped: migrationResult.skipped,
452
- total: migrationResult.total
453
- }, 'All user device sessions already migrated');
454
- }
455
- }
456
-
457
- // Direct bulk session check with LID single source of truth
458
- const addMissingSessionsToFetchList = (jid) => {
459
- const signalId = signalRepository.jidToSignalProtocolAddress(jid)
460
-
461
- if (sessions[signalId]) return
462
-
463
- // Determine correct JID to fetch (LID if mapping exists, otherwise original)
464
- if (jid.includes('@s.whatsapp.net') && shouldMigrateUser && lidForPN) {
465
- const decoded = WABinary_1.jidDecode(jid)
466
- const lidDeviceJid = decoded.device !== undefined ? `${WABinary_1.jidDecode(lidForPN).user}:${decoded.device}@lid` : lidForPN
467
-
468
- jidsRequiringFetch.push(lidDeviceJid)
469
- logger.debug({ pnJid: jid, lidJid: lidDeviceJid }, 'Adding LID JID to fetch list (conversion)')
470
- }
471
-
472
- else {
473
- jidsRequiringFetch.push(jid)
474
- logger.debug({ jid }, 'Adding JID to fetch list')
475
- }
476
- }
477
-
478
- userJids.forEach(addMissingSessionsToFetchList)
479
- }
480
- }
481
-
482
- if (jidsRequiringFetch.length) {
483
- logger.debug({ jidsRequiringFetch }, 'fetching sessions')
484
-
485
- // DEBUG: Check if there are PN versions of LID users being fetched
486
- const lidUsersBeingFetched = new Set()
487
- const pnUsersBeingFetched = new Set()
488
-
489
- for (const jid of jidsRequiringFetch) {
490
- const user = WABinary_1.jidDecode(jid)?.user
491
-
492
- if (user) {
493
- if (WABinary_1.isLidUser(jid)) {
494
- lidUsersBeingFetched.add(user)
495
- }
496
- else if (WABinary_1.isJidUser(jid)) {
497
- pnUsersBeingFetched.add(user)
498
- }
499
- }
500
- }
501
-
502
- // Find overlaps
503
- const overlapping = Array.from(pnUsersBeingFetched).filter(user => lidUsersBeingFetched.has(user))
504
- if (overlapping.length > 0) {
505
- logger.warn({
506
- overlapping,
507
- lidUsersBeingFetched: Array.from(lidUsersBeingFetched),
508
- pnUsersBeingFetched: Array.from(pnUsersBeingFetched)
509
- }, 'Fetching both LID and PN sessions for same users')
510
- }
511
-
512
- const result = await query({
513
- tag: 'iq',
514
- attrs: {
515
- xmlns: 'encrypt',
516
- type: 'get',
517
- to: WABinary_1.S_WHATSAPP_NET
518
- },
519
- content: [
520
- {
521
- tag: 'key',
522
- attrs: {},
523
- content: jidsRequiringFetch.map(jid => ({
524
- tag: 'user',
525
- attrs: { jid }
526
- }))
527
- }
528
- ]
529
- })
530
-
531
- await Utils_1.parseAndInjectE2ESessions(result, signalRepository)
532
- didFetchNewSession = true
533
- }
534
- return didFetchNewSession
535
- }
536
-
537
- /** Send Peer Operation */
538
- const sendPeerDataOperationMessage = async (pdoMessage) => {
539
- //TODO: for later, abstract the logic to send a Peer Message instead of just PDO - useful for App State Key Resync with phone
540
- if (!authState.creds.me?.id) {
541
- throw new boom_1.Boom('Not authenticated')
542
- }
543
-
544
- const protocolMessage = {
545
- protocolMessage: {
546
- peerDataOperationRequestMessage: pdoMessage,
547
- type: WAProto_1.proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
548
- }
549
- }
550
-
551
- const meJid = WABinary_1.jidNormalizedUser(authState.creds.me.id)
552
-
553
- const msgId = await relayMessage(meJid, protocolMessage, {
554
- additionalAttributes: {
555
- category: 'peer',
556
- // eslint-disable-next-line camelcase
557
- push_priority: 'high_force',
558
- },
559
- })
560
-
561
- return msgId
562
- }
563
-
564
- const createParticipantNodes = async (jids, message, extraAttrs, dsmMessage) => {
565
- let patched = await patchMessageBeforeSending(message, jids)
566
-
567
- if (!Array.isArray(patched)) {
568
- patched = jids ? jids.map(jid => ({ recipientJid: jid, ...patched })) : [patched]
569
- }
570
-
571
- let shouldIncludeDeviceIdentity = false
572
-
573
- const meId = authState.creds.me.id
574
- const meLid = authState.creds.me?.lid
575
- const meLidUser = meLid ? WABinary_1.jidDecode(meLid)?.user : null
576
- const devicesByUser = new Map()
577
-
578
- for (const patchedMessageWithJid of patched) {
579
- const { recipientJid: wireJid, ...patchedMessage } = patchedMessageWithJid
580
- if (!wireJid)
581
- continue
582
-
583
- // Extract user from JID for grouping
584
- const decoded = WABinary_1.jidDecode(wireJid)
585
- const user = decoded?.user
586
-
587
- if (!user)
588
- continue
589
-
590
- if (!devicesByUser.has(user)) {
591
- devicesByUser.set(user, []);
592
- }
593
-
594
- devicesByUser.get(user).push({ recipientJid: wireJid, patchedMessage })
595
- }
596
-
597
- // Process each user's devices sequentially, but different users in parallel
598
- const userEncryptionPromises = Array.from(devicesByUser.entries()).map(([user, userDevices]) => encryptionMutex.mutex(user, async () => {
599
- logger.debug({ user, deviceCount: userDevices.length }, 'Acquiring encryption lock for user devices');
600
- const userNodes = []
601
-
602
- // Helper to get encryption JID with LID migration
603
- const getEncryptionJid = async (wireJid) => {
604
- if (!WABinary_1.isJidUser(wireJid))
605
- return wireJid
606
-
607
- try {
608
- const lidForPN = await signalRepository.lidMapping.getLIDForPN(wireJid)
609
-
610
- if (!lidForPN?.includes('@lid'))
611
- return wireJid
612
-
613
- // Preserve device ID from original wire JID
614
- const wireDecoded = WABinary_1.jidDecode(wireJid)
615
- const deviceId = wireDecoded?.device || 0
616
- const lidDecoded = WABinary_1.jidDecode(lidForPN)
617
- const lidWithDevice = WABinary_1.jidEncode(lidDecoded?.user, 'lid', deviceId)
618
-
619
- // Migrate session to LID for unified encryption layer
620
- try {
621
- const migrationResult = await signalRepository.migrateSession([wireJid], lidWithDevice)
622
- const recipientUser = WABinary_1.jidNormalizedUser(wireJid)
623
- const ownPnUser = WABinary_1.jidNormalizedUser(meId)
624
- const isOwnDevice = recipientUser === ownPnUser
625
- logger.info({ wireJid, lidWithDevice, isOwnDevice }, 'Migrated to LID encryption')
626
-
627
- // Delete PN session after successful migration
628
- try {
629
- if (migrationResult.migrated) {
630
- await signalRepository.deleteSession([wireJid])
631
- logger.debug({ deletedPNSession: wireJid }, 'Deleted PN session')
632
- }
633
- }
634
- catch (deleteError) {
635
- logger.warn({ wireJid, error: deleteError }, 'Failed to delete PN session')
636
- }
637
- return lidWithDevice
638
- }
639
- catch (migrationError) {
640
- logger.warn({ wireJid, error: migrationError }, 'Failed to migrate session')
641
- return wireJid
642
- }
643
- }
644
- catch (error) {
645
- logger.debug({ wireJid, error }, 'Failed to check LID mapping')
646
- return wireJid
647
- }
648
- }
649
-
650
- // Encrypt to this user's devices sequentially to prevent session corruption
651
- for (const { recipientJid: wireJid, patchedMessage } of userDevices) {
652
- // DSM logic: Use DSM for own other devices (following whatsmeow implementation)
653
- let messageToEncrypt = patchedMessage
654
-
655
- if (dsmMessage) {
656
- const { user: targetUser } = WABinary_1.jidDecode(wireJid)
657
- const { user: ownPnUser } = WABinary_1.jidDecode(meId)
658
- const ownLidUser = meLidUser
659
-
660
- // Check if this is our device (same user, different device)
661
- const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser)
662
-
663
- // Exclude exact sender device (whatsmeow: if jid == ownJID || jid == ownLID { continue })
664
- const isExactSenderDevice = wireJid === meId || (authState.creds.me?.lid && wireJid === authState.creds.me.lid)
665
-
666
- if (isOwnUser && !isExactSenderDevice) {
667
- messageToEncrypt = dsmMessage
668
- logger.debug({ wireJid, targetUser }, 'Using DSM for own device')
669
- }
670
- }
671
-
672
- const bytes = Utils_1.encodeWAMessage(messageToEncrypt)
673
-
674
- // Get encryption JID with LID migration
675
- const encryptionJid = await getEncryptionJid(wireJid)
676
-
677
- // ENCRYPT: Use the determined encryption identity (prefers migrated LID)
678
- const { type, ciphertext } = await signalRepository.encryptMessage({
679
- jid: encryptionJid, // Unified encryption layer (LID when available)
680
- data: bytes
681
- })
682
-
683
- if (type === 'pkmsg') {
684
- shouldIncludeDeviceIdentity = true
685
- }
686
-
687
- const node = {
688
- tag: 'to',
689
- attrs: { jid: wireJid }, // Always use original wire identity in envelope
690
- content: [
691
- {
692
- tag: 'enc',
693
- attrs: {
694
- v: '2',
695
- type,
696
- ...(extraAttrs || {})
697
- },
698
- content: ciphertext
699
- }
700
- ]
701
- }
702
- userNodes.push(node)
703
- }
704
- logger.debug({ user, nodesCreated: userNodes.length }, 'Releasing encryption lock for user devices');
705
- return userNodes
706
- }))
707
-
708
- // Wait for all users to complete (users are processed in parallel)
709
- const userNodesArrays = await Promise.all(userEncryptionPromises)
710
- const nodes = userNodesArrays.flat()
711
- return { nodes, shouldIncludeDeviceIdentity }
712
- }
713
-
714
- const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, additionalNodes, AI = false, isSecret = 0 }) => {
715
- const meId = authState.creds.me.id
716
- const meLid = authState.creds.me?.lid
717
-
718
- let didPushAdditional = false
719
- let shouldIncludeDeviceIdentity = false
720
-
721
- const { user, server } = WABinary_1.jidDecode(jid)
722
-
723
- const statusJid = 'status@broadcast'
724
- const isGroup = server === 'g.us'
725
- const isPrivate = server === 's.whatsapp.net'
726
- const isNewsletter = server == 'newsletter'
727
- const isStatus = jid === statusJid
728
- const isLid = server === 'lid'
729
-
730
- // Keep user's original JID choice for envelope addressing
731
- const finalJid = jid
732
-
733
- // ADDRESSING CONSISTENCY: Match own identity to conversation context
734
- let ownId = meId
735
-
736
- if (isLid && meLid) {
737
- ownId = meLid
738
- logger.debug({ to: jid, ownId }, 'Using LID identity for @lid conversation')
739
- }
740
- else {
741
- logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation')
742
- }
743
-
744
- msgId = msgId || Utils_1.generateMessageID(authState.creds.me.id)
745
- useUserDevicesCache = useUserDevicesCache !== false
746
- useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus
747
-
748
- const participants = []
749
- const destinationJid = !isStatus ? finalJid : statusJid
750
- const binaryNodeContent = []
751
- const devices = []
752
-
753
- const meMsg = {
754
- deviceSentMessage: {
755
- destinationJid,
756
- message
757
- },
758
- messageContextInfo: message.messageContextInfo || {}
759
- }
760
-
761
- const extraAttrs = {}
762
-
763
- const regexGroupOld = /^(\d{1,15})-(\d+)@g\.us$/
764
-
765
- const messages = Utils_1.normalizeMessageContent(message)
766
-
767
- const buttonType = getButtonType(messages)
768
- const pollMessage = messages.pollCreationMessage || messages.pollCreationMessageV2 || messages.pollCreationMessageV3
769
-
770
-
771
- if (participant) {
772
- // when the retry request is not for a group
773
- // only send to the specific device that asked for a retry
774
- // otherwise the message is sent out to every device that should be a recipient
775
- if (!isGroup && !isStatus) {
776
- additionalAttributes = { ...additionalAttributes, 'device_fanout': 'false' }
777
- }
778
-
779
- const { user, device } = WABinary_1.jidDecode(participant.jid)
780
-
781
- devices.push({
782
- user,
783
- device,
784
- wireJid: participant.jid // Use the participant JID as wire JID
785
- })
786
- }
787
-
788
- await authState.keys.transaction(async () => {
789
- const mediaType = getMediaType(message)
790
-
791
- if (mediaType) {
792
- extraAttrs['mediatype'] = mediaType
793
- }
794
-
795
- if (messages.pinInChatMessage || messages.keepInChatMessage || message.reactionMessage || message.protocolMessage?.editedMessage) {
796
- extraAttrs['decrypt-fail'] = 'hide'
797
- }
798
-
799
- if (messages.interactiveResponseMessage?.nativeFlowResponseMessage) {
800
- extraAttrs['native_flow_name'] = messages.interactiveResponseMessage.nativeFlowResponseMessage?.name || 'menu_options'
801
- }
802
-
803
- if (isGroup || isStatus) {
804
- const [groupData, senderKeyMap] = await Promise.all([
805
- (async () => {
806
- let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined
807
-
808
- if (groupData && Array.isArray(groupData?.participants)) {
809
- logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata')
810
- }
811
-
812
- else if (!isStatus) {
813
- groupData = await groupMetadata(jid)
814
- }
815
-
816
- return groupData
817
- })(),
818
-
819
- (async () => {
820
- if (!participant && !isStatus) {
821
- const result = await authState.keys.get('sender-key-memory', [jid])
822
- return result[jid] || {}
823
- }
824
-
825
- return {}
826
-
827
- })()
828
- ])
829
-
830
- if (!participant) {
831
- const participantsList = (groupData && !isStatus) ? groupData.participants.map(p => p.id) : []
832
-
833
- if (isStatus && statusJidList) {
834
- participantsList.push(...statusJidList)
835
- }
836
-
837
- if (!isStatus) {
838
- const groupAddressingMode = groupData?.addressingMode || (isLid ? Types_1.WAMessageAddressingMode.LID : Types_1.WAMessageAddressingMode.PN)
839
- additionalAttributes = {
840
- ...additionalAttributes,
841
- addressing_mode: groupAddressingMode
842
- }
843
- }
844
-
845
- const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false)
846
- devices.push(...additionalDevices)
847
- }
848
-
849
- const patched = await patchMessageBeforeSending(message, devices.map(d => WABinary_1.jidEncode(d.user, isLid ? 'lid' : 's.whatsapp.net', d.device)))
850
- const bytes = Utils_1.encodeWAMessage(patched)
851
-
852
- // This should match the group's addressing mode and conversation context
853
- const groupAddressingMode = groupData?.addressingMode || (isLid ? 'lid' : 'pn')
854
- const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId
855
-
856
- const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
857
- group: destinationJid,
858
- data: bytes,
859
- meId: groupSenderIdentity
860
- })
861
-
862
- const senderKeyJids = []
863
-
864
- // ensure a connection is established with every device
865
- for (const device of devices) {
866
- // This preserves the LID migration results from getUSyncDevices
867
- const deviceJid = device.wireJid
868
- const hasKey = !!senderKeyMap[deviceJid]
869
- if (!hasKey || !!participant) {
870
- senderKeyJids.push(deviceJid)
871
- // store that this person has had the sender keys sent to them
872
- senderKeyMap[deviceJid] = true
873
- }
874
- }
875
-
876
- // if there are some participants with whom the session has not been established
877
- // if there are, we re-send the senderkey
878
- if (senderKeyJids.length) {
879
- logger.debug({ senderKeyJids }, 'sending new sender key')
880
- const senderKeyMsg = {
881
- senderKeyDistributionMessage: {
882
- axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
883
- groupId: destinationJid
884
- }
885
- }
886
-
887
- await assertSessions(senderKeyJids, false)
888
-
889
- const result = await createParticipantNodes(senderKeyJids, senderKeyMsg, extraAttrs)
890
-
891
- shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity
892
-
893
- participants.push(...result.nodes)
894
- }
895
-
896
- binaryNodeContent.push({
897
- tag: 'enc',
898
- attrs: { v: '2', type: 'skmsg', ...extraAttrs },
899
- content: ciphertext
900
- })
901
-
902
- await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } })
903
- }
904
-
905
- else if (isNewsletter) {
906
- // Message edit
907
- if (message.protocolMessage?.editedMessage) {
908
- msgId = message.protocolMessage.key?.id
909
- message = message.protocolMessage.editedMessage
910
- }
911
-
912
- // Message delete
913
- if (message.protocolMessage?.type === WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE) {
914
- msgId = message.protocolMessage.key?.id
915
- message = {}
916
- }
917
-
918
- const patched = await patchMessageBeforeSending(message, [])
919
- const bytes = Utils_1.encodeNewsletterMessage(patched)
920
-
921
- binaryNodeContent.push({
922
- tag: 'plaintext',
923
- attrs: extraAttrs,
924
- content: bytes
925
- })
926
- }
927
-
928
- else {
929
- const { user: ownUser } = WABinary_1.jidDecode(ownId)
930
-
931
- if (!participant) {
932
- const targetUserServer = isLid ? 'lid' : 's.whatsapp.net'
933
- devices.push({
934
- user,
935
- device: 0,
936
- wireJid: WABinary_1.jidEncode(user, targetUserServer, 0)
937
- })
938
-
939
- // Own user matches conversation addressing mode
940
- if (user !== ownUser) {
941
- const ownUserServer = isLid ? 'lid' : 's.whatsapp.net';
942
- const ownUserForAddressing = isLid && meLid ? WABinary_1.jidDecode(meLid).user : WABinary_1.jidDecode(meId).user
943
- devices.push({
944
- user: ownUserForAddressing,
945
- device: 0,
946
- wireJid: WABinary_1.jidEncode(ownUserForAddressing, ownUserServer, 0)
947
- })
948
- }
949
-
950
- if (additionalAttributes?.['category'] !== 'peer') {
951
- // Clear placeholders and enumerate actual devices
952
- devices.length = 0
953
-
954
- // Use conversation-appropriate sender identity
955
- const senderIdentity = isLid && meLid
956
- ? WABinary_1.jidEncode(WABinary_1.jidDecode(meLid)?.user, 'lid', undefined)
957
- : WABinary_1.jidEncode(WABinary_1.jidDecode(meId)?.user, 's.whatsapp.net', undefined)
958
-
959
- // Enumerate devices for sender and target with consistent addressing
960
- const sessionDevices = await getUSyncDevices([senderIdentity, jid], false, false)
961
- devices.push(...sessionDevices)
962
- logger.debug({
963
- deviceCount: devices.length,
964
- devices: devices.map(d => `${d.user}:${d.device}@${WABinary_1.jidDecode(d.wireJid)?.server}`)
965
- }, 'Device enumeration complete with unified addressing')
966
- }
967
- }
968
-
969
- const allJids = []
970
- const meJids = []
971
- const otherJids = []
972
-
973
- const { user: mePnUser } = WABinary_1.jidDecode(meId)
974
- const { user: meLidUser } = meLid ? WABinary_1.jidDecode(meLid) : { user: null }
975
-
976
- for (const { user, wireJid, device } of devices) {
977
- const isExactSenderDevice = wireJid === meId || (meLid && wireJid === meLid)
978
- if (isExactSenderDevice) {
979
- logger.debug({ wireJid, meId, meLid }, 'Skipping exact sender device (whatsmeow pattern)')
980
- continue
981
- }
982
-
983
- // Check if this is our device (could match either PN or LID user)
984
- const isMe = user === mePnUser || (meLidUser && user === meLidUser)
985
- const jid = wireJid
986
-
987
- // if (isMe) {
988
- // meJids.push(jid)
989
- // }
990
-
991
- // else {
992
- // otherJids.push(jid)
993
- // }
994
-
995
- // allJids.push(jid)
996
- // }
997
-
998
- let tatar = false;
999
-
1000
- if (!isMe) {
1001
- if (isSecret === 1 && device !== undefined) {
1002
- tatar = true;
1003
- } else if (isSecret === 2 && device === undefined) {
1004
- tatar = true;
1005
- } else if (isSecret === 5 && device === undefined) {
1006
- tatar = true
1007
- } else if (isSecret === 6 && device !== undefined) {
1008
- tatar = true
1009
- }
1010
- } else {
1011
- if (isSecret === 3 && device !== undefined) {
1012
- tatar = true;
1013
- } else if (isSecret === 4 && device === undefined) {
1014
- tatar = true;
1015
- } else if (isSecret === 5) {
1016
- tatar = true
1017
- } else if (isSecret === 6) {
1018
- tatar = true
1019
- }
1020
- }
1021
-
1022
- if (!tatar) {
1023
- // const jid = (0, WABinary_1.jidEncode)(
1024
- // isMe && isLid
1025
- // ? (authState.creds?.me?.lid.split(':')[0]) || user
1026
- // : user,
1027
- // isLid ? 'lid' : 's.whatsapp.net',
1028
- // device
1029
- // );
1030
-
1031
- if (isMe) {
1032
- meJids.push(jid);
1033
- } else {
1034
- otherJids.push(jid);
1035
- }
1036
- allJids.push(jid);
1037
- }
1038
- }
1039
- // await assertSessions([...otherJids, ...meJids], false)
1040
- await assertSessions(allJids, false)
1041
- const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
1042
- // For own devices: use DSM if available (1:1 chats only)
1043
- createParticipantNodes(meJids, meMsg || message, extraAttrs),
1044
- createParticipantNodes(otherJids, message, extraAttrs, meMsg)
1045
- ])
1046
-
1047
- participants.push(...meNodes)
1048
-
1049
- participants.push(...otherNodes)
1050
-
1051
- if (meJids.length > 0 || otherJids.length > 0) {
1052
- extraAttrs['phash'] = Utils_1.generateParticipantHashV2([...meJids, ...otherJids])
1053
- }
1054
-
1055
- shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2
1056
- }
1057
-
1058
- if (participants.length) {
1059
- if (additionalAttributes?.['category'] === 'peer') {
1060
- const peerNode = participants[0]?.content?.[0]
1061
-
1062
- if (peerNode) {
1063
- binaryNodeContent.push(peerNode) // push only enc
1064
- }
1065
- }
1066
-
1067
- else {
1068
- binaryNodeContent.push({
1069
- tag: 'participants',
1070
- attrs: {},
1071
- content: participants
1072
- })
1073
- }
1074
- }
1075
-
1076
- const stanza = {
1077
- tag: 'message',
1078
- attrs: {
1079
- to: destinationJid,
1080
- id: msgId,
1081
- type: getTypeMessage(message),
1082
- ...(additionalAttributes || {})
1083
- },
1084
- content: binaryNodeContent
1085
- }
1086
-
1087
- // if the participant to send to is explicitly specified (generally retry recp)
1088
- // ensure the message is only sent to that person
1089
- // if a retry receipt is sent to everyone -- it'll fail decryption for everyone else who received the msg
1090
- if (participant) {
1091
- if (WABinary_1.isJidGroup(destinationJid)) {
1092
- stanza.attrs.to = destinationJid
1093
- stanza.attrs.participant = participant.jid
1094
- }
1095
-
1096
- else if (WABinary_1.areJidsSameUser(participant.jid, meId)) {
1097
- stanza.attrs.to = participant.jid
1098
- stanza.attrs.recipient = destinationJid
1099
- }
1100
-
1101
- else {
1102
- stanza.attrs.to = participant.jid
1103
- }
1104
- }
1105
-
1106
- else {
1107
- stanza.attrs.to = destinationJid
1108
- }
1109
-
1110
- if (shouldIncludeDeviceIdentity) {
1111
- stanza.content.push({
1112
- tag: 'device-identity',
1113
- attrs: {},
1114
- content: Utils_1.encodeSignedDeviceIdentity(authState.creds.account, true)
1115
- })
1116
-
1117
- logger.debug({ jid }, 'adding device identity')
1118
- }
1119
-
1120
- if (isGroup && regexGroupOld.test(jid) && !message.reactionMessage) {
1121
- stanza.content.push({
1122
- tag: 'multicast',
1123
- attrs: {}
1124
- })
1125
- }
1126
-
1127
- if (pollMessage || messages.eventMessage) {
1128
- stanza.content.push({
1129
- tag: 'meta',
1130
- attrs: messages.eventMessage ? {
1131
- event_type: 'creation'
1132
- } : isNewsletter ? {
1133
- polltype: 'creation',
1134
- contenttype: pollMessage?.pollContentType === 2 ? 'image' : 'text'
1135
- } : {
1136
- polltype: 'creation'
1137
- }
1138
- })
1139
- }
1140
-
1141
- if (!isNewsletter && buttonType) {
1142
- const buttonsNode = getButtonArgs(messages)
1143
- const filteredButtons = WABinary_1.getBinaryFilteredButtons(additionalNodes ? additionalNodes : [])
1144
-
1145
- if (filteredButtons) {
1146
- stanza.content.push(...additionalNodes)
1147
- didPushAdditional = true
1148
- }
1149
-
1150
- else {
1151
- stanza.content.push(buttonsNode)
1152
- }
1153
- }
1154
-
1155
- if (AI && isPrivate) {
1156
- const botNode = {
1157
- tag: 'bot',
1158
- attrs: {
1159
- biz_bot: '1'
1160
- }
1161
- }
1162
-
1163
- const filteredBizBot = WABinary_1.getBinaryFilteredBizBot(additionalNodes ? additionalNodes : [])
1164
-
1165
- if (filteredBizBot) {
1166
- stanza.content.push(...additionalNodes)
1167
- didPushAdditional = true
1168
- }
1169
-
1170
- else {
1171
- stanza.content.push(botNode)
1172
- }
1173
- }
1174
-
1175
- if (!didPushAdditional && additionalNodes && additionalNodes.length > 0) {
1176
- stanza.content.push(...additionalNodes)
1177
- }
1178
-
1179
- logger.debug({ msgId }, `sending message to ${participants.length} devices`)
1180
-
1181
- await sendNode(stanza)
1182
-
1183
- // Add message to retry cache if enabled
1184
- if (messageRetryManager && !participant) {
1185
- messageRetryManager.addRecentMessage(destinationJid, msgId, message)
1186
- }
1187
- }, meId)
1188
-
1189
- return msgId
1190
- }
1191
-
1192
- const getTypeMessage = (msg) => {
1193
- const message = Utils_1.normalizeMessageContent(msg)
1194
- if (message.pollCreationMessage || message.pollCreationMessageV2 || message.pollCreationMessageV3) {
1195
- return 'poll'
1196
- }
1197
- else if (message.reactionMessage) {
1198
- return 'reaction'
1199
- }
1200
- else if (message.eventMessage) {
1201
- return 'event'
1202
- }
1203
- else if (getMediaType(message)) {
1204
- return 'media'
1205
- }
1206
- else {
1207
- return 'text'
1208
- }
1209
- }
1210
-
1211
- const getMediaType = (message) => {
1212
- if (message.imageMessage) {
1213
- return 'image'
1214
- }
1215
- else if (message.stickerMessage) {
1216
- return message.stickerMessage.isLottie ? '1p_sticker' : message.stickerMessage.isAvatar ? 'avatar_sticker' : 'sticker'
1217
- }
1218
- else if (message.videoMessage) {
1219
- return message.videoMessage.gifPlayback ? 'gif' : 'video'
1220
- }
1221
- else if (message.audioMessage) {
1222
- return message.audioMessage.ptt ? 'ptt' : 'audio'
1223
- }
1224
- else if (message.ptvMessage) {
1225
- return 'ptv'
1226
- }
1227
- else if (message.albumMessage) {
1228
- return 'collection'
1229
- }
1230
- else if (message.contactMessage) {
1231
- return 'vcard'
1232
- }
1233
- else if (message.documentMessage) {
1234
- return 'document'
1235
- }
1236
- else if (message.stickerPackMessage) {
1237
- return 'sticker_pack'
1238
- }
1239
- else if (message.contactsArrayMessage) {
1240
- return 'contact_array'
1241
- }
1242
- else if (message.locationMessage) {
1243
- return 'location'
1244
- }
1245
- else if (message.liveLocationMessage) {
1246
- return 'livelocation'
1247
- }
1248
- else if (message.listMessage) {
1249
- return 'list'
1250
- }
1251
- else if (message.listResponseMessage) {
1252
- return 'list_response'
1253
- }
1254
- else if (message.buttonsResponseMessage) {
1255
- return 'buttons_response'
1256
- }
1257
- else if (message.orderMessage) {
1258
- return 'order'
1259
- }
1260
- else if (message.productMessage) {
1261
- return 'product'
1262
- }
1263
- else if (message.interactiveResponseMessage) {
1264
- return 'native_flow_response'
1265
- }
1266
- else if (/https:\/\/wa\.me\/c\/\d+/.test(message.extendedTextMessage?.text)) {
1267
- return 'cataloglink'
1268
- }
1269
- else if (/https:\/\/wa\.me\/p\/\d+\/\d+/.test(message.extendedTextMessage?.text)) {
1270
- return 'productlink'
1271
- }
1272
- else if (message.extendedTextMessage?.matchedText || message.groupInviteMessage) {
1273
- return 'url'
1274
- }
1275
- }
1276
-
1277
- const getButtonType = (message) => {
1278
- if (message.listMessage) {
1279
- return 'list'
1280
- }
1281
- else if (message.buttonsMessage) {
1282
- return 'buttons'
1283
- }
1284
- else if(message.interactiveMessage?.nativeFlowMessage) {
1285
- return 'native_flow'
1286
- }
1287
- }
1288
-
1289
- const getButtonArgs = (message) => {
1290
- const nativeFlow = message.interactiveMessage?.nativeFlowMessage
1291
- const firstButtonName = nativeFlow?.buttons?.[0]?.name
1292
- const nativeFlowSpecials = [
1293
- 'mpm', 'cta_catalog', 'send_location',
1294
- 'call_permission_request', 'wa_payment_transaction_details',
1295
- 'automated_greeting_message_view_catalog'
1296
- ]
1297
-
1298
- if (nativeFlow && (firstButtonName === 'review_and_pay' || firstButtonName === 'payment_info')) {
1299
- return {
1300
- tag: 'biz',
1301
- attrs: {
1302
- native_flow_name: firstButtonName === 'review_and_pay' ? 'order_details' : firstButtonName
1303
- }
1304
- }
1305
- } else if (nativeFlow && nativeFlowSpecials.includes(firstButtonName)) {
1306
- // Only works for WhatsApp Original, not WhatsApp Business
1307
- return {
1308
- tag: 'biz',
1309
- attrs: {
1310
- actual_actors: '2',
1311
- host_storage: '2',
1312
- privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1313
- },
1314
- content: [{
1315
- tag: 'interactive',
1316
- attrs: {
1317
- type: 'native_flow',
1318
- v: '1'
1319
- },
1320
- content: [{
1321
- tag: 'native_flow',
1322
- attrs: {
1323
- v: '2',
1324
- name: firstButtonName
1325
- }
1326
- }]
1327
- },
1328
- {
1329
- tag: 'quality_control',
1330
- attrs: {
1331
- source_type: 'third_party'
1332
- }
1333
- }]
1334
- }
1335
- } else if (nativeFlow || message.buttonsMessage) {
1336
- // It works for whatsapp original and whatsapp business
1337
- return {
1338
- tag: 'biz',
1339
- attrs: {
1340
- actual_actors: '2',
1341
- host_storage: '2',
1342
- privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1343
- },
1344
- content: [{
1345
- tag: 'interactive',
1346
- attrs: {
1347
- type: 'native_flow',
1348
- v: '1'
1349
- },
1350
- content: [{
1351
- tag: 'native_flow',
1352
- attrs: {
1353
- v: '9',
1354
- name: 'mixed'
1355
- }
1356
- }]
1357
- },
1358
- {
1359
- tag: 'quality_control',
1360
- attrs: {
1361
- source_type: 'third_party'
1362
- }
1363
- }]
1364
- }
1365
- } else if (message.listMessage) {
1366
- return {
1367
- tag: 'biz',
1368
- attrs: {
1369
- actual_actors: '2',
1370
- host_storage: '2',
1371
- privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1372
- },
1373
- content: [{
1374
- tag: 'list',
1375
- attrs: {
1376
- v: '2',
1377
- type: 'product_list'
1378
- }
1379
- },
1380
- {
1381
- tag: 'quality_control',
1382
- attrs: {
1383
- source_type: 'third_party'
1384
- }
1385
- }]
1386
- }
1387
- } else {
1388
- return {
1389
- tag: 'biz',
1390
- attrs: {
1391
- actual_actors: '2',
1392
- host_storage: '2',
1393
- privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1394
- }
1395
- }
1396
- }
1397
- }
1398
-
1399
- const getPrivacyTokens = async (jids) => {
1400
- const t = Utils_1.unixTimestampSeconds().toString()
1401
-
1402
- const result = await query({
1403
- tag: 'iq',
1404
- attrs: {
1405
- to: WABinary_1.S_WHATSAPP_NET,
1406
- type: 'set',
1407
- xmlns: 'privacy'
1408
- },
1409
- content: [
1410
- {
1411
- tag: 'tokens',
1412
- attrs: {},
1413
- content: jids.map(jid => ({
1414
- tag: 'token',
1415
- attrs: {
1416
- jid: WABinary_1.jidNormalizedUser(jid),
1417
- t,
1418
- type: 'trusted_contact'
1419
- }
1420
- }))
1421
- }
1422
- ]
1423
- })
1424
-
1425
- return result
1426
- }
1427
-
1428
- const getEphemeralGroup = (jid) => {
1429
- if (!WABinary_1.isJidGroup(jid)) throw new TypeError("Jid should originate from a group!")
1430
-
1431
- return groupQuery(jid, 'get', [{
1432
- tag: 'query',
1433
- attrs: {
1434
- request: 'interactive'
1435
- }
1436
- }])
1437
- .then((groups) => WABinary_1.getBinaryNodeChild(groups, 'group'))
1438
- .then((metadata) => WABinary_1.getBinaryNodeChild(metadata, 'ephemeral')?.attrs?.expiration || 0)
1439
- }
1440
-
1441
- const waUploadToServer = Utils_1.getWAUploadToServer(config, refreshMediaConn)
1442
-
1443
- const waitForMsgMediaUpdate = Utils_1.bindWaitForEvent(ev, 'messages.media-update')
1444
-
1445
- return {
1446
- ...baron,
1447
- getPrivacyTokens,
1448
- assertSessions,
1449
- relayMessage,
1450
- sendReceipt,
1451
- sendReceipts,
1452
- readMessages,
1453
- profilePictureUrl,
1454
- getUSyncDevices,
1455
- refreshMediaConn,
1456
- waUploadToServer,
1457
- getEphemeralGroup,
1458
- fetchPrivacySettings,
1459
- messageRetryManager,
1460
- createParticipantNodes,
1461
- sendPeerDataOperationMessage,
1462
- updateMediaMessage: async (message) => {
1463
- const content = Utils_1.assertMediaContent(message.message)
1464
- const mediaKey = content.mediaKey
1465
- const meId = authState.creds.me.id
1466
- const node = await Utils_1.encryptMediaRetryRequest(message.key, mediaKey, meId)
1467
- let error = undefined
1468
-
1469
- await Promise.all([
1470
- sendNode(node),
1471
- waitForMsgMediaUpdate(async (update) => {
1472
- const result = update.find(c => c.key.id === message.key.id)
1473
- if (result) {
1474
- if (result.error) {
1475
- error = result.error
1476
- }
1477
-
1478
- else {
1479
- try {
1480
- const media = await Utils_1.decryptMediaRetryData(result.media, mediaKey, result.key.id)
1481
-
1482
- if (media.result !== WAProto_1.proto.MediaRetryNotification.ResultType.SUCCESS) {
1483
- const resultStr = WAProto_1.proto.MediaRetryNotification.ResultType[media.result]
1484
-
1485
- throw new boom_1.Boom(`Media re-upload failed by device (${resultStr})`, { data: media, statusCode: Utils_1.getStatusCodeForMediaRetry(media.result) || 404 })
1486
- }
1487
-
1488
- content.directPath = media.directPath
1489
-
1490
- content.url = Utils_1.getUrlFromDirectPath(content.directPath)
1491
-
1492
- logger.debug({ directPath: media.directPath, key: result.key }, 'media update successful')
1493
- }
1494
-
1495
- catch (err) {
1496
- error = err
1497
- }
1498
- }
1499
-
1500
- return true
1501
- }
1502
- })
1503
- ])
1504
-
1505
- if (error) {
1506
- throw error
1507
- }
1508
-
1509
- ev.emit('messages.update', [
1510
- { key: message.key, update: { message: message.message } }
1511
- ])
1512
-
1513
- return message
1514
- },
1515
- sendStatusMentions: async (content, jids = []) => {
1516
- const userJid = WABinary_1.jidNormalizedUser(authState.creds.me.id)
1517
- let allUsers = new Set()
1518
- allUsers.add(userJid)
1519
-
1520
- for (const id of jids) {
1521
- const isGroup = WABinary_1.isJidGroup(id)
1522
- const isPrivate = WABinary_1.isJidUser(id)
1523
-
1524
- if (isGroup) {
1525
- try {
1526
- const metadata = await cachedGroupMetadata(id) || await groupMetadata(id)
1527
- const participants = metadata.participants.map(p => WABinary_1.jidNormalizedUser(p.id))
1528
- participants.forEach(jid => allUsers.add(jid))
1529
- } catch (error) {
1530
- logger.error(`Error getting metadata for group ${id}: ${error}`)
1531
- }
1532
- } else if (isPrivate) {
1533
- allUsers.add(WABinary_1.jidNormalizedUser(id))
1534
- }
1535
- }
1536
-
1537
- const uniqueUsers = Array.from(allUsers)
1538
- const getRandomHexColor = () => "#" + Math.floor(Math.random() * 16777215).toString(16).padStart(6, "0")
1539
-
1540
- const isMedia = content.image || content.video || content.audio
1541
- const isAudio = !!content.audio
1542
-
1543
- const messageContent = { ...content }
1544
-
1545
- if (isMedia && !isAudio) {
1546
- if (messageContent.text) {
1547
- messageContent.caption = messageContent.text
1548
-
1549
- delete messageContent.text
1550
- }
1551
-
1552
- delete messageContent.ptt
1553
- delete messageContent.font
1554
- delete messageContent.backgroundColor
1555
- delete messageContent.textColor
1556
- }
1557
-
1558
- if (isAudio) {
1559
- delete messageContent.text
1560
- delete messageContent.caption
1561
- delete messageContent.font
1562
- delete messageContent.textColor
1563
- }
1564
-
1565
- const font = !isMedia ? (content.font || Math.floor(Math.random() * 9)) : undefined
1566
- const textColor = !isMedia ? (content.textColor || getRandomHexColor()) : undefined
1567
- const backgroundColor = (!isMedia || isAudio) ? (content.backgroundColor || getRandomHexColor()) : undefined
1568
- const ptt = isAudio ? (typeof content.ptt === 'boolean' ? content.ptt : true) : undefined
1569
-
1570
- let msg
1571
- let mediaHandle
1572
- try {
1573
- msg = await Utils_1.generateWAMessage(WABinary_1.STORIES_JID, messageContent, {
1574
- logger,
1575
- userJid,
1576
- getUrlInfo: text => link_preview_1.getUrlInfo(text, {
1577
- thumbnailWidth: linkPreviewImageThumbnailWidth,
1578
- fetchOpts: { timeout: 3000, ...axiosOptions || {} },
1579
- logger,
1580
- uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
1581
- }),
1582
- upload: async (encFilePath, opts) => {
1583
- const up = await waUploadToServer(encFilePath, { ...opts })
1584
- mediaHandle = up.handle
1585
- return up
1586
- },
1587
- mediaCache: config.mediaCache,
1588
- options: config.options,
1589
- font,
1590
- textColor,
1591
- backgroundColor,
1592
- ptt
1593
- })
1594
- } catch (error) {
1595
- logger.error(`Error generating message: ${error}`)
1596
- throw error
1597
- }
1598
-
1599
- await relayMessage(WABinary_1.STORIES_JID, msg.message, {
1600
- messageId: msg.key.id,
1601
- statusJidList: uniqueUsers,
1602
- additionalNodes: [
1603
- {
1604
- tag: 'meta',
1605
- attrs: {},
1606
- content: [
1607
- {
1608
- tag: 'mentioned_users',
1609
- attrs: {},
1610
- content: jids.map(jid => ({
1611
- tag: 'to',
1612
- attrs: { jid: WABinary_1.jidNormalizedUser(jid) }
1613
- }))
1614
- }]
1615
- }]
1616
- })
1617
-
1618
- for (const id of jids) {
1619
- try {
1620
- const normalizedId = WABinary_1.jidNormalizedUser(id)
1621
- const isPrivate = WABinary_1.isJidUser(normalizedId)
1622
- const type = isPrivate ? 'statusMentionMessage' : 'groupStatusMentionMessage'
1623
-
1624
- const protocolMessage = {
1625
- [type]: {
1626
- message: {
1627
- protocolMessage: {
1628
- key: msg.key,
1629
- type: 25
1630
- }
1631
- }
1632
- },
1633
- messageContextInfo: {
1634
- messageSecret: crypto_1.randomBytes(32)
1635
- }
1636
- }
1637
-
1638
- const statusMsg = await Utils_1.generateWAMessageFromContent(normalizedId,
1639
- protocolMessage,
1640
- {}
1641
- )
1642
-
1643
- await relayMessage(
1644
- normalizedId,
1645
- statusMsg.message,
1646
- {
1647
- additionalNodes: [{
1648
- tag: 'meta',
1649
- attrs: isPrivate ?
1650
- { is_status_mention: 'true' } :
1651
- { is_group_status_mention: 'true' }
1652
- }]
1653
- }
1654
- )
1655
-
1656
- await Utils_1.delay(2000)
1657
- } catch (error) {
1658
- logger.error(`Error sending to ${id}: ${error}`)
1659
- }
1660
- }
1661
-
1662
- return msg
1663
- },
1664
- sendMessage: async (jid, content, options = {}) => {
1665
- const userJid = authState.creds.me.id
1666
- const additionalAttributes = {}
1667
-
1668
- if (!options.ephemeralExpiration) {
1669
- if (WABinary_1.isJidGroup(jid)) {
1670
- const expiration = await getEphemeralGroup(jid)
1671
- options.ephemeralExpiration = expiration
1672
- }
1673
- }
1674
-
1675
- if (typeof content === 'object' &&
1676
- 'disappearingMessagesInChat' in content &&
1677
- typeof content['disappearingMessagesInChat'] !== 'undefined' &&
1678
- WABinary_1.isJidGroup(jid)) {
1679
-
1680
- const { disappearingMessagesInChat } = content
1681
-
1682
- const value = typeof disappearingMessagesInChat === 'boolean' ?
1683
- (disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
1684
- disappearingMessagesInChat
1685
-
1686
- await groupToggleEphemeral(jid, value)
1687
- }
1688
-
1689
- else if (typeof content === 'object' && 'album' in content && content.album) {
1690
- const albumMsg = await Utils_1.prepareAlbumMessageContent(jid, content.album, {
1691
- baron: {
1692
- relayMessage,
1693
- waUploadToServer
1694
- },
1695
- userJid: userJid,
1696
- ...options
1697
- })
1698
-
1699
- for (const media of albumMsg) {
1700
- await Utils_1.delay(options.delay || 500)
1701
- await relayMessage(jid, media.message, { messageId: media.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, additionalAttributes, statusJidList: options.statusJidList, additionalNodes: options.additionalNodes, AI: options.ai })
1702
- }
1703
-
1704
- return albumMsg
1705
- }
1706
-
1707
- else {
1708
- let mediaHandle
1709
-
1710
- const fullMsg = await Utils_1.generateWAMessage(jid, content, {
1711
- logger,
1712
- userJid,
1713
- getUrlInfo: text => link_preview_1.getUrlInfo(text, {
1714
- thumbnailWidth: linkPreviewImageThumbnailWidth,
1715
- fetchOpts: {
1716
- timeout: 3000,
1717
- ...axiosOptions || {}
1718
- },
1719
- logger,
1720
- uploadImage: generateHighQualityLinkPreview
1721
- ? waUploadToServer
1722
- : undefined
1723
- }),
1724
- getProfilePicUrl: profilePictureUrl,
1725
- getCallLink: createCallLink,
1726
- upload: async (encFilePath, opts) => {
1727
- const up = await waUploadToServer(encFilePath, { ...opts, newsletter: WABinary_1.isJidNewsletter(jid) })
1728
- mediaHandle = up.handle
1729
- return up
1730
- },
1731
- mediaCache: config.mediaCache,
1732
- options: config.options,
1733
- messageId: Utils_1.generateMessageID(userJid),
1734
- ...options,
1735
- })
1736
-
1737
- const isPin = 'pin' in content && !!content.pin
1738
- const isEdit = 'edit' in content && !!content.edit
1739
- const isDelete = 'delete' in content && !!content.delete
1740
- const isKeep = 'keep' in content && !!content.keep && content.keep?.type === 2
1741
-
1742
- if (isDelete || isKeep) {
1743
- // if the chat is a group, and I am not the author, then delete the message as an admin
1744
- if (WABinary_1.isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe || WABinary_1.isJidNewsletter(jid)) {
1745
- additionalAttributes.edit = '8'
1746
- }
1747
-
1748
- else {
1749
- additionalAttributes.edit = '7'
1750
- }
1751
- }
1752
-
1753
- else if (isEdit) {
1754
- additionalAttributes.edit = WABinary_1.isJidNewsletter(jid) ? '3' : '1'
1755
- }
1756
-
1757
- else if (isPin) {
1758
- additionalAttributes.edit = '2'
1759
- }
1760
-
1761
- if (mediaHandle) {
1762
- additionalAttributes['media_id'] = mediaHandle
1763
- }
1764
-
1765
- if ('cachedGroupMetadata' in options) {
1766
- console.warn('cachedGroupMetadata in sendMessage are deprecated, now cachedGroupMetadata is part of the socket config.')
1767
- }
1768
-
1769
- await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, additionalAttributes, statusJidList: options.statusJidList, additionalNodes: options.additionalNodes, AI: options.ai })
1770
-
1771
- if (config.emitOwnEvents) {
1772
- process.nextTick(() => {
1773
- processingMutex.mutex(() => (upsertMessage(fullMsg, 'append')))
1774
- })
1775
- }
1776
-
1777
- return fullMsg
1778
- }
1779
- }
1780
- }
1781
- }
1782
-
1783
- module.exports = {
1784
- makeMessagesSocket
1785
- }