@badzz88/baileys 8.5.4 → 8.5.6

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 (269) hide show
  1. package/README.md +2 -2
  2. package/WAProto/fix-imports.js +69 -79
  3. package/WAProto/index.d.ts +15305 -87935
  4. package/WAProto/index.js +41109 -194076
  5. package/engine-requirements.js +15 -8
  6. package/package.json +23 -19
  7. package/src/Defaults/index.js +186 -0
  8. package/src/Signal/Group/ciphertext-message.js +15 -0
  9. package/src/Signal/Group/group-session-builder.js +86 -0
  10. package/src/Signal/Group/group_cipher.js +82 -0
  11. package/src/Signal/Group/index.js +140 -0
  12. package/src/Signal/Group/keyhelper.js +77 -0
  13. package/src/Signal/Group/sender-chain-key.js +29 -0
  14. package/src/Signal/Group/sender-key-distribution-message.js +66 -0
  15. package/src/Signal/Group/sender-key-message.js +69 -0
  16. package/src/Signal/Group/sender-key-name.js +51 -0
  17. package/src/Signal/Group/sender-key-record.js +44 -0
  18. package/src/Signal/Group/sender-key-state.js +87 -0
  19. package/src/Signal/Group/sender-message-key.js +29 -0
  20. package/src/Signal/libsignal.js +455 -0
  21. package/src/Signal/lid-mapping.js +273 -0
  22. package/src/Socket/Client/index.js +31 -0
  23. package/src/Socket/Client/types.js +13 -0
  24. package/src/Socket/Client/websocket.js +61 -0
  25. package/src/Socket/aigroups.js +221 -0
  26. package/src/Socket/business.js +411 -0
  27. package/src/Socket/chats.js +1449 -0
  28. package/src/Socket/communities.js +463 -0
  29. package/src/Socket/graphql.js +523 -0
  30. package/src/Socket/groups.js +516 -0
  31. package/src/Socket/index.js +31 -0
  32. package/src/Socket/interactive-handler.js +527 -0
  33. package/src/Socket/interop.js +339 -0
  34. package/src/Socket/luxu.js +349 -0
  35. package/src/Socket/managed-account.js +98 -0
  36. package/src/Socket/messages-recv.js +2685 -0
  37. package/src/Socket/messages-send.js +2047 -0
  38. package/src/Socket/mex.js +57 -0
  39. package/src/Socket/newsletter.js +455 -0
  40. package/src/Socket/privacy.js +125 -0
  41. package/src/Socket/registration.js +236 -0
  42. package/src/Socket/socket.js +983 -0
  43. package/src/Socket/text-router.js +65 -0
  44. package/src/Socket/username.js +130 -0
  45. package/src/Store/index.js +33 -0
  46. package/src/Store/keyed-db.js +118 -0
  47. package/src/Store/make-cache-manager-store.js +84 -0
  48. package/src/Store/make-in-memory-store.js +551 -0
  49. package/src/Store/make-ordered-dictionary.js +81 -0
  50. package/src/Store/object-repository.js +26 -0
  51. package/src/Types/Auth.js +31 -0
  52. package/src/Types/Bussines.js +2 -0
  53. package/src/Types/Call.js +2 -0
  54. package/src/Types/Chat.js +4 -0
  55. package/src/Types/Contact.js +2 -0
  56. package/src/Types/Events.js +2 -0
  57. package/src/Types/GroupMetadata.js +2 -0
  58. package/src/Types/Label.js +26 -0
  59. package/src/Types/LabelAssociation.js +8 -0
  60. package/src/Types/Message.js +93 -0
  61. package/src/Types/Mex.js +112 -0
  62. package/src/Types/Newsletter.js +109 -0
  63. package/src/Types/Product.js +2 -0
  64. package/src/Types/Signal.js +2 -0
  65. package/src/Types/Socket.js +2 -0
  66. package/src/Types/State.js +62 -0
  67. package/src/Types/USync.js +2 -0
  68. package/src/Types/index.js +56 -0
  69. package/src/Utils/auth-utils.js +254 -0
  70. package/src/Utils/browser-utils.js +112 -0
  71. package/src/Utils/business.js +240 -0
  72. package/src/Utils/chat-utils.js +1230 -0
  73. package/src/Utils/command-loader.d.ts +27 -0
  74. package/src/Utils/command-loader.js +89 -0
  75. package/src/Utils/companion-reg-client-utils.js +40 -0
  76. package/src/Utils/consumer-application.js +105 -0
  77. package/src/Utils/crypto.js +118 -0
  78. package/src/Utils/curve25519-js.js +242 -0
  79. package/src/Utils/decode-wa-message.js +529 -0
  80. package/src/Utils/event-buffer.js +580 -0
  81. package/src/Utils/generics.js +483 -0
  82. package/src/Utils/group-history.js +44 -0
  83. package/src/Utils/history.js +232 -0
  84. package/src/Utils/identity-change-handler.js +52 -0
  85. package/src/Utils/index.js +58 -0
  86. package/src/Utils/jid-display-normalization.js +195 -0
  87. package/src/Utils/link-preview.js +135 -0
  88. package/src/Utils/logger.js +8 -0
  89. package/src/Utils/lt-hash.js +25 -0
  90. package/src/Utils/make-mutex.js +36 -0
  91. package/src/Utils/message-composer.js +471 -0
  92. package/src/Utils/message-retry-manager.js +217 -0
  93. package/src/Utils/messages-media.js +843 -0
  94. package/src/Utils/messages.js +2817 -0
  95. package/src/Utils/meta-ai-msmsg.js +222 -0
  96. package/src/Utils/native-bridge.js +68 -0
  97. package/src/Utils/noise-handler.js +169 -0
  98. package/src/Utils/offline-node-processor.js +34 -0
  99. package/src/Utils/pre-key-manager.js +90 -0
  100. package/src/Utils/process-message.js +950 -0
  101. package/src/Utils/reporting-utils.js +261 -0
  102. package/src/Utils/session-pool.d.ts +14 -0
  103. package/src/Utils/session-pool.js +70 -0
  104. package/src/Utils/signal.js +217 -0
  105. package/src/Utils/stanza-ack.js +30 -0
  106. package/src/Utils/sticker.d.ts +13 -0
  107. package/src/Utils/sticker.js +123 -0
  108. package/src/Utils/sync-action-utils.js +45 -0
  109. package/src/Utils/tc-token-utils.js +158 -0
  110. package/src/Utils/use-multi-file-auth-state.js +111 -0
  111. package/src/Utils/validate-connection.js +209 -0
  112. package/src/Utils/view-once-cache.d.ts +12 -0
  113. package/src/Utils/view-once-cache.js +63 -0
  114. package/src/Utils/voip-rekey.js +22 -0
  115. package/src/WABinary/constants.js +1304 -0
  116. package/src/WABinary/decode.js +342 -0
  117. package/src/WABinary/encode.js +225 -0
  118. package/src/WABinary/generic-utils.js +238 -0
  119. package/src/WABinary/index.js +34 -0
  120. package/src/WABinary/jid-utils.js +351 -0
  121. package/src/WABinary/types.js +2 -0
  122. package/src/WAM/BinaryInfo.js +13 -0
  123. package/src/WAM/constants.js +39484 -0
  124. package/src/WAM/encode.js +149 -0
  125. package/src/WAM/index.js +32 -0
  126. package/src/WAUSync/Protocols/USyncBotProfileProtocol.js +53 -0
  127. package/src/WAUSync/Protocols/USyncBusinessProtocol.js +44 -0
  128. package/src/WAUSync/Protocols/USyncContactProtocol.js +55 -0
  129. package/src/WAUSync/Protocols/USyncDeviceProtocol.js +55 -0
  130. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.js +31 -0
  131. package/src/WAUSync/Protocols/USyncFeatureProtocol.js +54 -0
  132. package/src/WAUSync/Protocols/USyncLIDProtocol.js +32 -0
  133. package/src/WAUSync/Protocols/USyncNewsletterProtocol.js +473 -0
  134. package/src/WAUSync/Protocols/USyncPictureProtocol.js +34 -0
  135. package/src/WAUSync/Protocols/USyncSidelistProtocol.js +29 -0
  136. package/src/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
  137. package/src/WAUSync/Protocols/USyncTextStatusProtocol.js +38 -0
  138. package/src/WAUSync/Protocols/USyncUsernameProtocol.js +28 -0
  139. package/src/WAUSync/Protocols/index.js +40 -0
  140. package/src/WAUSync/USyncQuery.js +126 -0
  141. package/src/WAUSync/USyncUser.js +50 -0
  142. package/src/WAUSync/index.js +32 -0
  143. package/src/antiban.js +4152 -0
  144. package/{lib → src}/index.js +51 -49
  145. package/lib/Defaults/index.js +0 -195
  146. package/lib/Signal/Group/ciphertext-message.js +0 -15
  147. package/lib/Signal/Group/group-session-builder.js +0 -92
  148. package/lib/Signal/Group/group_cipher.js +0 -89
  149. package/lib/Signal/Group/index.js +0 -136
  150. package/lib/Signal/Group/keyhelper.js +0 -73
  151. package/lib/Signal/Group/sender-chain-key.js +0 -32
  152. package/lib/Signal/Group/sender-key-distribution-message.js +0 -66
  153. package/lib/Signal/Group/sender-key-message.js +0 -69
  154. package/lib/Signal/Group/sender-key-name.js +0 -50
  155. package/lib/Signal/Group/sender-key-record.js +0 -44
  156. package/lib/Signal/Group/sender-key-state.js +0 -97
  157. package/lib/Signal/Group/sender-message-key.js +0 -30
  158. package/lib/Signal/libsignal.js +0 -470
  159. package/lib/Signal/lid-mapping.js +0 -280
  160. package/lib/Socket/Client/index.js +0 -30
  161. package/lib/Socket/Client/types.js +0 -13
  162. package/lib/Socket/Client/websocket.js +0 -62
  163. package/lib/Socket/aigroups.js +0 -240
  164. package/lib/Socket/business.js +0 -414
  165. package/lib/Socket/chats.js +0 -2165
  166. package/lib/Socket/communities.js +0 -545
  167. package/lib/Socket/graphql.js +0 -863
  168. package/lib/Socket/groups.js +0 -685
  169. package/lib/Socket/index.js +0 -41
  170. package/lib/Socket/interactive-handler.js +0 -579
  171. package/lib/Socket/interop.js +0 -430
  172. package/lib/Socket/managed-account.js +0 -214
  173. package/lib/Socket/messages-recv.js +0 -3000
  174. package/lib/Socket/messages-send.js +0 -2155
  175. package/lib/Socket/mex.js +0 -47
  176. package/lib/Socket/newsletter.js +0 -814
  177. package/lib/Socket/privacy.js +0 -261
  178. package/lib/Socket/registration.js +0 -434
  179. package/lib/Socket/socket.js +0 -1074
  180. package/lib/Socket/username.js +0 -160
  181. package/lib/Store/index.js +0 -36
  182. package/lib/Store/make-cache-manager-store.js +0 -90
  183. package/lib/Store/make-in-memory-store.js +0 -488
  184. package/lib/Store/make-ordered-dictionary.js +0 -81
  185. package/lib/Store/object-repository.js +0 -29
  186. package/lib/Types/Auth.js +0 -38
  187. package/lib/Types/Bussines.js +0 -2
  188. package/lib/Types/Call.js +0 -2
  189. package/lib/Types/Chat.js +0 -4
  190. package/lib/Types/Contact.js +0 -2
  191. package/lib/Types/Events.js +0 -2
  192. package/lib/Types/GroupMetadata.js +0 -2
  193. package/lib/Types/Label.js +0 -27
  194. package/lib/Types/LabelAssociation.js +0 -9
  195. package/lib/Types/Message.js +0 -95
  196. package/lib/Types/Newsletter.js +0 -152
  197. package/lib/Types/Product.js +0 -2
  198. package/lib/Types/Signal.js +0 -2
  199. package/lib/Types/Socket.js +0 -2
  200. package/lib/Types/State.js +0 -70
  201. package/lib/Types/USync.js +0 -2
  202. package/lib/Types/index.js +0 -55
  203. package/lib/Utils/auth-utils.js +0 -301
  204. package/lib/Utils/browser-utils.js +0 -114
  205. package/lib/Utils/business.js +0 -243
  206. package/lib/Utils/chat-utils.js +0 -1272
  207. package/lib/Utils/consumer-application.js +0 -107
  208. package/lib/Utils/crypto.js +0 -125
  209. package/lib/Utils/decode-wa-message.js +0 -793
  210. package/lib/Utils/event-buffer.js +0 -583
  211. package/lib/Utils/generics.js +0 -617
  212. package/lib/Utils/group-history.js +0 -51
  213. package/lib/Utils/history.js +0 -244
  214. package/lib/Utils/identity-change-handler.js +0 -52
  215. package/lib/Utils/index.js +0 -53
  216. package/lib/Utils/jid-display-normalization.js +0 -218
  217. package/lib/Utils/link-preview.js +0 -138
  218. package/lib/Utils/logger.js +0 -9
  219. package/lib/Utils/lt-hash.js +0 -6
  220. package/lib/Utils/make-mutex.js +0 -36
  221. package/lib/Utils/message-composer.js +0 -479
  222. package/lib/Utils/message-inspect.js +0 -393
  223. package/lib/Utils/message-retry-manager.js +0 -205
  224. package/lib/Utils/messages-media.js +0 -925
  225. package/lib/Utils/messages.js +0 -2482
  226. package/lib/Utils/meta-ai-msmsg.js +0 -122
  227. package/lib/Utils/noise-handler.js +0 -194
  228. package/lib/Utils/offline-node-processor.js +0 -37
  229. package/lib/Utils/pre-key-manager.js +0 -97
  230. package/lib/Utils/process-message.js +0 -1139
  231. package/lib/Utils/reporting-utils.js +0 -262
  232. package/lib/Utils/signal.js +0 -189
  233. package/lib/Utils/stanza-ack.js +0 -67
  234. package/lib/Utils/sync-action-utils.js +0 -51
  235. package/lib/Utils/tc-token-utils.js +0 -156
  236. package/lib/Utils/use-multi-file-auth-state.js +0 -137
  237. package/lib/Utils/validate-connection.js +0 -259
  238. package/lib/Utils/voip-rekey.js +0 -22
  239. package/lib/WABinary/constants.js +0 -1304
  240. package/lib/WABinary/decode.js +0 -377
  241. package/lib/WABinary/encode.js +0 -58
  242. package/lib/WABinary/generic-utils.js +0 -150
  243. package/lib/WABinary/index.js +0 -33
  244. package/lib/WABinary/jid-utils.js +0 -374
  245. package/lib/WABinary/types.js +0 -2
  246. package/lib/WAM/BinaryInfo.js +0 -13
  247. package/lib/WAM/constants.js +0 -39486
  248. package/lib/WAM/encode.js +0 -142
  249. package/lib/WAM/index.js +0 -31
  250. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +0 -55
  251. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +0 -100
  252. package/lib/WAUSync/Protocols/USyncContactProtocol.js +0 -60
  253. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +0 -65
  254. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +0 -27
  255. package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +0 -72
  256. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +0 -31
  257. package/lib/WAUSync/Protocols/USyncNewsletterProtocol.js +0 -865
  258. package/lib/WAUSync/Protocols/USyncPictureProtocol.js +0 -32
  259. package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +0 -29
  260. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +0 -44
  261. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +0 -38
  262. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +0 -28
  263. package/lib/WAUSync/Protocols/index.js +0 -40
  264. package/lib/WAUSync/USyncBackoff.js +0 -26
  265. package/lib/WAUSync/USyncQuery.js +0 -204
  266. package/lib/WAUSync/USyncUser.js +0 -58
  267. package/lib/WAUSync/index.js +0 -32
  268. package/lib/antiban.js +0 -4391
  269. /package/{lib → src}/Defaults/phonenumber-mcc.json +0 -0
@@ -1,2155 +0,0 @@
1
- 'use strict'
2
- var __importDefault =
3
- (this && this.__importDefault) ||
4
- function (mod) {
5
- return mod && mod.__esModule ? mod : { default: mod }
6
- }
7
- Object.defineProperty(exports, '__esModule', { value: true })
8
- exports.makeMessagesSocket = void 0
9
- const node_cache_1 = __importDefault(require('@cacheable/node-cache'))
10
- const boom_1 = require('@hapi/boom')
11
- const index_js_1 = require('../../WAProto/index.js')
12
- const Defaults_1 = require('../Defaults')
13
- const Utils_1 = require('../Utils')
14
- const link_preview_1 = require('../Utils/link-preview')
15
- const make_mutex_1 = require('../Utils/make-mutex')
16
- const reporting_utils_1 = require('../Utils/reporting-utils')
17
- const tc_token_utils_1 = require('../Utils/tc-token-utils')
18
- const jid_display_normalization_1 = require('../Utils/jid-display-normalization')
19
- const WABinary_1 = require('../WABinary')
20
- const WAUSync_1 = require('../WAUSync')
21
- const message_composer_1 = require('../Utils/message-composer.js')
22
- const interactive_handler_1 = require('./interactive-handler.js')
23
- const username_1 = require('./username')
24
- const { setBotMessageSecret } = require('../Utils/decode-wa-message')
25
- const makeMessagesSocket = config => {
26
- const {
27
- logger,
28
- linkPreviewImageThumbnailWidth,
29
- generateHighQualityLinkPreview,
30
- options: httpRequestOptions,
31
- patchMessageBeforeSending,
32
- cachedGroupMetadata,
33
- enableRecentMessageCache,
34
- maxMsgRetryCount
35
- } = config
36
- const sock = (0, username_1.makeUsernameSocket)(config)
37
- const {
38
- ev,
39
- authState,
40
- messageMutex,
41
- signalRepository,
42
- upsertMessage,
43
- query,
44
- fetchPrivacySettings,
45
- sendNode,
46
- groupMetadata,
47
- groupToggleEphemeral,
48
- trustInteropContact
49
- } = sock
50
- const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping)
51
-
52
-
53
- const resolveStatusAudience = async (groupJids, includeMe = false) => {
54
- const myJid = authState.creds.me?.id
55
- const seen = new Set()
56
- const allUsers = []
57
- for (const gjid of groupJids) {
58
- let meta
59
- try {
60
- meta = cachedGroupMetadata ? await cachedGroupMetadata(gjid) : null
61
- if (!meta) meta = await groupMetadata(gjid)
62
- } catch {
63
- continue
64
- }
65
- for (const p of meta?.participants || []) {
66
- const id = p.id
67
- if (!id || seen.has(id)) continue
68
- if (!includeMe && id === myJid) continue
69
- seen.add(id)
70
- allUsers.push(id)
71
- }
72
- }
73
- return { allUsers }
74
- }
75
-
76
- const inFlightTcTokenIssuance = new Set()
77
- const userDevicesCache =
78
- config.userDevicesCache ||
79
- new node_cache_1.default({
80
- stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES,
81
- useClones: false
82
- })
83
- const peerSessionsCache = new node_cache_1.default({
84
- stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES,
85
- useClones: false
86
- })
87
-
88
- const messageRetryManager = enableRecentMessageCache
89
- ? new Utils_1.MessageRetryManager(logger, maxMsgRetryCount)
90
- : null
91
-
92
- const encryptionMutex = (0, make_mutex_1.makeKeyedMutex)()
93
- let mediaConn
94
- const refreshMediaConn = async (forceGet = false) => {
95
- const media = await mediaConn
96
- if (!media || forceGet || new Date().getTime() - media.fetchDate.getTime() > media.ttl * 1000) {
97
- mediaConn = (async () => {
98
- const result = await query({
99
- tag: 'iq',
100
- attrs: {
101
- type: 'set',
102
- xmlns: 'w:m',
103
- to: WABinary_1.S_WHATSAPP_NET
104
- },
105
- content: [{ tag: 'media_conn', attrs: {} }]
106
- })
107
- const mediaConnNode = (0, WABinary_1.getBinaryNodeChild)(result, 'media_conn')
108
-
109
- const node = {
110
- hosts: (0, WABinary_1.getBinaryNodeChildren)(mediaConnNode, 'host').map(({ attrs }) => ({
111
- hostname: attrs.hostname,
112
- maxContentLengthBytes: +attrs.maxContentLengthBytes
113
- })),
114
- auth: mediaConnNode.attrs.auth,
115
- ttl: +mediaConnNode.attrs.ttl,
116
- fetchDate: new Date()
117
- }
118
- logger.debug('fetched media conn')
119
- return node
120
- })()
121
- }
122
- return mediaConn
123
- }
124
-
125
- const sendReceipt = async (jid, participant, messageIds, type, sts) => {
126
- if (!messageIds || messageIds.length === 0) {
127
- throw new boom_1.Boom('missing ids in receipt')
128
- }
129
- const isInterop = (0, WABinary_1.isInteropUser)(jid)
130
- const node = {
131
- tag: 'receipt',
132
- attrs: {
133
- id: messageIds[0]
134
- }
135
- }
136
- const isReadReceipt = type === 'read' || type === 'read-self'
137
- if (isReadReceipt) {
138
- node.attrs.t = (0, Utils_1.unixTimestampSeconds)().toString()
139
- }
140
- if (type === 'sender' && ((0, WABinary_1.isPnUser)(jid) || (0, WABinary_1.isLidUser)(jid))) {
141
- node.attrs.recipient = jid
142
- node.attrs.to = participant
143
- } else if (isInterop && !type) {
144
-
145
- const { user } = (0, WABinary_1.jidDecode)(jid)
146
- node.attrs.to = `${user}:0@interop`
147
- } else {
148
- node.attrs.to = jid
149
- if (participant) {
150
- node.attrs.participant = participant
151
- }
152
- }
153
- if (type) {
154
- node.attrs.type = type
155
- }
156
-
157
- if (isInterop && sts) {
158
- node.attrs.sts = sts
159
- }
160
- const remainingMessageIds = messageIds.slice(1)
161
- if (remainingMessageIds.length) {
162
- node.content = [
163
- {
164
- tag: 'list',
165
- attrs: {},
166
- content: remainingMessageIds.map(id => ({
167
- tag: 'item',
168
- attrs: { id }
169
- }))
170
- }
171
- ]
172
- }
173
- logger.debug({ attrs: node.attrs, messageIds }, 'sending receipt for messages')
174
- await sendNode(node)
175
- }
176
-
177
- const sendReceipts = async (keys, type) => {
178
- const recps = (0, Utils_1.aggregateMessageKeysNotFromMe)(keys)
179
- for (const { jid, participant, messageIds, sts } of recps) {
180
- await sendReceipt(jid, participant, messageIds, type, sts)
181
- }
182
- }
183
-
184
- const readMessages = async keys => {
185
- const privacySettings = await fetchPrivacySettings()
186
-
187
- const readType = privacySettings.readreceipts === 'all' ? 'read' : 'read-self'
188
- await sendReceipts(keys, readType)
189
- }
190
-
191
- const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
192
- const deviceResults = []
193
- if (!useCache) {
194
- logger.debug('not using cache for devices')
195
- }
196
- const toFetch = []
197
- const jidsWithUser = jids
198
- .map(jid => {
199
- const decoded = (0, WABinary_1.jidDecode)(jid)
200
- const user = decoded?.user
201
- const device = decoded?.device
202
- const isExplicitDevice = typeof device === 'number' && device >= 0
203
- if (isExplicitDevice && user) {
204
- deviceResults.push({
205
- user,
206
- device,
207
- jid
208
- })
209
- return null
210
- }
211
- jid = (0, WABinary_1.jidNormalizedUser)(jid)
212
- return { jid, user }
213
- })
214
- .filter(jid => jid !== null)
215
- let mgetDevices
216
- if (useCache && userDevicesCache.mget) {
217
- const usersToFetch = jidsWithUser.map(j => j?.user).filter(Boolean)
218
- mgetDevices = await userDevicesCache.mget(usersToFetch)
219
- }
220
- for (const { jid, user } of jidsWithUser) {
221
- if (useCache) {
222
- const devices = mgetDevices?.[user] || (userDevicesCache.mget ? undefined : await userDevicesCache.get(user))
223
- if (devices) {
224
- const devicesWithJid = devices.map(d => ({
225
- ...d,
226
- jid: (0, WABinary_1.jidEncode)(d.user, d.server, d.device)
227
- }))
228
- deviceResults.push(...devicesWithJid)
229
- logger.trace({ user }, 'using cache for devices')
230
- } else {
231
- toFetch.push(jid)
232
- }
233
- } else {
234
- toFetch.push(jid)
235
- }
236
- }
237
- if (!toFetch.length) {
238
- return deviceResults
239
- }
240
- const requestedLidUsers = new Set()
241
- for (const jid of toFetch) {
242
- if ((0, WABinary_1.isLidUser)(jid) || (0, WABinary_1.isHostedLidUser)(jid)) {
243
- const user = (0, WABinary_1.jidDecode)(jid)?.user
244
- if (user) requestedLidUsers.add(user)
245
- }
246
- }
247
- const query = new WAUSync_1.USyncQuery().withContext('message').withDeviceProtocol().withLIDProtocol()
248
-
249
-
250
- const pnJidsToFetch = toFetch.filter(jid => (0, WABinary_1.isPnUser)(jid) || (0, WABinary_1.isHostedPnUser)(jid))
251
- const cachedLidPairs = pnJidsToFetch.length
252
- ? (await signalRepository.lidMapping.getLIDsForPNs(pnJidsToFetch)) || []
253
- : []
254
- const cachedLidByPn = new Map(cachedLidPairs.map(({ pn, lid }) => [pn, lid]))
255
- for (const jid of toFetch) {
256
- const syncUser = new WAUSync_1.USyncUser().withId(jid)
257
- const cachedLid = cachedLidByPn.get(jid)
258
- if (cachedLid) syncUser.withLid(cachedLid)
259
- query.withUser(syncUser)
260
- }
261
- const result = await sock.executeUSyncQuery(query)
262
- if (result) {
263
- const lidResults = result.list.filter(a => !!a.lid)
264
- if (lidResults.length > 0) {
265
- logger.trace('Storing LID maps from device call')
266
- await signalRepository.lidMapping.storeLIDPNMappings(lidResults.map(a => ({ lid: a.lid, pn: a.id })))
267
-
268
- try {
269
- const lids = lidResults.map(a => a.lid)
270
- if (lids.length) {
271
- await assertSessions(lids, true)
272
- }
273
- } catch (e) {
274
- logger.warn({ e, count: lidResults.length }, 'failed to assert sessions for newly mapped LIDs')
275
- }
276
- }
277
- const extracted = (0, Utils_1.extractDeviceJids)(
278
- result?.list,
279
- authState.creds.me.id,
280
- authState.creds.me.lid,
281
- ignoreZeroDevices
282
- )
283
- const deviceMap = {}
284
- for (const item of extracted) {
285
- deviceMap[item.user] = deviceMap[item.user] || []
286
- deviceMap[item.user]?.push(item)
287
- }
288
-
289
- for (const [user, userDevices] of Object.entries(deviceMap)) {
290
- const isLidUser = requestedLidUsers.has(user)
291
-
292
- for (const item of userDevices) {
293
- const finalJid = isLidUser
294
- ? (0, WABinary_1.jidEncode)(user, item.server, item.device)
295
- : (0, WABinary_1.jidEncode)(item.user, item.server, item.device)
296
- deviceResults.push({
297
- ...item,
298
- jid: finalJid
299
- })
300
- logger.debug(
301
- {
302
- user: item.user,
303
- device: item.device,
304
- finalJid,
305
- usedLid: isLidUser
306
- },
307
- 'Processed device with LID priority'
308
- )
309
- }
310
- }
311
- if (userDevicesCache.mset) {
312
-
313
- await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({ key, value })))
314
- } else {
315
- for (const key in deviceMap) {
316
- if (deviceMap[key]) await userDevicesCache.set(key, deviceMap[key])
317
- }
318
- }
319
- const userDeviceUpdates = {}
320
- for (const [userId, devices] of Object.entries(deviceMap)) {
321
- if (devices && devices.length > 0) {
322
- userDeviceUpdates[userId] = devices.map(d => d.device?.toString() || '0')
323
- }
324
- }
325
- if (Object.keys(userDeviceUpdates).length > 0) {
326
- try {
327
- await authState.keys.set({ 'device-list': userDeviceUpdates })
328
- logger.debug(
329
- { userCount: Object.keys(userDeviceUpdates).length },
330
- 'stored user device lists for bulk migration'
331
- )
332
- } catch (error) {
333
- logger.warn({ error }, 'failed to store user device lists')
334
- }
335
- }
336
- }
337
- return deviceResults
338
- }
339
-
340
- const updateMemberLabel = (jid, memberLabel) => {
341
- return relayMessage(
342
- jid,
343
- {
344
- protocolMessage: {
345
- type: index_js_1.proto.Message.ProtocolMessage.Type.GROUP_MEMBER_LABEL_CHANGE,
346
- memberLabel: {
347
- label: memberLabel?.slice(0, 30),
348
- labelTimestamp: (0, Utils_1.unixTimestampSeconds)()
349
- }
350
- }
351
- },
352
- {
353
- additionalNodes: [
354
- {
355
- tag: 'meta',
356
- attrs: {
357
- tag_reason: 'user_update',
358
- appdata: 'member_tag'
359
- },
360
- content: undefined
361
- }
362
- ]
363
- }
364
- )
365
- }
366
- const assertSessions = async (jids, force) => {
367
- let didFetchNewSession = false
368
- const uniqueJids = [...new Set(jids)]
369
- const jidsRequiringFetch = []
370
- logger.debug({ jids }, 'assertSessions call with jids')
371
-
372
- for (const jid of uniqueJids) {
373
- const signalId = signalRepository.jidToSignalProtocolAddress(jid)
374
- const cachedSession = peerSessionsCache.get(signalId)
375
- if (cachedSession !== undefined) {
376
- if (cachedSession && !force) {
377
- continue
378
- }
379
- } else {
380
- const sessionValidation = await signalRepository.validateSession(jid)
381
- const hasSession = sessionValidation.exists
382
- peerSessionsCache.set(signalId, hasSession)
383
- if (hasSession && !force) {
384
- continue
385
- }
386
- }
387
- jidsRequiringFetch.push(jid)
388
- }
389
- if (jidsRequiringFetch.length) {
390
-
391
- const wireJids = [
392
- ...jidsRequiringFetch.filter(jid => !!(0, WABinary_1.isLidUser)(jid) || !!(0, WABinary_1.isHostedLidUser)(jid)),
393
- ...(
394
- (await signalRepository.lidMapping.getLIDsForPNs(
395
- jidsRequiringFetch.filter(jid => !!(0, WABinary_1.isPnUser)(jid) || !!(0, WABinary_1.isHostedPnUser)(jid))
396
- )) || []
397
- ).map(a => a.lid),
398
- ...jidsRequiringFetch.filter(jid => (0, WABinary_1.isInteropUser)(jid))
399
- ]
400
- const interopFetches = wireJids.filter(j => (0, WABinary_1.isInteropUser)(j))
401
- if (interopFetches.length) {
402
- logger.info({ interopFetches }, '[interop] fetching pre-key bundle for interop device(s)')
403
- }
404
- logger.debug({ jidsRequiringFetch, wireJids }, 'fetching sessions')
405
- if (!wireJids.length) {
406
- logger.debug({ jidsRequiringFetch }, 'assertSessions: no wire JIDs to fetch (all unsupported domain)')
407
- return didFetchNewSession
408
- }
409
- const result = await query({
410
- tag: 'iq',
411
- attrs: {
412
- xmlns: 'encrypt',
413
- type: 'get',
414
- to: WABinary_1.S_WHATSAPP_NET
415
- },
416
- content: [
417
- {
418
- tag: 'key',
419
- attrs: {},
420
- content: wireJids.map(jid => {
421
- const attrs = { jid }
422
- if (force) attrs.reason = 'identity'
423
- return { tag: 'user', attrs }
424
- })
425
- }
426
- ]
427
- })
428
- if (interopFetches.length) {
429
- logger.debug({ interopFetches }, '[interop] pre-key IQ response received')
430
- }
431
- await (0, Utils_1.parseAndInjectE2ESessions)(result, signalRepository)
432
- didFetchNewSession = true
433
-
434
- for (const wireJid of wireJids) {
435
- const signalId = signalRepository.jidToSignalProtocolAddress(wireJid)
436
- peerSessionsCache.set(signalId, true)
437
- }
438
- }
439
- return didFetchNewSession
440
- }
441
- const sendPeerDataOperationMessage = async pdoMessage => {
442
-
443
- if (!authState.creds.me?.id) {
444
- throw new boom_1.Boom('Not authenticated')
445
- }
446
- const protocolMessage = {
447
- protocolMessage: {
448
- peerDataOperationRequestMessage: pdoMessage,
449
- type: index_js_1.proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
450
- }
451
- }
452
- const meJid = (0, WABinary_1.jidNormalizedUser)(authState.creds.me.id)
453
- const msgId = await relayMessage(meJid, protocolMessage, {
454
- additionalAttributes: {
455
- category: 'peer',
456
- push_priority: 'high_force'
457
- },
458
- additionalNodes: [
459
- {
460
- tag: 'meta',
461
- attrs: { appdata: 'default' }
462
- }
463
- ]
464
- })
465
- return msgId
466
- }
467
- const createParticipantNodes = async (recipientJids, message, extraAttrs, dsmMessage) => {
468
- if (!recipientJids.length) {
469
- return { nodes: [], shouldIncludeDeviceIdentity: false }
470
- }
471
- const patched = await patchMessageBeforeSending(message, recipientJids)
472
- const patchedMessages = Array.isArray(patched)
473
- ? patched
474
- : recipientJids.map(jid => ({ recipientJid: jid, message: patched }))
475
- let shouldIncludeDeviceIdentity = false
476
- const meId = authState.creds.me.id
477
- const meLid = authState.creds.me?.lid
478
- const meLidUser = meLid ? (0, WABinary_1.jidDecode)(meLid)?.user : null
479
- const encryptionPromises = patchedMessages.map(async ({ recipientJid: jid, message: patchedMessage }) => {
480
- try {
481
- if (!jid) return null
482
- let msgToEncrypt = patchedMessage
483
- if (dsmMessage) {
484
- const { user: targetUser } = (0, WABinary_1.jidDecode)(jid)
485
- const { user: ownPnUser } = (0, WABinary_1.jidDecode)(meId)
486
- const ownLidUser = meLidUser
487
- const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser)
488
- const isExactSenderDevice = jid === meId || (meLid && jid === meLid)
489
- if (isOwnUser && !isExactSenderDevice) {
490
- msgToEncrypt = dsmMessage
491
- logger.debug({ jid, targetUser }, 'Using DSM for own device')
492
- }
493
- }
494
- const bytes = (0, Utils_1.encodeWAMessage)(msgToEncrypt)
495
- const mutexKey = jid
496
- const node = await encryptionMutex.mutex(mutexKey, async () => {
497
- const { type, ciphertext } = await signalRepository.encryptMessage({ jid, data: bytes })
498
- if (type === 'pkmsg') {
499
- shouldIncludeDeviceIdentity = true
500
- }
501
- return {
502
- tag: 'to',
503
- attrs: { jid },
504
- content: [
505
- {
506
- tag: 'enc',
507
- attrs: { v: '2', type, ...(extraAttrs || {}) },
508
- content: ciphertext
509
- }
510
- ]
511
- }
512
- })
513
- return node
514
- } catch (err) {
515
- logger.error({ jid, err }, 'Failed to encrypt for recipient')
516
- return null
517
- }
518
- })
519
- const nodes = (await Promise.all(encryptionPromises)).filter(node => node !== null)
520
- if (recipientJids.length > 0 && nodes.length === 0) {
521
- throw new boom_1.Boom('All encryptions failed', { statusCode: 500 })
522
- }
523
- return { nodes, shouldIncludeDeviceIdentity }
524
- }
525
- const relayMessage = async (
526
- jid,
527
- message,
528
- {
529
- messageId: msgId,
530
- participant,
531
- additionalAttributes,
532
- additionalNodes,
533
- useUserDevicesCache,
534
- useCachedGroupMetadata,
535
- statusJidList,
536
- statusPrivacy,
537
- AI = false
538
- }
539
- ) => {
540
- const meId = authState.creds.me.id
541
- const meLid = authState.creds.me?.lid
542
- const isRetryResend = Boolean(participant?.jid)
543
- let shouldIncludeDeviceIdentity = isRetryResend
544
- const statusJid = 'status@broadcast'
545
- const { user, server } = (0, WABinary_1.jidDecode)(jid)
546
- const isGroup = server === 'g.us'
547
- const isStatus = jid === statusJid
548
- const isLid = server === 'lid'
549
- const isNewsletter = server === 'newsletter'
550
- const isInterop = (0, WABinary_1.isInteropUser)(jid)
551
- const isGroupOrStatus = isGroup || isStatus
552
- const finalJid = jid
553
- msgId = msgId || (0, Utils_1.generateMessageIDV2)(meId)
554
- useUserDevicesCache = useUserDevicesCache !== false
555
- useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus
556
- const participants = []
557
- const destinationJid = !isStatus ? finalJid : statusJid
558
- const binaryNodeContent = []
559
- const devices = []
560
- let reportingMessage
561
- const meMsg = {
562
- deviceSentMessage: {
563
- destinationJid,
564
- message
565
- },
566
- messageContextInfo: message.messageContextInfo
567
- }
568
- const extraAttrs = {}
569
-
570
- const regexGroupOld = /^(\d{1,15})-(\d+)@g\.us$/
571
-
572
- const messages = Utils_1.normalizeMessageContent(message)
573
-
574
- const buttonType = getButtonType(messages)
575
- const pollMessage = messages.pollCreationMessage || messages.pollCreationMessageV2 || messages.pollCreationMessageV3
576
-
577
- if (participant) {
578
- if (!isGroup && !isStatus) {
579
- additionalAttributes = { ...additionalAttributes, device_fanout: 'false' }
580
- }
581
- const { user, device } = (0, WABinary_1.jidDecode)(participant.jid)
582
- devices.push({
583
- user,
584
- device,
585
- jid: participant.jid
586
- })
587
- }
588
- await authState.keys.transaction(async () => {
589
- const mediaType = getMediaType(message)
590
- if (mediaType) {
591
- extraAttrs['mediatype'] = mediaType
592
- }
593
- if (isNewsletter) {
594
- const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message
595
- const bytes = (0, Utils_1.encodeNewsletterMessage)(patched)
596
- binaryNodeContent.push({
597
- tag: 'plaintext',
598
- attrs: {},
599
- content: bytes
600
- })
601
- const stanza = {
602
- tag: 'message',
603
- attrs: {
604
- to: jid,
605
- id: msgId,
606
- type: getTypeMessage(message),
607
- ...(additionalAttributes || {})
608
- },
609
- content: binaryNodeContent
610
- }
611
- logger.debug({ msgId }, `sending newsletter message to ${jid}`)
612
- await sendNode(stanza)
613
- return
614
- }
615
- if (
616
- (0, Utils_1.normalizeMessageContent)(message)?.pinInChatMessage ||
617
- (0, Utils_1.normalizeMessageContent)(message)?.reactionMessage
618
- ) {
619
- extraAttrs['decrypt-fail'] = 'hide'
620
- }
621
- if (isGroupOrStatus && !isRetryResend) {
622
- const [groupData, senderKeyMap] = await Promise.all([
623
- (async () => {
624
- let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined
625
- if (groupData && Array.isArray(groupData?.participants)) {
626
- logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata')
627
- } else if (!isStatus) {
628
- groupData = await groupMetadata(jid)
629
- }
630
- return groupData
631
- })(),
632
- (async () => {
633
- if (!participant && !isStatus) {
634
-
635
-
636
- const result = await authState.keys.get('sender-key-memory', [jid])
637
- return result[jid] || {}
638
- }
639
- return {}
640
- })()
641
- ])
642
- const participantsList = groupData ? groupData.participants.map(p => p.id) : []
643
- if (groupData?.ephemeralDuration && groupData.ephemeralDuration > 0) {
644
- additionalAttributes = {
645
- ...additionalAttributes,
646
- expiration: groupData.ephemeralDuration.toString()
647
- }
648
- }
649
- if (isStatus && statusJidList) {
650
- participantsList.push(...statusJidList)
651
- }
652
- const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false)
653
- devices.push(...additionalDevices)
654
- if (isGroup) {
655
- additionalAttributes = {
656
- ...additionalAttributes,
657
- addressing_mode: groupData?.addressingMode || 'lid'
658
- }
659
- }
660
- if (message?.groupStatusMessageV2 && !message?.messageContextInfo?.messageSecret) {
661
- const { randomBytes } = require('crypto')
662
- message = {
663
- ...message,
664
- messageContextInfo: {
665
- ...(message.messageContextInfo || {}),
666
- messageSecret: randomBytes(32)
667
- },
668
- groupStatusMessageV2: {
669
- ...message.groupStatusMessageV2,
670
- message: {
671
- ...(message.groupStatusMessageV2.message || {}),
672
- messageContextInfo: {
673
- ...(message.groupStatusMessageV2.message?.messageContextInfo || {}),
674
- messageSecret: message.messageContextInfo?.messageSecret || randomBytes(32)
675
- }
676
- }
677
- }
678
- }
679
- }
680
- if (message.listMessage) {
681
- const list = message.listMessage
682
- const interactiveMessage = {
683
- nativeFlowMessage: {
684
- buttons: [
685
- {
686
- name: 'single_select',
687
- buttonParamsJson: JSON.stringify({
688
- title: list.buttonText || 'Select',
689
- sections: (list.sections || []).map(section => ({
690
- title: section.title || '',
691
- highlight_label: '',
692
- rows: (section.rows || []).map(row => ({
693
- header: '',
694
- title: row.title || '',
695
- description: row.description || '',
696
- id: row.rowId || row.id || ''
697
- }))
698
- }))
699
- })
700
- }
701
- ],
702
- messageParamsJson: '',
703
- messageVersion: 1
704
- },
705
- body: { text: list.description || '' },
706
- footer: list.footerText ? { text: list.footerText } : undefined,
707
- header: list.title ? { title: list.title, hasMediaAttachment: false, subtitle: '' } : undefined,
708
- contextInfo: list.contextInfo
709
- }
710
- message = { interactiveMessage }
711
- } else if (message.buttonsMessage) {
712
- const bMsg = message.buttonsMessage
713
- const buttons = (bMsg.buttons || []).map(btn => ({
714
- name: 'quick_reply',
715
- buttonParamsJson: JSON.stringify({
716
- display_text: btn.buttonText?.displayText || btn.buttonText || '',
717
- id: btn.buttonId || btn.buttonText?.displayText || ''
718
- })
719
- }))
720
- const interactiveMessage = {
721
- nativeFlowMessage: {
722
- buttons,
723
- messageParamsJson: '',
724
- messageVersion: 1
725
- },
726
- body: { text: bMsg.contentText || bMsg.text || '' },
727
- footer: bMsg.footerText ? { text: bMsg.footerText } : undefined,
728
- header: bMsg.text
729
- ? { title: bMsg.text, hasMediaAttachment: false, subtitle: '' }
730
- : bMsg.imageMessage || bMsg.videoMessage || bMsg.documentMessage
731
- ? {
732
- hasMediaAttachment: true,
733
- ...(bMsg.imageMessage ? { imageMessage: bMsg.imageMessage } : {}),
734
- ...(bMsg.videoMessage ? { videoMessage: bMsg.videoMessage } : {})
735
- }
736
- : undefined,
737
- contextInfo: bMsg.contextInfo
738
- }
739
- message = { interactiveMessage }
740
- } else if (message.templateMessage) {
741
- const tmpl = message.templateMessage.hydratedTemplate || message.templateMessage.fourRowTemplate
742
- if (tmpl) {
743
- const hydratedButtons = tmpl.hydratedButtons || []
744
- const buttons = hydratedButtons
745
- .map(hBtn => {
746
- if (hBtn.quickReplyButton) {
747
- return {
748
- name: 'quick_reply',
749
- buttonParamsJson: JSON.stringify({
750
- display_text: hBtn.quickReplyButton.displayText || '',
751
- id: hBtn.quickReplyButton.id || hBtn.quickReplyButton.displayText || ''
752
- })
753
- }
754
- } else if (hBtn.urlButton) {
755
- return {
756
- name: 'cta_url',
757
- buttonParamsJson: JSON.stringify({
758
- display_text: hBtn.urlButton.displayText || '',
759
- url: hBtn.urlButton.url || '',
760
- merchant_url: hBtn.urlButton.url || ''
761
- })
762
- }
763
- } else if (hBtn.callButton) {
764
- return {
765
- name: 'cta_call',
766
- buttonParamsJson: JSON.stringify({
767
- display_text: hBtn.callButton.displayText || '',
768
- phone_number: hBtn.callButton.phoneNumber || ''
769
- })
770
- }
771
- }
772
- return null
773
- })
774
- .filter(Boolean)
775
- const interactiveMessage = {
776
- nativeFlowMessage: {
777
- buttons,
778
- messageParamsJson: '',
779
- messageVersion: 1
780
- },
781
- body: { text: tmpl.hydratedContentText || tmpl.contentText || '' },
782
- footer: tmpl.hydratedFooterText ? { text: tmpl.hydratedFooterText } : undefined,
783
- header: tmpl.hydratedTitleText
784
- ? { title: tmpl.hydratedTitleText, hasMediaAttachment: false, subtitle: '' }
785
- : tmpl.imageMessage || tmpl.videoMessage || tmpl.documentMessage
786
- ? {
787
- hasMediaAttachment: true,
788
- ...(tmpl.imageMessage ? { imageMessage: tmpl.imageMessage } : {}),
789
- ...(tmpl.videoMessage ? { videoMessage: tmpl.videoMessage } : {})
790
- }
791
- : undefined,
792
- contextInfo: tmpl.contextInfo
793
- }
794
- message = { interactiveMessage }
795
- }
796
- }
797
- const patched = await patchMessageBeforeSending(message)
798
- if (Array.isArray(patched)) {
799
- throw new boom_1.Boom('Per-jid patching is not supported in groups')
800
- }
801
- const bytes = (0, Utils_1.encodeWAMessage)(patched)
802
- reportingMessage = patched
803
- const groupAddressingMode = additionalAttributes?.['addressing_mode'] || groupData?.addressingMode || 'lid'
804
- const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId
805
- const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
806
- group: destinationJid,
807
- data: bytes,
808
- meId: groupSenderIdentity
809
- })
810
- const senderKeyRecipients = []
811
- for (const device of devices) {
812
- const deviceJid = device.jid
813
- const hasKey = !!senderKeyMap[deviceJid]
814
- if (
815
- (!hasKey || !!participant) &&
816
- !(0, WABinary_1.isHostedLidUser)(deviceJid) &&
817
- !(0, WABinary_1.isHostedPnUser)(deviceJid) &&
818
- device.device !== 99
819
- ) {
820
-
821
-
822
- senderKeyRecipients.push(deviceJid)
823
- senderKeyMap[deviceJid] = true
824
- }
825
- }
826
- if (senderKeyRecipients.length) {
827
- logger.debug({ senderKeyJids: senderKeyRecipients }, 'sending new sender key')
828
- const senderKeyMsg = {
829
- senderKeyDistributionMessage: {
830
- axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
831
- groupId: destinationJid
832
- }
833
- }
834
- const senderKeySessionTargets = senderKeyRecipients
835
- await assertSessions(senderKeySessionTargets)
836
- const result = await createParticipantNodes(senderKeyRecipients, senderKeyMsg, extraAttrs)
837
- shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity
838
- participants.push(...result.nodes)
839
- }
840
- binaryNodeContent.push({
841
- tag: 'enc',
842
- attrs: { v: '2', type: 'skmsg', ...extraAttrs },
843
- content: ciphertext
844
- })
845
- await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } })
846
- } else {
847
-
848
-
849
- let ownId = meId
850
- if (isLid && meLid) {
851
- ownId = meLid
852
- logger.debug({ to: jid, ownId }, 'Using LID identity for @lid conversation')
853
- } else {
854
- logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation')
855
- }
856
- const { user: ownUser } = (0, WABinary_1.jidDecode)(ownId)
857
- if (!participant) {
858
- const patchedForReporting = await patchMessageBeforeSending(message, [jid])
859
- reportingMessage = Array.isArray(patchedForReporting)
860
- ? patchedForReporting.find(item => item.recipientJid === jid) || patchedForReporting[0]
861
- : patchedForReporting
862
- }
863
- if (!isRetryResend) {
864
- const targetUserServer = isLid ? 'lid' : isInterop ? 'interop' : 's.whatsapp.net'
865
- devices.push({
866
- user,
867
- device: 0,
868
- jid: (0, WABinary_1.jidEncode)(user, targetUserServer, 0)
869
- })
870
-
871
- if (user !== ownUser && !isInterop) {
872
- const ownUserServer = isLid ? 'lid' : 's.whatsapp.net'
873
- const ownUserForAddressing =
874
- isLid && meLid ? (0, WABinary_1.jidDecode)(meLid).user : (0, WABinary_1.jidDecode)(meId).user
875
- devices.push({
876
- user: ownUserForAddressing,
877
- device: 0,
878
- jid: (0, WABinary_1.jidEncode)(ownUserForAddressing, ownUserServer, 0)
879
- })
880
- }
881
- if (additionalAttributes?.['category'] !== 'peer' && !isInterop) {
882
-
883
- devices.length = 0
884
-
885
- const senderIdentity =
886
- isLid && meLid
887
- ? (0, WABinary_1.jidEncode)((0, WABinary_1.jidDecode)(meLid)?.user, 'lid', undefined)
888
- : (0, WABinary_1.jidEncode)((0, WABinary_1.jidDecode)(meId)?.user, 's.whatsapp.net', undefined)
889
-
890
- const sessionDevices = await getUSyncDevices([senderIdentity, jid], true, false)
891
- devices.push(...sessionDevices)
892
- logger.debug(
893
- {
894
- deviceCount: devices.length,
895
- devices: devices.map(d => `${d.user}:${d.device}@${(0, WABinary_1.jidDecode)(d.jid)?.server}`)
896
- },
897
- 'Device enumeration complete with unified addressing'
898
- )
899
- }
900
- }
901
- const allRecipients = []
902
- const meRecipients = []
903
- const otherRecipients = []
904
- const { user: mePnUser } = (0, WABinary_1.jidDecode)(meId)
905
- const { user: meLidUser } = meLid ? (0, WABinary_1.jidDecode)(meLid) : { user: null }
906
- for (const { user, jid } of devices) {
907
- const isExactSenderDevice = jid === meId || (meLid && jid === meLid)
908
- if (isExactSenderDevice) {
909
- logger.debug({ jid, meId, meLid }, 'Skipping exact sender device (whatsmeow pattern)')
910
- continue
911
- }
912
-
913
- const isMe = user === mePnUser || user === meLidUser
914
- if (isMe) {
915
- meRecipients.push(jid)
916
- } else {
917
- otherRecipients.push(jid)
918
- }
919
- allRecipients.push(jid)
920
- }
921
- await assertSessions(allRecipients)
922
- const [
923
- { nodes: meNodes, shouldIncludeDeviceIdentity: s1 },
924
- { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }
925
- ] = await Promise.all([
926
-
927
- createParticipantNodes(meRecipients, meMsg || message, extraAttrs),
928
- createParticipantNodes(otherRecipients, message, extraAttrs, meMsg)
929
- ])
930
- participants.push(...meNodes)
931
- participants.push(...otherNodes)
932
- if (meRecipients.length > 0 || otherRecipients.length > 0) {
933
- extraAttrs['phash'] = (0, Utils_1.generateParticipantHashV2)([...meRecipients, ...otherRecipients])
934
- }
935
- shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2
936
- }
937
- if (isRetryResend) {
938
- const isParticipantLid = (0, WABinary_1.isLidUser)(participant.jid)
939
- const isMe = (0, WABinary_1.areJidsSameUser)(participant.jid, isParticipantLid ? meLid : meId)
940
- const encodedMessageToSend = isMe
941
- ? (0, Utils_1.encodeWAMessage)({
942
- deviceSentMessage: {
943
- destinationJid,
944
- message
945
- }
946
- })
947
- : (0, Utils_1.encodeWAMessage)(message)
948
- const { type, ciphertext: encryptedContent } = await signalRepository.encryptMessage({
949
- data: encodedMessageToSend,
950
- jid: participant.jid
951
- })
952
- binaryNodeContent.push({
953
- tag: 'enc',
954
- attrs: {
955
- v: '2',
956
- type,
957
- count: (participant.count ?? 0).toString()
958
- },
959
- content: encryptedContent
960
- })
961
- }
962
- if (participants.length) {
963
- if (additionalAttributes?.['category'] === 'peer') {
964
- const peerNode = participants[0]?.content?.[0]
965
- if (peerNode) {
966
- binaryNodeContent.push(peerNode)
967
- }
968
- } else if (isInterop) {
969
-
970
-
971
- const recipientNode = participants.find(p => (0, WABinary_1.isInteropUser)(p?.attrs?.jid))
972
- const encNode = (recipientNode ?? participants[0])?.content?.[0]
973
- if (encNode) {
974
- binaryNodeContent.push(encNode)
975
- }
976
- } else {
977
- binaryNodeContent.push({
978
- tag: 'participants',
979
- attrs: {},
980
- content: participants
981
- })
982
- }
983
- }
984
- const stanza = {
985
- tag: 'message',
986
- attrs: {
987
- id: msgId,
988
- to: destinationJid,
989
- type: getTypeMessage(message),
990
- ...(additionalAttributes || {})
991
- },
992
- content: binaryNodeContent
993
- }
994
-
995
-
996
-
997
- if (participant) {
998
- if ((0, WABinary_1.isJidGroup)(destinationJid)) {
999
- stanza.attrs.to = destinationJid
1000
- stanza.attrs.participant = participant.jid
1001
- } else if ((0, WABinary_1.areJidsSameUser)(participant.jid, meId)) {
1002
- stanza.attrs.to = participant.jid
1003
- stanza.attrs.recipient = destinationJid
1004
- } else {
1005
- stanza.attrs.to = participant.jid
1006
- }
1007
- } else {
1008
- stanza.attrs.to = destinationJid
1009
- }
1010
- if (shouldIncludeDeviceIdentity) {
1011
- stanza.content.push({
1012
- tag: 'device-identity',
1013
- attrs: {},
1014
- content: (0, Utils_1.encodeSignedDeviceIdentity)(authState.creds.account, true)
1015
- })
1016
- logger.debug({ jid }, 'adding device identity')
1017
- }
1018
-
1019
- if (isGroup && regexGroupOld.test(jid) && !message.reactionMessage) {
1020
- stanza.content.push({
1021
- tag: 'multicast',
1022
- attrs: {}
1023
- })
1024
- }
1025
-
1026
-
1027
- if (isStatus && statusPrivacy && !additionalAttributes?.edit) {
1028
- stanza.content.push({
1029
- tag: 'meta',
1030
- attrs: { status_setting: statusPrivacy, session_scope: 'status' }
1031
- })
1032
- }
1033
-
1034
- if (pollMessage || messages.eventMessage) {
1035
- stanza.content.push({
1036
- tag: 'meta',
1037
- attrs: messages.eventMessage
1038
- ? {
1039
- event_type: 'creation'
1040
- }
1041
- : isNewsletter
1042
- ? {
1043
- polltype: 'creation',
1044
- contenttype: pollMessage?.pollContentType === 2 ? 'image' : 'text'
1045
- }
1046
- : {
1047
- polltype: 'creation'
1048
- }
1049
- })
1050
- }
1051
- if (
1052
- !isNewsletter &&
1053
- !isRetryResend &&
1054
- reportingMessage?.messageContextInfo?.messageSecret &&
1055
- (0, reporting_utils_1.shouldIncludeReportingToken)(reportingMessage)
1056
- ) {
1057
- try {
1058
- const encoded = (0, Utils_1.encodeWAMessage)(reportingMessage)
1059
- const reportingKey = {
1060
- id: msgId,
1061
- fromMe: true,
1062
- remoteJid: destinationJid,
1063
- participant: participant?.jid
1064
- }
1065
- const reportingNode = await (0, reporting_utils_1.getMessageReportingToken)(
1066
- encoded,
1067
- reportingMessage,
1068
- reportingKey
1069
- )
1070
- if (reportingNode) {
1071
- stanza.content.push(reportingNode)
1072
- logger.trace({ jid }, 'added reporting token to message')
1073
- }
1074
- } catch (error) {
1075
- logger.warn({ jid, trace: error?.stack }, 'failed to attach reporting token')
1076
- }
1077
- }
1078
-
1079
- let didPushAdditional = false
1080
- if (!isNewsletter && buttonType) {
1081
- const buttonsNode = getButtonArgs(messages)
1082
- const filteredButtons = WABinary_1.getBinaryFilteredButtons(additionalNodes ? additionalNodes : [])
1083
-
1084
- if (filteredButtons) {
1085
- stanza.content.push(...additionalNodes)
1086
- didPushAdditional = true
1087
- } else {
1088
- stanza.content.push(buttonsNode)
1089
- }
1090
- }
1091
- if (!AI && (0, WABinary_1.isPnUser)(destinationJid)) {
1092
- const alreadyHasBizBot =
1093
- WABinary_1.getBinaryFilteredBizBot(additionalNodes || []) ||
1094
- WABinary_1.getBinaryFilteredBizBot(stanza.content)
1095
- if (!alreadyHasBizBot) {
1096
- stanza.content.push({ tag: 'bot', attrs: { biz_bot: '1' } })
1097
- }
1098
- } else if (AI && !isGroup && !isStatus && !isNewsletter) {
1099
- const existingBizBot = WABinary_1.getBinaryFilteredBizBot(additionalNodes || [])
1100
- if (!existingBizBot) {
1101
- stanza.content.push({ tag: 'bot', attrs: { biz_bot: '1' } })
1102
- }
1103
- }
1104
-
1105
- const isPeerMessage = additionalAttributes?.['category'] === 'peer'
1106
- const is1on1Send = !isGroup && !isRetryResend && !isStatus && !isNewsletter && !isPeerMessage
1107
-
1108
- const tcTokenJid = is1on1Send
1109
- ? await (0, tc_token_utils_1.resolveTcTokenJid)(destinationJid, getLIDForPN)
1110
- : destinationJid
1111
- const contactTcTokenData = is1on1Send ? await authState.keys.get('tctoken', [tcTokenJid]) : {}
1112
- const existingTokenEntry = contactTcTokenData[tcTokenJid]
1113
- let tcTokenBuffer = existingTokenEntry?.token
1114
-
1115
- if (tcTokenBuffer?.length && (0, tc_token_utils_1.isTcTokenExpired)(existingTokenEntry?.timestamp)) {
1116
- logger.debug({ jid: destinationJid, timestamp: existingTokenEntry?.timestamp }, 'tctoken expired, clearing')
1117
- tcTokenBuffer = undefined
1118
- const cleared =
1119
- existingTokenEntry?.senderTimestamp !== undefined
1120
- ? { token: Buffer.alloc(0), senderTimestamp: existingTokenEntry.senderTimestamp }
1121
- : null
1122
- try {
1123
- await authState.keys.set({ tctoken: { [tcTokenJid]: cleared } })
1124
- } catch (err) {
1125
- logger.debug({ jid: destinationJid, err: err?.message }, 'failed to persist tctoken expiry cleanup')
1126
- }
1127
- }
1128
- if (tcTokenBuffer?.length && sock.serverProps.privacyTokenOn1to1) {
1129
- stanza.content.push({
1130
- tag: 'tctoken',
1131
- attrs: {},
1132
- content: tcTokenBuffer
1133
- })
1134
- }
1135
-
1136
- if (is1on1Send && !tcTokenBuffer?.length) {
1137
- try {
1138
- const saltStore = await authState.keys.get('nct-salt', ['default'])
1139
- const nctSalt = saltStore?.['default']
1140
- if (nctSalt?.length) {
1141
- const recipientLid = await getLIDForPN(destinationJid)
1142
- if (recipientLid) {
1143
- const { createHmac } = require('crypto')
1144
- const lidStr = (0, WABinary_1.isLidUser)(recipientLid)
1145
- ? recipientLid
1146
- : `${recipientLid.split('@')[0]}@lid`
1147
- const cs = createHmac('sha256', nctSalt).update(lidStr, 'utf8').digest()
1148
- stanza.content.push({ tag: 'cstoken', attrs: {}, content: cs })
1149
- logger.debug({ jid: destinationJid, lid: lidStr }, 'nct: attached cstoken')
1150
- }
1151
- }
1152
- } catch (err) {
1153
- logger.debug({ jid: destinationJid, err: err?.message }, 'nct: cstoken attach failed')
1154
- }
1155
- }
1156
- if (additionalNodes && additionalNodes.length > 0 && !didPushAdditional) {
1157
- stanza.content.push(...additionalNodes)
1158
- }
1159
- logger.debug({ msgId }, `sending message to ${participants.length} devices`)
1160
- await sendNode(stanza)
1161
-
1162
-
1163
- if (message.messageContextInfo?.messageSecret) {
1164
- setBotMessageSecret(msgId, message.messageContextInfo.messageSecret, destinationJid)
1165
- }
1166
-
1167
- const isProtocolMsg = !!(0, Utils_1.normalizeMessageContent)(message)?.protocolMessage
1168
- const isBotOrPSA =
1169
- destinationJid === WABinary_1.PSA_WID ||
1170
- (0, WABinary_1.isJidBot)(destinationJid) ||
1171
- (0, WABinary_1.isJidMetaAI)(destinationJid)
1172
- if (
1173
- is1on1Send &&
1174
- !isProtocolMsg &&
1175
- !isBotOrPSA &&
1176
- (0, tc_token_utils_1.shouldSendNewTcToken)(existingTokenEntry?.senderTimestamp) &&
1177
- !inFlightTcTokenIssuance.has(tcTokenJid)
1178
- ) {
1179
- inFlightTcTokenIssuance.add(tcTokenJid)
1180
- const issueTimestamp = (0, Utils_1.unixTimestampSeconds)()
1181
- const getPNForLID = signalRepository.lidMapping.getPNForLID.bind(signalRepository.lidMapping)
1182
- ;(0, tc_token_utils_1.resolveIssuanceJid)(
1183
- destinationJid,
1184
- sock.serverProps.lidTrustedTokenIssueToLid,
1185
- getLIDForPN,
1186
- getPNForLID
1187
- )
1188
- .then(issueJid => issuePrivacyTokens([issueJid], issueTimestamp))
1189
- .then(async result => {
1190
- await (0, tc_token_utils_1.storeTcTokensFromIqResult)({
1191
- result,
1192
- fallbackJid: tcTokenJid,
1193
- keys: authState.keys,
1194
- getLIDForPN
1195
- })
1196
- const currentData = await authState.keys.get('tctoken', [tcTokenJid])
1197
- const currentEntry = currentData[tcTokenJid]
1198
- const indexWrite = await (0, tc_token_utils_1.buildMergedTcTokenIndexWrite)(authState.keys, [tcTokenJid])
1199
- await authState.keys.set({
1200
- tctoken: {
1201
- [tcTokenJid]: {
1202
- token: Buffer.alloc(0),
1203
- ...currentEntry,
1204
- senderTimestamp: issueTimestamp
1205
- },
1206
- ...indexWrite
1207
- }
1208
- })
1209
- })
1210
- .catch(err => {
1211
- logger.debug({ jid: destinationJid, err: err?.message }, 'fire-and-forget tctoken issuance failed')
1212
- })
1213
- .finally(() => {
1214
- inFlightTcTokenIssuance.delete(tcTokenJid)
1215
- })
1216
- }
1217
-
1218
- if (messageRetryManager && !participant) {
1219
- messageRetryManager.addRecentMessage(destinationJid, msgId, message)
1220
- }
1221
- if (isInterop && !isRetryResend) {
1222
- await trustInteropContact(destinationJid).catch(err => {
1223
- logger.debug({ err, jid: destinationJid }, 'failed to trust interop contact')
1224
- })
1225
- }
1226
- }, meId)
1227
- return msgId
1228
- }
1229
- const getTypeMessage = msg => {
1230
- const message = Utils_1.normalizeMessageContent(msg)
1231
- if (message.pollCreationMessage || message.pollCreationMessageV2 || message.pollCreationMessageV3) {
1232
- return 'poll'
1233
- } else if (message.reactionMessage) {
1234
- return 'reaction'
1235
- } else if (message.eventMessage) {
1236
- return 'event'
1237
- } else if (getMediaType(message)) {
1238
- return 'media'
1239
- } else {
1240
- return 'text'
1241
- }
1242
- }
1243
-
1244
- const getMediaType = message => {
1245
- if (message.imageMessage) {
1246
- return 'image'
1247
- } else if (message.stickerMessage) {
1248
- return message.stickerMessage.isLottie
1249
- ? '1p_sticker'
1250
- : message.stickerMessage.isAvatar
1251
- ? 'avatar_sticker'
1252
- : 'sticker'
1253
- } else if (message.videoMessage) {
1254
- return message.videoMessage.gifPlayback ? 'gif' : 'video'
1255
- } else if (message.audioMessage) {
1256
- return message.audioMessage.ptt ? 'ptt' : 'audio'
1257
- } else if (message.ptvMessage) {
1258
- return 'ptv'
1259
- } else if (message.albumMessage) {
1260
- return 'collection'
1261
- } else if (message.contactMessage) {
1262
- return 'vcard'
1263
- } else if (message.documentMessage) {
1264
- return 'document'
1265
- } else if (message.stickerPackMessage) {
1266
- return 'sticker_pack'
1267
- } else if (message.contactsArrayMessage) {
1268
- return 'contact_array'
1269
- } else if (message.locationMessage) {
1270
- return 'location'
1271
- } else if (message.liveLocationMessage) {
1272
- return 'livelocation'
1273
- } else if (message.listMessage) {
1274
- return 'list'
1275
- } else if (message.listResponseMessage) {
1276
- return 'list_response'
1277
- } else if (message.buttonsResponseMessage) {
1278
- return 'buttons_response'
1279
- } else if (message.orderMessage) {
1280
- return 'order'
1281
- } else if (message.productMessage) {
1282
- return 'product'
1283
- } else if (message.interactiveResponseMessage) {
1284
- return 'native_flow_response'
1285
- } else if (/https:\/\/wa\.me\/c\/\d+/.test(message.extendedTextMessage?.text)) {
1286
- return 'cataloglink'
1287
- } else if (/https:\/\/wa\.me\/p\/\d+\/\d+/.test(message.extendedTextMessage?.text)) {
1288
- return 'productlink'
1289
- } else if (message.extendedTextMessage?.matchedText || message.groupInviteMessage) {
1290
- return 'url'
1291
- }
1292
- }
1293
- const getButtonType = message => {
1294
- if (message.listMessage) {
1295
- return 'list'
1296
- } else if (message.buttonsMessage) {
1297
- return 'buttons'
1298
- } else if (message.interactiveMessage?.nativeFlowMessage) {
1299
- const firstButtonName = message.interactiveMessage.nativeFlowMessage.buttons?.[0]?.name
1300
- if (firstButtonName === 'review_and_pay') {
1301
- return 'review_and_pay'
1302
- } else if (firstButtonName === 'review_order') {
1303
- return 'review_order'
1304
- } else if (firstButtonName === 'payment_info') {
1305
- return 'payment_info'
1306
- } else if (firstButtonName === 'payment_status') {
1307
- return 'payment_status'
1308
- } else if (firstButtonName === 'payment_method') {
1309
- return 'payment_method'
1310
- } else if (firstButtonName === 'pix') {
1311
- return 'pix'
1312
- } else if (firstButtonName === 'pay') {
1313
- return 'pay'
1314
- }
1315
- return 'native_flow'
1316
- }
1317
- }
1318
-
1319
- const getButtonArgs = message => {
1320
- const nativeFlow = message.interactiveMessage?.nativeFlowMessage
1321
- const firstButtonName = nativeFlow?.buttons?.[0]?.name
1322
- const nativeFlowSpecials = [
1323
- 'mpm',
1324
- 'cta_catalog',
1325
- 'send_location',
1326
- 'call_permission_request',
1327
- 'wa_payment_transaction_details',
1328
- 'automated_greeting_message_view_catalog'
1329
- ]
1330
-
1331
- if (nativeFlow && (firstButtonName === 'review_and_pay' || firstButtonName === 'payment_info')) {
1332
- return {
1333
- tag: 'biz',
1334
- attrs: {
1335
- native_flow_name: firstButtonName === 'review_and_pay' ? 'order_details' : firstButtonName
1336
- }
1337
- }
1338
- } else if (nativeFlow && nativeFlowSpecials.includes(firstButtonName)) {
1339
-
1340
- return {
1341
- tag: 'biz',
1342
- attrs: {
1343
- actual_actors: '2',
1344
- host_storage: '2',
1345
- privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1346
- },
1347
- content: [
1348
- {
1349
- tag: 'interactive',
1350
- attrs: {
1351
- type: 'native_flow',
1352
- v: '1'
1353
- },
1354
- content: [
1355
- {
1356
- tag: 'native_flow',
1357
- attrs: {
1358
- v: '2',
1359
- name: firstButtonName
1360
- }
1361
- }
1362
- ]
1363
- },
1364
- {
1365
- tag: 'quality_control',
1366
- attrs: {
1367
- source_type: 'third_party'
1368
- }
1369
- }
1370
- ]
1371
- }
1372
- } else if (nativeFlow || message.buttonsMessage) {
1373
-
1374
- return {
1375
- tag: 'biz',
1376
- attrs: {
1377
- actual_actors: '2',
1378
- host_storage: '2',
1379
- privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1380
- },
1381
- content: [
1382
- {
1383
- tag: 'interactive',
1384
- attrs: {
1385
- type: 'native_flow',
1386
- v: '1'
1387
- },
1388
- content: [
1389
- {
1390
- tag: 'native_flow',
1391
- attrs: {
1392
- v: '9',
1393
- name: 'mixed'
1394
- }
1395
- }
1396
- ]
1397
- },
1398
- {
1399
- tag: 'quality_control',
1400
- attrs: {
1401
- source_type: 'third_party'
1402
- }
1403
- }
1404
- ]
1405
- }
1406
- } else if (message.listMessage) {
1407
- return {
1408
- tag: 'biz',
1409
- attrs: {
1410
- actual_actors: '2',
1411
- host_storage: '2',
1412
- privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1413
- },
1414
- content: [
1415
- {
1416
- tag: 'list',
1417
- attrs: {
1418
- v: '2',
1419
- type: 'product_list'
1420
- }
1421
- },
1422
- {
1423
- tag: 'quality_control',
1424
- attrs: {
1425
- source_type: 'third_party'
1426
- }
1427
- }
1428
- ]
1429
- }
1430
- } else {
1431
- return {
1432
- tag: 'biz',
1433
- attrs: {
1434
- actual_actors: '2',
1435
- host_storage: '2',
1436
- privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1437
- }
1438
- }
1439
- }
1440
- }
1441
- const issuePrivacyTokens = async (jids, timestamp) => {
1442
- const t = (timestamp ?? (0, Utils_1.unixTimestampSeconds)()).toString()
1443
- const result = await query({
1444
- tag: 'iq',
1445
- attrs: {
1446
- to: WABinary_1.S_WHATSAPP_NET,
1447
- type: 'set',
1448
- xmlns: 'privacy'
1449
- },
1450
- content: [
1451
- {
1452
- tag: 'tokens',
1453
- attrs: {},
1454
- content: jids.map(jid => ({
1455
- tag: 'token',
1456
- attrs: {
1457
- jid: (0, WABinary_1.jidNormalizedUser)(jid),
1458
- t,
1459
- type: 'trusted_contact'
1460
- }
1461
- }))
1462
- }
1463
- ]
1464
- })
1465
- return result
1466
- }
1467
- const getPrivacyTokens = issuePrivacyTokens
1468
- const waUploadToServer = (0, Utils_1.getWAUploadToServer)(config, refreshMediaConn)
1469
- const badzzne2 = new interactive_handler_1.badzz88(waUploadToServer, relayMessage, config, sock)
1470
- const waitForMsgMediaUpdate = (0, Utils_1.bindWaitForEvent)(ev, 'messages.media-update')
1471
- return {
1472
- ...sock,
1473
- issuePrivacyTokens,
1474
- getPrivacyTokens,
1475
- assertSessions,
1476
- relayMessage,
1477
- sendReceipt,
1478
- sendReceipts,
1479
- readMessages,
1480
- refreshMediaConn,
1481
- waUploadToServer,
1482
- fetchPrivacySettings,
1483
- sendPeerDataOperationMessage,
1484
- createParticipantNodes,
1485
- getUSyncDevices,
1486
- messageRetryManager,
1487
- updateMemberLabel,
1488
- updateMediaMessage: async message => {
1489
- const content = (0, Utils_1.assertMediaContent)(message.message)
1490
- const mediaKey = content.mediaKey
1491
- const meId = authState.creds.me.id
1492
- const node = (0, Utils_1.encryptMediaRetryRequest)(message.key, mediaKey, meId)
1493
- let error = undefined
1494
- await Promise.all([
1495
- sendNode(node),
1496
- waitForMsgMediaUpdate(async update => {
1497
- const result = update.find(c => c.key.id === message.key.id)
1498
- if (result) {
1499
- if (result.error) {
1500
- error = result.error
1501
- } else {
1502
- try {
1503
- const media = (0, Utils_1.decryptMediaRetryData)(result.media, mediaKey, result.key.id)
1504
- if (media.result !== index_js_1.proto.MediaRetryNotification.ResultType.SUCCESS) {
1505
- const resultStr = index_js_1.proto.MediaRetryNotification.ResultType[media.result]
1506
- throw new boom_1.Boom(`Media re-upload failed by device (${resultStr})`, {
1507
- data: media,
1508
- statusCode: (0, Utils_1.getStatusCodeForMediaRetry)(media.result) || 404
1509
- })
1510
- }
1511
- content.directPath = media.directPath
1512
- content.url = (0, Utils_1.getUrlFromDirectPath)(content.directPath)
1513
- logger.debug({ directPath: media.directPath, key: result.key }, 'media update successful')
1514
- } catch (err) {
1515
- error = err
1516
- }
1517
- }
1518
- return true
1519
- }
1520
- })
1521
- ])
1522
- if (error) {
1523
- throw error
1524
- }
1525
- ev.emit('messages.update', [{ key: message.key, update: { message: message.message } }])
1526
- return message
1527
- },
1528
-
1529
- sendGroupStatus: async (groupIdsOrContent = [], contentOrGroups = {}, opts = {}) => {
1530
- const toGroupIdArray = input => {
1531
- if (Array.isArray(input)) {
1532
- return input
1533
- }
1534
- if (typeof input === 'string') {
1535
- return [input]
1536
- }
1537
- return []
1538
- }
1539
- const normalizeGroupJid = value => {
1540
- if (typeof value !== 'string') {
1541
- return ''
1542
- }
1543
- const trimmed = value.trim()
1544
- if (!trimmed) {
1545
- return ''
1546
- }
1547
- if (/^\d{8,}$/.test(trimmed)) {
1548
- return `${trimmed}@g.us`
1549
- }
1550
- return trimmed
1551
- }
1552
- const useNewSignature = Array.isArray(groupIdsOrContent) || typeof groupIdsOrContent === 'string'
1553
- const groupIds = useNewSignature ? toGroupIdArray(groupIdsOrContent) : toGroupIdArray(contentOrGroups)
1554
- const content = useNewSignature ? contentOrGroups || {} : groupIdsOrContent || {}
1555
- const sendOpts = opts || {}
1556
- const groupJids = groupIds.map(normalizeGroupJid).filter(jid => (0, WABinary_1.isJidGroup)(jid))
1557
- const nonGroupJids = groupIds.filter(jid => !(0, WABinary_1.isJidGroup)(normalizeGroupJid(jid)))
1558
- if (nonGroupJids.length) {
1559
- logger.warn({ nonGroupJids }, 'ignoring non-group JIDs in sendGroupStatus')
1560
- }
1561
- if (!groupJids.length) {
1562
- return []
1563
- }
1564
- const { allUsers } = await resolveStatusAudience(groupJids, false)
1565
- if (!allUsers.length) {
1566
- return []
1567
- }
1568
- const msg = await generateStatusMessage({
1569
- ...content,
1570
- backgroundColor: content.backgroundColor || getRandomHexColor(),
1571
- font: normalizeStatusFont(content.font, logger)
1572
- })
1573
- await relayMessage(WABinary_1.STORIES_JID, msg.message, {
1574
- messageId: msg.key.id,
1575
- statusJidList: allUsers,
1576
- ...(sendOpts.relay || {})
1577
- })
1578
- return groupJids
1579
- },
1580
- sendAlbumMessage: async (jid, medias, options = {}) => {
1581
- const userJid = authState.creds.me.id
1582
- for (const media of medias) {
1583
- if (!media.image && !media.video) throw new TypeError(`medias[i] must have image or video property`)
1584
- }
1585
- if (medias.length < 2) throw new RangeError('Minimum 2 media')
1586
- const time = options.delay || 500
1587
- delete options.delay
1588
- const album = await (0, Utils_1.generateWAMessageFromContent)(
1589
- jid,
1590
- {
1591
- albumMessage: {
1592
- expectedImageCount: medias.filter(media => media.image).length,
1593
- expectedVideoCount: medias.filter(media => media.video).length,
1594
- ...options
1595
- }
1596
- },
1597
- { userJid, ...options }
1598
- )
1599
- await relayMessage(jid, album.message, { messageId: album.key.id })
1600
- let mediaHandle
1601
- let msg
1602
- for (const i in medias) {
1603
- const media = medias[i]
1604
- if (media.image) {
1605
- msg = await (0, Utils_1.generateWAMessage)(
1606
- jid,
1607
- {
1608
- image: media.image,
1609
- ...media,
1610
- ...options
1611
- },
1612
- {
1613
- userJid,
1614
- upload: async (readStream, opts) => {
1615
- const up = await waUploadToServer(readStream, {
1616
- ...opts,
1617
- newsletter: (0, WABinary_1.isJidNewsletter)(jid)
1618
- })
1619
- mediaHandle = up.handle
1620
- return up
1621
- },
1622
- mediaAbProps: authState.creds.mediaAbProps,
1623
- ...options
1624
- }
1625
- )
1626
- } else if (media.video) {
1627
- msg = await (0, Utils_1.generateWAMessage)(
1628
- jid,
1629
- {
1630
- video: media.video,
1631
- ...media,
1632
- ...options
1633
- },
1634
- {
1635
- userJid,
1636
- upload: async (readStream, opts) => {
1637
- const up = await waUploadToServer(readStream, {
1638
- ...opts,
1639
- newsletter: (0, WABinary_1.isJidNewsletter)(jid)
1640
- })
1641
- mediaHandle = up.handle
1642
- return up
1643
- },
1644
- mediaAbProps: authState.creds.mediaAbProps,
1645
- ...options
1646
- }
1647
- )
1648
- }
1649
- if (msg) {
1650
- msg.message.messageContextInfo = {
1651
- messageAssociation: {
1652
- associationType: 1,
1653
- parentMessageKey: album.key
1654
- }
1655
- }
1656
- }
1657
- await relayMessage(jid, msg.message, { messageId: msg.key.id })
1658
- await (0, Utils_1.delay)(time)
1659
- }
1660
- return album
1661
- },
1662
-
1663
- sendStatusMention: async (content, jids = []) => {
1664
- return await badzzne2.sendStatusWhatsApp(content, jids)
1665
- },
1666
- sendTable: async (jid, title, headers, rows, quoted, options = {}) => {
1667
- const { message, messageId } = message_composer_1.generateTableContent(title, headers, rows, quoted, options)
1668
- await relayMessage(jid, message, { messageId })
1669
- return { message, messageId }
1670
- },
1671
- sendList: async (jid, title, items, quoted, options = {}) => {
1672
- const { message, messageId } = message_composer_1.generateListContent(title, items, quoted, options)
1673
- await relayMessage(jid, message, { messageId })
1674
- return { message, messageId }
1675
- },
1676
- sendCodeBlock: async (jid, code, quoted, options = {}) => {
1677
- const { message, messageId } = message_composer_1.generateCodeBlockContent(code, quoted, options)
1678
- await relayMessage(jid, message, { messageId })
1679
- return { message, messageId }
1680
- },
1681
- sendLatex: async (jid, quoted, options) => {
1682
- const { message, messageId } = message_composer_1.generateLatexContent(quoted, options)
1683
- await relayMessage(jid, message, { messageId })
1684
- return { message, messageId }
1685
- },
1686
- sendLatexImage: async (jid, quoted, options, renderLatexToPng, uploadFn) => {
1687
- const { message, messageId } = await message_composer_1.generateLatexImageContent(
1688
- quoted,
1689
- options,
1690
- uploadFn,
1691
- renderLatexToPng
1692
- )
1693
- await relayMessage(jid, message, { messageId })
1694
- return { message, messageId }
1695
- },
1696
- sendLatexInlineImage: async (jid, quoted, options, renderLatexToPng, uploadFn) => {
1697
- const { message, messageId } = await message_composer_1.generateLatexInlineImageContent(
1698
- quoted,
1699
- options,
1700
- uploadFn,
1701
- renderLatexToPng
1702
- )
1703
- await relayMessage(jid, message, { messageId })
1704
- return { message, messageId }
1705
- },
1706
- captureUnifiedResponse: message_composer_1.captureUnifiedResponse,
1707
- sendUnifiedResponse: async (jid, quoted, captured) => {
1708
- const { message, messageId } = message_composer_1.generateUnifiedResponseContent(quoted, captured)
1709
- await relayMessage(jid, message, { messageId })
1710
- return { message, messageId }
1711
- },
1712
- sendRichMessage: async (jid, submessages, quoted, options = {}) => {
1713
- const { message, messageId } = message_composer_1.generateRichMessageContent(submessages, quoted, options)
1714
- await relayMessage(jid, message, { messageId })
1715
- return { message, messageId }
1716
- },
1717
- sendMessage: async (jid, content, options = {}) => {
1718
- const userJid = authState.creds.me.id
1719
-
1720
- if (
1721
- typeof content === 'object' &&
1722
- Array.isArray(content.buttons) &&
1723
- content.buttons.length > 0 &&
1724
- content.buttons.some(b => b.nativeFlowInfo)
1725
- ) {
1726
- const interactiveButtons = content.buttons.map(b => {
1727
- if (b.nativeFlowInfo) {
1728
- return {
1729
- name: b.nativeFlowInfo.name,
1730
- buttonParamsJson: b.nativeFlowInfo.paramsJson || '{}'
1731
- }
1732
- }
1733
- return {
1734
- name: 'quick_reply',
1735
- buttonParamsJson: JSON.stringify({
1736
- display_text: b.buttonText?.displayText || b.buttonId || 'Button',
1737
- id: b.buttonId || b.buttonText?.displayText || 'btn'
1738
- })
1739
- }
1740
- })
1741
- const { buttons, headerType, viewOnce, ...rest } = content
1742
- content = { ...rest, interactiveButtons }
1743
- }
1744
- if (
1745
- typeof content === 'object' &&
1746
- Array.isArray(content.interactiveButtons) &&
1747
- content.interactiveButtons.length > 0
1748
- ) {
1749
- const {
1750
- text = '',
1751
- caption = '',
1752
- title = '',
1753
- footer = '',
1754
- interactiveButtons,
1755
- hasMediaAttachment = false,
1756
- image = null,
1757
- video = null,
1758
- document = null,
1759
- mimetype = null,
1760
- jpegThumbnail = null,
1761
- location = null,
1762
- product = null,
1763
- businessOwnerJid = null,
1764
- externalAdReply = null
1765
- } = content
1766
-
1767
- const processedButtons = []
1768
- for (let i = 0; i < interactiveButtons.length; i++) {
1769
- const btn = interactiveButtons[i]
1770
- if (!btn || typeof btn !== 'object') throw new Error(`interactiveButtons[${i}] must be an object`)
1771
- if (btn.name && btn.buttonParamsJson) {
1772
- processedButtons.push(btn)
1773
- continue
1774
- }
1775
- if (btn.id || btn.text || btn.displayText) {
1776
- processedButtons.push({
1777
- name: 'quick_reply',
1778
- buttonParamsJson: JSON.stringify({
1779
- display_text: btn.text || btn.displayText || `Button ${i + 1}`,
1780
- id: btn.id || `quick_${i + 1}`
1781
- })
1782
- })
1783
- continue
1784
- }
1785
- if (btn.buttonId && btn.buttonText?.displayText) {
1786
- processedButtons.push({
1787
- name: 'quick_reply',
1788
- buttonParamsJson: JSON.stringify({ display_text: btn.buttonText.displayText, id: btn.buttonId })
1789
- })
1790
- continue
1791
- }
1792
- throw new Error(`interactiveButtons[${i}] has invalid shape`)
1793
- }
1794
- let messageContent = {}
1795
- if (image) {
1796
- const mi = Buffer.isBuffer(image)
1797
- ? { image }
1798
- : { image: { url: typeof image === 'object' ? image.url : image } }
1799
- const pm = await (0, Utils_1.prepareWAMessageMedia)(mi, { upload: waUploadToServer })
1800
- messageContent.header = { title: title || '', hasMediaAttachment: true, imageMessage: pm.imageMessage }
1801
- } else if (video) {
1802
- const mi = Buffer.isBuffer(video)
1803
- ? { video }
1804
- : { video: { url: typeof video === 'object' ? video.url : video } }
1805
- const pm = await (0, Utils_1.prepareWAMessageMedia)(mi, { upload: waUploadToServer })
1806
- messageContent.header = { title: title || '', hasMediaAttachment: true, videoMessage: pm.videoMessage }
1807
- } else if (document) {
1808
- const mi = Buffer.isBuffer(document)
1809
- ? { document }
1810
- : { document: { url: typeof document === 'object' ? document.url : document } }
1811
- if (mimetype && typeof mi.document === 'object') mi.document.mimetype = mimetype
1812
- if (jpegThumbnail) {
1813
- const thumb = Buffer.isBuffer(jpegThumbnail)
1814
- ? jpegThumbnail
1815
- : await (async () => {
1816
- try {
1817
- const r = await fetch(jpegThumbnail)
1818
- return Buffer.from(await r.arrayBuffer())
1819
- } catch {
1820
- return undefined
1821
- }
1822
- })()
1823
- if (thumb) mi.document.jpegThumbnail = thumb
1824
- }
1825
- const pm = await (0, Utils_1.prepareWAMessageMedia)(mi, { upload: waUploadToServer })
1826
- messageContent.header = { title: title || '', hasMediaAttachment: true, documentMessage: pm.documentMessage }
1827
- } else if (location && typeof location === 'object') {
1828
- messageContent.header = {
1829
- title: title || location.name || 'Location',
1830
- hasMediaAttachment: false,
1831
- locationMessage: {
1832
- degreesLatitude: location.degreesLatitude || location.degressLatitude || 0,
1833
- degreesLongitude: location.degreesLongitude || location.degressLongitude || 0,
1834
- name: location.name || '',
1835
- address: location.address || ''
1836
- }
1837
- }
1838
- } else if (product && typeof product === 'object') {
1839
- let productImageMessage = null
1840
- if (product.productImage) {
1841
- const mi = Buffer.isBuffer(product.productImage)
1842
- ? { image: product.productImage }
1843
- : {
1844
- image: {
1845
- url: typeof product.productImage === 'object' ? product.productImage.url : product.productImage
1846
- }
1847
- }
1848
- const pm = await (0, Utils_1.prepareWAMessageMedia)(mi, { upload: waUploadToServer })
1849
- productImageMessage = pm.imageMessage
1850
- }
1851
- messageContent.header = {
1852
- title: title || product.title || 'Product',
1853
- hasMediaAttachment: false,
1854
- productMessage: {
1855
- product: {
1856
- productImage: productImageMessage,
1857
- productId: product.productId || '',
1858
- title: product.title || '',
1859
- description: product.description || '',
1860
- currencyCode: product.currencyCode || 'USD',
1861
- priceAmount1000: parseInt(product.priceAmount1000, 10) || 0,
1862
- retailerId: product.retailerId || '',
1863
- url: product.url || '',
1864
- productImageCount: product.productImageCount || 1
1865
- },
1866
- businessOwnerJid: businessOwnerJid || product.businessOwnerJid || userJid
1867
- }
1868
- }
1869
- } else if (title) {
1870
- messageContent.header = { title, hasMediaAttachment: false }
1871
- }
1872
- const hasMedia = !!(image || video || document || location || product)
1873
- const bodyText = hasMedia ? caption : text || caption
1874
- if (bodyText) messageContent.body = { text: bodyText }
1875
- if (footer) messageContent.footer = { text: footer }
1876
- messageContent.nativeFlowMessage = { buttons: processedButtons }
1877
- if (externalAdReply && typeof externalAdReply === 'object') {
1878
- messageContent.contextInfo = {
1879
- externalAdReply: {
1880
- title: externalAdReply.title || '',
1881
- body: externalAdReply.body || '',
1882
- mediaType: externalAdReply.mediaType || 1,
1883
- sourceUrl: externalAdReply.sourceUrl || externalAdReply.url || '',
1884
- thumbnailUrl: externalAdReply.thumbnailUrl || externalAdReply.thumbnail || '',
1885
- renderLargerThumbnail: externalAdReply.renderLargerThumbnail || false,
1886
- showAdAttribution: externalAdReply.showAdAttribution !== false,
1887
- containsAutoReply: externalAdReply.containsAutoReply || false,
1888
- ...(externalAdReply.mediaUrl && { mediaUrl: externalAdReply.mediaUrl }),
1889
- ...(Buffer.isBuffer(externalAdReply.thumbnail) && { thumbnail: externalAdReply.thumbnail }),
1890
- ...(externalAdReply.jpegThumbnail && { jpegThumbnail: externalAdReply.jpegThumbnail })
1891
- },
1892
- ...(options.mentionedJid && { mentionedJid: options.mentionedJid })
1893
- }
1894
- } else if (options.mentionedJid) {
1895
- messageContent.contextInfo = { mentionedJid: options.mentionedJid }
1896
- }
1897
- const payload = index_js_1.proto.Message.InteractiveMessage.create(messageContent)
1898
- const msg = (0, Utils_1.generateWAMessageFromContent)(
1899
- jid,
1900
- { viewOnceMessage: { message: { interactiveMessage: payload } } },
1901
- { userJid, quoted: options?.quoted || null }
1902
- )
1903
- const additionalNodes = [
1904
- {
1905
- tag: 'biz',
1906
- attrs: {},
1907
- content: [
1908
- {
1909
- tag: 'interactive',
1910
- attrs: { type: 'native_flow', v: '1' },
1911
- content: [{ tag: 'native_flow', attrs: { v: '9', name: 'mixed' } }]
1912
- }
1913
- ]
1914
- }
1915
- ]
1916
- await relayMessage(jid, msg.message, { messageId: msg.key.id, additionalNodes })
1917
- return msg
1918
- }
1919
- if (
1920
- typeof content === 'object' &&
1921
- 'disappearingMessagesInChat' in content &&
1922
- typeof content['disappearingMessagesInChat'] !== 'undefined' &&
1923
- (0, WABinary_1.isJidGroup)(jid)
1924
- ) {
1925
- const { disappearingMessagesInChat } = content
1926
- const value =
1927
- typeof disappearingMessagesInChat === 'boolean'
1928
- ? disappearingMessagesInChat
1929
- ? WA_DEFAULT_EPHEMERAL
1930
- : 0
1931
- : disappearingMessagesInChat
1932
- await groupToggleEphemeral(jid, value)
1933
- } else if (badzzne2.detectType(content)) {
1934
- const { quoted } = options
1935
- const messageType = badzzne2.detectType(content)
1936
- switch (messageType) {
1937
- case 'PAYMENT': {
1938
- const paymentContent = await badzzne2.handlePayment(content, quoted)
1939
- return await relayMessage(jid, paymentContent, {
1940
- messageId: (0, Utils_1.generateMessageIDV2)(userJid)
1941
- })
1942
- }
1943
- case 'PRODUCT': {
1944
- const productContent = await badzzne2.handleProduct(content, jid, quoted)
1945
- const productMsg = await (0, Utils_1.generateWAMessageFromContent)(jid, productContent, { quoted, userJid })
1946
- return await relayMessage(jid, productMsg.message, {
1947
- messageId: productMsg.key.id
1948
- })
1949
- }
1950
- case 'INTERACTIVE': {
1951
- const interactiveContent = await badzzne2.handleInteractive(content, jid, quoted)
1952
- const interactiveMsg = await (0, Utils_1.generateWAMessageFromContent)(jid, interactiveContent, {
1953
- quoted,
1954
- userJid
1955
- })
1956
- return await relayMessage(jid, interactiveMsg.message, {
1957
- messageId: interactiveMsg.key.id
1958
- })
1959
- }
1960
- case 'INTERACTIVE_BUTTONS': {
1961
- const ibContent = await badzzne2.handleInteractiveButtons(content, jid, quoted)
1962
- const ibMsg = await (0, Utils_1.generateWAMessageFromContent)(jid, ibContent, { quoted, userJid })
1963
- return await relayMessage(jid, ibMsg.message, {
1964
- messageId: ibMsg.key.id
1965
- })
1966
- }
1967
- case 'ALBUM':
1968
- return await badzzne2.handleAlbum(content, jid, quoted)
1969
- case 'EVENT':
1970
- return await badzzne2.handleEvent(content, jid, quoted)
1971
- case 'POLL_RESULT':
1972
- return await badzzne2.handlePollResult(content, jid, quoted)
1973
- case 'GROUP_STORY':
1974
- return await badzzne2.handleGroupStory(content, jid, quoted)
1975
- }
1976
- } else {
1977
- let mediaHandle
1978
- const { ai, ...optionsWithoutAI } = options
1979
- const fullMsg = await (0, Utils_1.generateWAMessage)(jid, content, {
1980
- logger,
1981
- userJid,
1982
- getUrlInfo: text =>
1983
- (0, link_preview_1.getUrlInfo)(text, {
1984
- thumbnailWidth: linkPreviewImageThumbnailWidth,
1985
- fetchOpts: {
1986
- timeout: 3000,
1987
- ...(httpRequestOptions || {})
1988
- },
1989
- logger,
1990
- uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
1991
- }),
1992
- getProfilePicUrl: sock.profilePictureUrl,
1993
- getCallLink: sock.createCallLink,
1994
- newsletter: (0, WABinary_1.isJidNewsletter)(jid),
1995
- upload: async (encFilePath, opts) => {
1996
- const up = await waUploadToServer(encFilePath, {
1997
- ...opts,
1998
- newsletter: (0, WABinary_1.isJidNewsletter)(jid)
1999
- })
2000
- mediaHandle = up.handle
2001
- return up
2002
- },
2003
- mediaCache: config.mediaCache,
2004
- options: config.options,
2005
- messageId: (0, Utils_1.generateMessageIDV2)(sock.user?.id),
2006
-
2007
- mediaAbProps: authState.creds.mediaAbProps,
2008
- ...optionsWithoutAI
2009
- })
2010
- if (!mediaHandle) {
2011
- const msgContent = fullMsg.message
2012
- const msgTypes = ['audioMessage', 'imageMessage', 'videoMessage', 'documentMessage', 'stickerMessage']
2013
- for (const t of msgTypes) {
2014
- if (msgContent?.[t]?._uploadHandle) {
2015
- mediaHandle = msgContent[t]._uploadHandle
2016
-
2017
- delete msgContent[t]._uploadHandle
2018
- break
2019
- }
2020
- }
2021
- }
2022
- const isEventMsg = 'event' in content && !!content.event
2023
- const isDeleteMsg = 'delete' in content && !!content.delete
2024
- const isEditMsg = 'edit' in content && !!content.edit
2025
- const isPinMsg = 'pin' in content && !!content.pin
2026
- const isPollMessage = 'poll' in content && !!content.poll
2027
- const additionalAttributes = {}
2028
- const additionalNodes = []
2029
- if (isDeleteMsg) {
2030
- if ((0, WABinary_1.isJidGroup)(content.delete?.remoteJid) && !content.delete?.fromMe) {
2031
- additionalAttributes.edit = '8'
2032
- } else {
2033
- additionalAttributes.edit = '7'
2034
- }
2035
- if (content.delete?.server_id) {
2036
- additionalAttributes.server_id = String(content.delete.server_id)
2037
- }
2038
- } else if (isEditMsg) {
2039
- additionalAttributes.edit = '1'
2040
- } else if (isPinMsg) {
2041
- additionalAttributes.edit = '2'
2042
- } else if (isPollMessage) {
2043
- additionalNodes.push({
2044
- tag: 'meta',
2045
- attrs: {
2046
- polltype: 'creation'
2047
- }
2048
- })
2049
- } else if (isEventMsg) {
2050
- additionalNodes.push({
2051
- tag: 'meta',
2052
- attrs: {
2053
- event_type: 'creation'
2054
- }
2055
- })
2056
- }
2057
- const buttonType = getButtonType(fullMsg.message)
2058
- if (content?.audio && options?.contextInfo) {
2059
- const msgContent = fullMsg.message
2060
- if (msgContent?.audioMessage) {
2061
- msgContent.audioMessage.contextInfo = options.contextInfo
2062
- }
2063
- }
2064
- if (buttonType) {
2065
- const btnNode = getButtonArgs(fullMsg.message)
2066
- if (btnNode) additionalNodes.push(btnNode)
2067
- }
2068
- if (mediaHandle) {
2069
- additionalAttributes['media_id'] = mediaHandle
2070
- }
2071
- await relayMessage(jid, fullMsg.message, {
2072
- messageId: fullMsg.key.id,
2073
- useCachedGroupMetadata: options.useCachedGroupMetadata,
2074
- additionalAttributes,
2075
- statusJidList: options.statusJidList,
2076
- statusPrivacy: options.statusPrivacy,
2077
- additionalNodes,
2078
- AI: ai || false
2079
- })
2080
- if (config.emitOwnEvents) {
2081
- process.nextTick(async () => {
2082
- await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'))
2083
- })
2084
- }
2085
- return fullMsg
2086
- }
2087
- },
2088
-
2089
- sendMetaAI: async (jid1, text, opts = {}) => {
2090
- const crypto = require('crypto')
2091
- const { proto } = require('../../WAProto/index.js')
2092
- const META_AI_BOT_JID = '867051314767696@bot'
2093
- const yourJid = jid1 || ''
2094
- const jid = opts.jid || META_AI_BOT_JID
2095
- const threadId = opts.threadId || Utils_1.generateMessageIDV2(yourJid)
2096
- const now = Date.now()
2097
- const senderTimestamp = opts.senderTimestamp || String(Math.floor(now / 1000))
2098
- const messageSecret = opts.messageSecret || crypto.randomBytes(32)
2099
- const senderKeyHash = opts.senderKeyHash || crypto.randomBytes(8).toString('base64')
2100
- const message = {
2101
- extendedTextMessage: proto.Message.ExtendedTextMessage.fromObject({
2102
- text,
2103
- previewType: 'NONE',
2104
- contextInfo: proto.ContextInfo.fromObject({
2105
- botMessageSharingInfo: {
2106
- botEntryPointOrigin: 'FAVICON',
2107
- forwardScore: 0
2108
- }
2109
- }),
2110
- inviteLinkGroupTypeV2: 'DEFAULT'
2111
- }),
2112
- messageContextInfo: proto.MessageContextInfo.fromObject({
2113
- deviceListMetadata: {
2114
- senderKeyHash,
2115
- senderTimestamp
2116
- },
2117
- deviceListMetadataVersion: 2,
2118
- messageSecret,
2119
- botMetadata: {
2120
- botModeSelectionMetadata: {
2121
- overrideMode: [0]
2122
- },
2123
- botThreadInfo: {
2124
- serverInfo: { title: text.substring(0, 50) },
2125
- clientInfo: { type: 'DEFAULT' }
2126
- },
2127
- botRenderingConfigMetadata: {
2128
- bloksVersioningId: '1eb86e6f4117d052e6bab62fe758a2e2af43747b85c5c1a886c8262bac462ea4',
2129
- pixelDensity: 2.625
2130
- }
2131
- },
2132
- threadId: [
2133
- {
2134
- threadType: 'AI_THREAD',
2135
- threadKey: {
2136
- remoteJid: '0002@s.whatsapp.net',
2137
- fromMe: true,
2138
- id: threadId
2139
- }
2140
- }
2141
- ]
2142
- })
2143
- }
2144
- const msgId = (0, Utils_1.generateMessageIDV2)(yourJid)
2145
- const messageOptions = {
2146
- messageId: msgId,
2147
- quoted: opts.quoted,
2148
- links: opts.links
2149
- }
2150
- await relayMessage(jid, message, messageOptions)
2151
- return msgId
2152
- }
2153
- }
2154
- }
2155
- exports.makeMessagesSocket = makeMessagesSocket