@fhynella/baileys 2.0.7 → 2.2.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/lib/Defaults/baileys-version.json +2 -2
- package/lib/Defaults/connection.js +1 -1
- package/lib/Defaults/constants.js +13 -1
- package/lib/Defaults/history.js +3 -1
- package/lib/Signal/Group/sender-chain-key.js +1 -14
- package/lib/Signal/Group/sender-key-distribution-message.js +2 -2
- package/lib/Signal/Group/sender-key-record.js +2 -11
- package/lib/Signal/Group/sender-key-state.js +11 -57
- package/lib/Signal/libsignal.js +200 -116
- package/lib/Signal/lid-mapping.js +121 -68
- package/lib/Socket/Client/websocket.js +9 -2
- package/lib/Socket/business.js +5 -1
- package/lib/Socket/chats.js +180 -89
- package/lib/Socket/community.js +169 -41
- package/lib/Socket/groups.js +25 -21
- package/lib/Socket/messages-recv.js +458 -333
- package/lib/Socket/messages-send.js +517 -572
- package/lib/Socket/mex.js +61 -0
- package/lib/Socket/newsletter.js +159 -252
- package/lib/Socket/socket.js +283 -100
- package/lib/Types/Newsletter.js +32 -25
- package/lib/Utils/auth-utils.js +189 -354
- package/lib/Utils/browser-utils.js +43 -0
- package/lib/Utils/chat-utils.js +166 -41
- package/lib/Utils/decode-wa-message.js +77 -35
- package/lib/Utils/event-buffer.js +80 -24
- package/lib/Utils/generics.js +28 -128
- package/lib/Utils/history.js +10 -8
- package/lib/Utils/index.js +1 -1
- package/lib/Utils/link-preview.js +17 -32
- package/lib/Utils/lt-hash.js +28 -22
- package/lib/Utils/make-mutex.js +26 -28
- package/lib/Utils/message-retry-manager.js +51 -3
- package/lib/Utils/messages-media.js +364 -173
- package/lib/Utils/messages.js +735 -727
- package/lib/Utils/noise-handler.js +33 -2
- package/lib/Utils/pre-key-manager.js +126 -0
- package/lib/Utils/process-message.js +115 -55
- package/lib/Utils/signal.js +45 -18
- package/lib/Utils/validate-connection.js +52 -29
- package/lib/WABinary/constants.js +1268 -1268
- package/lib/WABinary/decode.js +58 -4
- package/lib/WABinary/encode.js +54 -7
- package/lib/WABinary/jid-utils.js +58 -11
- package/lib/WAM/constants.js +19064 -11563
- package/lib/WAM/encode.js +57 -8
- package/lib/WAUSync/USyncQuery.js +35 -19
- package/package.json +8 -7
- package/lib/Socket/usync.js +0 -83
package/lib/Utils/messages.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true })
|
|
4
4
|
|
|
5
5
|
const { Boom } = require("@hapi/boom")
|
|
6
|
-
const axios_1 = require("axios")
|
|
7
6
|
const { randomBytes } = require("crypto")
|
|
8
7
|
const { promises } = require("fs")
|
|
9
8
|
const { proto } = require("../../WAProto")
|
|
@@ -97,6 +96,7 @@ const assertColor = async (color) => {
|
|
|
97
96
|
|
|
98
97
|
const prepareWAMessageMedia = async (message, options) => {
|
|
99
98
|
const logger = options.logger
|
|
99
|
+
|
|
100
100
|
let mediaType
|
|
101
101
|
|
|
102
102
|
for (const key of MEDIA_KEYS) {
|
|
@@ -106,7 +106,7 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
if (!mediaType) {
|
|
109
|
-
throw new Boom('Invalid media type', { statusCode: 400 })
|
|
109
|
+
throw new Boom('Invalid media type', { statusCode: 400 })
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
const uploadData = {
|
|
@@ -133,11 +133,15 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
133
133
|
|
|
134
134
|
if (cacheableKey) {
|
|
135
135
|
const mediaBuff = await options.mediaCache.get(cacheableKey)
|
|
136
|
+
|
|
136
137
|
if (mediaBuff) {
|
|
137
138
|
logger?.debug({ cacheableKey }, 'got media cache hit')
|
|
138
|
-
|
|
139
|
+
|
|
140
|
+
const obj = proto.Message.decode(mediaBuff)
|
|
139
141
|
const key = `${mediaType}Message`
|
|
142
|
+
|
|
140
143
|
Object.assign(obj[key], { ...uploadData, media: undefined })
|
|
144
|
+
|
|
141
145
|
return obj
|
|
142
146
|
}
|
|
143
147
|
}
|
|
@@ -147,7 +151,7 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
147
151
|
if (isNewsletter) {
|
|
148
152
|
logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter')
|
|
149
153
|
const { filePath, fileSha256, fileLength } = await getRawMediaUploadData(uploadData.media, options.mediaTypeOverride || mediaType, logger)
|
|
150
|
-
const fileSha256B64 = fileSha256.toString('base64')
|
|
154
|
+
const fileSha256B64 = fileSha256.toString('base64');
|
|
151
155
|
const { mediaUrl, directPath } = await options.upload(filePath, {
|
|
152
156
|
fileEncSha256B64: fileSha256B64,
|
|
153
157
|
mediaType: mediaType,
|
|
@@ -173,6 +177,10 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
173
177
|
delete obj.videoMessage
|
|
174
178
|
}
|
|
175
179
|
|
|
180
|
+
if (obj.stickerMessage) {
|
|
181
|
+
obj.stickerMessage.stickerSentTs = Date.now()
|
|
182
|
+
}
|
|
183
|
+
|
|
176
184
|
if (cacheableKey) {
|
|
177
185
|
logger?.debug({ cacheableKey }, 'set cache');
|
|
178
186
|
await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish())
|
|
@@ -186,15 +194,12 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
186
194
|
const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true
|
|
187
195
|
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true
|
|
188
196
|
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation
|
|
189
|
-
|
|
190
197
|
const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await encryptedStream(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
191
198
|
logger,
|
|
192
199
|
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
193
200
|
opts: options.options
|
|
194
201
|
})
|
|
195
|
-
|
|
196
202
|
const fileEncSha256B64 = fileEncSha256.toString('base64')
|
|
197
|
-
|
|
198
203
|
const [{ mediaUrl, directPath }] = await Promise.all([
|
|
199
204
|
(async () => {
|
|
200
205
|
const result = await options.upload(encFilePath, {
|
|
@@ -205,20 +210,19 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
205
210
|
logger?.debug({ mediaType, cacheableKey }, 'uploaded media')
|
|
206
211
|
return result
|
|
207
212
|
})(),
|
|
208
|
-
|
|
209
213
|
(async () => {
|
|
210
214
|
try {
|
|
211
215
|
if (requiresThumbnailComputation) {
|
|
212
216
|
const { thumbnail, originalImageDimensions } = await generateThumbnail(originalFilePath, mediaType, options)
|
|
217
|
+
|
|
213
218
|
uploadData.jpegThumbnail = thumbnail
|
|
219
|
+
|
|
214
220
|
if (!uploadData.width && originalImageDimensions) {
|
|
215
221
|
uploadData.width = originalImageDimensions.width
|
|
216
222
|
uploadData.height = originalImageDimensions.height
|
|
217
|
-
|
|
218
223
|
logger?.debug('set dimensions')
|
|
219
224
|
}
|
|
220
|
-
|
|
221
|
-
logger?.debug('generated thumbnail');
|
|
225
|
+
logger?.debug('generated thumbnail')
|
|
222
226
|
}
|
|
223
227
|
|
|
224
228
|
if (requiresDurationComputation) {
|
|
@@ -275,7 +279,7 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
275
279
|
}
|
|
276
280
|
|
|
277
281
|
if (cacheableKey) {
|
|
278
|
-
logger?.debug({ cacheableKey }, 'set cache')
|
|
282
|
+
logger?.debug({ cacheableKey }, 'set cache')
|
|
279
283
|
await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish())
|
|
280
284
|
}
|
|
281
285
|
|
|
@@ -292,7 +296,7 @@ const prepareAlbumMessageContent = async (jid, albums, options) => {
|
|
|
292
296
|
}
|
|
293
297
|
|
|
294
298
|
const validCount = albums.filter(m => ('image' in m) || ('video' in m)).length
|
|
295
|
-
|
|
299
|
+
|
|
296
300
|
if (validCount === 0) {
|
|
297
301
|
throw new Error("albums contains no valid media. Use 'image' or 'video' keys.")
|
|
298
302
|
}
|
|
@@ -411,23 +415,49 @@ const generateForwardMessageContent = (message, forceForward) => {
|
|
|
411
415
|
return content
|
|
412
416
|
}
|
|
413
417
|
|
|
418
|
+
const hasNonNullishProperty = (message, key) => {
|
|
419
|
+
return (
|
|
420
|
+
typeof message === 'object' &&
|
|
421
|
+
message !== null &&
|
|
422
|
+
key in message &&
|
|
423
|
+
message[key] !== null &&
|
|
424
|
+
message[key] !== undefined
|
|
425
|
+
)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function hasOptionalProperty(obj, key) {
|
|
429
|
+
return (
|
|
430
|
+
typeof obj === 'object' &&
|
|
431
|
+
obj !== null &&
|
|
432
|
+
key in obj &&
|
|
433
|
+
obj[key] !== null
|
|
434
|
+
)
|
|
435
|
+
}
|
|
436
|
+
|
|
414
437
|
const generateWAMessageContent = async (message, options) => {
|
|
415
438
|
let m = {}
|
|
416
|
-
|
|
439
|
+
|
|
440
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
417
441
|
const extContent = { text: message.text }
|
|
442
|
+
|
|
418
443
|
let urlInfo = message.linkPreview
|
|
419
444
|
|
|
420
|
-
if (typeof urlInfo ===
|
|
421
|
-
urlInfo = await generateLinkPreviewIfRequired(
|
|
445
|
+
if (typeof urlInfo === "undefined") {
|
|
446
|
+
urlInfo = await generateLinkPreviewIfRequired(
|
|
447
|
+
message.text,
|
|
448
|
+
options.getUrlInfo,
|
|
449
|
+
options.logger
|
|
450
|
+
)
|
|
422
451
|
}
|
|
423
452
|
|
|
424
453
|
if (urlInfo) {
|
|
425
|
-
extContent.canonicalUrl = urlInfo[
|
|
426
|
-
extContent.matchedText = urlInfo[
|
|
454
|
+
extContent.canonicalUrl = urlInfo["canonical-url"]
|
|
455
|
+
extContent.matchedText = urlInfo["matched-text"]
|
|
427
456
|
extContent.jpegThumbnail = urlInfo.jpegThumbnail
|
|
428
457
|
extContent.description = urlInfo.description
|
|
429
458
|
extContent.title = urlInfo.title
|
|
430
459
|
extContent.previewType = 0
|
|
460
|
+
|
|
431
461
|
const img = urlInfo.highQualityThumbnail
|
|
432
462
|
|
|
433
463
|
if (img) {
|
|
@@ -442,848 +472,853 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
442
472
|
}
|
|
443
473
|
|
|
444
474
|
if (options.backgroundColor) {
|
|
445
|
-
extContent.backgroundArgb = await assertColor(
|
|
475
|
+
extContent.backgroundArgb = await assertColor(
|
|
476
|
+
options.backgroundColor
|
|
477
|
+
)
|
|
446
478
|
}
|
|
447
479
|
|
|
448
480
|
if (options.textColor) {
|
|
449
|
-
extContent.textArgb = await assertColor(options.textColor)
|
|
481
|
+
extContent.textArgb = await assertColor(options.textColor)
|
|
450
482
|
}
|
|
451
483
|
|
|
452
484
|
if (options.font) {
|
|
453
485
|
extContent.font = options.font
|
|
454
486
|
}
|
|
455
487
|
|
|
456
|
-
extContent.contextInfo = {
|
|
457
|
-
...(message.contextInfo || {}),
|
|
458
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
459
|
-
}
|
|
460
|
-
|
|
461
488
|
m.extendedTextMessage = extContent
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
else if ('contacts' in message) {
|
|
489
|
+
} else if (hasNonNullishProperty(message, "contacts")) {
|
|
465
490
|
const contactLen = message.contacts.contacts.length
|
|
466
491
|
|
|
467
492
|
let contactMessage
|
|
468
493
|
|
|
469
494
|
if (!contactLen) {
|
|
470
|
-
throw new Boom(
|
|
495
|
+
throw new Boom("require atleast 1 contact", { statusCode: 400 })
|
|
471
496
|
}
|
|
472
497
|
|
|
473
498
|
if (contactLen === 1) {
|
|
474
499
|
contactMessage = {
|
|
475
|
-
|
|
500
|
+
contactMessage: WAProto.Message.ContactMessage.fromObject(
|
|
501
|
+
message.contacts.contacts[0]
|
|
502
|
+
),
|
|
476
503
|
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
else {
|
|
504
|
+
} else {
|
|
480
505
|
contactMessage = {
|
|
481
|
-
|
|
506
|
+
contactsArrayMessage: WAProto.Message.ContactsArrayMessage.fromObject(
|
|
507
|
+
message.contacts
|
|
508
|
+
),
|
|
482
509
|
}
|
|
483
510
|
}
|
|
484
511
|
|
|
485
|
-
const [type] = Object.keys(contactMessage)
|
|
486
|
-
|
|
487
|
-
contactMessage[type].contextInfo = {
|
|
488
|
-
...(message.contextInfo || {}),
|
|
489
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
490
|
-
}
|
|
491
|
-
|
|
492
512
|
m = contactMessage
|
|
493
|
-
}
|
|
513
|
+
} else if (hasNonNullishProperty(message, "contacts")) {
|
|
514
|
+
const contactLen = message.contacts.contacts.length
|
|
494
515
|
|
|
495
|
-
|
|
496
|
-
let locationMessage
|
|
516
|
+
let contactMessage
|
|
497
517
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
liveLocationMessage: WAProto.Message.LiveLocationMessage.fromObject(message.location)
|
|
501
|
-
}
|
|
518
|
+
if (!contactLen) {
|
|
519
|
+
throw new Boom("require atleast 1 contact", { statusCode: 400 })
|
|
502
520
|
}
|
|
503
521
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
522
|
+
if (contactLen === 1) {
|
|
523
|
+
contactMessage = {
|
|
524
|
+
contactMessage: WAProto.Message.ContactMessage.fromObject(
|
|
525
|
+
message.contacts.contacts[0]
|
|
526
|
+
),
|
|
527
|
+
}
|
|
528
|
+
} else {
|
|
529
|
+
contactMessage = {
|
|
530
|
+
contactsArrayMessage: WAProto.Message.ContactsArrayMessage.fromObject(
|
|
531
|
+
message.contacts
|
|
532
|
+
),
|
|
507
533
|
}
|
|
508
534
|
}
|
|
509
535
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
locationMessage
|
|
513
|
-
|
|
514
|
-
|
|
536
|
+
m = contactMessage
|
|
537
|
+
} else if (hasNonNullishProperty(message, "location")) {
|
|
538
|
+
let locationMessage
|
|
539
|
+
|
|
540
|
+
if (message.live) {
|
|
541
|
+
locationMessage = {
|
|
542
|
+
liveLocationMessage: WAProto.Message.LiveLocationMessage.fromObject(
|
|
543
|
+
message.location
|
|
544
|
+
),
|
|
545
|
+
}
|
|
546
|
+
} else {
|
|
547
|
+
locationMessage = {
|
|
548
|
+
locationMessage: WAProto.Message.LocationMessage.fromObject(
|
|
549
|
+
message.location
|
|
550
|
+
),
|
|
551
|
+
}
|
|
515
552
|
}
|
|
516
553
|
|
|
517
554
|
m = locationMessage
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
else if ('react' in message) {
|
|
555
|
+
} else if (hasNonNullishProperty(message, "react")) {
|
|
521
556
|
if (!message.react.senderTimestampMs) {
|
|
522
557
|
message.react.senderTimestampMs = Date.now()
|
|
523
558
|
}
|
|
524
559
|
|
|
525
|
-
m.reactionMessage = WAProto.Message.ReactionMessage.fromObject(
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
else if (
|
|
560
|
+
m.reactionMessage = WAProto.Message.ReactionMessage.fromObject(
|
|
561
|
+
message.react
|
|
562
|
+
)
|
|
563
|
+
} else if (hasNonNullishProperty(message, "delete")) {
|
|
529
564
|
m.protocolMessage = {
|
|
530
565
|
key: message.delete,
|
|
531
|
-
type: WAProto.Message.ProtocolMessage.Type.REVOKE
|
|
566
|
+
type: WAProto.Message.ProtocolMessage.Type.REVOKE,
|
|
532
567
|
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
const mess = generateForwardMessageContent(message.forward, message.force)
|
|
537
|
-
const [type] = Object.keys(mess)
|
|
538
|
-
|
|
539
|
-
mess[type].contextInfo = {
|
|
540
|
-
...(message.contextInfo || {}),
|
|
541
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
568
|
+
} else if (hasNonNullishProperty(message, "sharePhoneNumber")) {
|
|
569
|
+
m.protocolMessage = {
|
|
570
|
+
type: WAProto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER,
|
|
542
571
|
}
|
|
543
|
-
|
|
544
|
-
m =
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
else if (
|
|
548
|
-
const exp =
|
|
549
|
-
|
|
550
|
-
|
|
572
|
+
} else if (hasNonNullishProperty(message, "requestPhoneNumber")) {
|
|
573
|
+
m.requestPhoneNumberMessage = {}
|
|
574
|
+
} else if (hasNonNullishProperty(message, "forward")) {
|
|
575
|
+
m = generateForwardMessageContent(message.forward, message.force)
|
|
576
|
+
} else if (hasNonNullishProperty(message, "disappearingMessagesInChat")) {
|
|
577
|
+
const exp =
|
|
578
|
+
typeof message.disappearingMessagesInChat === "boolean"
|
|
579
|
+
? message.disappearingMessagesInChat
|
|
580
|
+
? WA_DEFAULT_EPHEMERAL
|
|
581
|
+
: 0
|
|
582
|
+
: message.disappearingMessagesInChat
|
|
551
583
|
m = prepareDisappearingMessageSettingContent(exp)
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
else if ('groupInvite' in message) {
|
|
555
|
-
m.groupInviteMessage = {}
|
|
584
|
+
} else if (hasNonNullishProperty(message, "groupInvite")) {
|
|
585
|
+
m.groupInviteMessage = {}
|
|
556
586
|
|
|
557
587
|
m.groupInviteMessage.inviteCode = message.groupInvite.code
|
|
558
588
|
m.groupInviteMessage.inviteExpiration = message.groupInvite.expiration
|
|
559
589
|
m.groupInviteMessage.caption = message.groupInvite.caption
|
|
560
590
|
m.groupInviteMessage.groupJid = message.groupInvite.jid
|
|
561
|
-
m.groupInviteMessage.groupName = message.groupInvite.name
|
|
562
|
-
m.groupInviteMessage.contextInfo = message.contextInfo
|
|
591
|
+
m.groupInviteMessage.groupName = message.groupInvite.name
|
|
592
|
+
m.groupInviteMessage.contextInfo = message.contextInfo
|
|
563
593
|
|
|
564
594
|
if (options.getProfilePicUrl) {
|
|
565
|
-
const pfpUrl = await options.getProfilePicUrl(
|
|
566
|
-
|
|
595
|
+
const pfpUrl = await options.getProfilePicUrl(
|
|
596
|
+
message.groupInvite.jid
|
|
597
|
+
)
|
|
598
|
+
const { thumbnail } = await generateThumbnail(pfpUrl, "image")
|
|
567
599
|
m.groupInviteMessage.jpegThumbnail = thumbnail
|
|
568
600
|
}
|
|
569
|
-
|
|
570
|
-
m.
|
|
571
|
-
...(message.contextInfo || {}),
|
|
572
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
else if ('adminInvite' in message) {
|
|
577
|
-
m.newsletterAdminInviteMessage = {}
|
|
601
|
+
} else if (hasNonNullishProperty(message, "adminInvite")) {
|
|
602
|
+
m.newsletterAdminInviteMessage = {}
|
|
578
603
|
|
|
579
604
|
m.newsletterAdminInviteMessage.newsletterJid = message.adminInvite.jid
|
|
580
|
-
m.newsletterAdminInviteMessage.newsletterName=
|
|
605
|
+
m.newsletterAdminInviteMessage.newsletterName =
|
|
606
|
+
message.adminInvite.name
|
|
581
607
|
m.newsletterAdminInviteMessage.caption = message.adminInvite.caption
|
|
582
|
-
m.newsletterAdminInviteMessage.inviteExpiration =
|
|
583
|
-
|
|
608
|
+
m.newsletterAdminInviteMessage.inviteExpiration =
|
|
609
|
+
message.adminInvite.expiration
|
|
610
|
+
m.newsletterAdminInviteMessage.contextInfo = message.contextInfo
|
|
584
611
|
|
|
585
612
|
if (options.getProfilePicUrl) {
|
|
586
|
-
const pfpUrl = await options.getProfilePicUrl(
|
|
587
|
-
|
|
613
|
+
const pfpUrl = await options.getProfilePicUrl(
|
|
614
|
+
message.adminInvite.jid
|
|
615
|
+
)
|
|
616
|
+
const { thumbnail } = await generateThumbnail(pfpUrl, "image")
|
|
588
617
|
m.newsletterAdminInviteMessage.jpegThumbnail = thumbnail
|
|
589
618
|
}
|
|
590
|
-
|
|
591
|
-
m.newsletterAdminInviteMessage.contextInfo = {
|
|
592
|
-
...(message.contextInfo || {}),
|
|
593
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
else if ('pin' in message) {
|
|
598
|
-
m.pinInChatMessage = {}
|
|
599
|
-
m.messageContextInfo = {}
|
|
600
|
-
|
|
601
|
-
m.pinInChatMessage.key = message.pin.key
|
|
602
|
-
m.pinInChatMessage.type = message.pin?.type || 1
|
|
603
|
-
m.pinInChatMessage.senderTimestampMs = message.pin?.time || Date.now()
|
|
604
|
-
m.messageContextInfo.messageAddOnDurationInSecs = message.pin.type === 1 ? message.pin.time || 86400 : 0
|
|
605
|
-
m.messageContextInfo.messageAddOnExpiryType = proto.MessageContextInfo.MessageAddonExpiryType.STATIC
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
else if ('keep' in message) {
|
|
619
|
+
} else if (hasNonNullishProperty(message, "keep")) {
|
|
609
620
|
m.keepInChatMessage = {}
|
|
610
621
|
|
|
611
622
|
m.keepInChatMessage.key = message.keep.key
|
|
612
623
|
m.keepInChatMessage.keepType = message.keep?.type || 1
|
|
613
624
|
m.keepInChatMessage.timestampMs = message.keep?.time || Date.now()
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
else if ('call' in message) {
|
|
625
|
+
} else if (hasNonNullishProperty(message, "call")) {
|
|
617
626
|
m.scheduledCallCreationMessage = {}
|
|
618
627
|
|
|
619
|
-
m.scheduledCallCreationMessage.scheduledTimestampMs =
|
|
628
|
+
m.scheduledCallCreationMessage.scheduledTimestampMs =
|
|
629
|
+
message.call?.time || Date.now()
|
|
620
630
|
m.scheduledCallCreationMessage.callType = message.call?.type || 1
|
|
621
|
-
m.scheduledCallCreationMessage.title =
|
|
631
|
+
m.scheduledCallCreationMessage.title =
|
|
632
|
+
message.call?.name || "Call Creation"
|
|
633
|
+
} else if (hasNonNullishProperty(message, "paymentInvite")) {
|
|
634
|
+
m.messageContextInfo = {}
|
|
635
|
+
m.paymentInviteMessage = {}
|
|
636
|
+
|
|
637
|
+
m.paymentInviteMessage.expiryTimestamp =
|
|
638
|
+
message.paymentInvite?.expiry || 0
|
|
639
|
+
m.paymentInviteMessage.serviceType = message.paymentInvite?.type || 2
|
|
640
|
+
} else if (hasNonNullishProperty(message, "ptv")) {
|
|
641
|
+
const { videoMessage } = await prepareWAMessageMedia(
|
|
642
|
+
{ video: message.video },
|
|
643
|
+
options
|
|
644
|
+
)
|
|
645
|
+
|
|
646
|
+
m.ptvMessage = videoMessage
|
|
647
|
+
} else if (hasNonNullishProperty(message, "order")) {
|
|
648
|
+
m.orderMessage = WAProto.Message.OrderMessage.fromObject(message.order)
|
|
649
|
+
} else if (hasNonNullishProperty(message, "product")) {
|
|
650
|
+
const { imageMessage } = await prepareWAMessageMedia(
|
|
651
|
+
{ image: message.product.productImage },
|
|
652
|
+
options
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
m.productMessage = WAProto.Message.ProductMessage.fromObject({
|
|
656
|
+
...message,
|
|
657
|
+
product: {
|
|
658
|
+
...message.product,
|
|
659
|
+
productImage: imageMessage,
|
|
660
|
+
},
|
|
661
|
+
})
|
|
662
|
+
} else if (hasNonNullishProperty(message, "album")) {
|
|
663
|
+
const imageMessages = message.album.filter((item) => "image" in item)
|
|
664
|
+
const videoMessages = message.album.filter((item) => "video" in item)
|
|
665
|
+
|
|
666
|
+
m.albumMessage = WAProto.Message.AlbumMessage.fromObject({
|
|
667
|
+
expectedImageCount: imageMessages.length,
|
|
668
|
+
expectedVideoCount: videoMessages.length,
|
|
669
|
+
})
|
|
670
|
+
} else if (hasNonNullishProperty(message, "event")) {
|
|
671
|
+
m.eventMessage = WAProto.Message.EventMessage.fromObject(message.event)
|
|
622
672
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
673
|
+
if (!message.event.startTime) {
|
|
674
|
+
m.eventMessage.startTime = unixTimestampSeconds() + 86400
|
|
626
675
|
}
|
|
627
|
-
}
|
|
628
676
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
677
|
+
if (options.getCallLink && message.event.call) {
|
|
678
|
+
const link = await options.getCallLink(
|
|
679
|
+
message.event.call,
|
|
680
|
+
m.eventMessage.startTime
|
|
681
|
+
)
|
|
682
|
+
m.eventMessage.joinLink = link
|
|
683
|
+
}
|
|
684
|
+
} else if (hasNonNullishProperty(message, "pollResult")) {
|
|
685
|
+
if (!Array.isArray(message.pollResult.values)) {
|
|
686
|
+
throw new Boom("Invalid pollResult values", { statusCode: 400 })
|
|
687
|
+
}
|
|
632
688
|
|
|
633
|
-
|
|
634
|
-
|
|
689
|
+
const pollResultSnapshotMessage = {
|
|
690
|
+
name: message.pollResult.name,
|
|
691
|
+
pollVotes: message.pollResult.values.map(
|
|
692
|
+
([optionName, optionVoteCount]) => ({
|
|
693
|
+
optionName,
|
|
694
|
+
optionVoteCount,
|
|
695
|
+
})
|
|
696
|
+
),
|
|
697
|
+
}
|
|
635
698
|
|
|
636
|
-
m.
|
|
637
|
-
|
|
638
|
-
|
|
699
|
+
m.pollResultSnapshotMessage = pollResultSnapshotMessage
|
|
700
|
+
} else if (hasNonNullishProperty(message, "poll")) {
|
|
701
|
+
if (!Array.isArray(message.poll.values)) {
|
|
702
|
+
throw new Boom("Invalid poll values", { statusCode: 400 })
|
|
639
703
|
}
|
|
640
|
-
}
|
|
641
704
|
|
|
642
|
-
|
|
705
|
+
if (
|
|
706
|
+
message.poll.selectableCount < 0 ||
|
|
707
|
+
message.poll.selectableCount > message.poll.values.length
|
|
708
|
+
) {
|
|
709
|
+
throw new Boom(
|
|
710
|
+
`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`,
|
|
711
|
+
{ statusCode: 400 }
|
|
712
|
+
)
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
const pollCreationMessage = {
|
|
716
|
+
name: message.poll.name,
|
|
717
|
+
selectableOptionsCount: message.poll?.selectableCount || 0,
|
|
718
|
+
options: message.poll.values.map((optionName) => ({ optionName })),
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
if (message.poll?.toAnnouncementGroup) {
|
|
722
|
+
m.pollCreationMessageV2 = pollCreationMessage
|
|
723
|
+
} else {
|
|
724
|
+
if (message.poll.selectableCount > 0) {
|
|
725
|
+
m.pollCreationMessageV3 = pollCreationMessage
|
|
726
|
+
} else {
|
|
727
|
+
m.pollCreationMessage = pollCreationMessage
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
} else if (hasNonNullishProperty(message, "payment")) {
|
|
731
|
+
const requestPaymentMessage = {
|
|
732
|
+
amount: {
|
|
733
|
+
currencyCode: message.payment?.currency || "IDR",
|
|
734
|
+
offset: message.payment?.offset || 0,
|
|
735
|
+
value: message.payment?.amount || 999999999,
|
|
736
|
+
},
|
|
737
|
+
expiryTimestamp: message.payment?.expiry || 0,
|
|
738
|
+
amount1000: message.payment?.amount || 999999999 * 1000,
|
|
739
|
+
currencyCodeIso4217: message.payment?.currency || "IDR",
|
|
740
|
+
requestFrom: message.payment?.from || "0@s.whatsapp.net",
|
|
741
|
+
noteMessage: {
|
|
742
|
+
extendedTextMessage: {
|
|
743
|
+
text: message.payment?.note || "Notes",
|
|
744
|
+
},
|
|
745
|
+
},
|
|
746
|
+
background: {
|
|
747
|
+
placeholderArgb:
|
|
748
|
+
message.payment?.image?.placeholderArgb || 4278190080,
|
|
749
|
+
textArgb: message.payment?.image?.textArgb || 4294967295,
|
|
750
|
+
subtextArgb: message.payment?.image?.subtextArgb || 4294967295,
|
|
751
|
+
type: 1,
|
|
752
|
+
},
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
m.requestPaymentMessage = requestPaymentMessage
|
|
756
|
+
} else if (hasNonNullishProperty(message, "stickerPack")) {
|
|
757
|
+
const {
|
|
758
|
+
stickers,
|
|
759
|
+
cover,
|
|
760
|
+
name,
|
|
761
|
+
publisher,
|
|
762
|
+
packId,
|
|
763
|
+
description,
|
|
764
|
+
} = message.stickerPack
|
|
765
|
+
|
|
766
|
+
const { zip } = require("fflate")
|
|
767
|
+
|
|
768
|
+
const stickerData = {}
|
|
769
|
+
const stickerPromises = stickers.map(async (s, i) => {
|
|
770
|
+
const { stream } = await getStream(s.sticker)
|
|
771
|
+
const buffer = await toBuffer(stream)
|
|
772
|
+
const hash = sha256(buffer).toString("base64url")
|
|
773
|
+
const fileName = `${i.toString().padStart(2, "0")}_${hash}.webp`
|
|
774
|
+
|
|
775
|
+
stickerData[fileName] = [new Uint8Array(buffer), { level: 0 }]
|
|
776
|
+
|
|
777
|
+
return {
|
|
778
|
+
fileName,
|
|
779
|
+
mimetype: "image/webp",
|
|
780
|
+
isAnimated: s.isAnimated || false,
|
|
781
|
+
isLottie: s.isLottie || false,
|
|
782
|
+
emojis: s.emojis || [],
|
|
783
|
+
accessibilityLabel: s.accessibilityLabel || "",
|
|
784
|
+
}
|
|
785
|
+
})
|
|
786
|
+
|
|
787
|
+
const stickerMetadata = await Promise.all(stickerPromises)
|
|
788
|
+
|
|
789
|
+
const zipBuffer = await new Promise((resolve, reject) => {
|
|
790
|
+
zip(stickerData, (err, data) => {
|
|
791
|
+
if (err) {
|
|
792
|
+
reject(err)
|
|
793
|
+
} else {
|
|
794
|
+
resolve(Buffer.from(data))
|
|
795
|
+
}
|
|
796
|
+
})
|
|
797
|
+
})
|
|
798
|
+
|
|
799
|
+
const coverBuffer = await toBuffer((await getStream(cover)).stream)
|
|
800
|
+
|
|
801
|
+
const [stickerPackUpload, coverUpload] = await Promise.all([
|
|
802
|
+
encryptedStream(zipBuffer, "sticker-pack", {
|
|
803
|
+
logger: options.logger,
|
|
804
|
+
opts: options.options,
|
|
805
|
+
}),
|
|
806
|
+
prepareWAMessageMedia(
|
|
807
|
+
{ image: coverBuffer },
|
|
808
|
+
{ ...options, mediaTypeOverride: "image" }
|
|
809
|
+
),
|
|
810
|
+
])
|
|
811
|
+
|
|
812
|
+
const stickerPackUploadResult = await options.upload(
|
|
813
|
+
stickerPackUpload.encFilePath,
|
|
814
|
+
{
|
|
815
|
+
fileEncSha256B64: stickerPackUpload.fileEncSha256.toString(
|
|
816
|
+
"base64"
|
|
817
|
+
),
|
|
818
|
+
mediaType: "sticker-pack",
|
|
819
|
+
timeoutMs: options.mediaUploadTimeoutMs,
|
|
820
|
+
}
|
|
821
|
+
)
|
|
822
|
+
|
|
823
|
+
const coverImage = coverUpload.imageMessage
|
|
824
|
+
const imageDataHash = sha256(coverBuffer).toString("base64")
|
|
825
|
+
const stickerPackId = packId || generateMessageID()
|
|
826
|
+
|
|
827
|
+
m.stickerPackMessage = {
|
|
828
|
+
name,
|
|
829
|
+
publisher,
|
|
830
|
+
stickerPackId,
|
|
831
|
+
packDescription: description,
|
|
832
|
+
stickerPackOrigin:
|
|
833
|
+
proto.Message.StickerPackMessage.StickerPackOrigin.THIRD_PARTY,
|
|
834
|
+
stickerPackSize: stickerPackUpload.fileLength,
|
|
835
|
+
stickers: stickerMetadata,
|
|
836
|
+
fileSha256: stickerPackUpload.fileSha256,
|
|
837
|
+
fileEncSha256: stickerPackUpload.fileEncSha256,
|
|
838
|
+
mediaKey: stickerPackUpload.mediaKey,
|
|
839
|
+
directPath: stickerPackUploadResult.directPath,
|
|
840
|
+
fileLength: stickerPackUpload.fileLength,
|
|
841
|
+
mediaKeyTimestamp: unixTimestampSeconds(),
|
|
842
|
+
trayIconFileName: `${stickerPackId}.png`,
|
|
843
|
+
imageDataHash,
|
|
844
|
+
thumbnailDirectPath: coverImage.directPath,
|
|
845
|
+
thumbnailFileSha256: coverImage.fileSha256,
|
|
846
|
+
thumbnailFileEncSha256: coverImage.fileEncSha256,
|
|
847
|
+
thumbnailHeight: coverImage.height,
|
|
848
|
+
thumbnailWidth: coverImage.width,
|
|
849
|
+
}
|
|
850
|
+
} else {
|
|
851
|
+
m = await prepareWAMessageMedia(message, options)
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
if (hasNonNullishProperty(message, "buttonReply")) {
|
|
643
855
|
switch (message.type) {
|
|
644
|
-
|
|
856
|
+
case "list":
|
|
645
857
|
m.listResponseMessage = {
|
|
646
858
|
title: message.buttonReply.title,
|
|
647
859
|
description: message.buttonReply.description,
|
|
648
860
|
singleSelectReply: {
|
|
649
|
-
|
|
650
|
-
},
|
|
651
|
-
lisType:
|
|
861
|
+
selectedRowId: message.buttonReply.rowId,
|
|
862
|
+
},
|
|
863
|
+
lisType:
|
|
864
|
+
proto.Message.ListResponseMessage.ListType
|
|
865
|
+
.SINGLE_SELECT,
|
|
652
866
|
}
|
|
653
867
|
break
|
|
654
|
-
case
|
|
868
|
+
case "template":
|
|
655
869
|
m.templateButtonReplyMessage = {
|
|
656
870
|
selectedDisplayText: message.buttonReply.displayText,
|
|
657
871
|
selectedId: message.buttonReply.id,
|
|
658
|
-
selectedIndex: message.buttonReply.index
|
|
872
|
+
selectedIndex: message.buttonReply.index,
|
|
659
873
|
}
|
|
660
874
|
break
|
|
661
|
-
case
|
|
875
|
+
case "plain":
|
|
662
876
|
m.buttonsResponseMessage = {
|
|
663
877
|
selectedButtonId: message.buttonReply.id,
|
|
664
878
|
selectedDisplayText: message.buttonReply.displayText,
|
|
665
|
-
type:
|
|
879
|
+
type:
|
|
880
|
+
proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT,
|
|
666
881
|
}
|
|
667
882
|
break
|
|
668
|
-
case
|
|
883
|
+
case "interactive":
|
|
669
884
|
m.interactiveResponseMessage = {
|
|
670
885
|
body: {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
886
|
+
text: message.buttonReply.displayText,
|
|
887
|
+
format:
|
|
888
|
+
proto.Message.InteractiveResponseMessage.Body.Format
|
|
889
|
+
.EXTENSIONS_1,
|
|
890
|
+
},
|
|
674
891
|
nativeFlowResponseMessage: {
|
|
675
|
-
|
|
676
|
-
paramsJson: message.buttonReply.nativeFlows.paramsJson,
|
|
677
|
-
version: message.buttonReply.nativeFlows.version
|
|
678
|
-
}
|
|
892
|
+
name: message.buttonReply.nativeFlows.name,
|
|
893
|
+
paramsJson: message.buttonReply.nativeFlows.paramsJson,
|
|
894
|
+
version: message.buttonReply.nativeFlows.version,
|
|
895
|
+
},
|
|
679
896
|
}
|
|
680
|
-
break
|
|
897
|
+
break
|
|
681
898
|
}
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
899
|
+
} else if (hasNonNullishProperty(message, "sections")) {
|
|
900
|
+
m.listMessage = {
|
|
901
|
+
title: message.title,
|
|
902
|
+
buttonText: message.buttonText,
|
|
903
|
+
footerText: message.footer,
|
|
904
|
+
description: message.text,
|
|
905
|
+
sections: message.sections,
|
|
906
|
+
listType: proto.Message.ListMessage.ListType.SINGLE_SELECT,
|
|
907
|
+
}
|
|
908
|
+
} else if (hasNonNullishProperty(message, "productList")) {
|
|
909
|
+
const thumbnail = message.thumbnail
|
|
910
|
+
? await generateThumbnail(message.thumbnail, "image")
|
|
911
|
+
: null
|
|
912
|
+
|
|
913
|
+
m.listMessage = {
|
|
914
|
+
title: message.title,
|
|
915
|
+
buttonText: message.buttonText,
|
|
916
|
+
footerText: message.footer,
|
|
917
|
+
description: message.text,
|
|
918
|
+
productListInfo: {
|
|
919
|
+
productSections: message.productList,
|
|
920
|
+
headerImage: {
|
|
921
|
+
productId: message.productList[0].products[0].productId,
|
|
922
|
+
jpegThumbnail: thumbnail?.thumbnail || null,
|
|
923
|
+
},
|
|
924
|
+
businessOwnerJid: message.businessOwnerJid,
|
|
925
|
+
},
|
|
926
|
+
listType: proto.Message.ListMessage.ListType.PRODUCT_LIST,
|
|
706
927
|
}
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
m.eventMessage.startTime = unixTimestampSeconds() + 86400
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
if (options.getCallLink && message.event.call) {
|
|
717
|
-
const link = await options.getCallLink(message.event.call, m.eventMessage.startTime)
|
|
718
|
-
m.eventMessage.joinLink = link
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
m.eventMessage.contextInfo = {
|
|
723
|
-
...(message.contextInfo || {}),
|
|
724
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
928
|
+
} else if (hasNonNullishProperty(message, "buttons")) {
|
|
929
|
+
const buttonsMessage = {
|
|
930
|
+
buttons: message.buttons.map((b) => ({
|
|
931
|
+
...b,
|
|
932
|
+
type: proto.Message.ButtonsMessage.Button.Type.RESPONSE,
|
|
933
|
+
})),
|
|
725
934
|
}
|
|
726
|
-
}
|
|
727
935
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
productImage: imageMessage,
|
|
936
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
937
|
+
buttonsMessage.contentText = message.text
|
|
938
|
+
buttonsMessage.headerType =
|
|
939
|
+
proto.Message.ButtonsMessage.HeaderType.EMPTY
|
|
940
|
+
} else {
|
|
941
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
942
|
+
buttonsMessage.contentText = message.caption
|
|
736
943
|
}
|
|
737
|
-
})
|
|
738
|
-
|
|
739
|
-
m.productMessage.contextInfo = {
|
|
740
|
-
...(message.contextInfo || {}),
|
|
741
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
944
|
|
|
745
|
-
|
|
746
|
-
if (!Array.isArray(message.pollResult.values)) {
|
|
747
|
-
throw new Boom('Invalid pollResult values', { statusCode: 400 })
|
|
748
|
-
}
|
|
945
|
+
const type = Object.keys(m)[0].replace("Message", "").toUpperCase()
|
|
749
946
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
pollVotes: message.pollResult.values.map(([optionName, optionVoteCount]) => ({
|
|
753
|
-
optionName,
|
|
754
|
-
optionVoteCount
|
|
755
|
-
}))
|
|
756
|
-
}
|
|
947
|
+
buttonsMessage.headerType =
|
|
948
|
+
proto.Message.ButtonsMessage.HeaderType[type]
|
|
757
949
|
|
|
758
|
-
|
|
759
|
-
...(message.contextInfo || {}),
|
|
760
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
950
|
+
Object.assign(buttonsMessage, m)
|
|
761
951
|
}
|
|
762
952
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
if (!Array.isArray(message.poll.values)) {
|
|
768
|
-
throw new Boom('Invalid poll values', { statusCode: 400 })
|
|
953
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
954
|
+
buttonsMessage.text = message.title
|
|
955
|
+
buttonsMessage.headerType =
|
|
956
|
+
proto.Message.ButtonsMessage.HeaderType.TEXT
|
|
769
957
|
}
|
|
770
958
|
|
|
771
|
-
if (message
|
|
772
|
-
|
|
773
|
-
throw new Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, { statusCode: 400 })
|
|
959
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
960
|
+
buttonsMessage.footerText = message.footer
|
|
774
961
|
}
|
|
775
962
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
pollCreationMessage.contextInfo = {
|
|
783
|
-
...(message.contextInfo || {}),
|
|
784
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
785
|
-
}
|
|
963
|
+
m = { buttonsMessage }
|
|
964
|
+
} else if (hasNonNullishProperty(message, "templateButtons")) {
|
|
965
|
+
const hydratedTemplate = {
|
|
966
|
+
hydratedButtons: message.templateButtons,
|
|
967
|
+
}
|
|
786
968
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
m.pollCreationMessage = pollCreationMessage
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
else if ('payment' in message) {
|
|
799
|
-
const requestPaymentMessage = {
|
|
800
|
-
amount: {
|
|
801
|
-
currencyCode: message.payment?.currency || 'IDR',
|
|
802
|
-
offset: message.payment?.offset || 0,
|
|
803
|
-
value: message.payment?.amount || 999999999
|
|
804
|
-
},
|
|
805
|
-
expiryTimestamp: message.payment?.expiry || 0,
|
|
806
|
-
amount1000: message.payment?.amount || 999999999 * 1000,
|
|
807
|
-
currencyCodeIso4217: message.payment?.currency || 'IDR',
|
|
808
|
-
requestFrom: message.payment?.from || '0@s.whatsapp.net',
|
|
809
|
-
noteMessage: {
|
|
810
|
-
extendedTextMessage: {
|
|
811
|
-
text: message.payment?.note || 'Notes'
|
|
812
|
-
}
|
|
813
|
-
},
|
|
814
|
-
background: {
|
|
815
|
-
placeholderArgb: message.payment?.image?.placeholderArgb || 4278190080,
|
|
816
|
-
textArgb: message.payment?.image?.textArgb || 4294967295,
|
|
817
|
-
subtextArgb: message.payment?.image?.subtextArgb || 4294967295,
|
|
818
|
-
type: 1
|
|
819
|
-
}
|
|
820
|
-
}
|
|
969
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
970
|
+
hydratedTemplate.hydratedContentText = message.text
|
|
971
|
+
} else {
|
|
972
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
973
|
+
hydratedTemplate.hydratedContentText = message.caption
|
|
974
|
+
}
|
|
821
975
|
|
|
822
|
-
|
|
823
|
-
...(message.contextInfo || {}),
|
|
824
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
976
|
+
Object.assign(msg, m)
|
|
825
977
|
}
|
|
826
978
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
else if ('stickerPack' in message) {
|
|
831
|
-
const { stickers, cover, name, publisher, packId, description } = message.stickerPack
|
|
832
|
-
|
|
833
|
-
const { zip } = require('fflate')
|
|
834
|
-
|
|
835
|
-
const stickerData = {}
|
|
836
|
-
const stickerPromises = stickers.map(async (s, i) => {
|
|
837
|
-
const { stream } = await getStream(s.sticker)
|
|
838
|
-
const buffer = await toBuffer(stream)
|
|
839
|
-
const hash = sha256(buffer).toString('base64url')
|
|
840
|
-
const fileName = `${i.toString().padStart(2, '0')}_${hash}.webp`
|
|
841
|
-
stickerData[fileName] = [new Uint8Array(buffer), { level: 0 }]
|
|
842
|
-
|
|
843
|
-
return {
|
|
844
|
-
fileName,
|
|
845
|
-
mimetype: 'image/webp',
|
|
846
|
-
isAnimated: s.isAnimated || false,
|
|
847
|
-
isLottie: s.isLottie || false,
|
|
848
|
-
emojis: s.emojis || [],
|
|
849
|
-
accessibilityLabel: s.accessibilityLabel || ''
|
|
850
|
-
}
|
|
851
|
-
})
|
|
852
|
-
|
|
853
|
-
const stickerMetadata = await Promise.all(stickerPromises)
|
|
854
|
-
|
|
855
|
-
const zipBuffer = await new Promise((resolve, reject) => {
|
|
856
|
-
zip(stickerData, (err, data) => {
|
|
857
|
-
if (err) {
|
|
858
|
-
reject(err)
|
|
859
|
-
} else {
|
|
860
|
-
resolve(Buffer.from(data))
|
|
861
|
-
}
|
|
862
|
-
})
|
|
863
|
-
})
|
|
864
|
-
|
|
865
|
-
const coverBuffer = await toBuffer((await getStream(cover)).stream)
|
|
866
|
-
|
|
867
|
-
const [stickerPackUpload, coverUpload] = await Promise.all([
|
|
868
|
-
encryptedStream(zipBuffer, 'sticker-pack', { logger: options.logger, opts: options.options }),
|
|
869
|
-
prepareWAMessageMedia({ image: coverBuffer }, { ...options, mediaTypeOverride: 'image' })
|
|
870
|
-
])
|
|
871
|
-
|
|
872
|
-
const stickerPackUploadResult = await options.upload(stickerPackUpload.encFilePath, {
|
|
873
|
-
fileEncSha256B64: stickerPackUpload.fileEncSha256.toString('base64'),
|
|
874
|
-
mediaType: 'sticker-pack',
|
|
875
|
-
timeoutMs: options.mediaUploadTimeoutMs
|
|
876
|
-
})
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
const coverImage = coverUpload.imageMessage
|
|
880
|
-
const imageDataHash = sha256(coverBuffer).toString('base64')
|
|
881
|
-
const stickerPackId = packId || generateMessageID()
|
|
882
|
-
|
|
883
|
-
m.stickerPackMessage = {
|
|
884
|
-
name,
|
|
885
|
-
publisher,
|
|
886
|
-
stickerPackId,
|
|
887
|
-
packDescription: description,
|
|
888
|
-
stickerPackOrigin: proto.Message.StickerPackMessage.StickerPackOrigin.THIRD_PARTY,
|
|
889
|
-
stickerPackSize: stickerPackUpload.fileLength,
|
|
890
|
-
stickers: stickerMetadata,
|
|
891
|
-
fileSha256: stickerPackUpload.fileSha256,
|
|
892
|
-
fileEncSha256: stickerPackUpload.fileEncSha256,
|
|
893
|
-
mediaKey: stickerPackUpload.mediaKey,
|
|
894
|
-
directPath: stickerPackUploadResult.directPath,
|
|
895
|
-
fileLength: stickerPackUpload.fileLength,
|
|
896
|
-
mediaKeyTimestamp: unixTimestampSeconds(),
|
|
897
|
-
trayIconFileName: `${stickerPackId}.png`,
|
|
898
|
-
imageDataHash,
|
|
899
|
-
thumbnailDirectPath: coverImage.directPath,
|
|
900
|
-
thumbnailFileSha256: coverImage.fileSha256,
|
|
901
|
-
thumbnailFileEncSha256: coverImage.fileEncSha256,
|
|
902
|
-
thumbnailHeight: coverImage.height,
|
|
903
|
-
thumbnailWidth: coverImage.width
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
m.stickerPackMessage.contextInfo = {
|
|
907
|
-
...(message.contextInfo || {}),
|
|
908
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
else if ('sharePhoneNumber' in message) {
|
|
913
|
-
m.protocolMessage = {
|
|
914
|
-
type: WAProto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
|
|
979
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
980
|
+
hydratedTemplate.hydratedFooterText = message.footer
|
|
915
981
|
}
|
|
916
|
-
}
|
|
917
982
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
983
|
+
m = { templateMessage: { hydratedTemplate } }
|
|
984
|
+
} else if (hasNonNullishProperty(message, "interactiveButtons")) {
|
|
985
|
+
const interactiveMessage = {
|
|
986
|
+
nativeFlowMessage: {
|
|
987
|
+
buttons: message.interactiveButtons,
|
|
988
|
+
},
|
|
989
|
+
}
|
|
925
990
|
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
991
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
992
|
+
interactiveMessage.body = {
|
|
993
|
+
text: message.text,
|
|
994
|
+
}
|
|
929
995
|
}
|
|
930
996
|
|
|
931
|
-
|
|
932
|
-
|
|
997
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
998
|
+
interactiveMessage.header = {
|
|
999
|
+
title: message.title,
|
|
1000
|
+
subtitle: null,
|
|
1001
|
+
hasMediaAttachment: false,
|
|
1002
|
+
}
|
|
933
1003
|
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
}
|
|
1004
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1005
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1006
|
+
}
|
|
1007
|
+
} else {
|
|
1008
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
1009
|
+
interactiveMessage.body = {
|
|
1010
|
+
text: message.caption,
|
|
1011
|
+
}
|
|
943
1012
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1013
|
+
interactiveMessage.header = {
|
|
1014
|
+
title: null,
|
|
1015
|
+
subtitle: null,
|
|
1016
|
+
hasMediaAttachment: false,
|
|
1017
|
+
...Object.assign(interactiveMessage, m),
|
|
1018
|
+
}
|
|
948
1019
|
|
|
949
|
-
|
|
950
|
-
|
|
1020
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1021
|
+
interactiveMessage.header.title = message.title
|
|
1022
|
+
}
|
|
951
1023
|
|
|
952
|
-
|
|
953
|
-
|
|
1024
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1025
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1026
|
+
}
|
|
954
1027
|
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
productSections: message.productList,
|
|
962
|
-
headerImage: {
|
|
963
|
-
productId: message.productList[0].products[0].productId,
|
|
964
|
-
jpegThumbnail: thumbnail?.thumbnail || null
|
|
965
|
-
},
|
|
966
|
-
businessOwnerJid: message.businessOwnerJid
|
|
967
|
-
},
|
|
968
|
-
listType: proto.Message.ListMessage.ListType.PRODUCT_LIST
|
|
1028
|
+
if (hasNonNullishProperty(message, "hasMediaAttachment")) {
|
|
1029
|
+
interactiveMessage.header.hasMediaAttachment = Boolean(
|
|
1030
|
+
message.hasMediaAttachment
|
|
1031
|
+
)
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
969
1034
|
}
|
|
970
1035
|
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1036
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
1037
|
+
interactiveMessage.footer = {
|
|
1038
|
+
text: message.footer,
|
|
1039
|
+
}
|
|
974
1040
|
}
|
|
975
1041
|
|
|
976
|
-
m = {
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1042
|
+
m = { interactiveMessage }
|
|
1043
|
+
} else if (hasNonNullishProperty(message, "shop")) {
|
|
1044
|
+
const interactiveMessage = {
|
|
1045
|
+
shopStorefrontMessage: {
|
|
1046
|
+
surface: message.shop.surface,
|
|
1047
|
+
id: message.shop.id,
|
|
1048
|
+
},
|
|
982
1049
|
}
|
|
983
1050
|
|
|
984
|
-
if (
|
|
985
|
-
|
|
986
|
-
|
|
1051
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
1052
|
+
interactiveMessage.body = {
|
|
1053
|
+
text: message.text,
|
|
1054
|
+
}
|
|
987
1055
|
}
|
|
988
1056
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1057
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1058
|
+
interactiveMessage.header = {
|
|
1059
|
+
title: message.title,
|
|
1060
|
+
subtitle: null,
|
|
1061
|
+
hasMediaAttachment: false,
|
|
992
1062
|
}
|
|
993
1063
|
|
|
994
|
-
|
|
1064
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1065
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1066
|
+
}
|
|
1067
|
+
} else {
|
|
1068
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
1069
|
+
interactiveMessage.body = {
|
|
1070
|
+
text: message.caption,
|
|
1071
|
+
}
|
|
995
1072
|
|
|
996
|
-
|
|
1073
|
+
interactiveMessage.header = {
|
|
1074
|
+
title: null,
|
|
1075
|
+
subtitle: null,
|
|
1076
|
+
hasMediaAttachment: false,
|
|
1077
|
+
...Object.assign(interactiveMessage, m),
|
|
1078
|
+
}
|
|
997
1079
|
|
|
998
|
-
|
|
999
|
-
|
|
1080
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1081
|
+
interactiveMessage.header.title = message.title
|
|
1082
|
+
}
|
|
1000
1083
|
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1084
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1085
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1086
|
+
}
|
|
1004
1087
|
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1088
|
+
if (hasNonNullishProperty(message, "hasMediaAttachment")) {
|
|
1089
|
+
interactiveMessage.header.hasMediaAttachment = Boolean(
|
|
1090
|
+
message.hasMediaAttachment
|
|
1091
|
+
)
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1008
1094
|
}
|
|
1009
1095
|
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1096
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
1097
|
+
interactiveMessage.footer = {
|
|
1098
|
+
text: message.footer,
|
|
1099
|
+
}
|
|
1013
1100
|
}
|
|
1014
1101
|
|
|
1015
|
-
m = {
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1102
|
+
m = { interactiveMessage }
|
|
1103
|
+
} else if (hasNonNullishProperty(message, "collection")) {
|
|
1104
|
+
const interactiveMessage = {
|
|
1105
|
+
collectionMessage: {
|
|
1106
|
+
bizJid: message.collection.bizJid,
|
|
1107
|
+
id: message.collection.id,
|
|
1108
|
+
messageVersion: message?.collection?.version,
|
|
1109
|
+
},
|
|
1021
1110
|
}
|
|
1022
1111
|
|
|
1023
|
-
if (
|
|
1024
|
-
|
|
1112
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
1113
|
+
interactiveMessage.body = {
|
|
1114
|
+
text: message.text,
|
|
1115
|
+
}
|
|
1025
1116
|
}
|
|
1026
1117
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1118
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1119
|
+
interactiveMessage.header = {
|
|
1120
|
+
title: message.title,
|
|
1121
|
+
subtitle: null,
|
|
1122
|
+
hasMediaAttachment: false,
|
|
1030
1123
|
}
|
|
1031
1124
|
|
|
1032
|
-
|
|
1033
|
-
|
|
1125
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1126
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1127
|
+
}
|
|
1128
|
+
} else {
|
|
1129
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
1130
|
+
interactiveMessage.body = {
|
|
1131
|
+
text: message.caption,
|
|
1132
|
+
}
|
|
1034
1133
|
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1134
|
+
interactiveMessage.header = {
|
|
1135
|
+
title: null,
|
|
1136
|
+
subtitle: null,
|
|
1137
|
+
hasMediaAttachment: false,
|
|
1138
|
+
...Object.assign(interactiveMessage, m),
|
|
1139
|
+
}
|
|
1038
1140
|
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
}
|
|
1141
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1142
|
+
interactiveMessage.header.title = message.title
|
|
1143
|
+
}
|
|
1043
1144
|
|
|
1044
|
-
|
|
1045
|
-
|
|
1145
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1146
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1147
|
+
}
|
|
1046
1148
|
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
if ('text' in message) {
|
|
1055
|
-
interactiveMessage.body = {
|
|
1056
|
-
text: message.text
|
|
1057
|
-
},
|
|
1058
|
-
interactiveMessage.header = {
|
|
1059
|
-
title: message.title,
|
|
1060
|
-
subtitle: message.subtitle,
|
|
1061
|
-
hasMediaAttachment: false
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
else {
|
|
1066
|
-
if ('caption' in message) {
|
|
1067
|
-
interactiveMessage.body = {
|
|
1068
|
-
text: message.caption
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
interactiveMessage.header = {
|
|
1072
|
-
title: message.title,
|
|
1073
|
-
subtitle: message.subtitle,
|
|
1074
|
-
hasMediaAttachment: message.hasMediaAttachment ? message.hasMediaAttachment : false,
|
|
1075
|
-
...Object.assign(interactiveMessage, m)
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
if ('footer' in message && !!message.footer) {
|
|
1081
|
-
interactiveMessage.footer = {
|
|
1082
|
-
text: message.footer
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
interactiveMessage.contextInfo = {
|
|
1087
|
-
...(message.contextInfo || {}),
|
|
1088
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
m = { interactiveMessage }
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
else if ('shop' in message && !!message.shop) {
|
|
1095
|
-
const interactiveMessage = {
|
|
1096
|
-
shopStorefrontMessage: {
|
|
1097
|
-
surface: message.shop.surface,
|
|
1098
|
-
id: message.shop.id
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
if ('text' in message) {
|
|
1103
|
-
interactiveMessage.body = {
|
|
1104
|
-
text: message.text
|
|
1105
|
-
},
|
|
1106
|
-
interactiveMessage.header = {
|
|
1107
|
-
title: message.title,
|
|
1108
|
-
subtitle: message.subtitle,
|
|
1109
|
-
hasMediaAttachment: false
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
else {
|
|
1114
|
-
if ('caption' in message) {
|
|
1115
|
-
interactiveMessage.body = {
|
|
1116
|
-
text: message.caption
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
interactiveMessage.header = {
|
|
1120
|
-
title: message.title,
|
|
1121
|
-
subtitle: message.subtitle,
|
|
1122
|
-
hasMediaAttachment: message.hasMediaAttachment ? message.hasMediaAttachment : false,
|
|
1123
|
-
...Object.assign(interactiveMessage, m)
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
if ('footer' in message && !!message.footer) {
|
|
1129
|
-
interactiveMessage.footer = {
|
|
1130
|
-
text: message.footer
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
|
|
1134
|
-
interactiveMessage.contextInfo = {
|
|
1135
|
-
...(message.contextInfo || {}),
|
|
1136
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
m = { interactiveMessage }
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
else if ('collection' in message && !!message.collection) {
|
|
1143
|
-
const interactiveMessage = {
|
|
1144
|
-
collectionMessage: {
|
|
1145
|
-
bizJid: message.collection.bizJid,
|
|
1146
|
-
id: message.collection.id,
|
|
1147
|
-
messageVersion: message?.collection?.version
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
|
|
1151
|
-
if ('text' in message) {
|
|
1152
|
-
interactiveMessage.body = {
|
|
1153
|
-
text: message.text
|
|
1154
|
-
},
|
|
1155
|
-
interactiveMessage.header = {
|
|
1156
|
-
title: message.title,
|
|
1157
|
-
subtitle: message.subtitle,
|
|
1158
|
-
hasMediaAttachment: false
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
else {
|
|
1163
|
-
if ('caption' in message) {
|
|
1164
|
-
interactiveMessage.body = {
|
|
1165
|
-
text: message.caption
|
|
1166
|
-
}
|
|
1167
|
-
interactiveMessage.header = {
|
|
1168
|
-
title: message.title,
|
|
1169
|
-
subtitle: message.subtitle,
|
|
1170
|
-
hasMediaAttachment: message.hasMediaAttachment ? message.hasMediaAttachment : false,
|
|
1171
|
-
...Object.assign(interactiveMessage, m)
|
|
1149
|
+
if (hasNonNullishProperty(message, "hasMediaAttachment")) {
|
|
1150
|
+
interactiveMessage.header.hasMediaAttachment = Boolean(
|
|
1151
|
+
message.hasMediaAttachment
|
|
1152
|
+
)
|
|
1153
|
+
}
|
|
1172
1154
|
}
|
|
1173
|
-
|
|
1174
|
-
}
|
|
1155
|
+
}
|
|
1175
1156
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1157
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
1158
|
+
interactiveMessage.footer = {
|
|
1159
|
+
text: message.footer,
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1181
1162
|
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1163
|
+
m = { interactiveMessage }
|
|
1164
|
+
} else if (hasNonNullishProperty(message, "cards")) {
|
|
1165
|
+
const slides = await Promise.all(
|
|
1166
|
+
message.cards.map(async (slide) => {
|
|
1167
|
+
const {
|
|
1168
|
+
image,
|
|
1169
|
+
video,
|
|
1170
|
+
product,
|
|
1171
|
+
title,
|
|
1172
|
+
body,
|
|
1173
|
+
footer,
|
|
1174
|
+
buttons,
|
|
1175
|
+
} = slide
|
|
1186
1176
|
|
|
1187
|
-
|
|
1188
|
-
}
|
|
1177
|
+
let header
|
|
1189
1178
|
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1179
|
+
if (product) {
|
|
1180
|
+
const { imageMessage } = await prepareWAMessageMedia(
|
|
1181
|
+
{ image: product.productImage, ...options },
|
|
1182
|
+
options
|
|
1183
|
+
)
|
|
1184
|
+
header = {
|
|
1185
|
+
productMessage: {
|
|
1186
|
+
product: {
|
|
1187
|
+
...product,
|
|
1188
|
+
productImage: imageMessage,
|
|
1189
|
+
},
|
|
1190
|
+
...slide,
|
|
1202
1191
|
},
|
|
1203
|
-
...slide
|
|
1204
1192
|
}
|
|
1193
|
+
} else if (image) {
|
|
1194
|
+
header = await prepareWAMessageMedia(
|
|
1195
|
+
{ image: image, ...options },
|
|
1196
|
+
options
|
|
1197
|
+
)
|
|
1198
|
+
} else if (video) {
|
|
1199
|
+
header = await prepareWAMessageMedia(
|
|
1200
|
+
{ video: video, ...options },
|
|
1201
|
+
options
|
|
1202
|
+
)
|
|
1205
1203
|
}
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
else if (image) {
|
|
1209
|
-
header = await prepareWAMessageMedia({ image: image, ...options }, options)
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
else if (video) {
|
|
1213
|
-
header = await prepareWAMessageMedia({ video: video, ...options }, options)
|
|
1214
|
-
}
|
|
1215
1204
|
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1205
|
+
const msg = {
|
|
1206
|
+
header: {
|
|
1207
|
+
title,
|
|
1208
|
+
hasMediaAttachment: true,
|
|
1209
|
+
...header,
|
|
1210
|
+
},
|
|
1211
|
+
body: {
|
|
1212
|
+
text: body,
|
|
1213
|
+
},
|
|
1214
|
+
footer: {
|
|
1215
|
+
text: footer,
|
|
1216
|
+
},
|
|
1217
|
+
nativeFlowMessage: {
|
|
1218
|
+
buttons,
|
|
1219
|
+
},
|
|
1230
1220
|
}
|
|
1231
|
-
}
|
|
1232
1221
|
|
|
1233
|
-
|
|
1234
|
-
|
|
1222
|
+
return msg
|
|
1223
|
+
})
|
|
1224
|
+
)
|
|
1235
1225
|
|
|
1236
1226
|
const interactiveMessage = {
|
|
1237
1227
|
carouselMessage: {
|
|
1238
|
-
cards: slides
|
|
1228
|
+
cards: slides,
|
|
1229
|
+
},
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
1233
|
+
interactiveMessage.body = {
|
|
1234
|
+
text: message.text,
|
|
1239
1235
|
}
|
|
1240
1236
|
}
|
|
1241
1237
|
|
|
1242
|
-
if (
|
|
1243
|
-
interactiveMessage.body = {
|
|
1244
|
-
text: message.text
|
|
1245
|
-
},
|
|
1238
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1246
1239
|
interactiveMessage.header = {
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1240
|
+
title: message.title,
|
|
1241
|
+
subtitle: null,
|
|
1242
|
+
hasMediaAttachment: false,
|
|
1250
1243
|
}
|
|
1251
|
-
}
|
|
1252
1244
|
|
|
1253
|
-
|
|
1254
|
-
interactiveMessage.
|
|
1255
|
-
|
|
1245
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1246
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1247
|
+
}
|
|
1248
|
+
} else {
|
|
1249
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
1250
|
+
interactiveMessage.body = {
|
|
1251
|
+
text: message.caption,
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
interactiveMessage.header = {
|
|
1255
|
+
title: null,
|
|
1256
|
+
subtitle: null,
|
|
1257
|
+
hasMediaAttachment: false,
|
|
1258
|
+
...Object.assign(interactiveMessage, m),
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1262
|
+
interactiveMessage.header.title = message.title
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1266
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
if (hasNonNullishProperty(message, "hasMediaAttachment")) {
|
|
1270
|
+
interactiveMessage.header.hasMediaAttachment = Boolean(
|
|
1271
|
+
message.hasMediaAttachment
|
|
1272
|
+
)
|
|
1273
|
+
}
|
|
1256
1274
|
}
|
|
1257
1275
|
}
|
|
1258
1276
|
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1277
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
1278
|
+
interactiveMessage.footer = {
|
|
1279
|
+
text: message.footer,
|
|
1280
|
+
}
|
|
1262
1281
|
}
|
|
1263
1282
|
|
|
1264
1283
|
m = { interactiveMessage }
|
|
1265
1284
|
}
|
|
1266
1285
|
|
|
1267
|
-
if (
|
|
1268
|
-
|
|
1269
|
-
}
|
|
1286
|
+
if (hasOptionalProperty(message, "ephemeral")) {
|
|
1287
|
+
m = { ephemeralMessage: { message: m } }
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
if (hasOptionalProperty(message, "mentions") && message.mentions?.length) {
|
|
1291
|
+
const messageType = Object.keys(m)[0]
|
|
1292
|
+
const key = m[messageType]
|
|
1270
1293
|
|
|
1271
|
-
|
|
1272
|
-
|
|
1294
|
+
if ("contextInfo" in key && !!key.contextInfo) {
|
|
1295
|
+
key.contextInfo.mentionedJid = message.mentions
|
|
1296
|
+
} else if (key) {
|
|
1297
|
+
key.contextInfo = {
|
|
1298
|
+
mentionedJid: message.mentions,
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1273
1301
|
}
|
|
1274
1302
|
|
|
1275
|
-
if (
|
|
1276
|
-
|
|
1303
|
+
if (hasOptionalProperty(message, "contextInfo") && !!message.contextInfo) {
|
|
1304
|
+
const messageType = Object.keys(m)[0]
|
|
1305
|
+
const key = m[messageType]
|
|
1306
|
+
|
|
1307
|
+
if ("contextInfo" in key && !!key.contextInfo) {
|
|
1308
|
+
key.contextInfo = { ...key.contextInfo, ...message.contextInfo }
|
|
1309
|
+
} else if (key) {
|
|
1310
|
+
key.contextInfo = message.contextInfo
|
|
1311
|
+
}
|
|
1277
1312
|
}
|
|
1278
1313
|
|
|
1279
|
-
if (
|
|
1314
|
+
if (hasOptionalProperty(message, "edit")) {
|
|
1280
1315
|
m = {
|
|
1281
1316
|
protocolMessage: {
|
|
1282
1317
|
key: message.edit,
|
|
1283
1318
|
editedMessage: m,
|
|
1284
1319
|
timestampMs: Date.now(),
|
|
1285
|
-
type: WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT
|
|
1286
|
-
}
|
|
1320
|
+
type: WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT,
|
|
1321
|
+
},
|
|
1287
1322
|
}
|
|
1288
1323
|
}
|
|
1289
1324
|
|
|
@@ -1401,7 +1436,7 @@ const generateWAMessage = async (jid, content, options) => {
|
|
|
1401
1436
|
const getContentType = (content) => {
|
|
1402
1437
|
if (content) {
|
|
1403
1438
|
const keys = Object.keys(content)
|
|
1404
|
-
const key = keys.find(k => (k === 'conversation' || k.endsWith('Message') || k.endsWith('V2') || k.endsWith('V3') || k.endsWith('V4')
|
|
1439
|
+
const key = keys.find(k => (k === 'conversation' || k.endsWith('Message') || k.endsWith('V2') || k.endsWith('V3') || k.endsWith('V4')) && k !== 'senderKeyDistributionMessage' && k !== 'messageContextInfo')
|
|
1405
1440
|
|
|
1406
1441
|
return key
|
|
1407
1442
|
}
|
|
@@ -1448,7 +1483,6 @@ const normalizeMessageContent = (content) => {
|
|
|
1448
1483
|
|| (message?.statusMentionMessage)
|
|
1449
1484
|
|| (message?.groupStatusMessageV2)
|
|
1450
1485
|
|| (message?.pollCreationMessageV4)
|
|
1451
|
-
|| (message?.pollCreationMessageV5)
|
|
1452
1486
|
|| (message?.associatedChildMessage)
|
|
1453
1487
|
|| (message?.groupMentionedMessage)
|
|
1454
1488
|
|| (message?.groupStatusMentionMessage)
|
|
@@ -1575,8 +1609,8 @@ const updateMessageWithPollUpdate = (msg, update) => {
|
|
|
1575
1609
|
const updateMessageWithEventResponse = (msg, update) => {
|
|
1576
1610
|
const authorID = getKeyAuthor(update.eventResponseMessageKey)
|
|
1577
1611
|
const responses = (msg.eventResponses || [])
|
|
1578
|
-
|
|
1579
|
-
|
|
1612
|
+
.filter(r => getKeyAuthor(r.eventResponseMessageKey) !== authorID)
|
|
1613
|
+
|
|
1580
1614
|
responses.push(update)
|
|
1581
1615
|
msg.eventResponses = responses
|
|
1582
1616
|
}
|
|
@@ -1640,18 +1674,18 @@ function getAggregateResponsesInEventMessage({ eventResponses }, meLid) {
|
|
|
1640
1674
|
const responseMap = {}
|
|
1641
1675
|
|
|
1642
1676
|
for (const type of responseTypes) {
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1677
|
+
responseMap[type] = {
|
|
1678
|
+
response: type,
|
|
1679
|
+
responders: []
|
|
1680
|
+
}
|
|
1647
1681
|
}
|
|
1648
|
-
|
|
1682
|
+
|
|
1649
1683
|
for (const update of eventResponses) {
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1684
|
+
const { response } = update.response || 0
|
|
1685
|
+
const responseType = proto.Message.EventResponseMessage.EventResponseType[response]
|
|
1686
|
+
if (responseType !== 'UNKNOWN' && responseMap[responseType]) {
|
|
1687
|
+
responseMap[responseType].responders.push(getKeyAuthor(update.eventResponseMessageKey, meLid))
|
|
1688
|
+
}
|
|
1655
1689
|
}
|
|
1656
1690
|
|
|
1657
1691
|
return Object.values(responseMap)
|
|
@@ -1687,15 +1721,15 @@ const REUPLOAD_REQUIRED_STATUS = [410, 404]
|
|
|
1687
1721
|
*/
|
|
1688
1722
|
const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
1689
1723
|
const result = await downloadMsg().catch(async (error) => {
|
|
1690
|
-
if (ctx &&
|
|
1691
|
-
|
|
1724
|
+
if (ctx &&
|
|
1725
|
+
typeof error?.status === 'number' && // treat errors with status as HTTP failures requiring reupload
|
|
1726
|
+
REUPLOAD_REQUIRED_STATUS.includes(error.status)) {
|
|
1692
1727
|
ctx.logger.info({ key: message.key }, 'sending reupload media request...')
|
|
1693
1728
|
|
|
1694
1729
|
// request reupload
|
|
1695
1730
|
message = await ctx.reuploadRequest(message)
|
|
1696
1731
|
|
|
1697
1732
|
const result = await downloadMsg()
|
|
1698
|
-
|
|
1699
1733
|
return result
|
|
1700
1734
|
}
|
|
1701
1735
|
|
|
@@ -1712,7 +1746,9 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
|
1712
1746
|
}
|
|
1713
1747
|
|
|
1714
1748
|
const contentType = getContentType(mContent)
|
|
1749
|
+
|
|
1715
1750
|
let mediaType = contentType?.replace('Message', '')
|
|
1751
|
+
|
|
1716
1752
|
const media = contentType === 'productMessage' ? mContent[contentType]?.product?.productImage : mContent[contentType]
|
|
1717
1753
|
|
|
1718
1754
|
if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
|
|
@@ -1728,7 +1764,6 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
|
1728
1764
|
}
|
|
1729
1765
|
mediaType = 'thumbnail-link'
|
|
1730
1766
|
}
|
|
1731
|
-
|
|
1732
1767
|
else {
|
|
1733
1768
|
download = media
|
|
1734
1769
|
}
|
|
@@ -1737,57 +1772,30 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
|
1737
1772
|
|
|
1738
1773
|
if (type === 'buffer') {
|
|
1739
1774
|
const bufferArray = []
|
|
1740
|
-
|
|
1741
1775
|
for await (const chunk of stream) {
|
|
1742
|
-
bufferArray.push(chunk)
|
|
1776
|
+
bufferArray.push(chunk);
|
|
1743
1777
|
}
|
|
1744
|
-
|
|
1745
|
-
return Buffer.concat(bufferArray)
|
|
1778
|
+
return Buffer.concat(bufferArray);
|
|
1746
1779
|
}
|
|
1747
|
-
|
|
1748
1780
|
return stream
|
|
1749
1781
|
}
|
|
1750
1782
|
}
|
|
1751
1783
|
|
|
1752
|
-
/** Checks whether the given message is a media message if it is returns the inner content */
|
|
1784
|
+
/** Checks whether the given message is a media message; if it is returns the inner content */
|
|
1753
1785
|
const assertMediaContent = (content) => {
|
|
1754
1786
|
content = extractMessageContent(content)
|
|
1755
1787
|
|
|
1756
|
-
const mediaContent = content?.documentMessage
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1788
|
+
const mediaContent = content?.documentMessage ||
|
|
1789
|
+
content?.imageMessage ||
|
|
1790
|
+
content?.videoMessage ||
|
|
1791
|
+
content?.audioMessage ||
|
|
1792
|
+
content?.stickerMessage
|
|
1761
1793
|
|
|
1762
1794
|
if (!mediaContent) {
|
|
1763
|
-
throw new Boom('given message is not a media message', { statusCode: 400, data: content })
|
|
1795
|
+
throw new Boom('given message is not a media message', { statusCode: 400, data: content });
|
|
1764
1796
|
}
|
|
1765
|
-
return mediaContent
|
|
1766
|
-
}
|
|
1767
1797
|
|
|
1768
|
-
|
|
1769
|
-
* this is an experimental patch to make buttons work
|
|
1770
|
-
* Don't know how it works, but it does for now
|
|
1771
|
-
*/
|
|
1772
|
-
const patchMessageForMdIfRequired = (message) => {
|
|
1773
|
-
if (message?.buttonsMessage ||
|
|
1774
|
-
message?.templateMessage ||
|
|
1775
|
-
message?.listMessage ||
|
|
1776
|
-
message?.interactiveMessage?.nativeFlowMesaage
|
|
1777
|
-
) {
|
|
1778
|
-
message = {
|
|
1779
|
-
viewOnceMessageV2Extension: {
|
|
1780
|
-
message: {
|
|
1781
|
-
messageContextInfo: {
|
|
1782
|
-
deviceListMetadataVersion: 2,
|
|
1783
|
-
deviceListMetadata: {}
|
|
1784
|
-
},
|
|
1785
|
-
...message
|
|
1786
|
-
}
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1789
|
-
}
|
|
1790
|
-
return message
|
|
1798
|
+
return mediaContent
|
|
1791
1799
|
}
|
|
1792
1800
|
|
|
1793
1801
|
module.exports = {
|
|
@@ -1801,6 +1809,7 @@ module.exports = {
|
|
|
1801
1809
|
generateWAMessageFromContent,
|
|
1802
1810
|
generateWAMessage,
|
|
1803
1811
|
getContentType,
|
|
1812
|
+
hasNonNullishProperty,
|
|
1804
1813
|
normalizeMessageContent,
|
|
1805
1814
|
extractMessageContent,
|
|
1806
1815
|
getDevice,
|
|
@@ -1812,6 +1821,5 @@ module.exports = {
|
|
|
1812
1821
|
getAggregateResponsesInEventMessage,
|
|
1813
1822
|
aggregateMessageKeysNotFromMe,
|
|
1814
1823
|
downloadMediaMessage,
|
|
1815
|
-
assertMediaContent
|
|
1816
|
-
patchMessageForMdIfRequired
|
|
1824
|
+
assertMediaContent
|
|
1817
1825
|
}
|