@badzz88/baileys 8.4.7 → 8.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1055 -337
- package/WAProto/index.js +5 -5
- package/lib/Defaults/index.js +187 -127
- package/lib/Defaults/phonenumber-mcc.json +223 -0
- package/lib/Signal/Group/ciphertext-message.js +14 -11
- package/lib/Signal/Group/group-session-builder.js +91 -29
- package/lib/Signal/Group/group_cipher.js +88 -81
- package/lib/Signal/Group/index.js +136 -12
- package/lib/Signal/Group/keyhelper.js +70 -15
- package/lib/Signal/Group/sender-chain-key.js +31 -25
- package/lib/Signal/Group/sender-key-distribution-message.js +65 -62
- package/lib/Signal/Group/sender-key-message.js +68 -65
- package/lib/Signal/Group/sender-key-name.js +43 -41
- package/lib/Signal/Group/sender-key-record.js +43 -40
- package/lib/Signal/Group/sender-key-state.js +96 -83
- package/lib/Signal/Group/sender-message-key.js +29 -25
- package/lib/Signal/libsignal.js +483 -424
- package/lib/Signal/lid-mapping.js +261 -276
- package/lib/Socket/Client/index.js +30 -3
- package/lib/Socket/Client/types.js +12 -10
- package/lib/Socket/Client/websocket.js +61 -53
- package/lib/Socket/aigroups.js +240 -0
- package/lib/Socket/business.js +422 -379
- package/lib/Socket/chats.js +1816 -1193
- package/lib/Socket/communities.js +549 -431
- package/lib/Socket/graphql.js +656 -0
- package/lib/Socket/groups.js +764 -374
- package/lib/Socket/index.js +38 -11
- package/lib/Socket/interactive-handler.js +522 -0
- package/lib/Socket/interop.js +549 -0
- package/lib/Socket/luxu.js +6 -5
- package/lib/Socket/managed-account.js +183 -0
- package/lib/Socket/messages-recv.js +2439 -1915
- package/lib/Socket/messages-send.js +1642 -1242
- package/lib/Socket/mex.js +59 -40
- package/lib/Socket/newsletter.js +812 -249
- package/lib/Socket/privacy.js +449 -0
- package/lib/Socket/registration.js +427 -0
- package/lib/Socket/socket.js +1077 -965
- package/lib/Socket/text-router.js +83 -0
- package/lib/Socket/username.js +237 -140
- package/lib/Store/index.js +36 -10
- package/lib/Store/make-cache-manager-store.js +85 -80
- package/lib/Store/make-in-memory-store.js +591 -185
- package/lib/Store/make-ordered-dictionary.js +78 -72
- package/lib/Store/object-repository.js +25 -28
- package/lib/Types/Auth.js +38 -2
- package/lib/Types/Bussines.js +2 -2
- package/lib/Types/Call.js +2 -2
- package/lib/Types/Chat.js +4 -8
- package/lib/Types/Contact.js +2 -2
- package/lib/Types/Events.js +2 -2
- package/lib/Types/GroupMetadata.js +2 -2
- package/lib/Types/Label.js +26 -24
- package/lib/Types/LabelAssociation.js +8 -6
- package/lib/Types/Message.js +95 -11
- package/lib/Types/Mex.js +112 -37
- package/lib/Types/Newsletter.js +121 -0
- package/lib/Types/Product.js +2 -2
- package/lib/Types/Signal.js +2 -2
- package/lib/Types/Socket.js +2 -3
- package/lib/Types/State.js +70 -56
- package/lib/Types/USync.js +2 -2
- package/lib/Types/index.js +55 -26
- package/lib/Utils/auth-utils.js +292 -288
- package/lib/Utils/browser-utils.js +113 -48
- package/lib/Utils/business.js +240 -224
- package/lib/Utils/chat-utils.js +1205 -869
- package/lib/Utils/command-loader.d.ts +31 -0
- package/lib/Utils/command-loader.js +100 -0
- package/lib/Utils/companion-reg-client-utils.js +41 -34
- package/lib/Utils/consumer-application.js +107 -0
- package/lib/Utils/crypto.js +144 -107
- package/lib/Utils/curve25519-js.js +275 -0
- package/lib/Utils/decode-wa-message.js +518 -308
- package/lib/Utils/event-buffer.js +596 -611
- package/lib/Utils/generics.js +514 -354
- package/lib/Utils/group-history.js +60 -0
- package/lib/Utils/history.js +244 -134
- package/lib/Utils/identity-change-handler.js +51 -49
- package/lib/Utils/index.js +57 -23
- package/lib/Utils/jid-display-normalization.js +218 -0
- package/lib/Utils/link-preview.js +135 -77
- package/lib/Utils/logger.js +9 -3
- package/lib/Utils/lt-hash.js +37 -6
- package/lib/Utils/make-mutex.js +36 -33
- package/lib/Utils/message-composer.js +439 -233
- package/lib/Utils/message-retry-manager.js +265 -260
- package/lib/Utils/messages-media.js +855 -747
- package/lib/Utils/messages.js +2528 -884
- package/lib/Utils/meta-ai-msmsg.js +262 -0
- package/lib/Utils/native-bridge.js +82 -0
- package/lib/Utils/noise-handler.js +195 -200
- package/lib/Utils/offline-node-processor.js +35 -33
- package/lib/Utils/pre-key-manager.js +103 -102
- package/lib/Utils/process-message.js +978 -560
- package/lib/Utils/reporting-utils.js +257 -253
- package/lib/Utils/session-pool.d.ts +16 -0
- package/lib/Utils/session-pool.js +94 -0
- package/lib/Utils/signal.js +218 -195
- package/lib/Utils/stanza-ack.js +31 -29
- package/lib/Utils/sticker.d.ts +17 -0
- package/lib/Utils/sticker.js +145 -0
- package/lib/Utils/sync-action-utils.js +50 -45
- package/lib/Utils/tc-token-utils.js +137 -139
- package/lib/Utils/use-multi-file-auth-state.js +109 -109
- package/lib/Utils/validate-connection.js +218 -202
- package/lib/Utils/view-once-cache.d.ts +9 -0
- package/lib/Utils/view-once-cache.js +79 -0
- package/lib/Utils/voip-rekey.js +22 -0
- package/lib/WABinary/constants.js +1302 -1299
- package/lib/WABinary/decode.js +343 -262
- package/lib/WABinary/encode.js +12 -4
- package/lib/WABinary/generic-utils.js +223 -187
- package/lib/WABinary/index.js +33 -6
- package/lib/WABinary/jid-utils.js +351 -88
- package/lib/WABinary/types.js +2 -2
- package/lib/WAM/BinaryInfo.js +12 -9
- package/lib/WAM/constants.js +39486 -22853
- package/lib/WAM/encode.js +132 -140
- package/lib/WAM/index.js +31 -4
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +55 -0
- package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +43 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +53 -51
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +56 -53
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +29 -26
- package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +59 -0
- package/lib/WAUSync/Protocols/USyncLIDProtocol.js +31 -0
- package/lib/WAUSync/Protocols/USyncPictureProtocol.js +32 -0
- package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +29 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +38 -37
- package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +38 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +26 -24
- package/lib/WAUSync/Protocols/index.js +39 -6
- package/lib/WAUSync/USyncQuery.js +132 -97
- package/lib/WAUSync/USyncUser.js +49 -30
- package/lib/WAUSync/index.js +31 -4
- package/lib/antiban.js +4637 -0
- package/lib/index.js +48 -15
- package/package.json +55 -92
- package/lib/WAUSync/Protocols/USyncNewsletterProtocol.js +0 -263
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +0 -51
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +0 -29
package/lib/Utils/messages.js
CHANGED
|
@@ -1,31 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
'use strict'
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true })
|
|
3
|
+
exports.assertMediaContent =
|
|
4
|
+
exports.downloadMediaMessage =
|
|
5
|
+
exports.aggregateMessageKeysNotFromMe =
|
|
6
|
+
exports.updateMessageWithEventResponse =
|
|
7
|
+
exports.updateMessageWithPollUpdate =
|
|
8
|
+
exports.updateMessageWithReaction =
|
|
9
|
+
exports.updateMessageWithReceipt =
|
|
10
|
+
exports.getDevice =
|
|
11
|
+
exports.extractMessageContent =
|
|
12
|
+
exports.normalizeMessageContent =
|
|
13
|
+
exports.getContentType =
|
|
14
|
+
exports.generateWAMessage =
|
|
15
|
+
exports.generateWAMessageFromContent =
|
|
16
|
+
exports.generateWAMessageContent =
|
|
17
|
+
exports.hasNonNullishProperty =
|
|
18
|
+
exports.generateForwardMessageContent =
|
|
19
|
+
exports.prepareDisappearingMessageSettingContent =
|
|
20
|
+
exports.prepareWAMessageMedia =
|
|
21
|
+
exports.generateLinkPreviewIfRequired =
|
|
22
|
+
exports.extractUrlFromText =
|
|
23
|
+
void 0
|
|
24
|
+
exports.getAggregateVotesInPollMessage = getAggregateVotesInPollMessage
|
|
25
|
+
exports.getAggregateResponsesInEventMessage = getAggregateResponsesInEventMessage
|
|
26
|
+
const boom_1 = require('@hapi/boom')
|
|
27
|
+
const crypto_1 = require('crypto')
|
|
28
|
+
const fs_1 = require('fs')
|
|
29
|
+
const index_js_1 = require('../../WAProto/index.js')
|
|
30
|
+
const WAProto_1 = require('../../WAProto/index.js')
|
|
31
|
+
const Defaults_1 = require('../Defaults')
|
|
32
|
+
const Types_1 = require('../Types')
|
|
33
|
+
const WABinary_1 = require('../WABinary')
|
|
34
|
+
const crypto_2 = require('./crypto')
|
|
35
|
+
const generics_1 = require('./generics')
|
|
36
|
+
const messages_media_1 = require('./messages-media')
|
|
37
|
+
const reporting_utils_1 = require('./reporting-utils')
|
|
38
|
+
const jid_display_normalization_1 = require('./jid-display-normalization')
|
|
13
39
|
const MIMETYPE_MAP = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
40
|
+
image: 'image/jpeg',
|
|
41
|
+
video: 'video/mp4',
|
|
42
|
+
document: 'application/pdf',
|
|
43
|
+
audio: 'audio/ogg; codecs=opus',
|
|
44
|
+
sticker: 'image/webp',
|
|
45
|
+
'product-catalog-image': 'image/jpeg'
|
|
46
|
+
}
|
|
21
47
|
const MessageTypeProto = {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
48
|
+
image: WAProto_1.proto.Message.ImageMessage,
|
|
49
|
+
video: WAProto_1.proto.Message.VideoMessage,
|
|
50
|
+
audio: WAProto_1.proto.Message.AudioMessage,
|
|
51
|
+
sticker: WAProto_1.proto.Message.StickerMessage,
|
|
52
|
+
document: WAProto_1.proto.Message.DocumentMessage
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Input payloads can carry protobuf media message keys (e.g. imageMessage).
|
|
56
|
+
const MEDIA_MESSAGE_TYPE_ALIASES = {
|
|
57
|
+
imageMessage: 'image',
|
|
58
|
+
videoMessage: 'video',
|
|
59
|
+
audioMessage: 'audio',
|
|
60
|
+
documentMessage: 'document',
|
|
61
|
+
stickerMessage: 'sticker',
|
|
62
|
+
// PTV = push-to-video (video note) payload.
|
|
63
|
+
ptvMessage: 'video'
|
|
64
|
+
}
|
|
65
|
+
const MEDIA_MESSAGE_TYPE_ALIAS_KEYS = Object.keys(MEDIA_MESSAGE_TYPE_ALIASES)
|
|
66
|
+
const hasMediaPayload = message =>
|
|
67
|
+
Defaults_1.MEDIA_KEYS.some(key => key in message) || MEDIA_MESSAGE_TYPE_ALIAS_KEYS.some(key => key in message)
|
|
68
|
+
|
|
69
|
+
const ButtonType = WAProto_1.proto.Message.ButtonsMessage.HeaderType
|
|
70
|
+
|
|
29
71
|
const RICH_RESPONSE_CODE_KEYWORDS = new Set([
|
|
30
72
|
'break',
|
|
31
73
|
'case',
|
|
@@ -153,251 +195,333 @@ const tokenizeCode = code => {
|
|
|
153
195
|
}
|
|
154
196
|
return merged
|
|
155
197
|
}
|
|
198
|
+
|
|
156
199
|
/**
|
|
157
200
|
* Uses a regex to test whether the string contains a URL, and returns the URL if it does.
|
|
158
201
|
* @param text eg. hello https://google.com
|
|
159
202
|
* @returns the URL, eg. https://google.com
|
|
160
203
|
*/
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
204
|
+
const extractUrlFromText = text => text.match(Defaults_1.URL_REGEX)?.[0]
|
|
205
|
+
exports.extractUrlFromText = extractUrlFromText
|
|
206
|
+
const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
|
|
207
|
+
const url = (0, exports.extractUrlFromText)(text)
|
|
208
|
+
if (!!getUrlInfo && url) {
|
|
209
|
+
try {
|
|
210
|
+
const urlInfo = await getUrlInfo(url)
|
|
211
|
+
return urlInfo
|
|
212
|
+
} catch (error) {
|
|
213
|
+
// ignore if fails
|
|
214
|
+
logger?.warn({ trace: error.stack }, 'url generation failed')
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
exports.generateLinkPreviewIfRequired = generateLinkPreviewIfRequired
|
|
219
|
+
const assertColor = async color => {
|
|
220
|
+
let assertedColor
|
|
221
|
+
if (typeof color === 'number') {
|
|
222
|
+
assertedColor = color > 0 ? color : 0xffffffff + Number(color) + 1
|
|
223
|
+
} else {
|
|
224
|
+
let hex = color.trim().replace('#', '')
|
|
225
|
+
if (hex.length <= 6) {
|
|
226
|
+
hex = 'FF' + hex.padStart(6, '0')
|
|
227
|
+
}
|
|
228
|
+
assertedColor = parseInt(hex, 16)
|
|
229
|
+
return assertedColor
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const prepareWAMessageMedia = async (message, options) => {
|
|
233
|
+
const logger = options.logger
|
|
234
|
+
let mediaType
|
|
235
|
+
for (const key of Defaults_1.MEDIA_KEYS) {
|
|
236
|
+
if (key in message) {
|
|
237
|
+
mediaType = key
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (!mediaType) {
|
|
241
|
+
throw new boom_1.Boom('Invalid media type', { statusCode: 400 })
|
|
242
|
+
}
|
|
243
|
+
const uploadData = {
|
|
244
|
+
...message,
|
|
245
|
+
media: message[mediaType]
|
|
246
|
+
}
|
|
247
|
+
delete uploadData[mediaType]
|
|
248
|
+
// check if cacheable + generate cache key
|
|
249
|
+
const cacheableKey =
|
|
250
|
+
typeof uploadData.media === 'object' &&
|
|
251
|
+
'url' in uploadData.media &&
|
|
252
|
+
!!uploadData.media.url &&
|
|
253
|
+
!!options.mediaCache &&
|
|
254
|
+
mediaType + ':' + uploadData.media.url.toString()
|
|
255
|
+
if (mediaType === 'document' && !uploadData.fileName) {
|
|
256
|
+
uploadData.fileName = 'file'
|
|
257
|
+
}
|
|
258
|
+
if (!uploadData.mimetype) {
|
|
259
|
+
uploadData.mimetype = MIMETYPE_MAP[mediaType]
|
|
260
|
+
}
|
|
261
|
+
if (cacheableKey) {
|
|
262
|
+
const mediaBuff = await options.mediaCache.get(cacheableKey)
|
|
263
|
+
if (mediaBuff) {
|
|
264
|
+
logger?.debug({ cacheableKey }, 'got media cache hit')
|
|
265
|
+
const obj = index_js_1.proto.Message.decode(mediaBuff)
|
|
266
|
+
const key = `${mediaType}Message`
|
|
267
|
+
Object.assign(obj[key], { ...uploadData, media: undefined })
|
|
268
|
+
return obj
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const isNewsletter = !!options.jid && (0, WABinary_1.isJidNewsletter)(options.jid)
|
|
272
|
+
if (isNewsletter) {
|
|
273
|
+
logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter')
|
|
274
|
+
const { filePath, fileSha256, fileLength } = await (0, messages_media_1.getRawMediaUploadData)(
|
|
275
|
+
uploadData.media,
|
|
276
|
+
options.mediaTypeOverride || mediaType,
|
|
277
|
+
logger
|
|
278
|
+
)
|
|
279
|
+
const fileSha256B64 = fileSha256.toString('base64')
|
|
280
|
+
const { mediaUrl, directPath } = await options.upload(filePath, {
|
|
281
|
+
fileEncSha256B64: fileSha256B64,
|
|
282
|
+
mediaType: mediaType,
|
|
283
|
+
timeoutMs: options.mediaUploadTimeoutMs
|
|
284
|
+
})
|
|
285
|
+
await fs_1.promises.unlink(filePath)
|
|
286
|
+
const obj = WAProto_1.proto.Message.fromObject({
|
|
287
|
+
// todo: add more support here
|
|
288
|
+
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
289
|
+
url: mediaUrl,
|
|
290
|
+
directPath,
|
|
291
|
+
fileSha256,
|
|
292
|
+
fileLength,
|
|
293
|
+
...uploadData,
|
|
294
|
+
media: undefined
|
|
295
|
+
})
|
|
296
|
+
})
|
|
297
|
+
if (uploadData.ptv) {
|
|
298
|
+
obj.ptvMessage = obj.videoMessage
|
|
299
|
+
delete obj.videoMessage
|
|
300
|
+
}
|
|
301
|
+
if (obj.stickerMessage) {
|
|
302
|
+
obj.stickerMessage.stickerSentTs = Date.now()
|
|
303
|
+
}
|
|
304
|
+
if (cacheableKey) {
|
|
305
|
+
logger?.debug({ cacheableKey }, 'set cache')
|
|
306
|
+
await options.mediaCache.set(cacheableKey, WAProto_1.proto.Message.encode(obj).finish())
|
|
307
|
+
}
|
|
308
|
+
return obj
|
|
309
|
+
}
|
|
310
|
+
const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined'
|
|
311
|
+
const requiresThumbnailComputation =
|
|
312
|
+
(mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined'
|
|
313
|
+
|
|
314
|
+
const requiresWaveformProcessing =
|
|
315
|
+
mediaType === 'audio' && uploadData.ptt === true && typeof uploadData.waveform === 'undefined'
|
|
316
|
+
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true
|
|
317
|
+
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation
|
|
318
|
+
const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await (0,
|
|
319
|
+
messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
320
|
+
logger,
|
|
321
|
+
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
322
|
+
opts: options.options
|
|
323
|
+
})
|
|
324
|
+
const fileEncSha256B64 = fileEncSha256.toString('base64')
|
|
325
|
+
const [{ mediaUrl, directPath }] = await Promise.all([
|
|
326
|
+
(async () => {
|
|
327
|
+
const result = await options.upload(encFilePath, {
|
|
328
|
+
fileEncSha256B64,
|
|
329
|
+
mediaType,
|
|
330
|
+
timeoutMs: options.mediaUploadTimeoutMs
|
|
331
|
+
})
|
|
332
|
+
logger?.debug({ mediaType, cacheableKey }, 'uploaded media')
|
|
333
|
+
return result
|
|
334
|
+
})(),
|
|
335
|
+
(async () => {
|
|
336
|
+
try {
|
|
337
|
+
if (requiresThumbnailComputation) {
|
|
338
|
+
const { thumbnail, originalImageDimensions } = await (0, messages_media_1.generateThumbnail)(
|
|
339
|
+
originalFilePath,
|
|
340
|
+
mediaType,
|
|
341
|
+
options
|
|
342
|
+
)
|
|
343
|
+
uploadData.jpegThumbnail = thumbnail
|
|
344
|
+
if (!uploadData.width && originalImageDimensions) {
|
|
345
|
+
uploadData.width = originalImageDimensions.width
|
|
346
|
+
uploadData.height = originalImageDimensions.height
|
|
347
|
+
logger?.debug('set dimensions')
|
|
348
|
+
}
|
|
349
|
+
logger?.debug('generated thumbnail')
|
|
350
|
+
}
|
|
351
|
+
if (requiresDurationComputation) {
|
|
352
|
+
uploadData.seconds = await (0, messages_media_1.getAudioDuration)(originalFilePath)
|
|
353
|
+
logger?.debug('computed audio duration')
|
|
354
|
+
}
|
|
355
|
+
if (requiresWaveformProcessing) {
|
|
356
|
+
uploadData.waveform = await (0, messages_media_1.getAudioWaveform)(originalFilePath, logger)
|
|
357
|
+
logger?.debug('processed waveform')
|
|
358
|
+
}
|
|
359
|
+
if (requiresAudioBackground) {
|
|
360
|
+
uploadData.backgroundArgb = await assertColor(options.backgroundColor)
|
|
361
|
+
logger?.debug('computed backgroundColor audio status')
|
|
362
|
+
}
|
|
363
|
+
} catch (error) {
|
|
364
|
+
logger?.warn({ trace: error.stack }, 'failed to obtain extra info')
|
|
365
|
+
}
|
|
366
|
+
})()
|
|
367
|
+
]).finally(async () => {
|
|
368
|
+
try {
|
|
369
|
+
await fs_1.promises.unlink(encFilePath)
|
|
370
|
+
if (originalFilePath) {
|
|
371
|
+
await fs_1.promises.unlink(originalFilePath)
|
|
372
|
+
}
|
|
373
|
+
logger?.debug('removed tmp files')
|
|
374
|
+
} catch (error) {
|
|
375
|
+
logger?.warn('failed to remove tmp file')
|
|
376
|
+
}
|
|
377
|
+
})
|
|
378
|
+
const obj = WAProto_1.proto.Message.fromObject({
|
|
379
|
+
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
380
|
+
url: mediaUrl,
|
|
381
|
+
directPath,
|
|
382
|
+
mediaKey,
|
|
383
|
+
fileEncSha256,
|
|
384
|
+
fileSha256,
|
|
385
|
+
fileLength,
|
|
386
|
+
mediaKeyTimestamp: (0, generics_1.unixTimestampSeconds)(),
|
|
387
|
+
...uploadData,
|
|
388
|
+
media: undefined
|
|
389
|
+
})
|
|
390
|
+
})
|
|
391
|
+
if (uploadData.ptv) {
|
|
392
|
+
obj.ptvMessage = obj.videoMessage
|
|
393
|
+
delete obj.videoMessage
|
|
394
|
+
}
|
|
395
|
+
if (cacheableKey) {
|
|
396
|
+
logger?.debug({ cacheableKey }, 'set cache')
|
|
397
|
+
await options.mediaCache.set(cacheableKey, WAProto_1.proto.Message.encode(obj).finish())
|
|
398
|
+
}
|
|
399
|
+
return obj
|
|
400
|
+
}
|
|
401
|
+
exports.prepareWAMessageMedia = prepareWAMessageMedia
|
|
402
|
+
const prepareDisappearingMessageSettingContent = ephemeralExpiration => {
|
|
403
|
+
ephemeralExpiration = ephemeralExpiration || 0
|
|
404
|
+
const content = {
|
|
405
|
+
ephemeralMessage: {
|
|
406
|
+
message: {
|
|
407
|
+
protocolMessage: {
|
|
408
|
+
type: WAProto_1.proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
|
|
409
|
+
ephemeralExpiration
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return WAProto_1.proto.Message.fromObject(content)
|
|
415
|
+
}
|
|
416
|
+
exports.prepareDisappearingMessageSettingContent = prepareDisappearingMessageSettingContent
|
|
361
417
|
/**
|
|
362
418
|
* Generate forwarded message content like WA does
|
|
363
419
|
* @param message the message to forward
|
|
364
420
|
* @param options.forceForward will show the message as forwarded even if it is from you
|
|
365
421
|
*/
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
422
|
+
const generateForwardMessageContent = (message, forceForward) => {
|
|
423
|
+
let content = message.message
|
|
424
|
+
if (!content) {
|
|
425
|
+
throw new boom_1.Boom('no content in message', { statusCode: 400 })
|
|
426
|
+
}
|
|
427
|
+
// hacky copy
|
|
428
|
+
content = (0, exports.normalizeMessageContent)(content)
|
|
429
|
+
content = index_js_1.proto.Message.decode(index_js_1.proto.Message.encode(content).finish())
|
|
430
|
+
let key = Object.keys(content)[0]
|
|
431
|
+
let score = content?.[key]?.contextInfo?.forwardingScore || 0
|
|
432
|
+
score += message.key.fromMe && !forceForward ? 0 : 1
|
|
433
|
+
if (key === 'conversation') {
|
|
434
|
+
content.extendedTextMessage = { text: content[key] }
|
|
435
|
+
delete content.conversation
|
|
436
|
+
key = 'extendedTextMessage'
|
|
437
|
+
}
|
|
438
|
+
const key_ = content?.[key]
|
|
439
|
+
if (score > 0) {
|
|
440
|
+
key_.contextInfo = { forwardingScore: score, isForwarded: true }
|
|
441
|
+
} else {
|
|
442
|
+
key_.contextInfo = {}
|
|
443
|
+
}
|
|
444
|
+
return content
|
|
445
|
+
}
|
|
446
|
+
exports.generateForwardMessageContent = generateForwardMessageContent
|
|
447
|
+
const hasNonNullishProperty = (message, key) => {
|
|
448
|
+
return (
|
|
449
|
+
typeof message === 'object' &&
|
|
450
|
+
message !== null &&
|
|
451
|
+
key in message &&
|
|
452
|
+
message[key] !== null &&
|
|
453
|
+
message[key] !== undefined
|
|
454
|
+
)
|
|
455
|
+
}
|
|
456
|
+
exports.hasNonNullishProperty = hasNonNullishProperty
|
|
398
457
|
function hasOptionalProperty(obj, key) {
|
|
399
|
-
|
|
458
|
+
return typeof obj === 'object' && obj !== null && key in obj && obj[key] !== null
|
|
459
|
+
}
|
|
460
|
+
const normalizeEarFields = ear => {
|
|
461
|
+
const result = { ...ear }
|
|
462
|
+
const applyAlias = (fromKey, toKey) => {
|
|
463
|
+
if (result[fromKey] !== undefined && result[toKey] === undefined) result[toKey] = result[fromKey]
|
|
464
|
+
}
|
|
465
|
+
applyAlias('thumbnail_url', 'thumbnailUrl')
|
|
466
|
+
applyAlias('thumbnailUrl', 'thumbnail')
|
|
467
|
+
applyAlias('source_url', 'sourceUrl')
|
|
468
|
+
applyAlias('media_type', 'mediaType')
|
|
469
|
+
applyAlias('show_ad_attribution', 'showAdAttribution')
|
|
470
|
+
applyAlias('render_larger_thumbnail', 'renderLargerThumbnail')
|
|
471
|
+
if (result.thumbnail && !result.jpegThumbnail) result.jpegThumbnail = result.thumbnail
|
|
472
|
+
if (result.largeThumbnail !== undefined && result.renderLargerThumbnail === undefined)
|
|
473
|
+
result.renderLargerThumbnail = result.largeThumbnail
|
|
474
|
+
if (result.url && !result.sourceUrl) result.sourceUrl = result.url
|
|
475
|
+
delete result.thumbnail
|
|
476
|
+
delete result.largeThumbnail
|
|
477
|
+
delete result.url
|
|
478
|
+
delete result.thumbnail_url
|
|
479
|
+
delete result.source_url
|
|
480
|
+
delete result.media_type
|
|
481
|
+
delete result.show_ad_attribution
|
|
482
|
+
delete result.render_larger_thumbnail
|
|
483
|
+
return result
|
|
484
|
+
}
|
|
485
|
+
const normalizeQuickReplyButton = button => {
|
|
486
|
+
var _a
|
|
487
|
+
if (button.name && typeof button.name === 'string') {
|
|
488
|
+
return {
|
|
489
|
+
name: button.name,
|
|
490
|
+
buttonParamsJson:
|
|
491
|
+
typeof button.buttonParamsJson === 'string'
|
|
492
|
+
? button.buttonParamsJson
|
|
493
|
+
: JSON.stringify(button.buttonParamsJson || {})
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
if (button.type === 4 && button.nativeFlowInfo) {
|
|
497
|
+
const { name, paramsJson } = button.nativeFlowInfo
|
|
498
|
+
return {
|
|
499
|
+
name: name || 'quick_reply',
|
|
500
|
+
buttonParamsJson: typeof paramsJson === 'string' ? paramsJson : JSON.stringify(paramsJson || {})
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
const buttonTextObject = button.buttonText && typeof button.buttonText === 'object' ? button.buttonText : undefined
|
|
504
|
+
const displayTextCandidates = [
|
|
505
|
+
button.text,
|
|
506
|
+
button.displayText,
|
|
507
|
+
button.display_text,
|
|
508
|
+
typeof button.buttonText === 'string' ? button.buttonText : undefined,
|
|
509
|
+
buttonTextObject === null || buttonTextObject === void 0 ? void 0 : buttonTextObject.displayText,
|
|
510
|
+
buttonTextObject === null || buttonTextObject === void 0 ? void 0 : buttonTextObject.display_text
|
|
511
|
+
]
|
|
512
|
+
const displayText = displayTextCandidates.find(value => typeof value === 'string' && value.length > 0) || ''
|
|
513
|
+
const id =
|
|
514
|
+
button.buttonId || button.id || ((_a = button.buttonParamsJson) === null || _a === void 0 ? void 0 : _a.id) || ''
|
|
515
|
+
return {
|
|
516
|
+
name: 'quick_reply',
|
|
517
|
+
buttonParamsJson: JSON.stringify({
|
|
518
|
+
display_text: displayText,
|
|
519
|
+
id
|
|
520
|
+
})
|
|
521
|
+
}
|
|
400
522
|
}
|
|
523
|
+
const asciiDecode = arr => arr.map(e => String.fromCharCode(e)).join('')
|
|
524
|
+
|
|
401
525
|
const applyContextInfoAndMentions = (interactiveMessage, message) => {
|
|
402
526
|
if ('contextInfo' in message && !!message.contextInfo) {
|
|
403
527
|
interactiveMessage.contextInfo = message.contextInfo
|
|
@@ -409,11 +533,563 @@ const applyContextInfoAndMentions = (interactiveMessage, message) => {
|
|
|
409
533
|
}
|
|
410
534
|
}
|
|
411
535
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
536
|
+
const buildPaymentNoteMessage = async (paymentPayload, options, fallbackText = '') => {
|
|
537
|
+
let notes
|
|
538
|
+
if (paymentPayload === null || paymentPayload === void 0 ? void 0 : paymentPayload.sticker) {
|
|
539
|
+
const stickerPrep = await (0, exports.prepareWAMessageMedia)({ sticker: paymentPayload.sticker }, options)
|
|
540
|
+
notes = {
|
|
541
|
+
stickerMessage: {
|
|
542
|
+
...(stickerPrep === null || stickerPrep === void 0 ? void 0 : stickerPrep.stickerMessage),
|
|
543
|
+
contextInfo: paymentPayload === null || paymentPayload === void 0 ? void 0 : paymentPayload.contextInfo
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
} else if (
|
|
547
|
+
typeof (paymentPayload === null || paymentPayload === void 0 ? void 0 : paymentPayload.note) === 'string'
|
|
548
|
+
) {
|
|
549
|
+
notes = {
|
|
550
|
+
extendedTextMessage: {
|
|
551
|
+
text: paymentPayload.note,
|
|
552
|
+
contextInfo: paymentPayload === null || paymentPayload === void 0 ? void 0 : paymentPayload.contextInfo
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
} else if (
|
|
556
|
+
(paymentPayload === null || paymentPayload === void 0 ? void 0 : paymentPayload.noteMessage) &&
|
|
557
|
+
typeof paymentPayload.noteMessage === 'object'
|
|
558
|
+
) {
|
|
559
|
+
const noteKeys = Object.keys(paymentPayload.noteMessage)
|
|
560
|
+
const allowedNoteMessageKeys = ['extendedTextMessage', 'stickerMessage']
|
|
561
|
+
const hasOnlyAllowedKeys = noteKeys.length > 0 && noteKeys.every(key => allowedNoteMessageKeys.includes(key))
|
|
562
|
+
if (!noteKeys.length || !hasOnlyAllowedKeys) {
|
|
563
|
+
throw new boom_1.Boom('Invalid payment noteMessage', { statusCode: 400 })
|
|
564
|
+
}
|
|
565
|
+
notes = paymentPayload.noteMessage
|
|
566
|
+
} else {
|
|
567
|
+
notes = { extendedTextMessage: { text: fallbackText } }
|
|
568
|
+
}
|
|
569
|
+
return notes
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
const generateWAMessageContent = async (message, options) => {
|
|
573
|
+
var _a, _b
|
|
574
|
+
let m = {}
|
|
575
|
+
const hasCaptionWithoutMedia = 'caption' in message && !hasMediaPayload(message)
|
|
576
|
+
const hasCaptionContainer =
|
|
577
|
+
('groupStatus' in message && !!message.groupStatus) || ('viewOnce' in message && !!message.viewOnce)
|
|
578
|
+
if ((0, exports.hasNonNullishProperty)(message, 'text')) {
|
|
579
|
+
const extContent = { text: message.text }
|
|
580
|
+
let urlInfo = message.linkPreview
|
|
581
|
+
if (typeof urlInfo === 'undefined') {
|
|
582
|
+
urlInfo = await (0, exports.generateLinkPreviewIfRequired)(message.text, options.getUrlInfo, options.logger)
|
|
583
|
+
}
|
|
584
|
+
if (urlInfo) {
|
|
585
|
+
extContent.matchedText = urlInfo['matched-text']
|
|
586
|
+
extContent.jpegThumbnail = urlInfo.jpegThumbnail
|
|
587
|
+
extContent.description = urlInfo.description
|
|
588
|
+
extContent.title = urlInfo.title
|
|
589
|
+
extContent.previewType = 0
|
|
590
|
+
const img = urlInfo.highQualityThumbnail
|
|
591
|
+
if (img) {
|
|
592
|
+
extContent.thumbnailDirectPath = img.directPath
|
|
593
|
+
extContent.mediaKey = img.mediaKey
|
|
594
|
+
extContent.mediaKeyTimestamp = img.mediaKeyTimestamp
|
|
595
|
+
extContent.thumbnailWidth = img.width
|
|
596
|
+
extContent.thumbnailHeight = img.height
|
|
597
|
+
extContent.thumbnailSha256 = img.fileSha256
|
|
598
|
+
extContent.thumbnailEncSha256 = img.fileEncSha256
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (options.backgroundColor) {
|
|
602
|
+
extContent.backgroundArgb = await assertColor(options.backgroundColor)
|
|
603
|
+
}
|
|
604
|
+
if (options.font) {
|
|
605
|
+
extContent.font = options.font
|
|
606
|
+
}
|
|
607
|
+
if (
|
|
608
|
+
options.jid &&
|
|
609
|
+
(0, WABinary_1.isInteropUser)(options.jid) &&
|
|
610
|
+
!options.backgroundColor &&
|
|
611
|
+
!options.font &&
|
|
612
|
+
!urlInfo
|
|
613
|
+
) {
|
|
614
|
+
m.conversation = message.text
|
|
615
|
+
} else {
|
|
616
|
+
m.extendedTextMessage = extContent
|
|
617
|
+
}
|
|
618
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'contacts')) {
|
|
619
|
+
const contactLen = message.contacts.contacts.length
|
|
620
|
+
if (!contactLen) {
|
|
621
|
+
throw new boom_1.Boom('require atleast 1 contact', { statusCode: 400 })
|
|
622
|
+
}
|
|
623
|
+
if (contactLen === 1) {
|
|
624
|
+
m.contactMessage = WAProto_1.proto.Message.ContactMessage.create(message.contacts.contacts[0])
|
|
625
|
+
} else {
|
|
626
|
+
m.contactsArrayMessage = WAProto_1.proto.Message.ContactsArrayMessage.create(message.contacts)
|
|
627
|
+
}
|
|
628
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'location')) {
|
|
629
|
+
m.locationMessage = WAProto_1.proto.Message.LocationMessage.create(message.location)
|
|
630
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'react')) {
|
|
631
|
+
if (!message.react.senderTimestampMs) {
|
|
632
|
+
message.react.senderTimestampMs = Date.now()
|
|
633
|
+
}
|
|
634
|
+
m.reactionMessage = WAProto_1.proto.Message.ReactionMessage.create(message.react)
|
|
635
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'delete')) {
|
|
636
|
+
m.protocolMessage = {
|
|
637
|
+
key: message.delete,
|
|
638
|
+
type: WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE
|
|
639
|
+
}
|
|
640
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'forward')) {
|
|
641
|
+
m = (0, exports.generateForwardMessageContent)(message.forward, message.force)
|
|
642
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'disappearingMessagesInChat')) {
|
|
643
|
+
const exp =
|
|
644
|
+
typeof message.disappearingMessagesInChat === 'boolean'
|
|
645
|
+
? message.disappearingMessagesInChat
|
|
646
|
+
? Defaults_1.WA_DEFAULT_EPHEMERAL
|
|
647
|
+
: 0
|
|
648
|
+
: message.disappearingMessagesInChat
|
|
649
|
+
m = (0, exports.prepareDisappearingMessageSettingContent)(exp)
|
|
650
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'groupInvite')) {
|
|
651
|
+
m.groupInviteMessage = {}
|
|
652
|
+
m.groupInviteMessage.inviteCode = message.groupInvite.inviteCode
|
|
653
|
+
m.groupInviteMessage.inviteExpiration = message.groupInvite.inviteExpiration
|
|
654
|
+
m.groupInviteMessage.caption = message.groupInvite.text
|
|
655
|
+
m.groupInviteMessage.groupJid = message.groupInvite.jid
|
|
656
|
+
m.groupInviteMessage.groupName = message.groupInvite.subject
|
|
657
|
+
//TODO: use built-in interface and get disappearing mode info etc.
|
|
658
|
+
//TODO: cache / use store!?
|
|
659
|
+
if (options.getProfilePicUrl) {
|
|
660
|
+
const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview')
|
|
661
|
+
if (pfpUrl) {
|
|
662
|
+
const resp = await fetch(pfpUrl, { method: 'GET', dispatcher: options?.options?.dispatcher })
|
|
663
|
+
if (resp.ok) {
|
|
664
|
+
const buf = Buffer.from(await resp.arrayBuffer())
|
|
665
|
+
m.groupInviteMessage.jpegThumbnail = buf
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'pin')) {
|
|
670
|
+
m.pinInChatMessage = {}
|
|
671
|
+
m.messageContextInfo = {}
|
|
672
|
+
m.pinInChatMessage.key = message.pin
|
|
673
|
+
m.pinInChatMessage.type = message.type
|
|
674
|
+
m.pinInChatMessage.senderTimestampMs = Date.now()
|
|
675
|
+
m.messageContextInfo.messageAddOnDurationInSecs = message.type === 1 ? message.time || 86400 : 0
|
|
676
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'buttonReply')) {
|
|
677
|
+
switch (message.type) {
|
|
678
|
+
case 'template':
|
|
679
|
+
m.templateButtonReplyMessage = {
|
|
680
|
+
selectedDisplayText: message.buttonReply.displayText,
|
|
681
|
+
selectedId: message.buttonReply.id,
|
|
682
|
+
selectedIndex: message.buttonReply.index
|
|
683
|
+
}
|
|
684
|
+
break
|
|
685
|
+
case 'plain':
|
|
686
|
+
m.buttonsResponseMessage = {
|
|
687
|
+
selectedButtonId: message.buttonReply.id,
|
|
688
|
+
selectedDisplayText: message.buttonReply.displayText,
|
|
689
|
+
type: index_js_1.proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
|
|
690
|
+
}
|
|
691
|
+
break
|
|
692
|
+
case 'interactive':
|
|
693
|
+
m.interactiveResponseMessage = {
|
|
694
|
+
body: {
|
|
695
|
+
text: message.buttonReply.displayText,
|
|
696
|
+
format: WAProto_1.proto.Message.InteractiveResponseMessage.Body.Format.EXTENSIONS_1
|
|
697
|
+
},
|
|
698
|
+
nativeFlowResponseMessage: {
|
|
699
|
+
name: message.buttonReply.nativeFlows.name,
|
|
700
|
+
paramsJson: message.buttonReply.nativeFlows.paramsJson,
|
|
701
|
+
version: message.buttonReply.nativeFlows.version
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
break
|
|
705
|
+
case 'list':
|
|
706
|
+
m.listResponseMessage = {
|
|
707
|
+
title: message.buttonReply.title,
|
|
708
|
+
description: message.buttonReply.description,
|
|
709
|
+
singleSelectReply: {
|
|
710
|
+
selectedRowId: message.buttonReply.rowId
|
|
711
|
+
},
|
|
712
|
+
listType: WAProto_1.proto.Message.ListResponseMessage.ListType.SINGLE_SELECT
|
|
713
|
+
}
|
|
714
|
+
break
|
|
715
|
+
}
|
|
716
|
+
} else if (hasOptionalProperty(message, 'ptv') && message.ptv) {
|
|
717
|
+
const { videoMessage } = await (0, exports.prepareWAMessageMedia)({ video: message.video }, options)
|
|
718
|
+
m.ptvMessage = videoMessage
|
|
719
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'product')) {
|
|
720
|
+
const { imageMessage } = await (0, exports.prepareWAMessageMedia)({ image: message.product.productImage }, options)
|
|
721
|
+
m.productMessage = WAProto_1.proto.Message.ProductMessage.create({
|
|
722
|
+
...message,
|
|
723
|
+
product: {
|
|
724
|
+
...message.product,
|
|
725
|
+
productImage: imageMessage
|
|
726
|
+
}
|
|
727
|
+
})
|
|
728
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'listReply')) {
|
|
729
|
+
m.listResponseMessage = { ...message.listReply }
|
|
730
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'event')) {
|
|
731
|
+
m.eventMessage = {}
|
|
732
|
+
const startTime = Math.floor(message.event.startDate.getTime() / 1000)
|
|
733
|
+
if (message.event.call && options.getCallLink) {
|
|
734
|
+
const token = await options.getCallLink(message.event.call, { startTime })
|
|
735
|
+
m.eventMessage.joinLink =
|
|
736
|
+
(message.event.call === 'audio' ? Defaults_1.CALL_AUDIO_PREFIX : Defaults_1.CALL_VIDEO_PREFIX) + token
|
|
737
|
+
}
|
|
738
|
+
m.messageContextInfo = {
|
|
739
|
+
// encKey
|
|
740
|
+
messageSecret: message.event.messageSecret || (0, crypto_1.randomBytes)(32)
|
|
741
|
+
}
|
|
742
|
+
m.eventMessage.name = message.event.name
|
|
743
|
+
m.eventMessage.description = message.event.description
|
|
744
|
+
m.eventMessage.startTime = startTime
|
|
745
|
+
m.eventMessage.endTime = message.event.endDate ? message.event.endDate.getTime() / 1000 : undefined
|
|
746
|
+
m.eventMessage.isCanceled = message.event.isCancelled ?? false
|
|
747
|
+
m.eventMessage.extraGuestsAllowed = message.event.extraGuestsAllowed
|
|
748
|
+
m.eventMessage.isScheduleCall = message.event.isScheduleCall ?? false
|
|
749
|
+
m.eventMessage.location = message.event.location
|
|
750
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'poll')) {
|
|
751
|
+
;(_a = message.poll).selectableCount || (_a.selectableCount = 0)
|
|
752
|
+
;(_b = message.poll).toAnnouncementGroup || (_b.toAnnouncementGroup = false)
|
|
753
|
+
if (!Array.isArray(message.poll.values)) {
|
|
754
|
+
throw new boom_1.Boom('Invalid poll values', { statusCode: 400 })
|
|
755
|
+
}
|
|
756
|
+
if (message.poll.selectableCount < 0 || message.poll.selectableCount > message.poll.values.length) {
|
|
757
|
+
throw new boom_1.Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, {
|
|
758
|
+
statusCode: 400
|
|
759
|
+
})
|
|
760
|
+
}
|
|
761
|
+
m.messageContextInfo = {
|
|
762
|
+
messageSecret: message.poll.messageSecret || (0, crypto_1.randomBytes)(32)
|
|
763
|
+
}
|
|
764
|
+
const isQuiz = message.poll.type === 'quiz' || message.poll.pollType === WAProto_1.proto.Message.PollType.QUIZ
|
|
765
|
+
const pollTypeEnum = WAProto_1.proto.Message.PollType
|
|
766
|
+
const pollCreationMessage = {
|
|
767
|
+
name: message.poll.name,
|
|
768
|
+
selectableOptionsCount: message.poll.selectableCount,
|
|
769
|
+
options: message.poll.values.map(optionName => ({ optionName })),
|
|
770
|
+
pollType: isQuiz ? pollTypeEnum.QUIZ : pollTypeEnum.POLL,
|
|
771
|
+
...(isQuiz && message.poll.correctAnswer ? { correctAnswer: { optionName: message.poll.correctAnswer } } : {}),
|
|
772
|
+
...(message.poll.endTime
|
|
773
|
+
? {
|
|
774
|
+
endTime:
|
|
775
|
+
message.poll.endTime instanceof Date
|
|
776
|
+
? Math.floor(message.poll.endTime.getTime() / 1000)
|
|
777
|
+
: Number(message.poll.endTime)
|
|
778
|
+
}
|
|
779
|
+
: {}),
|
|
780
|
+
...(message.poll.hideParticipantName !== undefined
|
|
781
|
+
? { hideParticipantName: !!message.poll.hideParticipantName }
|
|
782
|
+
: {}),
|
|
783
|
+
...(message.poll.allowAddOption !== undefined ? { allowAddOption: !!message.poll.allowAddOption } : {})
|
|
784
|
+
}
|
|
785
|
+
if (message.poll.version === 6 || message.poll.v6) {
|
|
786
|
+
m.pollCreationMessageV6 = pollCreationMessage
|
|
787
|
+
} else if (message.poll.version === 5 || message.poll.v5) {
|
|
788
|
+
m.pollCreationMessageV5 = pollCreationMessage
|
|
789
|
+
} else if (message.poll.toAnnouncementGroup) {
|
|
790
|
+
// poll v2 is for community announcement groups (single select and multiple)
|
|
791
|
+
m.pollCreationMessageV2 = pollCreationMessage
|
|
792
|
+
} else {
|
|
793
|
+
if (message.poll.selectableCount === 1) {
|
|
794
|
+
//poll v3 is for single select polls
|
|
795
|
+
m.pollCreationMessageV3 = pollCreationMessage
|
|
796
|
+
} else {
|
|
797
|
+
// poll for multiple choice polls
|
|
798
|
+
m.pollCreationMessage = pollCreationMessage
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
} else if ('inviteAdmin' in message) {
|
|
802
|
+
m.newsletterAdminInviteMessage = {}
|
|
803
|
+
m.newsletterAdminInviteMessage.inviteExpiration = message.inviteAdmin.inviteExpiration
|
|
804
|
+
m.newsletterAdminInviteMessage.caption = message.inviteAdmin.text
|
|
805
|
+
m.newsletterAdminInviteMessage.newsletterJid = message.inviteAdmin.jid
|
|
806
|
+
m.newsletterAdminInviteMessage.newsletterName = message.inviteAdmin.subject
|
|
807
|
+
m.newsletterAdminInviteMessage.jpegThumbnail = message.inviteAdmin.thumbnail
|
|
808
|
+
} else if ('requestPayment' in message || 'requestPaymentMessage' in message) {
|
|
809
|
+
if ('requestPayment' in message && 'requestPaymentMessage' in message) {
|
|
810
|
+
throw new boom_1.Boom('Use either requestPayment or requestPaymentMessage, not both', { statusCode: 400 })
|
|
811
|
+
}
|
|
812
|
+
const requestPayment = message.requestPayment || message.requestPaymentMessage
|
|
813
|
+
const notes = await buildPaymentNoteMessage(requestPayment, options)
|
|
814
|
+
const amountValue = requestPayment.amount ?? requestPayment.amount1000
|
|
815
|
+
const amount1000Raw =
|
|
816
|
+
typeof (amountValue === null || amountValue === void 0 ? void 0 : amountValue.toNumber) === 'function'
|
|
817
|
+
? amountValue.toNumber()
|
|
818
|
+
: Number(amountValue)
|
|
819
|
+
const amount1000 = Number.isFinite(amount1000Raw) ? Math.round(amount1000Raw) : amount1000Raw
|
|
820
|
+
const currencyCodeIso4217 = requestPayment.currency ?? requestPayment.currencyCodeIso4217
|
|
821
|
+
const requestFrom = requestPayment.from ?? requestPayment.requestFrom ?? options.recipientJid
|
|
822
|
+
const missingFields = []
|
|
823
|
+
if (amountValue === undefined) missingFields.push('amount/amount1000')
|
|
824
|
+
if (currencyCodeIso4217 === undefined) missingFields.push('currency/currencyCodeIso4217')
|
|
825
|
+
if (requestFrom === undefined) missingFields.push('from/requestFrom')
|
|
826
|
+
if (missingFields.length) {
|
|
827
|
+
throw new boom_1.Boom(`Invalid requestPayment fields: missing ${missingFields.join(', ')}`, { statusCode: 400 })
|
|
828
|
+
}
|
|
829
|
+
if (
|
|
830
|
+
typeof amount1000 !== 'number' ||
|
|
831
|
+
!Number.isFinite(amount1000) ||
|
|
832
|
+
!Number.isInteger(amount1000) ||
|
|
833
|
+
amount1000 <= 0
|
|
834
|
+
) {
|
|
835
|
+
throw new boom_1.Boom('Invalid requestPayment fields: amount/amount1000 must be a positive integer', {
|
|
836
|
+
statusCode: 400
|
|
837
|
+
})
|
|
838
|
+
}
|
|
839
|
+
const bg = requestPayment.background
|
|
840
|
+
m.requestPaymentMessage = WAProto_1.proto.Message.RequestPaymentMessage.fromObject({
|
|
841
|
+
expiryTimestamp: requestPayment.expiry ?? requestPayment.expiryTimestamp,
|
|
842
|
+
amount1000,
|
|
843
|
+
currencyCodeIso4217,
|
|
844
|
+
requestFrom,
|
|
845
|
+
noteMessage: notes,
|
|
846
|
+
...(bg != null ? { background: bg } : {})
|
|
847
|
+
})
|
|
848
|
+
} else if ('sendPayment' in message || 'sendPaymentMessage' in message) {
|
|
849
|
+
if ('sendPayment' in message && 'sendPaymentMessage' in message) {
|
|
850
|
+
throw new boom_1.Boom('Use either sendPayment or sendPaymentMessage, not both', { statusCode: 400 })
|
|
851
|
+
}
|
|
852
|
+
const sendPayment = message.sendPayment || message.sendPaymentMessage
|
|
853
|
+
const notes = await buildPaymentNoteMessage(sendPayment, options, message.text || '')
|
|
854
|
+
const requestMessageKey = sendPayment.requestMessageKey ?? sendPayment.requestKey ?? sendPayment.request
|
|
855
|
+
if (!requestMessageKey) {
|
|
856
|
+
throw new boom_1.Boom('Invalid sendPayment fields: missing requestMessageKey/requestKey/request', {
|
|
857
|
+
statusCode: 400
|
|
858
|
+
})
|
|
859
|
+
}
|
|
860
|
+
m.sendPaymentMessage = WAProto_1.proto.Message.SendPaymentMessage.fromObject({
|
|
861
|
+
noteMessage: notes,
|
|
862
|
+
requestMessageKey,
|
|
863
|
+
...(sendPayment.background != null ? { background: sendPayment.background } : {}),
|
|
864
|
+
...(sendPayment.transactionData != null ? { transactionData: sendPayment.transactionData } : {})
|
|
865
|
+
})
|
|
866
|
+
} else if ('declinePaymentRequest' in message || 'declinePaymentRequestMessage' in message) {
|
|
867
|
+
if ('declinePaymentRequest' in message && 'declinePaymentRequestMessage' in message) {
|
|
868
|
+
throw new boom_1.Boom('Use either declinePaymentRequest or declinePaymentRequestMessage, not both', {
|
|
869
|
+
statusCode: 400
|
|
870
|
+
})
|
|
871
|
+
}
|
|
872
|
+
const declinePayment = message.declinePaymentRequest || message.declinePaymentRequestMessage
|
|
873
|
+
const key = (declinePayment === null || declinePayment === void 0 ? void 0 : declinePayment.key) || declinePayment
|
|
874
|
+
if (!key) {
|
|
875
|
+
throw new boom_1.Boom('Invalid declinePaymentRequest fields: missing key', { statusCode: 400 })
|
|
876
|
+
}
|
|
877
|
+
m.declinePaymentRequestMessage = WAProto_1.proto.Message.DeclinePaymentRequestMessage.fromObject({ key })
|
|
878
|
+
} else if ('cancelPaymentRequest' in message || 'cancelPaymentRequestMessage' in message) {
|
|
879
|
+
if ('cancelPaymentRequest' in message && 'cancelPaymentRequestMessage' in message) {
|
|
880
|
+
throw new boom_1.Boom('Use either cancelPaymentRequest or cancelPaymentRequestMessage, not both', {
|
|
881
|
+
statusCode: 400
|
|
882
|
+
})
|
|
883
|
+
}
|
|
884
|
+
const cancelPayment = message.cancelPaymentRequest || message.cancelPaymentRequestMessage
|
|
885
|
+
const key = (cancelPayment === null || cancelPayment === void 0 ? void 0 : cancelPayment.key) || cancelPayment
|
|
886
|
+
if (!key) {
|
|
887
|
+
throw new boom_1.Boom('Invalid cancelPaymentRequest fields: missing key', { statusCode: 400 })
|
|
888
|
+
}
|
|
889
|
+
m.cancelPaymentRequestMessage = WAProto_1.proto.Message.CancelPaymentRequestMessage.fromObject({ key })
|
|
890
|
+
} else if ('requestPaymentFrom' in message && !!message.requestPaymentFrom) {
|
|
891
|
+
const noteText = message.text || ''
|
|
892
|
+
m.requestPaymentMessage = WAProto_1.proto.Message.RequestPaymentMessage.fromObject({
|
|
893
|
+
requestFrom: message.requestPaymentFrom,
|
|
894
|
+
noteMessage: { extendedTextMessage: { text: noteText } }
|
|
895
|
+
})
|
|
896
|
+
} else if ('invoiceNote' in message) {
|
|
897
|
+
const preparedInvoice = await (0, exports.prepareWAMessageMedia)(message, options)
|
|
898
|
+
const mediaType = Object.keys(preparedInvoice)[0]
|
|
899
|
+
const mediaMsg = preparedInvoice[mediaType] || {}
|
|
900
|
+
m.invoiceMessage = WAProto_1.proto.Message.InvoiceMessage.fromObject({
|
|
901
|
+
note: message.invoiceNote,
|
|
902
|
+
token: message.invoiceToken || '',
|
|
903
|
+
attachmentType: mediaType === 'imageMessage' ? 1 : 0,
|
|
904
|
+
attachmentMimetype: mediaMsg.mimetype,
|
|
905
|
+
attachmentMediaKey: mediaMsg.mediaKey,
|
|
906
|
+
attachmentMediaKeyTimestamp: mediaMsg.mediaKeyTimestamp,
|
|
907
|
+
attachmentFileSha256: mediaMsg.fileSha256,
|
|
908
|
+
attachmentFileEncSha256: mediaMsg.fileEncSha256,
|
|
909
|
+
attachmentDirectPath: mediaMsg.directPath,
|
|
910
|
+
attachmentJpegThumbnail: mediaMsg.jpegThumbnail
|
|
911
|
+
})
|
|
912
|
+
} else if ('orderText' in message) {
|
|
913
|
+
m.orderMessage = WAProto_1.proto.Message.OrderMessage.fromObject({
|
|
914
|
+
message: message.orderText,
|
|
915
|
+
thumbnail: message.thumbnail,
|
|
916
|
+
status: message.orderStatus || 1,
|
|
917
|
+
surface: message.orderSurface || 1
|
|
918
|
+
})
|
|
919
|
+
} else if ('paymentInviteServiceType' in message) {
|
|
920
|
+
m.paymentInviteMessage = {
|
|
921
|
+
serviceType: message.paymentInviteServiceType,
|
|
922
|
+
expiryTimestamp: message.paymentInviteExpiry
|
|
923
|
+
}
|
|
924
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'sharePhoneNumber')) {
|
|
925
|
+
m.protocolMessage = {
|
|
926
|
+
type: index_js_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
|
|
927
|
+
}
|
|
928
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'requestPhoneNumber')) {
|
|
929
|
+
m.requestPhoneNumberMessage = {}
|
|
930
|
+
} else if ((0, exports.hasNonNullishProperty)(message, 'limitSharing')) {
|
|
931
|
+
m.protocolMessage = {
|
|
932
|
+
type: index_js_1.proto.Message.ProtocolMessage.Type.LIMIT_SHARING,
|
|
933
|
+
limitSharing: {
|
|
934
|
+
sharingLimited: message.limitSharing === true,
|
|
935
|
+
trigger: 1,
|
|
936
|
+
limitSharingSettingTimestamp: Date.now(),
|
|
937
|
+
initiatedByMe: true
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
} else if ('album' in message) {
|
|
941
|
+
const imageMessages = message.album.filter(item => 'image' in item)
|
|
942
|
+
const videoMessages = message.album.filter(item => 'video' in item)
|
|
943
|
+
m.albumMessage = WAProto_1.proto.Message.AlbumMessage.fromObject({
|
|
944
|
+
expectedImageCount: imageMessages.length,
|
|
945
|
+
expectedVideoCount: videoMessages.length
|
|
946
|
+
})
|
|
947
|
+
} else if ('pollResult' in message) {
|
|
948
|
+
if (!Array.isArray(message.pollResult.values)) {
|
|
949
|
+
throw new boom_1.Boom('Invalid pollResult values', { statusCode: 400 })
|
|
950
|
+
}
|
|
951
|
+
const isQuizResult =
|
|
952
|
+
message.pollResult.type === 'quiz' || message.pollResult.pollType === WAProto_1.proto.Message.PollType.QUIZ
|
|
953
|
+
const pollVotes = message.pollResult.values.map(([optionName, optionVoteCount]) => ({
|
|
954
|
+
optionName,
|
|
955
|
+
optionVoteCount
|
|
956
|
+
}))
|
|
957
|
+
const snapshotPayload = {
|
|
958
|
+
name: message.pollResult.name,
|
|
959
|
+
pollVotes,
|
|
960
|
+
pollType: isQuizResult ? WAProto_1.proto.Message.PollType.QUIZ : WAProto_1.proto.Message.PollType.POLL
|
|
961
|
+
}
|
|
962
|
+
if (message.pollResult.version === 3 || message.pollResult.v3) {
|
|
963
|
+
m.pollResultSnapshotMessageV3 = WAProto_1.proto.Message.PollResultSnapshotMessage.fromObject(snapshotPayload)
|
|
964
|
+
} else {
|
|
965
|
+
m.pollResultSnapshotMessage = snapshotPayload
|
|
966
|
+
}
|
|
967
|
+
} else if ('stickerPack' in message || 'stickerPackMessage' in message) {
|
|
968
|
+
if ('stickerPack' in message && 'stickerPackMessage' in message) {
|
|
969
|
+
throw new boom_1.Boom('Cannot specify both stickerPack and stickerPackMessage; use only one property.', {
|
|
970
|
+
statusCode: 400
|
|
971
|
+
})
|
|
972
|
+
}
|
|
973
|
+
const stickerPackMessage = 'stickerPack' in message ? message.stickerPack : message.stickerPackMessage
|
|
974
|
+
m.stickerPackMessage = WAProto_1.proto.Message.StickerPackMessage.fromObject(stickerPackMessage)
|
|
975
|
+
} else if ('listMessage' in message) {
|
|
976
|
+
const lm = { ...message.listMessage }
|
|
977
|
+
if (lm.text !== undefined && lm.description === undefined) {
|
|
978
|
+
lm.description = lm.text
|
|
979
|
+
delete lm.text
|
|
980
|
+
}
|
|
981
|
+
m = { listMessage: lm }
|
|
982
|
+
} else if ('buttonsMessage' in message) {
|
|
983
|
+
m = {
|
|
984
|
+
buttonsMessage: WAProto_1.proto.Message.ButtonsMessage.fromObject(message.buttonsMessage)
|
|
985
|
+
}
|
|
986
|
+
} else if ('interactiveMessage' in message) {
|
|
987
|
+
m = { interactiveMessage: message.interactiveMessage }
|
|
988
|
+
} else if ('richResponse' in message) {
|
|
989
|
+
// handled in richResponse block below
|
|
990
|
+
} else if ('groupStatusMessage' in message) {
|
|
991
|
+
m = { groupStatusMessage: WAProto_1.proto.Message.GroupStatusMessage.fromObject(message.groupStatusMessage) }
|
|
992
|
+
} else if (hasCaptionWithoutMedia && !hasCaptionContainer) {
|
|
993
|
+
m.extendedTextMessage = { text: message.caption }
|
|
994
|
+
} else if (hasCaptionWithoutMedia && hasCaptionContainer) {
|
|
995
|
+
m = {}
|
|
996
|
+
} else if (!hasCaptionWithoutMedia && hasMediaPayload(message)) {
|
|
997
|
+
m = await (0, exports.prepareWAMessageMedia)(message, options)
|
|
998
|
+
}
|
|
999
|
+
if ('buttons' in message && !!message.buttons) {
|
|
1000
|
+
const interactiveMessage = {
|
|
1001
|
+
nativeFlowMessage: WAProto_1.proto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
|
|
1002
|
+
buttons: message.buttons.map(normalizeQuickReplyButton)
|
|
1003
|
+
})
|
|
1004
|
+
}
|
|
1005
|
+
if ('text' in message) {
|
|
1006
|
+
interactiveMessage.body = { text: message.text }
|
|
1007
|
+
} else if ('caption' in message) {
|
|
1008
|
+
interactiveMessage.body = { text: message.caption }
|
|
1009
|
+
interactiveMessage.header = {
|
|
1010
|
+
title: message.title || '',
|
|
1011
|
+
subtitle: message.subtitle,
|
|
1012
|
+
hasMediaAttachment: Boolean(message.hasMediaAttachment)
|
|
1013
|
+
}
|
|
1014
|
+
Object.assign(interactiveMessage.header, m)
|
|
1015
|
+
}
|
|
1016
|
+
if ('title' in message && !!message.title && !interactiveMessage.header) {
|
|
1017
|
+
interactiveMessage.header = {
|
|
1018
|
+
title: message.title,
|
|
1019
|
+
subtitle: message.subtitle,
|
|
1020
|
+
hasMediaAttachment: Boolean(message.hasMediaAttachment)
|
|
1021
|
+
}
|
|
1022
|
+
} else if ('title' in message && !!message.title && interactiveMessage.header) {
|
|
1023
|
+
interactiveMessage.header.title = message.title
|
|
1024
|
+
if (message.subtitle !== undefined) {
|
|
1025
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
if ('footer' in message && !!message.footer) {
|
|
1029
|
+
interactiveMessage.footer = { text: message.footer }
|
|
1030
|
+
}
|
|
1031
|
+
applyContextInfoAndMentions(interactiveMessage, message)
|
|
1032
|
+
m = { interactiveMessage }
|
|
1033
|
+
} else if ('templateButtons' in message && !!message.templateButtons) {
|
|
1034
|
+
const msg = {
|
|
1035
|
+
hydratedButtons: message.hasOwnProperty('templateButtons') ? message.templateButtons : message.templateButtons
|
|
1036
|
+
}
|
|
1037
|
+
if ('text' in message) {
|
|
1038
|
+
msg.hydratedContentText = message.text
|
|
1039
|
+
} else {
|
|
1040
|
+
if ('caption' in message) {
|
|
1041
|
+
msg.hydratedContentText = message.caption
|
|
1042
|
+
}
|
|
1043
|
+
Object.assign(msg, m)
|
|
1044
|
+
}
|
|
1045
|
+
if ('footer' in message && !!message.footer) {
|
|
1046
|
+
msg.hydratedFooterText = message.footer
|
|
1047
|
+
}
|
|
1048
|
+
m = {
|
|
1049
|
+
templateMessage: {
|
|
1050
|
+
fourRowTemplate: msg,
|
|
1051
|
+
hydratedTemplate: msg
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
if ('sections' in message && !!message.sections) {
|
|
1056
|
+
const listMessage = {
|
|
1057
|
+
sections: message.sections,
|
|
1058
|
+
buttonText: message.buttonText,
|
|
1059
|
+
title: message.title,
|
|
1060
|
+
footerText: message.footer,
|
|
1061
|
+
description: message.text,
|
|
1062
|
+
listType: WAProto_1.proto.Message.ListMessage.ListType.SINGLE_SELECT
|
|
1063
|
+
}
|
|
1064
|
+
m = { listMessage }
|
|
1065
|
+
} else if ('productList' in message && !!message.productList) {
|
|
1066
|
+
if (
|
|
1067
|
+
!Array.isArray(message.productList) ||
|
|
1068
|
+
message.productList.length === 0 ||
|
|
1069
|
+
!Array.isArray(message.productList[0].products) ||
|
|
1070
|
+
message.productList[0].products.length === 0
|
|
1071
|
+
) {
|
|
1072
|
+
throw new boom_1.Boom('Invalid productList: must contain at least one section with one product', {
|
|
1073
|
+
statusCode: 400
|
|
1074
|
+
})
|
|
1075
|
+
}
|
|
1076
|
+
m.listMessage = {
|
|
1077
|
+
title: message.title,
|
|
1078
|
+
buttonText: message.buttonText,
|
|
1079
|
+
footerText: message.footer,
|
|
1080
|
+
description: message.text,
|
|
1081
|
+
productListInfo: {
|
|
1082
|
+
productSections: message.productList,
|
|
1083
|
+
headerImage: {
|
|
1084
|
+
productId: message.productList[0].products[0].productId
|
|
1085
|
+
},
|
|
1086
|
+
businessOwnerJid: message.businessOwnerJid
|
|
1087
|
+
},
|
|
1088
|
+
listType: WAProto_1.proto.Message.ListMessage.ListType.PRODUCT_LIST
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
if ('interactiveButtons' in message && !!message.interactiveButtons) {
|
|
1092
|
+
const nativeFlow = WAProto_1.proto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
|
|
417
1093
|
buttons: message.interactiveButtons,
|
|
418
1094
|
messageParamsJson: message.messageParams ?? "{}"
|
|
419
1095
|
});
|
|
@@ -480,34 +1156,53 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
480
1156
|
applyContextInfoAndMentions(interactiveMessage, message);
|
|
481
1157
|
m = { interactiveMessage };
|
|
482
1158
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
1159
|
+
if ('shop' in message && !!message.shop) {
|
|
1160
|
+
const interactiveMessage = {
|
|
1161
|
+
shopStorefrontMessage: WAProto_1.proto.Message.InteractiveMessage.ShopMessage.fromObject({
|
|
1162
|
+
surface: (_l = message.shop) === null || _l === void 0 ? void 0 : _l.surface,
|
|
1163
|
+
id: (_m = message.shop) === null || _m === void 0 ? void 0 : _m.id
|
|
1164
|
+
})
|
|
1165
|
+
}
|
|
1166
|
+
if ('text' in message) {
|
|
1167
|
+
interactiveMessage.body = {
|
|
1168
|
+
text: message.text
|
|
1169
|
+
}
|
|
1170
|
+
} else if ('caption' in message) {
|
|
1171
|
+
interactiveMessage.body = {
|
|
1172
|
+
text: message.caption
|
|
1173
|
+
}
|
|
1174
|
+
interactiveMessage.header = {
|
|
1175
|
+
title: message.title,
|
|
1176
|
+
subtitle: message.subtitle,
|
|
1177
|
+
hasMediaAttachment: Boolean(message.hasMediaAttachment)
|
|
1178
|
+
}
|
|
1179
|
+
Object.assign(interactiveMessage.header, m)
|
|
1180
|
+
}
|
|
1181
|
+
if ('footer' in message && !!message.footer) {
|
|
1182
|
+
interactiveMessage.footer = {
|
|
1183
|
+
text: message.footer
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
if ('title' in message && !!message.title) {
|
|
1187
|
+
interactiveMessage.header = {
|
|
1188
|
+
title: message.title,
|
|
1189
|
+
subtitle: message.subtitle,
|
|
1190
|
+
hasMediaAttachment: Boolean(message.hasMediaAttachment)
|
|
1191
|
+
}
|
|
1192
|
+
Object.assign(interactiveMessage.header, m)
|
|
1193
|
+
}
|
|
1194
|
+
applyContextInfoAndMentions(interactiveMessage, message)
|
|
1195
|
+
m = { interactiveMessage }
|
|
1196
|
+
if ('interactiveAsTemplate' in message && message.interactiveAsTemplate !== false) {
|
|
1197
|
+
m = { templateMessage: { interactiveMessageTemplate: interactiveMessage } }
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
if ('richResponse' in message) {
|
|
506
1201
|
const {
|
|
507
1202
|
text,
|
|
508
1203
|
code,
|
|
509
1204
|
language = 'javascript',
|
|
510
|
-
botJid = '
|
|
1205
|
+
botJid = '259786046210223@bot',
|
|
511
1206
|
table,
|
|
512
1207
|
latex,
|
|
513
1208
|
map,
|
|
@@ -537,12 +1232,22 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
537
1232
|
}
|
|
538
1233
|
})
|
|
539
1234
|
}
|
|
540
|
-
if (table
|
|
1235
|
+
if (table) {
|
|
1236
|
+
const isPlainArrayTable = Array.isArray(table)
|
|
1237
|
+
const rows = isPlainArrayTable ? table : table.rows
|
|
1238
|
+
if (!Array.isArray(rows)) {
|
|
1239
|
+
throw new boom_1.Boom(
|
|
1240
|
+
'richResponse.table must be an array of rows (e.g. [["h1","h2"],["a","b"]]) or { rows: [...] }',
|
|
1241
|
+
{ statusCode: 400 }
|
|
1242
|
+
)
|
|
1243
|
+
}
|
|
541
1244
|
sections.push({
|
|
542
1245
|
view_model: {
|
|
543
1246
|
primitive: {
|
|
544
|
-
rows:
|
|
545
|
-
cells: Array.isArray(row) ? row.map(c => ({ text: String(c) })) : row.cells
|
|
1247
|
+
rows: rows.map((row, idx) => ({
|
|
1248
|
+
cells: Array.isArray(row) ? row.map(c => ({ text: String(c) })) : row.cells,
|
|
1249
|
+
// when a plain 2D array is passed, the first row is treated as the table header
|
|
1250
|
+
isHeading: Array.isArray(row) ? isPlainArrayTable && idx === 0 : row.isHeading
|
|
546
1251
|
})),
|
|
547
1252
|
__typename: 'GenAITableUXPrimitive'
|
|
548
1253
|
},
|
|
@@ -604,14 +1309,14 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
604
1309
|
})
|
|
605
1310
|
}
|
|
606
1311
|
const unifiedData = {
|
|
607
|
-
response_id: responseId || randomUUID(),
|
|
1312
|
+
response_id: responseId || (0, crypto_1.randomUUID)(),
|
|
608
1313
|
sections
|
|
609
1314
|
}
|
|
610
|
-
return proto.Message.fromObject({
|
|
1315
|
+
return WAProto_1.proto.Message.fromObject({
|
|
611
1316
|
messageContextInfo: {
|
|
612
1317
|
deviceListMetadata: {},
|
|
613
1318
|
deviceListMetadataVersion: 2,
|
|
614
|
-
messageSecret: richSecret || randomBytes(32)
|
|
1319
|
+
messageSecret: richSecret || (0, crypto_1.randomBytes)(32)
|
|
615
1320
|
},
|
|
616
1321
|
botForwardedMessage: {
|
|
617
1322
|
message: {
|
|
@@ -633,628 +1338,1567 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
633
1338
|
}
|
|
634
1339
|
})
|
|
635
1340
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1341
|
+
if ('statusNotification' in message || 'statusNotificationMessage' in message) {
|
|
1342
|
+
const notifData = 'statusNotification' in message ? message.statusNotification : message.statusNotificationMessage
|
|
1343
|
+
m = { statusNotificationMessage: WAProto_1.proto.Message.StatusNotificationMessage.fromObject(notifData) }
|
|
1344
|
+
} else if ('statusQuestionAnswer' in message || 'statusQuestionAnswerMessage' in message) {
|
|
1345
|
+
const qaData =
|
|
1346
|
+
'statusQuestionAnswer' in message ? message.statusQuestionAnswer : message.statusQuestionAnswerMessage
|
|
1347
|
+
m = { statusQuestionAnswerMessage: WAProto_1.proto.Message.StatusQuestionAnswerMessage.fromObject(qaData) }
|
|
1348
|
+
} else if ('questionResponse' in message || 'questionResponseMessage' in message) {
|
|
1349
|
+
const qrData = 'questionResponse' in message ? message.questionResponse : message.questionResponseMessage
|
|
1350
|
+
m = { questionResponseMessage: WAProto_1.proto.Message.QuestionResponseMessage.fromObject(qrData) }
|
|
1351
|
+
} else if ('statusQuoted' in message || 'statusQuotedMessage' in message) {
|
|
1352
|
+
const sqData = 'statusQuoted' in message ? message.statusQuoted : message.statusQuotedMessage
|
|
1353
|
+
m = { statusQuotedMessage: WAProto_1.proto.Message.StatusQuotedMessage.fromObject(sqData) }
|
|
1354
|
+
} else if ('statusStickerInteraction' in message || 'statusStickerInteractionMessage' in message) {
|
|
1355
|
+
const ssiData =
|
|
1356
|
+
'statusStickerInteraction' in message ? message.statusStickerInteraction : message.statusStickerInteractionMessage
|
|
1357
|
+
m = { statusStickerInteractionMessage: WAProto_1.proto.Message.StatusStickerInteractionMessage.fromObject(ssiData) }
|
|
1358
|
+
} else if ('newsletterFollowerInvite' in message || 'newsletterFollowerInviteMessageV2' in message) {
|
|
1359
|
+
const nfiData =
|
|
1360
|
+
'newsletterFollowerInvite' in message
|
|
1361
|
+
? message.newsletterFollowerInvite
|
|
1362
|
+
: message.newsletterFollowerInviteMessageV2
|
|
1363
|
+
m = {
|
|
1364
|
+
newsletterFollowerInviteMessageV2: WAProto_1.proto.Message.NewsletterFollowerInviteMessage.fromObject(nfiData)
|
|
1365
|
+
}
|
|
1366
|
+
} else if ('messageHistoryNotice' in message) {
|
|
1367
|
+
m = { messageHistoryNotice: WAProto_1.proto.Message.MessageHistoryNotice.fromObject(message.messageHistoryNotice) }
|
|
1368
|
+
} else if ('scheduledCall' in message || 'scheduledCallCreationMessage' in message) {
|
|
1369
|
+
if ('scheduledCall' in message && 'scheduledCallCreationMessage' in message) {
|
|
1370
|
+
throw new boom_1.Boom('Use either scheduledCall or scheduledCallCreationMessage, not both', { statusCode: 400 })
|
|
1371
|
+
}
|
|
1372
|
+
const sc = message.scheduledCall || message.scheduledCallCreationMessage
|
|
1373
|
+
const scheduledTs =
|
|
1374
|
+
sc.scheduledAt instanceof Date
|
|
1375
|
+
? sc.scheduledAt.getTime()
|
|
1376
|
+
: sc.scheduledAt
|
|
1377
|
+
? Number(sc.scheduledAt)
|
|
1378
|
+
: sc.scheduledTimestampMs
|
|
1379
|
+
? Number(sc.scheduledTimestampMs)
|
|
1380
|
+
: Date.now() + 3600000
|
|
1381
|
+
const callTypeEnum = WAProto_1.proto.Message.ScheduledCallCreationMessage.CallType
|
|
1382
|
+
let callType = callTypeEnum.UNKNOWN
|
|
1383
|
+
if (sc.isVideo || sc.callType === 'video' || sc.callType === callTypeEnum.VIDEO) {
|
|
1384
|
+
callType = callTypeEnum.VIDEO
|
|
1385
|
+
} else if (sc.callType === 'voice' || sc.callType === callTypeEnum.VOICE || sc.callType === undefined) {
|
|
1386
|
+
callType = callTypeEnum.VOICE
|
|
1387
|
+
} else {
|
|
1388
|
+
callType = sc.callType ?? callTypeEnum.VOICE
|
|
1389
|
+
}
|
|
1390
|
+
m.scheduledCallCreationMessage = WAProto_1.proto.Message.ScheduledCallCreationMessage.fromObject({
|
|
1391
|
+
scheduledTimestampMs: scheduledTs,
|
|
1392
|
+
callType,
|
|
1393
|
+
title: sc.title || ''
|
|
1394
|
+
})
|
|
1395
|
+
} else if ('editScheduledCall' in message || 'scheduledCallEditMessage' in message) {
|
|
1396
|
+
if ('editScheduledCall' in message && 'scheduledCallEditMessage' in message) {
|
|
1397
|
+
throw new boom_1.Boom('Use either editScheduledCall or scheduledCallEditMessage, not both', { statusCode: 400 })
|
|
1398
|
+
}
|
|
1399
|
+
const esc = message.editScheduledCall || message.scheduledCallEditMessage
|
|
1400
|
+
const key = esc.key || esc
|
|
1401
|
+
if (!key || typeof key !== 'object' || !key.id) {
|
|
1402
|
+
throw new boom_1.Boom('editScheduledCall requires a valid message key with id', { statusCode: 400 })
|
|
1403
|
+
}
|
|
1404
|
+
m.scheduledCallEditMessage = WAProto_1.proto.Message.ScheduledCallEditMessage.fromObject({
|
|
1405
|
+
key,
|
|
1406
|
+
editType: WAProto_1.proto.Message.ScheduledCallEditMessage.EditType.CANCEL
|
|
1407
|
+
})
|
|
1408
|
+
} else if ('eventInvite' in message || 'eventInviteMessage' in message) {
|
|
1409
|
+
if ('eventInvite' in message && 'eventInviteMessage' in message) {
|
|
1410
|
+
throw new boom_1.Boom('Use either eventInvite or eventInviteMessage, not both', { statusCode: 400 })
|
|
1411
|
+
}
|
|
1412
|
+
const ei = message.eventInvite || message.eventInviteMessage
|
|
1413
|
+
const startTime =
|
|
1414
|
+
ei.startDate instanceof Date
|
|
1415
|
+
? Math.floor(ei.startDate.getTime() / 1000)
|
|
1416
|
+
: ei.startTime
|
|
1417
|
+
? Number(ei.startTime)
|
|
1418
|
+
: undefined
|
|
1419
|
+
const endTime =
|
|
1420
|
+
ei.endDate instanceof Date ? Math.floor(ei.endDate.getTime() / 1000) : ei.endTime ? Number(ei.endTime) : undefined
|
|
1421
|
+
if (!ei.eventId && !ei.id) {
|
|
1422
|
+
throw new boom_1.Boom('eventInvite requires an eventId', { statusCode: 400 })
|
|
1423
|
+
}
|
|
1424
|
+
m.eventInviteMessage = WAProto_1.proto.Message.EventInviteMessage.fromObject({
|
|
1425
|
+
eventId: ei.eventId || ei.id,
|
|
1426
|
+
eventTitle: ei.title || ei.eventTitle || '',
|
|
1427
|
+
caption: ei.text || ei.caption || '',
|
|
1428
|
+
startTime,
|
|
1429
|
+
endTime,
|
|
1430
|
+
isCanceled: ei.isCancelled ?? ei.isCanceled ?? false,
|
|
1431
|
+
jpegThumbnail: ei.thumbnail || ei.jpegThumbnail,
|
|
1432
|
+
contextInfo: ei.contextInfo
|
|
1433
|
+
})
|
|
1434
|
+
} else if ('comment' in message || 'commentMessage' in message) {
|
|
1435
|
+
if ('comment' in message && 'commentMessage' in message) {
|
|
1436
|
+
throw new boom_1.Boom('Use either comment or commentMessage, not both', { statusCode: 400 })
|
|
1437
|
+
}
|
|
1438
|
+
const cm = message.comment || message.commentMessage
|
|
1439
|
+
if (!cm.targetMessageKey && !cm.key) {
|
|
1440
|
+
throw new boom_1.Boom('comment requires a targetMessageKey', { statusCode: 400 })
|
|
1441
|
+
}
|
|
1442
|
+
m.commentMessage = WAProto_1.proto.Message.CommentMessage.fromObject({
|
|
1443
|
+
message: cm.message || cm.replyMessage,
|
|
1444
|
+
targetMessageKey: cm.targetMessageKey || cm.key
|
|
1445
|
+
})
|
|
1446
|
+
} else if ('splitPayment' in message || 'splitPaymentMessage' in message) {
|
|
1447
|
+
if ('splitPayment' in message && 'splitPaymentMessage' in message) {
|
|
1448
|
+
throw new boom_1.Boom('Use either splitPayment or splitPaymentMessage, not both', { statusCode: 400 })
|
|
1449
|
+
}
|
|
1450
|
+
const sp = message.splitPayment || message.splitPaymentMessage
|
|
1451
|
+
if (!sp.totalAmount || !sp.participants?.length) {
|
|
1452
|
+
throw new boom_1.Boom('splitPayment requires totalAmount and at least one participant', { statusCode: 400 })
|
|
1453
|
+
}
|
|
1454
|
+
m.splitPaymentMessage = WAProto_1.proto.Message.SplitPaymentMessage.fromObject({
|
|
1455
|
+
splitId: sp.splitId || (0, crypto_1.randomUUID)(),
|
|
1456
|
+
totalAmount: sp.totalAmount,
|
|
1457
|
+
description: sp.description || '',
|
|
1458
|
+
requesterJid: sp.requesterJid || options.userJid,
|
|
1459
|
+
participants: sp.participants.map(p => ({
|
|
1460
|
+
jid: p.jid,
|
|
1461
|
+
amount: p.amount,
|
|
1462
|
+
status: p.status ?? WAProto_1.proto.Message.SplitPaymentParticipant.SplitPaymentStatus.PENDING
|
|
1463
|
+
})),
|
|
1464
|
+
createdAtMs: sp.createdAtMs || Date.now(),
|
|
1465
|
+
contextInfo: sp.contextInfo
|
|
1466
|
+
})
|
|
1467
|
+
} else if ('p2pPaymentReminder' in message || 'p2PPaymentReminderNotification' in message) {
|
|
1468
|
+
if ('p2pPaymentReminder' in message && 'p2PPaymentReminderNotification' in message) {
|
|
1469
|
+
throw new boom_1.Boom('Use either p2pPaymentReminder or p2PPaymentReminderNotification, not both', {
|
|
1470
|
+
statusCode: 400
|
|
1471
|
+
})
|
|
1472
|
+
}
|
|
1473
|
+
const pr = message.p2pPaymentReminder || message.p2PPaymentReminderNotification
|
|
1474
|
+
const freqEnum = WAProto_1.proto.Message.P2PPaymentReminderNotification.ReminderFrequency
|
|
1475
|
+
const stateEnum = WAProto_1.proto.Message.P2PPaymentReminderNotification.ReminderState
|
|
1476
|
+
const freqMap = {
|
|
1477
|
+
weekly: freqEnum.WEEKLY,
|
|
1478
|
+
biweekly: freqEnum.BIWEEKLY,
|
|
1479
|
+
monthly: freqEnum.MONTHLY,
|
|
1480
|
+
custom: freqEnum.CUSTOM
|
|
1481
|
+
}
|
|
1482
|
+
const stateMap = {
|
|
1483
|
+
active: stateEnum.ACTIVE,
|
|
1484
|
+
paused: stateEnum.PAUSED,
|
|
1485
|
+
stopped: stateEnum.STOPPED,
|
|
1486
|
+
expired: stateEnum.EXPIRED,
|
|
1487
|
+
cancelled: stateEnum.CANCELLED
|
|
1488
|
+
}
|
|
1489
|
+
m.p2PPaymentReminderNotification = WAProto_1.proto.Message.P2PPaymentReminderNotification.fromObject({
|
|
1490
|
+
reminderId: pr.reminderId || (0, crypto_1.randomUUID)(),
|
|
1491
|
+
amount: pr.amount,
|
|
1492
|
+
frequency:
|
|
1493
|
+
typeof pr.frequency === 'string'
|
|
1494
|
+
? (freqMap[pr.frequency.toLowerCase()] ?? freqEnum.UNKNOWN_FREQUENCY)
|
|
1495
|
+
: (pr.frequency ?? freqEnum.UNKNOWN_FREQUENCY),
|
|
1496
|
+
nextReminderTimestamp: pr.nextReminderTimestamp,
|
|
1497
|
+
expiryTimestamp: pr.expiryTimestamp,
|
|
1498
|
+
state:
|
|
1499
|
+
typeof pr.state === 'string'
|
|
1500
|
+
? (stateMap[pr.state.toLowerCase()] ?? stateEnum.ACTIVE)
|
|
1501
|
+
: (pr.state ?? stateEnum.ACTIVE),
|
|
1502
|
+
description: pr.description || '',
|
|
1503
|
+
creatorJid: pr.creatorJid || options.userJid,
|
|
1504
|
+
receiverJid: pr.receiverJid,
|
|
1505
|
+
upiId: pr.upiId,
|
|
1506
|
+
createdTimestamp: pr.createdTimestamp || Date.now()
|
|
1507
|
+
})
|
|
1508
|
+
} else if ('conditionalReveal' in message || 'conditionalRevealMessage' in message) {
|
|
1509
|
+
if ('conditionalReveal' in message && 'conditionalRevealMessage' in message) {
|
|
1510
|
+
throw new boom_1.Boom('Use either conditionalReveal or conditionalRevealMessage, not both', { statusCode: 400 })
|
|
1511
|
+
}
|
|
1512
|
+
const cr = message.conditionalReveal || message.conditionalRevealMessage
|
|
1513
|
+
m.conditionalRevealMessage = WAProto_1.proto.Message.ConditionalRevealMessage.fromObject({
|
|
1514
|
+
conditionalRevealMessageType:
|
|
1515
|
+
WAProto_1.proto.Message.ConditionalRevealMessage.ConditionalRevealMessageType.SCHEDULED_MESSAGE,
|
|
1516
|
+
revealKeyId: cr.revealKeyId || (0, crypto_1.randomUUID)()
|
|
1517
|
+
})
|
|
1518
|
+
m.messageContextInfo = {
|
|
1519
|
+
messageSecret: cr.messageSecret || (0, crypto_1.randomBytes)(32)
|
|
1520
|
+
}
|
|
1521
|
+
} else if ('callLog' in message || 'callLogMessage' in message) {
|
|
1522
|
+
if ('callLog' in message && 'callLogMessage' in message) {
|
|
1523
|
+
throw new boom_1.Boom('Use either callLog or callLogMessage, not both', { statusCode: 400 })
|
|
1524
|
+
}
|
|
1525
|
+
const cl = message.callLog || message.callLogMessage
|
|
1526
|
+
const outcomeEnum = WAProto_1.proto.Message.CallLogMessage.CallOutcome
|
|
1527
|
+
const callTypeEnum = WAProto_1.proto.Message.CallLogMessage.CallType
|
|
1528
|
+
const outcomeMap = {
|
|
1529
|
+
connected: outcomeEnum.CONNECTED,
|
|
1530
|
+
missed: outcomeEnum.MISSED,
|
|
1531
|
+
failed: outcomeEnum.FAILED,
|
|
1532
|
+
rejected: outcomeEnum.REJECTED,
|
|
1533
|
+
accepted_elsewhere: outcomeEnum.ACCEPTED_ELSEWHERE,
|
|
1534
|
+
ongoing: outcomeEnum.ONGOING,
|
|
1535
|
+
silenced_by_dnd: outcomeEnum.SILENCED_BY_DND,
|
|
1536
|
+
silenced_unknown_caller: outcomeEnum.SILENCED_UNKNOWN_CALLER
|
|
1537
|
+
}
|
|
1538
|
+
const callTypeMap = {
|
|
1539
|
+
regular: callTypeEnum.REGULAR,
|
|
1540
|
+
scheduled_call: callTypeEnum.SCHEDULED_CALL,
|
|
1541
|
+
voice_chat: callTypeEnum.VOICE_CHAT
|
|
1542
|
+
}
|
|
1543
|
+
m.callLogMesssage = WAProto_1.proto.Message.CallLogMessage.fromObject({
|
|
1544
|
+
isVideo: cl.isVideo ?? false,
|
|
1545
|
+
callOutcome:
|
|
1546
|
+
typeof cl.outcome === 'string'
|
|
1547
|
+
? (outcomeMap[cl.outcome.toLowerCase()] ?? outcomeEnum.CONNECTED)
|
|
1548
|
+
: (cl.outcome ?? outcomeEnum.CONNECTED),
|
|
1549
|
+
durationSecs: cl.durationSecs || 0,
|
|
1550
|
+
callType:
|
|
1551
|
+
typeof cl.callType === 'string'
|
|
1552
|
+
? (callTypeMap[cl.callType.toLowerCase()] ?? callTypeEnum.REGULAR)
|
|
1553
|
+
: (cl.callType ?? callTypeEnum.REGULAR),
|
|
1554
|
+
participants: (cl.participants || []).map(p => ({
|
|
1555
|
+
jid: p.jid,
|
|
1556
|
+
callOutcome:
|
|
1557
|
+
typeof p.outcome === 'string'
|
|
1558
|
+
? (outcomeMap[p.outcome.toLowerCase()] ?? outcomeEnum.CONNECTED)
|
|
1559
|
+
: (p.outcome ?? p.callOutcome ?? outcomeEnum.CONNECTED)
|
|
1560
|
+
}))
|
|
1561
|
+
})
|
|
1562
|
+
} else if ('statusMention' in message || 'statusMentionMsg' in message) {
|
|
1563
|
+
const sm = message.statusMention || message.statusMentionMsg
|
|
1564
|
+
if (!sm || typeof sm !== 'object') {
|
|
1565
|
+
throw new boom_1.Boom('statusMention must be an object with a message property', { statusCode: 400 })
|
|
1566
|
+
}
|
|
1567
|
+
m.statusMentionMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1568
|
+
message: sm.message || sm
|
|
1569
|
+
})
|
|
1570
|
+
} else if ('question' in message || 'questionMessage' in message) {
|
|
1571
|
+
const q = message.question || message.questionMessage
|
|
1572
|
+
m.questionMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1573
|
+
message: q.message || (typeof q === 'object' && 'conversation' in q ? q : { conversation: String(q) })
|
|
1574
|
+
})
|
|
1575
|
+
} else if ('questionReply' in message || 'questionReplyMessage' in message) {
|
|
1576
|
+
const qr = message.questionReply || message.questionReplyMessage
|
|
1577
|
+
m.questionReplyMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1578
|
+
message: qr.message || (typeof qr === 'object' && 'conversation' in qr ? qr : { conversation: String(qr) })
|
|
1579
|
+
})
|
|
1580
|
+
} else if ('statusAddYours' in message) {
|
|
1581
|
+
const say = message.statusAddYours
|
|
1582
|
+
m.statusAddYours = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1583
|
+
message: say.message || say
|
|
1584
|
+
})
|
|
1585
|
+
} else if ('eventCoverImage' in message) {
|
|
1586
|
+
const eci = message.eventCoverImage
|
|
1587
|
+
m.eventCoverImage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1588
|
+
message: eci.message || eci
|
|
1589
|
+
})
|
|
1590
|
+
} else if ('spoilerMessage' in message || 'spoiler' in message) {
|
|
1591
|
+
const sp = message.spoilerMessage || message.spoiler
|
|
1592
|
+
m.spoilerMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1593
|
+
message: sp.message || sp
|
|
1594
|
+
})
|
|
1595
|
+
} else if ('lottieStickerMessage' in message || 'lottieSticker' in message) {
|
|
1596
|
+
const ls = message.lottieStickerMessage || message.lottieSticker
|
|
1597
|
+
m.lottieStickerMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1598
|
+
message: ls.message || ls
|
|
1599
|
+
})
|
|
1600
|
+
} else if ('groupStatusV2' in message || 'groupStatusMessageV2' in message) {
|
|
1601
|
+
const gsv2 = message.groupStatusV2 || message.groupStatusMessageV2
|
|
1602
|
+
m.groupStatusMessageV2 = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1603
|
+
message: gsv2.message || gsv2
|
|
1604
|
+
})
|
|
1605
|
+
} else if ('newsletterAdminProfile' in message || 'newsletterAdminProfileMessage' in message) {
|
|
1606
|
+
const nap = message.newsletterAdminProfile || message.newsletterAdminProfileMessage
|
|
1607
|
+
m.newsletterAdminProfileMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1608
|
+
message: nap.message || nap
|
|
1609
|
+
})
|
|
1610
|
+
} else if ('newsletterAdminProfileV2' in message || 'newsletterAdminProfileMessageV2' in message) {
|
|
1611
|
+
const nap2 = message.newsletterAdminProfileV2 || message.newsletterAdminProfileMessageV2
|
|
1612
|
+
m.newsletterAdminProfileMessageV2 = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1613
|
+
message: nap2.message || nap2
|
|
1614
|
+
})
|
|
1615
|
+
} else if ('botTask' in message || 'botTaskMessage' in message) {
|
|
1616
|
+
const bt = message.botTask || message.botTaskMessage
|
|
1617
|
+
m.botTaskMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1618
|
+
message: bt.message || bt
|
|
1619
|
+
})
|
|
1620
|
+
} else if ('botInvoke' in message || 'botInvokeMessage' in message) {
|
|
1621
|
+
const bi = message.botInvoke || message.botInvokeMessage
|
|
1622
|
+
m.botInvokeMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1623
|
+
message: bi.message || bi
|
|
1624
|
+
})
|
|
1625
|
+
} else if ('associatedChild' in message || 'associatedChildMessage' in message) {
|
|
1626
|
+
const ac = message.associatedChild || message.associatedChildMessage
|
|
1627
|
+
m.associatedChildMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1628
|
+
message: ac.message || ac
|
|
1629
|
+
})
|
|
1630
|
+
} else if ('groupStatusMention' in message || 'groupStatusMentionMessage' in message) {
|
|
1631
|
+
const gsm = message.groupStatusMention || message.groupStatusMentionMessage
|
|
1632
|
+
m.groupStatusMentionMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1633
|
+
message: gsm.message || gsm
|
|
1634
|
+
})
|
|
1635
|
+
} else if ('pollCreationOptionImage' in message || 'pollCreationOptionImageMessage' in message) {
|
|
1636
|
+
const pcoi = message.pollCreationOptionImage || message.pollCreationOptionImageMessage
|
|
1637
|
+
m.pollCreationOptionImageMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1638
|
+
message: pcoi.message || pcoi
|
|
1639
|
+
})
|
|
1640
|
+
} else if ('newsletterAdminProfileStatus' in message || 'newsletterAdminProfileStatusMessage' in message) {
|
|
1641
|
+
const naps = message.newsletterAdminProfileStatus || message.newsletterAdminProfileStatusMessage
|
|
1642
|
+
m.newsletterAdminProfileStatusMessage = WAProto_1.proto.Message.FutureProofMessage.fromObject({
|
|
1643
|
+
message: naps.message || naps
|
|
1644
|
+
})
|
|
1645
|
+
} else if ('placeholder' in message || 'placeholderMessage' in message) {
|
|
1646
|
+
const ph = message.placeholder || message.placeholderMessage
|
|
1647
|
+
const phTypeEnum = WAProto_1.proto.Message.PlaceholderMessage.PlaceholderType
|
|
1648
|
+
const phTypeMap = {
|
|
1649
|
+
e2e_reenable: phTypeEnum.PLACEHOLDER_MESSAGE_TYPE_E2E_REENABLE_MSG,
|
|
1650
|
+
linked_devices: phTypeEnum.PLACEHOLDER_MESSAGE_TYPE_LINKED_DEVICES_MESSAGE
|
|
1651
|
+
}
|
|
1652
|
+
m.placeholderMessage = WAProto_1.proto.Message.PlaceholderMessage.fromObject({
|
|
1653
|
+
type:
|
|
1654
|
+
typeof ph.type === 'string'
|
|
1655
|
+
? (phTypeMap[ph.type.toLowerCase()] ?? phTypeEnum.PLACEHOLDER_MESSAGE_TYPE_E2E_REENABLE_MSG)
|
|
1656
|
+
: (ph.type ?? phTypeEnum.PLACEHOLDER_MESSAGE_TYPE_E2E_REENABLE_MSG)
|
|
1657
|
+
})
|
|
1658
|
+
} else if ('tapLink' in message || 'tapLinkMessage' in message) {
|
|
1659
|
+
const tl = message.tapLink || message.tapLinkMessage
|
|
1660
|
+
const inner = {
|
|
1661
|
+
extendedTextMessage: {
|
|
1662
|
+
text: tl.text || tl.title || '',
|
|
1663
|
+
matchedText: tl.url || tl.tapUrl,
|
|
1664
|
+
title: tl.title || tl.text || '',
|
|
1665
|
+
contextInfo: {
|
|
1666
|
+
actionLink: {
|
|
1667
|
+
url: tl.url || tl.tapUrl || '',
|
|
1668
|
+
buttonTitle: tl.buttonTitle || 'Open'
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
Object.assign(m, inner)
|
|
1674
|
+
} else if ('citation' in message) {
|
|
1675
|
+
const cit = message.citation
|
|
1676
|
+
m.extendedTextMessage = {
|
|
1677
|
+
text: cit.text || cit.title || '',
|
|
1678
|
+
title: cit.title || '',
|
|
1679
|
+
description: cit.subtitle || cit.description || '',
|
|
1680
|
+
...(cit.imageUrl ? { jpegThumbnail: undefined, previewType: 0 } : {})
|
|
1681
|
+
}
|
|
1682
|
+
} else if ('embeddedMusic' in message) {
|
|
1683
|
+
const em = message.embeddedMusic
|
|
1684
|
+
m.extendedTextMessage = {
|
|
1685
|
+
text: em.text || `🎵 ${em.title || ''} — ${em.author || ''}`,
|
|
1686
|
+
title: em.title || '',
|
|
1687
|
+
description: em.author || em.artistAttribution || '',
|
|
1688
|
+
previewType: 0
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
if ('keepInChat' in message || 'keepInChatMessage' in message) {
|
|
1692
|
+
const kic = message.keepInChat || message.keepInChatMessage
|
|
1693
|
+
const keepTypeEnum = WAProto_1.proto.KeepType
|
|
1694
|
+
const keepTypeMap = { keep: keepTypeEnum.KEEP_FOR_ALL, undo: keepTypeEnum.UNDO_KEEP_FOR_ALL }
|
|
1695
|
+
m.keepInChatMessage = WAProto_1.proto.Message.KeepInChatMessage.fromObject({
|
|
1696
|
+
key: kic.key || kic,
|
|
1697
|
+
keepType:
|
|
1698
|
+
typeof kic.keepType === 'string'
|
|
1699
|
+
? (keepTypeMap[kic.keepType.toLowerCase()] ?? keepTypeEnum.KEEP_FOR_ALL)
|
|
1700
|
+
: (kic.keepType ?? keepTypeEnum.KEEP_FOR_ALL),
|
|
1701
|
+
timestampMs: kic.timestampMs || Date.now()
|
|
1702
|
+
})
|
|
1703
|
+
}
|
|
1704
|
+
if ('botFeedback' in message || 'botFeedbackMessage' in message) {
|
|
1705
|
+
const bf = message.botFeedback || message.botFeedbackMessage
|
|
1706
|
+
const kindEnum = WAProto_1.proto.BotFeedbackMessage.BotFeedbackKind
|
|
1707
|
+
const kindMap = {
|
|
1708
|
+
positive: kindEnum.BOT_FEEDBACK_POSITIVE,
|
|
1709
|
+
negative: kindEnum.BOT_FEEDBACK_NEGATIVE,
|
|
1710
|
+
negative_generic: kindEnum.BOT_FEEDBACK_NEGATIVE_GENERIC,
|
|
1711
|
+
negative_helpful: kindEnum.BOT_FEEDBACK_NEGATIVE_HELPFUL,
|
|
1712
|
+
negative_interesting: kindEnum.BOT_FEEDBACK_NEGATIVE_INTERESTING,
|
|
1713
|
+
negative_accurate: kindEnum.BOT_FEEDBACK_NEGATIVE_ACCURATE,
|
|
1714
|
+
negative_safe: kindEnum.BOT_FEEDBACK_NEGATIVE_SAFE,
|
|
1715
|
+
negative_other: kindEnum.BOT_FEEDBACK_NEGATIVE_OTHER
|
|
1716
|
+
}
|
|
1717
|
+
m.protocolMessage = {
|
|
1718
|
+
type: WAProto_1.proto.Message.ProtocolMessage.Type.BOT_FEEDBACK_MESSAGE,
|
|
1719
|
+
key: bf.key,
|
|
1720
|
+
botFeedbackMessage: WAProto_1.proto.BotFeedbackMessage.fromObject({
|
|
1721
|
+
feedbackId: bf.feedbackId || bf.key?.id || '',
|
|
1722
|
+
kind:
|
|
1723
|
+
typeof bf.kind === 'string'
|
|
1724
|
+
? (kindMap[bf.kind.toLowerCase()] ?? kindEnum.BOT_FEEDBACK_POSITIVE)
|
|
1725
|
+
: (bf.kind ?? kindEnum.BOT_FEEDBACK_POSITIVE)
|
|
1726
|
+
})
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
if ('pollAddOption' in message || 'pollAddOptionMessage' in message) {
|
|
1730
|
+
const pao = message.pollAddOption || message.pollAddOptionMessage
|
|
1731
|
+
if (!pao.pollCreationMessageKey && !pao.key) {
|
|
1732
|
+
throw new boom_1.Boom('pollAddOption requires a pollCreationMessageKey', { statusCode: 400 })
|
|
1733
|
+
}
|
|
1734
|
+
m.pollAddOptionMessage = WAProto_1.proto.Message.PollAddOptionMessage.fromObject({
|
|
1735
|
+
pollCreationMessageKey: pao.pollCreationMessageKey || pao.key,
|
|
1736
|
+
addOption: { optionName: pao.optionName || pao.option }
|
|
1737
|
+
})
|
|
1738
|
+
}
|
|
1739
|
+
if ('chatTheme' in message || 'chatThemeMessage' in message) {
|
|
1740
|
+
const ct = message.chatTheme || message.chatThemeMessage
|
|
1741
|
+
const themeSetting = {
|
|
1742
|
+
settingTimestampMs: Date.now(),
|
|
1743
|
+
clearTheme: ct.clear ?? false,
|
|
1744
|
+
colorSchemeId: ct.colorSchemeId
|
|
1745
|
+
}
|
|
1746
|
+
if (ct.solidColor) {
|
|
1747
|
+
const sc = typeof ct.solidColor === 'object' ? ct.solidColor : {}
|
|
1748
|
+
themeSetting.solidColor = WAProto_1.proto.Message.ChatSolidColorWallpaper.fromObject({
|
|
1749
|
+
colorLight: sc.colorLight || sc.color || '#FFFFFF',
|
|
1750
|
+
colorDark: sc.colorDark || sc.color || '#000000',
|
|
1751
|
+
isDoodleEnabled: sc.isDoodleEnabled ?? false
|
|
1752
|
+
})
|
|
1753
|
+
} else if (ct.stockImage) {
|
|
1754
|
+
const si = typeof ct.stockImage === 'object' ? ct.stockImage : {}
|
|
1755
|
+
themeSetting.stockImage = WAProto_1.proto.Message.ChatStockImageWallpaper.fromObject({
|
|
1756
|
+
stockImageId: si.id || si.stockImageId || String(ct.stockImage),
|
|
1757
|
+
dimLevel: (si.dimLevel ?? si.opacity != null) ? (si.opacity ?? 100) / 100 : 0
|
|
1758
|
+
})
|
|
1759
|
+
} else if (ct.defaultWallpaper) {
|
|
1760
|
+
themeSetting.defaultWallpaper = WAProto_1.proto.Message.ChatDefaultWallpaper.fromObject({
|
|
1761
|
+
isDoodleEnabled: ct.defaultWallpaper.isDoodleEnabled ?? false
|
|
1762
|
+
})
|
|
1763
|
+
} else if (ct.customImage) {
|
|
1764
|
+
themeSetting.customImage = WAProto_1.proto.Message.ChatCustomImageWallpaper.fromObject({
|
|
1765
|
+
directPath: ct.customImage.directPath,
|
|
1766
|
+
mediaKey: ct.customImage.mediaKey,
|
|
1767
|
+
fileEncSha256: ct.customImage.fileEncSha256,
|
|
1768
|
+
fileSha256: ct.customImage.fileSha256,
|
|
1769
|
+
dimLevel: ct.customImage.dimLevel ?? 0
|
|
1770
|
+
})
|
|
1771
|
+
}
|
|
1772
|
+
m.protocolMessage = {
|
|
1773
|
+
type: WAProto_1.proto.Message.ProtocolMessage.Type.CHAT_THEME_SETTING,
|
|
1774
|
+
chatThemeSetting: WAProto_1.proto.Message.ChatThemeSetting.fromObject(themeSetting)
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
if ('stopGeneration' in message) {
|
|
1778
|
+
const sg = message.stopGeneration
|
|
1779
|
+
m.protocolMessage = {
|
|
1780
|
+
type: WAProto_1.proto.Message.ProtocolMessage.Type.STOP_GENERATION_MESSAGE,
|
|
1781
|
+
key: sg.key || sg
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
if ('unscheduleMessage' in message) {
|
|
1785
|
+
const us = message.unscheduleMessage
|
|
1786
|
+
m.protocolMessage = {
|
|
1787
|
+
type: WAProto_1.proto.Message.ProtocolMessage.Type.MESSAGE_UNSCHEDULE,
|
|
1788
|
+
key: us.key || us
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
if ('bcall' in message || 'bcallMessage' in message) {
|
|
1792
|
+
const bc = message.bcall || message.bcallMessage
|
|
1793
|
+
const mediaTypeEnum = WAProto_1.proto.Message.BCallMessage.MediaType
|
|
1794
|
+
const mediaTypeMap = { audio: mediaTypeEnum.AUDIO, video: mediaTypeEnum.VIDEO }
|
|
1795
|
+
m.bcallMessage = WAProto_1.proto.Message.BCallMessage.fromObject({
|
|
1796
|
+
sessionId: bc.sessionId || (0, crypto_1.randomUUID)(),
|
|
1797
|
+
mediaType:
|
|
1798
|
+
typeof bc.mediaType === 'string'
|
|
1799
|
+
? (mediaTypeMap[bc.mediaType.toLowerCase()] ?? mediaTypeEnum.AUDIO)
|
|
1800
|
+
: (bc.mediaType ?? mediaTypeEnum.AUDIO),
|
|
1801
|
+
masterKey: bc.masterKey || (0, crypto_1.randomBytes)(32),
|
|
1802
|
+
caption: bc.caption || ''
|
|
1803
|
+
})
|
|
1804
|
+
}
|
|
1805
|
+
if ('liveLocationUpdate' in message) {
|
|
1806
|
+
const llu = message.liveLocationUpdate
|
|
1807
|
+
m.liveLocationMessage = WAProto_1.proto.Message.LiveLocationMessage.fromObject({
|
|
1808
|
+
degreesLatitude: llu.latitude,
|
|
1809
|
+
degreesLongitude: llu.longitude,
|
|
1810
|
+
accuracyInMeters: llu.accuracy,
|
|
1811
|
+
speedInMps: llu.speed,
|
|
1812
|
+
degreesClockwiseFromMagneticNorth: llu.heading,
|
|
1813
|
+
sequenceNumber: llu.sequence || 1,
|
|
1814
|
+
timeOffset: llu.timeOffset || 0,
|
|
1815
|
+
jpegThumbnail: llu.thumbnail
|
|
1816
|
+
})
|
|
1817
|
+
}
|
|
1818
|
+
if ('stopLiveLocation' in message) {
|
|
1819
|
+
const sll = message.stopLiveLocation
|
|
1820
|
+
m.protocolMessage = {
|
|
1821
|
+
type: WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE,
|
|
1822
|
+
key: sll.key || sll
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
if ('carousel' in message || 'carouselMessage' in message) {
|
|
1826
|
+
const c = message.carousel || message.carouselMessage
|
|
1827
|
+
if (!Array.isArray(c.cards) || !c.cards.length) {
|
|
1828
|
+
throw new boom_1.Boom('carousel requires at least one card', { statusCode: 400 })
|
|
1829
|
+
}
|
|
1830
|
+
const cardTypeEnum = WAProto_1.proto.Message.InteractiveMessage.CarouselMessage.CarouselCardType
|
|
1831
|
+
const cardTypeMap = {
|
|
1832
|
+
horizontal: cardTypeEnum.HSCROLL_CARDS,
|
|
1833
|
+
album: cardTypeEnum.ALBUM_IMAGE,
|
|
1834
|
+
hscroll: cardTypeEnum.HSCROLL_CARDS
|
|
1835
|
+
}
|
|
1836
|
+
m.interactiveMessage = {
|
|
1837
|
+
carouselMessage: WAProto_1.proto.Message.InteractiveMessage.CarouselMessage.fromObject({
|
|
1838
|
+
cards: c.cards.map(card => card.interactiveMessage || card),
|
|
1839
|
+
messageVersion: c.messageVersion || 1,
|
|
1840
|
+
carouselCardType:
|
|
1841
|
+
typeof c.cardType === 'string'
|
|
1842
|
+
? (cardTypeMap[c.cardType.toLowerCase()] ?? cardTypeEnum.HSCROLL_CARDS)
|
|
1843
|
+
: (c.carouselCardType ?? cardTypeEnum.HSCROLL_CARDS)
|
|
1844
|
+
})
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
if ('aiMediaCollection' in message || 'aiMediaCollectionMessage' in message) {
|
|
1848
|
+
const amc = message.aiMediaCollection || message.aiMediaCollectionMessage
|
|
1849
|
+
m.protocolMessage = {
|
|
1850
|
+
type: WAProto_1.proto.Message.ProtocolMessage.Type.AI_MEDIA_COLLECTION_MESSAGE,
|
|
1851
|
+
aiMediaCollectionMessage: WAProto_1.proto.AIMediaCollectionMessage.fromObject({
|
|
1852
|
+
collectionId: amc.collectionId || (0, crypto_1.randomUUID)(),
|
|
1853
|
+
expectedMediaCount: amc.expectedMediaCount || amc.count || 1,
|
|
1854
|
+
hasGlobalCaption: amc.hasGlobalCaption ?? false
|
|
1855
|
+
})
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
if ('botCapabilities' in message && Array.isArray(message.botCapabilities) && message.botCapabilities.length) {
|
|
1859
|
+
const capEnum = WAProto_1.proto.BotCapabilityMetadata.BotCapabilityType
|
|
1860
|
+
const capStrMap = Object.fromEntries(Object.entries(capEnum).map(([k, v]) => [k.toLowerCase(), v]))
|
|
1861
|
+
const caps = message.botCapabilities
|
|
1862
|
+
.map(c => (typeof c === 'string' ? (capStrMap[c.toLowerCase()] ?? capEnum.UNKNOWN) : c))
|
|
1863
|
+
.filter(c => typeof c === 'number' && c !== capEnum.UNKNOWN)
|
|
1864
|
+
m.messageContextInfo = m.messageContextInfo || {}
|
|
1865
|
+
m.messageContextInfo.botMetadata = WAProto_1.proto.BotMetadata.fromObject({
|
|
1866
|
+
capabilityMetadata: { capabilities: caps }
|
|
1867
|
+
})
|
|
1868
|
+
}
|
|
1869
|
+
if ('botThreadInfo' in message && message.botThreadInfo) {
|
|
1870
|
+
const bt = message.botThreadInfo
|
|
1871
|
+
const threadTypeEnum = WAProto_1.proto.AIThreadInfo.AIThreadClientInfo.AIThreadType
|
|
1872
|
+
const threadTypeMap = Object.fromEntries(Object.entries(threadTypeEnum).map(([k, v]) => [k.toLowerCase(), v]))
|
|
1873
|
+
const existing = m.messageContextInfo?.botMetadata
|
|
1874
|
+
? WAProto_1.proto.BotMetadata.toObject(m.messageContextInfo.botMetadata)
|
|
1875
|
+
: {}
|
|
1876
|
+
m.messageContextInfo = m.messageContextInfo || {}
|
|
1877
|
+
m.messageContextInfo.botMetadata = WAProto_1.proto.BotMetadata.fromObject({
|
|
1878
|
+
...existing,
|
|
1879
|
+
botThreadInfo: {
|
|
1880
|
+
clientInfo: {
|
|
1881
|
+
type: typeof bt.type === 'string'
|
|
1882
|
+
? (threadTypeMap[bt.type.toLowerCase()] ?? threadTypeEnum.UNKNOWN)
|
|
1883
|
+
: (bt.type ?? threadTypeEnum.UNKNOWN),
|
|
1884
|
+
sourceChatJid: bt.sourceChatJid || ''
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
})
|
|
1888
|
+
}
|
|
1889
|
+
if ('messageAssociation' in message && message.messageAssociation) {
|
|
1890
|
+
const ma = message.messageAssociation
|
|
1891
|
+
const assocTypeEnum = WAProto_1.proto.MessageAssociation.AssociationType
|
|
1892
|
+
const assocTypeMap = Object.fromEntries(Object.entries(assocTypeEnum).map(([k, v]) => [k.toLowerCase(), v]))
|
|
1893
|
+
m.messageContextInfo = m.messageContextInfo || {}
|
|
1894
|
+
m.messageContextInfo.messageAssociation = WAProto_1.proto.MessageAssociation.fromObject({
|
|
1895
|
+
associationType:
|
|
1896
|
+
typeof ma.type === 'string'
|
|
1897
|
+
? (assocTypeMap[ma.type.toLowerCase()] ?? assocTypeEnum.UNKNOWN)
|
|
1898
|
+
: (ma.associationType ?? ma.type ?? assocTypeEnum.UNKNOWN),
|
|
1899
|
+
parentMessageKey: ma.parentMessageKey || ma.parentKey,
|
|
1900
|
+
messageIndex: ma.messageIndex || 0
|
|
1901
|
+
})
|
|
1902
|
+
}
|
|
1903
|
+
if ('threadId' in message && message.threadId) {
|
|
1904
|
+
const tid = message.threadId
|
|
1905
|
+
const threadTypeEnum = WAProto_1.proto.ThreadID.ThreadType
|
|
1906
|
+
m.messageContextInfo = m.messageContextInfo || {}
|
|
1907
|
+
m.messageContextInfo.threadId = [
|
|
1908
|
+
WAProto_1.proto.ThreadID.fromObject({
|
|
1909
|
+
threadType:
|
|
1910
|
+
tid.type === 'ai'
|
|
1911
|
+
? threadTypeEnum.AI_THREAD
|
|
1912
|
+
: tid.type === 'replies'
|
|
1913
|
+
? threadTypeEnum.VIEW_REPLIES
|
|
1914
|
+
: (tid.threadType ?? threadTypeEnum.UNKNOWN),
|
|
1915
|
+
threadKey: tid.key || tid.threadKey
|
|
1916
|
+
})
|
|
1917
|
+
]
|
|
1918
|
+
}
|
|
1919
|
+
if ('featureEligibilities' in message && message.featureEligibilities) {
|
|
1920
|
+
const fe = message.featureEligibilities
|
|
1921
|
+
const [msgType] = Object.keys(m)
|
|
1922
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
1923
|
+
m[msgType].contextInfo = {
|
|
1924
|
+
...(m[msgType].contextInfo || {}),
|
|
1925
|
+
featureEligibilities: {
|
|
1926
|
+
cannotBeReactedTo: fe.cannotBeReactedTo ?? false,
|
|
1927
|
+
cannotBeRanked: fe.cannotBeRanked ?? false,
|
|
1928
|
+
canRequestFeedback: fe.canRequestFeedback ?? false,
|
|
1929
|
+
canBeReshared: fe.canBeReshared ?? true,
|
|
1930
|
+
canReceiveMultiReact: fe.canReceiveMultiReact ?? true
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
if ('forwardOrigin' in message) {
|
|
1936
|
+
const [msgType] = Object.keys(m)
|
|
1937
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
1938
|
+
const foEnum = WAProto_1.proto.ContextInfo.ForwardOrigin
|
|
1939
|
+
const foMap = {
|
|
1940
|
+
chat: foEnum.CHAT,
|
|
1941
|
+
status: foEnum.STATUS,
|
|
1942
|
+
channels: foEnum.CHANNELS,
|
|
1943
|
+
meta_ai: foEnum.META_AI,
|
|
1944
|
+
ugc: foEnum.UGC
|
|
1945
|
+
}
|
|
1946
|
+
m[msgType].contextInfo = {
|
|
1947
|
+
...(m[msgType].contextInfo || {}),
|
|
1948
|
+
forwardOrigin:
|
|
1949
|
+
typeof message.forwardOrigin === 'string'
|
|
1950
|
+
? (foMap[message.forwardOrigin.toLowerCase()] ?? foEnum.CHAT)
|
|
1951
|
+
: (message.forwardOrigin ?? foEnum.CHAT)
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
if ('statusAudienceMetadata' in message && message.statusAudienceMetadata) {
|
|
1956
|
+
const [msgType] = Object.keys(m)
|
|
1957
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
1958
|
+
const audType = WAProto_1.proto.ContextInfo.StatusAudienceMetadata.AudienceType
|
|
1959
|
+
const sam = message.statusAudienceMetadata
|
|
1960
|
+
m[msgType].contextInfo = {
|
|
1961
|
+
...(m[msgType].contextInfo || {}),
|
|
1962
|
+
statusAudienceMetadata: {
|
|
1963
|
+
audienceType: sam.closeFriends ? audType.CLOSE_FRIENDS : audType.UNKNOWN,
|
|
1964
|
+
listName: sam.listName,
|
|
1965
|
+
listEmoji: sam.listEmoji
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
if ('aiGenerated' in message && message.aiGenerated === true) {
|
|
1971
|
+
if (m.videoMessage) {
|
|
1972
|
+
m.videoMessage.videoSourceType = WAProto_1.proto.Message.VideoMessage.VideoSourceType.AI_GENERATED
|
|
1973
|
+
}
|
|
1974
|
+
if (m.imageMessage) {
|
|
1975
|
+
m.imageMessage.imageSourceType = WAProto_1.proto.Message.ImageMessage.ImageSourceType.AI_GENERATED
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
if ('aiModified' in message && message.aiModified === true) {
|
|
1979
|
+
if (m.imageMessage) {
|
|
1980
|
+
m.imageMessage.imageSourceType = WAProto_1.proto.Message.ImageMessage.ImageSourceType.AI_MODIFIED
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
if ('imageSourceType' in message) {
|
|
1984
|
+
if (m.imageMessage) {
|
|
1985
|
+
const istEnum = WAProto_1.proto.Message.ImageMessage.ImageSourceType
|
|
1986
|
+
const istMap = {
|
|
1987
|
+
user: istEnum.USER_IMAGE,
|
|
1988
|
+
ai_generated: istEnum.AI_GENERATED,
|
|
1989
|
+
ai_modified: istEnum.AI_MODIFIED,
|
|
1990
|
+
rasterized: istEnum.RASTERIZED_TEXT_STATUS
|
|
1991
|
+
}
|
|
1992
|
+
m.imageMessage.imageSourceType =
|
|
1993
|
+
typeof message.imageSourceType === 'string'
|
|
1994
|
+
? (istMap[message.imageSourceType.toLowerCase()] ?? istEnum.USER_IMAGE)
|
|
1995
|
+
: (message.imageSourceType ?? istEnum.USER_IMAGE)
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
if ('qrUrl' in message && message.qrUrl && m.imageMessage) {
|
|
1999
|
+
m.imageMessage.qrUrl = message.qrUrl
|
|
2000
|
+
}
|
|
2001
|
+
if ('videoContentUrl' in message && message.videoContentUrl && m.extendedTextMessage) {
|
|
2002
|
+
m.extendedTextMessage.videoContentUrl = message.videoContentUrl
|
|
2003
|
+
}
|
|
2004
|
+
if ('endCardTiles' in message && Array.isArray(message.endCardTiles) && m.extendedTextMessage) {
|
|
2005
|
+
m.extendedTextMessage.endCardTiles = message.endCardTiles.map(tile =>
|
|
2006
|
+
WAProto_1.proto.Message.VideoEndCard.fromObject({
|
|
2007
|
+
username: tile.username || tile.user,
|
|
2008
|
+
caption: tile.caption || tile.text,
|
|
2009
|
+
thumbnailImageUrl: tile.thumbnailUrl || tile.thumbnail,
|
|
2010
|
+
profilePictureUrl: tile.profilePictureUrl || tile.avatar
|
|
2011
|
+
})
|
|
2012
|
+
)
|
|
2013
|
+
}
|
|
2014
|
+
if ('musicMetadata' in message && message.musicMetadata && m.extendedTextMessage) {
|
|
2015
|
+
const mm = message.musicMetadata
|
|
2016
|
+
m.extendedTextMessage.musicMetadata = WAProto_1.proto.EmbeddedMusic.fromObject({
|
|
2017
|
+
songId: mm.songId,
|
|
2018
|
+
author: mm.author || mm.artist,
|
|
2019
|
+
title: mm.title,
|
|
2020
|
+
artistAttribution: mm.artistAttribution,
|
|
2021
|
+
isExplicit: mm.isExplicit ?? false,
|
|
2022
|
+
musicSongStartTimeInMs: mm.startTimeMs || 0,
|
|
2023
|
+
derivedContentStartTimeInMs: mm.derivedStartTimeMs || 0,
|
|
2024
|
+
overlapDurationInMs: mm.overlapDurationMs || 0
|
|
2025
|
+
})
|
|
2026
|
+
}
|
|
2027
|
+
if ('businessInteractionPills' in message && message.businessInteractionPills) {
|
|
2028
|
+
const bip = message.businessInteractionPills
|
|
2029
|
+
const pillTypeEnum = WAProto_1.proto.ContextInfo.BusinessInteractionPills.PillType
|
|
2030
|
+
const entryEnum = WAProto_1.proto.ContextInfo.BusinessInteractionPills.EntryPoint
|
|
2031
|
+
const pillMap = Object.fromEntries(Object.entries(pillTypeEnum).map(([k, v]) => [k.toLowerCase(), v]))
|
|
2032
|
+
const entryMap = Object.fromEntries(Object.entries(entryEnum).map(([k, v]) => [k.toLowerCase(), v]))
|
|
2033
|
+
const [msgType] = Object.keys(m)
|
|
2034
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2035
|
+
m[msgType].contextInfo = {
|
|
2036
|
+
...(m[msgType].contextInfo || {}),
|
|
2037
|
+
businessInteractionPills: WAProto_1.proto.ContextInfo.BusinessInteractionPills.fromObject({
|
|
2038
|
+
businessJid: bip.businessJid,
|
|
2039
|
+
entryPoint:
|
|
2040
|
+
typeof bip.entryPoint === 'string'
|
|
2041
|
+
? (entryMap[bip.entryPoint.toLowerCase()] ?? entryEnum.ENTRY_POINT_UNKNOWN)
|
|
2042
|
+
: bip.entryPoint,
|
|
2043
|
+
pills: (bip.pills || []).map(p => ({
|
|
2044
|
+
pillType:
|
|
2045
|
+
typeof p.type === 'string'
|
|
2046
|
+
? (pillMap[p.type.toLowerCase()] ?? pillTypeEnum.UNKNOWN)
|
|
2047
|
+
: (p.pillType ?? pillTypeEnum.UNKNOWN),
|
|
2048
|
+
actionUrl: p.url || p.actionUrl
|
|
2049
|
+
}))
|
|
2050
|
+
})
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
if ('dataSharingContext' in message && message.dataSharingContext) {
|
|
2055
|
+
const dsc = message.dataSharingContext
|
|
2056
|
+
const [msgType] = Object.keys(m)
|
|
2057
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2058
|
+
m[msgType].contextInfo = {
|
|
2059
|
+
...(m[msgType].contextInfo || {}),
|
|
2060
|
+
dataSharingContext: WAProto_1.proto.ContextInfo.DataSharingContext.fromObject({
|
|
2061
|
+
showMmDisclosure: dsc.showMmDisclosure ?? false,
|
|
2062
|
+
encryptedSignalTokenConsented: dsc.encryptedToken,
|
|
2063
|
+
dataSharingFlags: dsc.flags || 0
|
|
2064
|
+
})
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
if ('botSession' in message && message.botSession) {
|
|
2069
|
+
const bs = message.botSession
|
|
2070
|
+
const srcEnum = WAProto_1.proto.BotSessionSource
|
|
2071
|
+
const srcMap = Object.fromEntries(Object.entries(srcEnum).map(([k, v]) => [k.toLowerCase(), v]))
|
|
2072
|
+
m.messageContextInfo = m.messageContextInfo || {}
|
|
2073
|
+
const existing = m.messageContextInfo.botMetadata
|
|
2074
|
+
? WAProto_1.proto.BotMetadata.toObject(m.messageContextInfo.botMetadata)
|
|
2075
|
+
: {}
|
|
2076
|
+
m.messageContextInfo.botMetadata = WAProto_1.proto.BotMetadata.fromObject({
|
|
2077
|
+
...existing,
|
|
2078
|
+
sessionMetadata: {
|
|
2079
|
+
sessionId: bs.sessionId,
|
|
2080
|
+
sessionSource:
|
|
2081
|
+
typeof bs.source === 'string'
|
|
2082
|
+
? (srcMap[bs.source.toLowerCase()] ?? srcEnum.NONE)
|
|
2083
|
+
: (bs.sessionSource ?? srcEnum.NONE)
|
|
2084
|
+
}
|
|
2085
|
+
})
|
|
2086
|
+
}
|
|
2087
|
+
if ('botReminder' in message && message.botReminder) {
|
|
2088
|
+
const br = message.botReminder
|
|
2089
|
+
const actionEnum = WAProto_1.proto.BotReminderMetadata.ReminderAction
|
|
2090
|
+
const freqEnum = WAProto_1.proto.BotReminderMetadata.ReminderFrequency
|
|
2091
|
+
const actionMap = {
|
|
2092
|
+
notify: actionEnum.NOTIFY,
|
|
2093
|
+
create: actionEnum.CREATE,
|
|
2094
|
+
delete: actionEnum.DELETE,
|
|
2095
|
+
update: actionEnum.UPDATE
|
|
2096
|
+
}
|
|
2097
|
+
const freqMap = {
|
|
2098
|
+
once: freqEnum.ONCE,
|
|
2099
|
+
daily: freqEnum.DAILY,
|
|
2100
|
+
weekly: freqEnum.WEEKLY,
|
|
2101
|
+
biweekly: freqEnum.BIWEEKLY,
|
|
2102
|
+
monthly: freqEnum.MONTHLY
|
|
2103
|
+
}
|
|
2104
|
+
m.messageContextInfo = m.messageContextInfo || {}
|
|
2105
|
+
const existing = m.messageContextInfo.botMetadata
|
|
2106
|
+
? WAProto_1.proto.BotMetadata.toObject(m.messageContextInfo.botMetadata)
|
|
2107
|
+
: {}
|
|
2108
|
+
m.messageContextInfo.botMetadata = WAProto_1.proto.BotMetadata.fromObject({
|
|
2109
|
+
...existing,
|
|
2110
|
+
reminderMetadata: {
|
|
2111
|
+
requestMessageKey: br.requestMessageKey || br.key,
|
|
2112
|
+
action:
|
|
2113
|
+
typeof br.action === 'string'
|
|
2114
|
+
? (actionMap[br.action.toLowerCase()] ?? actionEnum.NOTIFY)
|
|
2115
|
+
: (br.action ?? actionEnum.NOTIFY),
|
|
2116
|
+
name: br.name,
|
|
2117
|
+
nextTriggerTimestamp: br.nextTriggerTimestamp || br.timestamp,
|
|
2118
|
+
frequency:
|
|
2119
|
+
typeof br.frequency === 'string'
|
|
2120
|
+
? (freqMap[br.frequency.toLowerCase()] ?? freqEnum.ONCE)
|
|
2121
|
+
: (br.frequency ?? freqEnum.ONCE)
|
|
2122
|
+
}
|
|
2123
|
+
})
|
|
2124
|
+
}
|
|
2125
|
+
if ('botPlugin' in message && message.botPlugin) {
|
|
2126
|
+
const bp = message.botPlugin
|
|
2127
|
+
const ptEnum = WAProto_1.proto.BotPluginMetadata.PluginType
|
|
2128
|
+
const spEnum = WAProto_1.proto.BotPluginMetadata.SearchProvider
|
|
2129
|
+
const ptMap = { reels: ptEnum.REELS, search: ptEnum.SEARCH }
|
|
2130
|
+
const spMap = { bing: spEnum.BING, google: spEnum.GOOGLE, support: spEnum.SUPPORT }
|
|
2131
|
+
m.messageContextInfo = m.messageContextInfo || {}
|
|
2132
|
+
const existing = m.messageContextInfo.botMetadata
|
|
2133
|
+
? WAProto_1.proto.BotMetadata.toObject(m.messageContextInfo.botMetadata)
|
|
2134
|
+
: {}
|
|
2135
|
+
m.messageContextInfo.botMetadata = WAProto_1.proto.BotMetadata.fromObject({
|
|
2136
|
+
...existing,
|
|
2137
|
+
pluginMetadata: WAProto_1.proto.BotPluginMetadata.fromObject({
|
|
2138
|
+
provider:
|
|
2139
|
+
typeof bp.provider === 'string'
|
|
2140
|
+
? (spMap[bp.provider.toLowerCase()] ?? spEnum.UNKNOWN)
|
|
2141
|
+
: (bp.provider ?? spEnum.UNKNOWN),
|
|
2142
|
+
pluginType:
|
|
2143
|
+
typeof bp.pluginType === 'string'
|
|
2144
|
+
? (ptMap[bp.pluginType.toLowerCase()] ?? ptEnum.UNKNOWN_PLUGIN)
|
|
2145
|
+
: (bp.pluginType ?? ptEnum.UNKNOWN_PLUGIN),
|
|
2146
|
+
searchProviderUrl: bp.searchProviderUrl,
|
|
2147
|
+
searchQuery: bp.searchQuery,
|
|
2148
|
+
thumbnailCdnUrl: bp.thumbnailCdnUrl,
|
|
2149
|
+
profilePhotoCdnUrl: bp.profilePhotoCdnUrl,
|
|
2150
|
+
expectedLinksCount: bp.expectedLinksCount || 0,
|
|
2151
|
+
referenceIndex: bp.referenceIndex || 0
|
|
2152
|
+
})
|
|
2153
|
+
})
|
|
2154
|
+
}
|
|
2155
|
+
if ('isSpoiler' in message && message.isSpoiler === true) {
|
|
2156
|
+
const [msgType] = Object.keys(m)
|
|
2157
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2158
|
+
m[msgType].contextInfo = {
|
|
2159
|
+
...(m[msgType].contextInfo || {}),
|
|
2160
|
+
isSpoiler: true
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
if ('expiration' in message && typeof message.expiration === 'number') {
|
|
2165
|
+
const [msgType] = Object.keys(m)
|
|
2166
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2167
|
+
m[msgType].contextInfo = {
|
|
2168
|
+
...(m[msgType].contextInfo || {}),
|
|
2169
|
+
expiration: message.expiration
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
if ('ephemeralSettingTimestamp' in message) {
|
|
2174
|
+
const [msgType] = Object.keys(m)
|
|
2175
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2176
|
+
m[msgType].contextInfo = {
|
|
2177
|
+
...(m[msgType].contextInfo || {}),
|
|
2178
|
+
ephemeralSettingTimestamp: message.ephemeralSettingTimestamp
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
if ('groupSubject' in message && message.groupSubject) {
|
|
2183
|
+
const [msgType] = Object.keys(m)
|
|
2184
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2185
|
+
m[msgType].contextInfo = {
|
|
2186
|
+
...(m[msgType].contextInfo || {}),
|
|
2187
|
+
groupSubject: message.groupSubject
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
if ('parentGroupJid' in message && message.parentGroupJid) {
|
|
2192
|
+
const [msgType] = Object.keys(m)
|
|
2193
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2194
|
+
m[msgType].contextInfo = {
|
|
2195
|
+
...(m[msgType].contextInfo || {}),
|
|
2196
|
+
parentGroupJid: message.parentGroupJid
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
if ('memberLabel' in message && message.memberLabel) {
|
|
2201
|
+
const [msgType] = Object.keys(m)
|
|
2202
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2203
|
+
m[msgType].contextInfo = {
|
|
2204
|
+
...(m[msgType].contextInfo || {}),
|
|
2205
|
+
memberLabel: message.memberLabel
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
if ('trustBanner' in message && message.trustBanner) {
|
|
2210
|
+
const tb = message.trustBanner
|
|
2211
|
+
const [msgType] = Object.keys(m)
|
|
2212
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2213
|
+
m[msgType].contextInfo = {
|
|
2214
|
+
...(m[msgType].contextInfo || {}),
|
|
2215
|
+
...(tb.type != null ? { trustBannerType: tb.type } : {}),
|
|
2216
|
+
...(tb.action != null ? { trustBannerAction: tb.action } : {})
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
if ('entryPoint' in message && message.entryPoint) {
|
|
2221
|
+
const ep = message.entryPoint
|
|
2222
|
+
const [msgType] = Object.keys(m)
|
|
2223
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2224
|
+
m[msgType].contextInfo = {
|
|
2225
|
+
...(m[msgType].contextInfo || {}),
|
|
2226
|
+
...(ep.source ? { entryPointConversionSource: ep.source } : {}),
|
|
2227
|
+
...(ep.app ? { entryPointConversionApp: ep.app } : {}),
|
|
2228
|
+
...(ep.delaySecs != null ? { entryPointConversionDelaySeconds: ep.delaySecs } : {}),
|
|
2229
|
+
...(ep.externalSource ? { entryPointConversionExternalSource: ep.externalSource } : {}),
|
|
2230
|
+
...(ep.externalMedium ? { entryPointConversionExternalMedium: ep.externalMedium } : {})
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
if ('utm' in message && message.utm) {
|
|
2235
|
+
const [msgType] = Object.keys(m)
|
|
2236
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2237
|
+
m[msgType].contextInfo = {
|
|
2238
|
+
...(m[msgType].contextInfo || {}),
|
|
2239
|
+
utm: WAProto_1.proto.ContextInfo.UTMInfo.fromObject({
|
|
2240
|
+
utmSource: message.utm.source,
|
|
2241
|
+
utmCampaign: message.utm.campaign
|
|
2242
|
+
})
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
if ('partiallySelectedContent' in message && message.partiallySelectedContent) {
|
|
2247
|
+
const [msgType] = Object.keys(m)
|
|
2248
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2249
|
+
m[msgType].contextInfo = {
|
|
2250
|
+
...(m[msgType].contextInfo || {}),
|
|
2251
|
+
partiallySelectedContent: message.partiallySelectedContent
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
if ('crossAppSource' in message && message.crossAppSource) {
|
|
2256
|
+
const [msgType] = Object.keys(m)
|
|
2257
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2258
|
+
m[msgType].contextInfo = {
|
|
2259
|
+
...(m[msgType].contextInfo || {}),
|
|
2260
|
+
crossAppSource: message.crossAppSource
|
|
2261
|
+
}
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
if ('isQuestion' in message && message.isQuestion === true) {
|
|
2265
|
+
const [msgType] = Object.keys(m)
|
|
2266
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2267
|
+
m[msgType].contextInfo = {
|
|
2268
|
+
...(m[msgType].contextInfo || {}),
|
|
2269
|
+
isQuestion: true
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
if ('afterReadDuration' in message && typeof message.afterReadDuration === 'number') {
|
|
2274
|
+
const [msgType] = Object.keys(m)
|
|
2275
|
+
if (msgType && m[msgType] && typeof m[msgType] === 'object') {
|
|
2276
|
+
m[msgType].contextInfo = {
|
|
2277
|
+
...(m[msgType].contextInfo || {}),
|
|
2278
|
+
afterReadDuration: message.afterReadDuration
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
m.messageContextInfo = {
|
|
2282
|
+
...(m.messageContextInfo || {}),
|
|
2283
|
+
messageAddOnDurationInSecs: message.afterReadDuration,
|
|
2284
|
+
messageAddOnExpiryType: index_js_1.proto.MessageContextInfo.MessageAddonExpiryType.DEPENDENT_ON_PARENT
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
if ('raw' in message && !!message.raw) {
|
|
2288
|
+
const { raw: _, externalAdReply: _ear, ...rawMsg } = message
|
|
2289
|
+
if ('externalAdReply' in message && !!message.externalAdReply) {
|
|
2290
|
+
const ear = normalizeEarFields(message.externalAdReply)
|
|
2291
|
+
const [rawType] = Object.keys(rawMsg)
|
|
2292
|
+
if (rawType && rawMsg[rawType]) {
|
|
2293
|
+
rawMsg[rawType].contextInfo = {
|
|
2294
|
+
...(rawMsg[rawType].contextInfo || {}),
|
|
2295
|
+
externalAdReply: ear
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
return WAProto_1.proto.Message.fromObject(rawMsg)
|
|
2300
|
+
} else if (Object.keys(m).length === 0) {
|
|
2301
|
+
m = await (0, exports.prepareWAMessageMedia)(message, options)
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
if (hasOptionalProperty(message, 'viewOnce') && !!message.viewOnce) {
|
|
2305
|
+
const viewOnceVersion = message.viewOnceVersion || message.viewOnce
|
|
2306
|
+
if (viewOnceVersion === 'v2' || viewOnceVersion === 2) {
|
|
2307
|
+
m = { viewOnceMessageV2: { message: m } }
|
|
2308
|
+
} else if (viewOnceVersion === 'v2ext' || viewOnceVersion === 'v2extension') {
|
|
2309
|
+
m = { viewOnceMessageV2Extension: { message: m } }
|
|
2310
|
+
} else {
|
|
2311
|
+
m = { viewOnceMessage: { message: m } }
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
if (hasOptionalProperty(message, 'documentWithCaption') && !!message.documentWithCaption) {
|
|
2315
|
+
m = { documentWithCaptionMessage: { message: m } }
|
|
2316
|
+
}
|
|
2317
|
+
if (hasOptionalProperty(message, 'ephemeral') && !!message.ephemeral) {
|
|
2318
|
+
m = { ephemeralMessage: { message: m } }
|
|
2319
|
+
}
|
|
2320
|
+
if (hasOptionalProperty(message, 'groupMentioned') && !!message.groupMentioned) {
|
|
2321
|
+
m = { groupMentionedMessage: { message: m } }
|
|
2322
|
+
}
|
|
2323
|
+
if ('groupStatus' in message && !!message.groupStatus) {
|
|
2324
|
+
m = { groupStatusMessage: { message: m } }
|
|
2325
|
+
}
|
|
2326
|
+
if (
|
|
2327
|
+
(hasOptionalProperty(message, 'mentions') && message.mentions?.length) ||
|
|
2328
|
+
(hasOptionalProperty(message, 'mentionAll') && message.mentionAll)
|
|
2329
|
+
) {
|
|
2330
|
+
const normalizedMentions = await (0, jid_display_normalization_1.normalizeMentionedJidsForSend)(
|
|
2331
|
+
message.mentions,
|
|
2332
|
+
options.groupData,
|
|
2333
|
+
options.signalRepository,
|
|
2334
|
+
options.logger
|
|
2335
|
+
)
|
|
2336
|
+
const messageType = Object.keys(m)[0]
|
|
2337
|
+
const key = m[messageType]
|
|
2338
|
+
if (key && 'contextInfo' in key) {
|
|
2339
|
+
key.contextInfo = key.contextInfo || {}
|
|
2340
|
+
if (normalizedMentions?.length) {
|
|
2341
|
+
key.contextInfo.mentionedJid = normalizedMentions
|
|
2342
|
+
}
|
|
2343
|
+
if (message.mentionAll) {
|
|
2344
|
+
key.contextInfo.nonJidMentions = 1
|
|
2345
|
+
} else if (!key) {
|
|
2346
|
+
key.contextInfo = {
|
|
2347
|
+
mentionedJid: normalizedMentions,
|
|
2348
|
+
nonJidMentions: message.mentionAll ? 1 : 0
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
if (hasOptionalProperty(message, 'edit')) {
|
|
2354
|
+
m = {
|
|
2355
|
+
protocolMessage: {
|
|
2356
|
+
key: message.edit,
|
|
2357
|
+
editedMessage: m,
|
|
2358
|
+
timestampMs: Date.now(),
|
|
2359
|
+
type: WAProto_1.proto.Message.ProtocolMessage.Type.MESSAGE_EDIT
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
if (hasOptionalProperty(message, 'contextInfo') && !!message.contextInfo) {
|
|
2364
|
+
const messageType = Object.keys(m)[0]
|
|
2365
|
+
const key = m[messageType]
|
|
2366
|
+
if ('contextInfo' in key && !!key.contextInfo) {
|
|
2367
|
+
key.contextInfo = { ...key.contextInfo, ...message.contextInfo }
|
|
2368
|
+
} else if (key) {
|
|
2369
|
+
key.contextInfo = message.contextInfo
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
if ((0, reporting_utils_1.shouldIncludeReportingToken)(m) && !(0, WABinary_1.isInteropUser)(options.jid)) {
|
|
2373
|
+
m.messageContextInfo = m.messageContextInfo || {}
|
|
2374
|
+
if (!m.messageContextInfo.messageSecret) {
|
|
2375
|
+
m.messageContextInfo.messageSecret = (0, crypto_1.randomBytes)(32)
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
if ('externalAdReply' in message && !!message.externalAdReply) {
|
|
2380
|
+
const wrappers = [
|
|
2381
|
+
'viewOnceMessage',
|
|
2382
|
+
'viewOnceMessageV2',
|
|
2383
|
+
'viewOnceMessageV2Extension',
|
|
2384
|
+
'ephemeralMessage',
|
|
2385
|
+
'groupStatusMessage',
|
|
2386
|
+
'templateMessage'
|
|
2387
|
+
]
|
|
2388
|
+
const [outerType] = Object.keys(m)
|
|
2389
|
+
const inner = wrappers.includes(outerType) ? m[outerType].message : m
|
|
2390
|
+
const [innerType] = Object.keys(inner)
|
|
2391
|
+
const innerPayload = innerType ? inner[innerType] : undefined
|
|
2392
|
+
if (innerType && innerType !== 'carouselMessage' && innerPayload && typeof innerPayload === 'object') {
|
|
2393
|
+
const ear = normalizeEarFields(message.externalAdReply)
|
|
2394
|
+
innerPayload.contextInfo = {
|
|
2395
|
+
...(innerPayload.contextInfo || {}),
|
|
2396
|
+
externalAdReply: ear
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
if ('secureMetaServiceLabel' in message && !!message.secureMetaServiceLabel) {
|
|
2401
|
+
const [messageType] = Object.keys(m)
|
|
2402
|
+
m[messageType] = m[messageType] || {}
|
|
2403
|
+
m[messageType].contextInfo = {
|
|
2404
|
+
...(m[messageType].contextInfo || {}),
|
|
2405
|
+
secureMetaServiceLabel: 1
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
return WAProto_1.proto.Message.create(m)
|
|
2410
|
+
}
|
|
2411
|
+
exports.generateWAMessageContent = generateWAMessageContent
|
|
2412
|
+
const generateWAMessageFromContent = (jid, message, options) => {
|
|
2413
|
+
// set timestamp to now
|
|
2414
|
+
// if not specified
|
|
2415
|
+
if (!options.timestamp) {
|
|
2416
|
+
options.timestamp = new Date()
|
|
2417
|
+
}
|
|
2418
|
+
const innerMessage = (0, exports.normalizeMessageContent)(message)
|
|
2419
|
+
const key = (0, exports.getContentType)(innerMessage)
|
|
2420
|
+
const timestamp = (0, generics_1.unixTimestampSeconds)(options.timestamp)
|
|
2421
|
+
const { quoted, userJid } = options
|
|
2422
|
+
if (quoted && !(0, WABinary_1.isJidNewsletter)(jid)) {
|
|
2423
|
+
const participant = quoted.key.fromMe
|
|
2424
|
+
? userJid // TODO: Add support for LIDs
|
|
2425
|
+
: quoted.participant || quoted.key.participant || quoted.key.remoteJid
|
|
2426
|
+
let quotedMsg = (0, exports.normalizeMessageContent)(quoted.message)
|
|
2427
|
+
const msgType = (0, exports.getContentType)(quotedMsg)
|
|
2428
|
+
// strip any redundant properties
|
|
2429
|
+
quotedMsg = index_js_1.proto.Message.create({ [msgType]: quotedMsg[msgType] })
|
|
2430
|
+
const quotedContent = quotedMsg[msgType]
|
|
2431
|
+
if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
|
|
2432
|
+
delete quotedContent.contextInfo
|
|
2433
|
+
}
|
|
2434
|
+
const contextInfo = ('contextInfo' in innerMessage[key] && innerMessage[key]?.contextInfo) || {}
|
|
2435
|
+
contextInfo.participant = (0, WABinary_1.jidNormalizedUser)(participant)
|
|
2436
|
+
contextInfo.stanzaId = quoted.key.id
|
|
2437
|
+
contextInfo.quotedMessage = quotedMsg
|
|
2438
|
+
// if a participant is quoted, then it must be a group
|
|
2439
|
+
// hence, remoteJid of group must also be entered
|
|
2440
|
+
if (jid !== quoted.key.remoteJid) {
|
|
2441
|
+
contextInfo.remoteJid = quoted.key.remoteJid
|
|
2442
|
+
}
|
|
2443
|
+
if (contextInfo && innerMessage[key]) {
|
|
2444
|
+
/* @ts-ignore */
|
|
2445
|
+
innerMessage[key].contextInfo = contextInfo
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
if (
|
|
2449
|
+
// if we want to send a disappearing message
|
|
2450
|
+
!!options.ephemeralExpiration &&
|
|
2451
|
+
// and it's not a protocol message -- delete, toggle disappear message
|
|
2452
|
+
key !== 'protocolMessage' &&
|
|
2453
|
+
// already not converted to disappearing message
|
|
2454
|
+
key !== 'ephemeralMessage' &&
|
|
2455
|
+
// newsletters don't support ephemeral messages
|
|
2456
|
+
!(0, WABinary_1.isJidNewsletter)(jid)
|
|
2457
|
+
) {
|
|
2458
|
+
/* @ts-ignore */
|
|
2459
|
+
innerMessage[key].contextInfo = {
|
|
2460
|
+
...(innerMessage[key].contextInfo || {}),
|
|
2461
|
+
expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL
|
|
2462
|
+
//ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
message = WAProto_1.proto.Message.create(message)
|
|
2466
|
+
const iosBros = options?.browser?.[0] === 'iOS' || options?.browser?.[1] === 'Safari'
|
|
2467
|
+
const androidBros = options?.browser?.[0] === 'Android'
|
|
2468
|
+
const pickedMessageId =
|
|
2469
|
+
options?.messageId ||
|
|
2470
|
+
(iosBros
|
|
2471
|
+
? (0, generics_1.generateIOSMessageID)()
|
|
2472
|
+
: androidBros
|
|
2473
|
+
? (0, generics_1.generateAndroMessageID)()
|
|
2474
|
+
: (0, generics_1.generateMessageIDV2)(userJid))
|
|
2475
|
+
const messageJSON = {
|
|
2476
|
+
key: {
|
|
2477
|
+
remoteJid: jid,
|
|
2478
|
+
fromMe: true,
|
|
2479
|
+
id: pickedMessageId
|
|
2480
|
+
},
|
|
2481
|
+
message: message,
|
|
2482
|
+
messageTimestamp: timestamp,
|
|
2483
|
+
messageStubParameters: [],
|
|
2484
|
+
participant: (0, WABinary_1.isJidGroup)(jid) || (0, WABinary_1.isJidStatusBroadcast)(jid) ? userJid : undefined, // TODO: Add support for LIDs
|
|
2485
|
+
status: Types_1.WAMessageStatus.PENDING
|
|
2486
|
+
}
|
|
2487
|
+
return WAProto_1.proto.WebMessageInfo.fromObject(messageJSON)
|
|
2488
|
+
}
|
|
2489
|
+
exports.generateWAMessageFromContent = generateWAMessageFromContent
|
|
2490
|
+
const generateWAMessage = async (jid, content, options) => {
|
|
2491
|
+
// ensure msg ID is with every log
|
|
2492
|
+
options.logger = options?.logger?.child({ msgId: options.messageId })
|
|
2493
|
+
// Pass jid in the options to generateWAMessageContent
|
|
2494
|
+
return (0, exports.generateWAMessageFromContent)(
|
|
2495
|
+
jid,
|
|
2496
|
+
await (0, exports.generateWAMessageContent)(content, { ...options, jid }),
|
|
2497
|
+
options
|
|
2498
|
+
)
|
|
2499
|
+
}
|
|
2500
|
+
exports.generateWAMessage = generateWAMessage
|
|
991
2501
|
/** Get the key to access the true type of content */
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
}
|
|
2502
|
+
const getContentType = content => {
|
|
2503
|
+
if (content) {
|
|
2504
|
+
const keys = Object.keys(content)
|
|
2505
|
+
const key = keys.find(k => (k === 'conversation' || k.includes('Message')) && k !== 'senderKeyDistributionMessage')
|
|
2506
|
+
return key
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
exports.getContentType = getContentType
|
|
999
2510
|
/**
|
|
1000
2511
|
* Normalizes ephemeral, view once messages to regular message content
|
|
1001
2512
|
* Eg. image messages in ephemeral messages, in view once messages etc.
|
|
1002
2513
|
* @param content
|
|
1003
2514
|
* @returns
|
|
1004
2515
|
*/
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
2516
|
+
const normalizeMessageContent = content => {
|
|
2517
|
+
if (!content) {
|
|
2518
|
+
return undefined
|
|
2519
|
+
}
|
|
2520
|
+
// set max iterations to prevent an infinite loop
|
|
2521
|
+
for (let i = 0; i < 5; i++) {
|
|
2522
|
+
const inner = getFutureProofMessage(content)
|
|
2523
|
+
if (!inner) {
|
|
2524
|
+
break
|
|
2525
|
+
}
|
|
2526
|
+
content = inner.message
|
|
2527
|
+
}
|
|
2528
|
+
return content
|
|
2529
|
+
function getFutureProofMessage(message) {
|
|
2530
|
+
return (
|
|
2531
|
+
message.ephemeralMessage ||
|
|
2532
|
+
message.viewOnceMessage ||
|
|
2533
|
+
message.documentWithCaptionMessage ||
|
|
2534
|
+
message.viewOnceMessageV2 ||
|
|
2535
|
+
message.viewOnceMessageV2Extension ||
|
|
2536
|
+
message.editedMessage ||
|
|
2537
|
+
message.groupMentionedMessage ||
|
|
2538
|
+
message.botInvokeMessage ||
|
|
2539
|
+
message.lottieStickerMessage ||
|
|
2540
|
+
message.eventCoverImage ||
|
|
2541
|
+
message.statusMentionMessage ||
|
|
2542
|
+
message.pollCreationOptionImageMessage ||
|
|
2543
|
+
message.associatedChildMessage ||
|
|
2544
|
+
message.groupStatusMentionMessage ||
|
|
2545
|
+
message.pollCreationMessageV4 ||
|
|
2546
|
+
message.pollCreationMessageV5 ||
|
|
2547
|
+
message.statusAddYours ||
|
|
2548
|
+
message.groupStatusMessage ||
|
|
2549
|
+
message.limitSharingMessage ||
|
|
2550
|
+
message.botTaskMessage ||
|
|
2551
|
+
message.questionMessage ||
|
|
2552
|
+
message.groupStatusMessageV2 ||
|
|
2553
|
+
message.botForwardedMessage ||
|
|
2554
|
+
message.questionReplyMessage ||
|
|
2555
|
+
message.newsletterAdminProfileMessage ||
|
|
2556
|
+
message.newsletterAdminProfileMessageV2 ||
|
|
2557
|
+
message.newsletterAdminProfileStatusMessage ||
|
|
2558
|
+
message.spoilerMessage ||
|
|
2559
|
+
message.groupStatusV3Message ||
|
|
2560
|
+
message.pollCreationMessageV6
|
|
2561
|
+
)
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2564
|
+
exports.normalizeMessageContent = normalizeMessageContent
|
|
1030
2565
|
/**
|
|
1031
2566
|
* Extract the true message content from a message
|
|
1032
2567
|
* Eg. extracts the inner message from a disappearing message/view once message
|
|
1033
2568
|
*/
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
return content;
|
|
1068
|
-
};
|
|
2569
|
+
const extractMessageContent = content => {
|
|
2570
|
+
const extractFromTemplateMessage = msg => {
|
|
2571
|
+
if (msg.imageMessage) {
|
|
2572
|
+
return { imageMessage: msg.imageMessage }
|
|
2573
|
+
} else if (msg.documentMessage) {
|
|
2574
|
+
return { documentMessage: msg.documentMessage }
|
|
2575
|
+
} else if (msg.videoMessage) {
|
|
2576
|
+
return { videoMessage: msg.videoMessage }
|
|
2577
|
+
} else if (msg.locationMessage) {
|
|
2578
|
+
return { locationMessage: msg.locationMessage }
|
|
2579
|
+
} else {
|
|
2580
|
+
return {
|
|
2581
|
+
conversation:
|
|
2582
|
+
'contentText' in msg ? msg.contentText : 'hydratedContentText' in msg ? msg.hydratedContentText : ''
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
content = (0, exports.normalizeMessageContent)(content)
|
|
2587
|
+
if (content?.buttonsMessage) {
|
|
2588
|
+
return extractFromTemplateMessage(content.buttonsMessage)
|
|
2589
|
+
}
|
|
2590
|
+
if (content?.templateMessage?.hydratedFourRowTemplate) {
|
|
2591
|
+
return extractFromTemplateMessage(content?.templateMessage?.hydratedFourRowTemplate)
|
|
2592
|
+
}
|
|
2593
|
+
if (content?.templateMessage?.hydratedTemplate) {
|
|
2594
|
+
return extractFromTemplateMessage(content?.templateMessage?.hydratedTemplate)
|
|
2595
|
+
}
|
|
2596
|
+
if (content?.templateMessage?.fourRowTemplate) {
|
|
2597
|
+
return extractFromTemplateMessage(content?.templateMessage?.fourRowTemplate)
|
|
2598
|
+
}
|
|
2599
|
+
return content
|
|
2600
|
+
}
|
|
2601
|
+
exports.extractMessageContent = extractMessageContent
|
|
1069
2602
|
/**
|
|
1070
2603
|
* Returns the device predicted by message ID
|
|
1071
2604
|
*/
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
2605
|
+
const getDevice = id =>
|
|
2606
|
+
/^3A.{18}$/.test(id)
|
|
2607
|
+
? 'ios'
|
|
2608
|
+
: /^3E.{20}$/.test(id)
|
|
2609
|
+
? 'web'
|
|
2610
|
+
: /^(.{21}|.{32})$/.test(id)
|
|
2611
|
+
? 'android'
|
|
2612
|
+
: /^(3F|.{18}$)/.test(id)
|
|
2613
|
+
? 'desktop'
|
|
2614
|
+
: 'api/baileys'
|
|
2615
|
+
exports.getDevice = getDevice
|
|
1081
2616
|
/** Upserts a receipt in the message */
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
2617
|
+
const updateMessageWithReceipt = (msg, receipt) => {
|
|
2618
|
+
msg.userReceipt = msg.userReceipt || []
|
|
2619
|
+
const recp = msg.userReceipt.find(m => m.userJid === receipt.userJid)
|
|
2620
|
+
if (recp) {
|
|
2621
|
+
Object.assign(recp, receipt)
|
|
2622
|
+
} else {
|
|
2623
|
+
msg.userReceipt.push(receipt)
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
exports.updateMessageWithReceipt = updateMessageWithReceipt
|
|
1092
2627
|
/** Update the message with a new reaction */
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
}
|
|
2628
|
+
const updateMessageWithReaction = (msg, reaction) => {
|
|
2629
|
+
const authorID = (0, generics_1.getKeyAuthor)(reaction.key)
|
|
2630
|
+
const reactions = (msg.reactions || []).filter(r => (0, generics_1.getKeyAuthor)(r.key) !== authorID)
|
|
2631
|
+
reaction.text = reaction.text || ''
|
|
2632
|
+
reactions.push(reaction)
|
|
2633
|
+
msg.reactions = reactions
|
|
2634
|
+
}
|
|
2635
|
+
exports.updateMessageWithReaction = updateMessageWithReaction
|
|
1100
2636
|
/** Update the message with a new poll update */
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
}
|
|
2637
|
+
const updateMessageWithPollUpdate = (msg, update) => {
|
|
2638
|
+
const authorID = (0, generics_1.getKeyAuthor)(update.pollUpdateMessageKey)
|
|
2639
|
+
const reactions = (msg.pollUpdates || []).filter(
|
|
2640
|
+
r => (0, generics_1.getKeyAuthor)(r.pollUpdateMessageKey) !== authorID
|
|
2641
|
+
)
|
|
2642
|
+
if (update.vote?.selectedOptions?.length) {
|
|
2643
|
+
reactions.push(update)
|
|
2644
|
+
}
|
|
2645
|
+
msg.pollUpdates = reactions
|
|
2646
|
+
}
|
|
2647
|
+
exports.updateMessageWithPollUpdate = updateMessageWithPollUpdate
|
|
1109
2648
|
/** Update the message with a new event response */
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
2649
|
+
const updateMessageWithEventResponse = (msg, update) => {
|
|
2650
|
+
const authorID = (0, generics_1.getKeyAuthor)(update.eventResponseMessageKey)
|
|
2651
|
+
const responses = (msg.eventResponses || []).filter(
|
|
2652
|
+
r => (0, generics_1.getKeyAuthor)(r.eventResponseMessageKey) !== authorID
|
|
2653
|
+
)
|
|
2654
|
+
responses.push(update)
|
|
2655
|
+
msg.eventResponses = responses
|
|
2656
|
+
}
|
|
2657
|
+
exports.updateMessageWithEventResponse = updateMessageWithEventResponse
|
|
1116
2658
|
/**
|
|
1117
2659
|
* Aggregates all poll updates in a poll.
|
|
1118
2660
|
* @param msg the poll creation message
|
|
1119
2661
|
* @param meId your jid
|
|
1120
2662
|
* @returns A list of options & their voters
|
|
1121
2663
|
*/
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
2664
|
+
function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
2665
|
+
const opts =
|
|
2666
|
+
message?.pollCreationMessage?.options ||
|
|
2667
|
+
message?.pollCreationMessageV2?.options ||
|
|
2668
|
+
message?.pollCreationMessageV3?.options ||
|
|
2669
|
+
message?.pollCreationMessageV5?.options ||
|
|
2670
|
+
message?.pollCreationMessageV6?.options ||
|
|
2671
|
+
message?.pollCreationMessageV4?.message?.pollCreationMessage?.options ||
|
|
2672
|
+
message?.pollCreationMessageV4?.message?.pollCreationMessageV3?.options ||
|
|
2673
|
+
[]
|
|
2674
|
+
const voteHashMap = opts.reduce((acc, opt) => {
|
|
2675
|
+
const hash = (0, crypto_2.sha256)(Buffer.from(opt.optionName || '')).toString()
|
|
2676
|
+
acc[hash] = {
|
|
2677
|
+
name: opt.optionName || '',
|
|
2678
|
+
voters: []
|
|
2679
|
+
}
|
|
2680
|
+
return acc
|
|
2681
|
+
}, {})
|
|
2682
|
+
for (const update of pollUpdates || []) {
|
|
2683
|
+
const { vote } = update
|
|
2684
|
+
if (!vote) {
|
|
2685
|
+
continue
|
|
2686
|
+
}
|
|
2687
|
+
for (const option of vote.selectedOptions || []) {
|
|
2688
|
+
const hash = option.toString()
|
|
2689
|
+
let data = voteHashMap[hash]
|
|
2690
|
+
if (!data) {
|
|
2691
|
+
voteHashMap[hash] = {
|
|
2692
|
+
name: 'Unknown',
|
|
2693
|
+
voters: []
|
|
2694
|
+
}
|
|
2695
|
+
data = voteHashMap[hash]
|
|
2696
|
+
}
|
|
2697
|
+
voteHashMap[hash].voters.push((0, generics_1.getKeyAuthor)(update.pollUpdateMessageKey, meId))
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
return Object.values(voteHashMap)
|
|
2701
|
+
}
|
|
2702
|
+
/** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
|
|
2703
|
+
const aggregateMessageKeysNotFromMe = keys => {
|
|
2704
|
+
const keyMap = {}
|
|
2705
|
+
for (const { remoteJid, id, participant, fromMe, sts } of keys) {
|
|
2706
|
+
if (!fromMe) {
|
|
2707
|
+
const uqKey = `${remoteJid}:${participant || ''}`
|
|
2708
|
+
if (!keyMap[uqKey]) {
|
|
2709
|
+
keyMap[uqKey] = {
|
|
2710
|
+
jid: remoteJid,
|
|
2711
|
+
participant: participant,
|
|
2712
|
+
messageIds: [],
|
|
2713
|
+
// sts is per-message; kept only for single-message interop receipts
|
|
2714
|
+
sts: sts
|
|
2715
|
+
}
|
|
2716
|
+
} else if (keyMap[uqKey].sts !== sts) {
|
|
2717
|
+
// Multiple messages with different sts — can't aggregate a single sts
|
|
2718
|
+
keyMap[uqKey].sts = undefined
|
|
2719
|
+
}
|
|
2720
|
+
keyMap[uqKey].messageIds.push(id)
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
return Object.values(keyMap)
|
|
2724
|
+
}
|
|
2725
|
+
exports.aggregateMessageKeysNotFromMe = aggregateMessageKeysNotFromMe
|
|
2726
|
+
|
|
2727
|
+
/**
|
|
2728
|
+
* Check if a WebMessageInfo has a scheduled reveal time (ConditionalRevealMessage)
|
|
2729
|
+
*/
|
|
2730
|
+
const isScheduledMessage = msg => !!msg?.scheduledMessageMetadata?.scheduledTime
|
|
2731
|
+
exports.isScheduledMessage = isScheduledMessage
|
|
2732
|
+
|
|
2733
|
+
/**
|
|
2734
|
+
* Get scheduled reveal time of a message as a Date, or null
|
|
2735
|
+
*/
|
|
2736
|
+
const getScheduledMessageTime = msg => {
|
|
2737
|
+
const t = msg?.scheduledMessageMetadata?.scheduledTime
|
|
2738
|
+
if (!t) return null
|
|
2739
|
+
return new Date(Number(t) * 1000)
|
|
2740
|
+
}
|
|
2741
|
+
exports.getScheduledMessageTime = getScheduledMessageTime
|
|
2742
|
+
|
|
2743
|
+
/**
|
|
2744
|
+
* Extract PaymentInfo from a WebMessageInfo (the payment status field, not the message content)
|
|
2745
|
+
*/
|
|
2746
|
+
const getMessagePaymentInfo = msg => msg?.paymentInfo || msg?.quotedPaymentInfo || null
|
|
2747
|
+
exports.getMessagePaymentInfo = getMessagePaymentInfo
|
|
2748
|
+
|
|
2749
|
+
/**
|
|
2750
|
+
* Get all comment metadata from a WebMessageInfo
|
|
2751
|
+
*/
|
|
2752
|
+
const getMessageCommentMetadata = msg => msg?.commentMetadata || null
|
|
2753
|
+
exports.getMessageCommentMetadata = getMessageCommentMetadata
|
|
2754
|
+
|
|
2755
|
+
/**
|
|
2756
|
+
* Get all message add-ons (reactions, poll updates, pins) from a WebMessageInfo
|
|
2757
|
+
*/
|
|
2758
|
+
const getMessageAddOns = msg => msg?.messageAddOns || []
|
|
2759
|
+
exports.getMessageAddOns = getMessageAddOns
|
|
2760
|
+
|
|
2761
|
+
/**
|
|
2762
|
+
* Get the quiz correct answer from a poll creation message, if it's a quiz
|
|
2763
|
+
*/
|
|
2764
|
+
const getPollCorrectAnswer = pollMsg => {
|
|
2765
|
+
const poll =
|
|
2766
|
+
pollMsg?.pollCreationMessage ||
|
|
2767
|
+
pollMsg?.pollCreationMessageV2 ||
|
|
2768
|
+
pollMsg?.pollCreationMessageV3 ||
|
|
2769
|
+
pollMsg?.pollCreationMessageV5 ||
|
|
2770
|
+
pollMsg?.pollCreationMessageV6
|
|
2771
|
+
if (!poll) return null
|
|
2772
|
+
const isQuiz = poll.pollType === WAProto_1.proto.Message.PollType?.QUIZ || poll.pollType === 1
|
|
2773
|
+
return isQuiz ? poll.correctAnswer?.optionName || null : null
|
|
1154
2774
|
}
|
|
2775
|
+
exports.getPollCorrectAnswer = getPollCorrectAnswer
|
|
2776
|
+
|
|
1155
2777
|
/**
|
|
1156
2778
|
* Aggregates all event responses in an event message.
|
|
1157
2779
|
* @param msg the event creation message
|
|
1158
|
-
* @param
|
|
2780
|
+
* @param meLid your lid
|
|
1159
2781
|
* @returns A list of response types & their responders
|
|
1160
2782
|
*/
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
2783
|
+
function getAggregateResponsesInEventMessage({ eventResponses }, meLid) {
|
|
2784
|
+
const responseTypes = ['GOING', 'NOT_GOING', 'MAYBE']
|
|
2785
|
+
const responseMap = {}
|
|
2786
|
+
|
|
2787
|
+
for (const type of responseTypes) {
|
|
2788
|
+
responseMap[type] = {
|
|
2789
|
+
response: type,
|
|
2790
|
+
responders: []
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
for (const update of eventResponses) {
|
|
2794
|
+
const { response } = update.response || {}
|
|
2795
|
+
const responseType = index_js_1.proto.Message.EventResponseMessage.EventResponseType[response]
|
|
2796
|
+
if (responseType !== 'UNKNOWN' && responseMap[responseType]) {
|
|
2797
|
+
responseMap[responseType].responders.push(generics_1.getKeyAuthor(update.eventResponseMessageKey, meLid))
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
|
|
2801
|
+
return Object.values(responseMap)
|
|
1177
2802
|
}
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
if (!fromMe) {
|
|
1183
|
-
const uqKey = `${remoteJid}:${participant || ''}`;
|
|
1184
|
-
if (!keyMap[uqKey]) {
|
|
1185
|
-
keyMap[uqKey] = {
|
|
1186
|
-
jid: remoteJid,
|
|
1187
|
-
participant: participant,
|
|
1188
|
-
messageIds: []
|
|
1189
|
-
};
|
|
1190
|
-
}
|
|
1191
|
-
keyMap[uqKey].messageIds.push(id);
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
return Object.values(keyMap);
|
|
1195
|
-
};
|
|
1196
|
-
const REUPLOAD_REQUIRED_STATUS = [410, 404];
|
|
2803
|
+
|
|
2804
|
+
exports.getAggregateResponsesInEventMessage = getAggregateResponsesInEventMessage
|
|
2805
|
+
|
|
2806
|
+
const REUPLOAD_REQUIRED_STATUS = [410, 404]
|
|
1197
2807
|
/**
|
|
1198
2808
|
* Downloads the given message. Throws an error if it's not a media message
|
|
1199
2809
|
*/
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
}
|
|
2810
|
+
const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
2811
|
+
const result = await downloadMsg().catch(async error => {
|
|
2812
|
+
if (
|
|
2813
|
+
ctx &&
|
|
2814
|
+
typeof error?.status === 'number' && // treat errors with status as HTTP failures requiring reupload
|
|
2815
|
+
REUPLOAD_REQUIRED_STATUS.includes(error.status)
|
|
2816
|
+
) {
|
|
2817
|
+
ctx.logger.info({ key: message.key }, 'sending reupload media request...')
|
|
2818
|
+
// request reupload
|
|
2819
|
+
message = await ctx.reuploadRequest(message)
|
|
2820
|
+
const result = await downloadMsg()
|
|
2821
|
+
return result
|
|
2822
|
+
}
|
|
2823
|
+
throw error
|
|
2824
|
+
})
|
|
2825
|
+
return result
|
|
2826
|
+
async function downloadMsg() {
|
|
2827
|
+
const mContent = (0, exports.extractMessageContent)(message.message)
|
|
2828
|
+
if (!mContent) {
|
|
2829
|
+
throw new boom_1.Boom('No message present', { statusCode: 400, data: message })
|
|
2830
|
+
}
|
|
2831
|
+
const contentType = (0, exports.getContentType)(mContent)
|
|
2832
|
+
let mediaType = contentType?.replace('Message', '')
|
|
2833
|
+
const media = mContent[contentType]
|
|
2834
|
+
if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
|
|
2835
|
+
throw new boom_1.Boom(`"${contentType}" message is not a media message`)
|
|
2836
|
+
}
|
|
2837
|
+
let download
|
|
2838
|
+
if ('thumbnailDirectPath' in media && !('url' in media)) {
|
|
2839
|
+
download = {
|
|
2840
|
+
directPath: media.thumbnailDirectPath,
|
|
2841
|
+
mediaKey: media.mediaKey
|
|
2842
|
+
}
|
|
2843
|
+
mediaType = 'thumbnail-link'
|
|
2844
|
+
} else {
|
|
2845
|
+
download = media
|
|
2846
|
+
}
|
|
2847
|
+
const stream = await (0, messages_media_1.downloadContentFromMessage)(download, mediaType, options)
|
|
2848
|
+
if (type === 'buffer') {
|
|
2849
|
+
const bufferArray = []
|
|
2850
|
+
for await (const chunk of stream) {
|
|
2851
|
+
bufferArray.push(chunk)
|
|
2852
|
+
}
|
|
2853
|
+
return Buffer.concat(bufferArray)
|
|
2854
|
+
}
|
|
2855
|
+
return stream
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2858
|
+
exports.downloadMediaMessage = downloadMediaMessage
|
|
1247
2859
|
/** Checks whether the given message is a media message; if it is returns the inner content */
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
2860
|
+
const assertMediaContent = content => {
|
|
2861
|
+
content = (0, exports.extractMessageContent)(content)
|
|
2862
|
+
const mediaContent =
|
|
2863
|
+
content?.documentMessage ||
|
|
2864
|
+
content?.imageMessage ||
|
|
2865
|
+
content?.videoMessage ||
|
|
2866
|
+
content?.audioMessage ||
|
|
2867
|
+
content?.stickerMessage
|
|
2868
|
+
if (!mediaContent) {
|
|
2869
|
+
throw new boom_1.Boom('given message is not a media message', { statusCode: 400, data: content })
|
|
2870
|
+
}
|
|
2871
|
+
return mediaContent
|
|
2872
|
+
}
|
|
2873
|
+
exports.assertMediaContent = assertMediaContent
|
|
2874
|
+
/**
|
|
2875
|
+
* Normalizes a bare user id to @s.whatsapp.net. Does not convert LID↔PN; use lidMapping / PN in key.remoteJidAlt when needed.
|
|
2876
|
+
*/
|
|
2877
|
+
const toJid = id => {
|
|
2878
|
+
if (!id) return ''
|
|
2879
|
+
if (id.includes('@')) return id
|
|
2880
|
+
return `${id}@s.whatsapp.net`
|
|
2881
|
+
}
|
|
2882
|
+
exports.toJid = toJid
|
|
2883
|
+
/**
|
|
2884
|
+
* Returns the peer LID JID when the key is LID-primary (decode sets remoteJid/participant to @lid when WA sends LID).
|
|
2885
|
+
*/
|
|
2886
|
+
const getSenderLid = message => {
|
|
2887
|
+
const k = message.key
|
|
2888
|
+
if (!k) {
|
|
2889
|
+
return { jid: '', lid: '' }
|
|
2890
|
+
}
|
|
2891
|
+
const jid = k.participant || k.remoteJid || ''
|
|
2892
|
+
if (jid.endsWith('@lid') || jid.endsWith('@hosted.lid')) {
|
|
2893
|
+
return { jid, lid: jid }
|
|
2894
|
+
}
|
|
2895
|
+
if (k.lid && typeof k.lid === 'string') {
|
|
2896
|
+
const lid = k.lid.includes('@') ? k.lid : (0, WABinary_1.jidEncode)(k.lid, 'lid')
|
|
2897
|
+
return { jid, lid }
|
|
2898
|
+
}
|
|
2899
|
+
if (k.participantLid && (0, WABinary_1.isLidUser)(k.participantLid)) {
|
|
2900
|
+
return { jid, lid: k.participantLid }
|
|
2901
|
+
}
|
|
2902
|
+
return { jid, lid: '' }
|
|
2903
|
+
}
|
|
2904
|
+
exports.getSenderLid = getSenderLid
|