@badzz88/baileys 8.4.9 → 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/WAProto/WAProto.proto +6 -347
- package/WAProto/fix-imports.js +85 -86
- package/WAProto/index.d.ts +25 -4913
- package/WAProto/index.js +93 -14069
- package/{src → lib}/Defaults/index.js +2 -13
- package/{src → lib}/Signal/Group/group_cipher.js +5 -5
- package/{src → lib}/Signal/Group/keyhelper.js +4 -4
- package/{src → lib}/Signal/Group/sender-chain-key.js +2 -2
- package/{src → lib}/Signal/Group/sender-key-distribution-message.js +1 -1
- package/{src → lib}/Signal/Group/sender-key-message.js +3 -3
- package/{src → lib}/Signal/Group/sender-key-record.js +1 -1
- package/{src → lib}/Signal/Group/sender-message-key.js +2 -2
- package/{src → lib}/Signal/libsignal.js +26 -6
- package/{src → lib}/Socket/chats.js +58 -616
- package/{src → lib}/Socket/communities.js +28 -59
- package/{src → lib}/Socket/graphql.js +103 -362
- package/{src → lib}/Socket/groups.js +29 -77
- package/{src → lib}/Socket/index.js +5 -3
- package/{src → lib}/Socket/interactive-handler.js +60 -117
- package/{src → lib}/Socket/interop.js +19 -36
- package/lib/Socket/luxu.js +387 -0
- package/{src → lib}/Socket/managed-account.js +27 -58
- package/{src → lib}/Socket/messages-recv.js +143 -715
- package/{src → lib}/Socket/messages-send.js +102 -412
- package/lib/Socket/mex.js +60 -0
- package/{src → lib}/Socket/newsletter.js +23 -266
- package/{src → lib}/Socket/privacy.js +38 -41
- package/{src → lib}/Socket/registration.js +106 -113
- package/{src → lib}/Socket/socket.js +101 -88
- package/{src → lib}/Socket/text-router.js +17 -1
- package/lib/Socket/username.js +243 -0
- package/lib/Store/keyed-db.js +108 -0
- package/{src → lib}/Store/make-in-memory-store.js +104 -6
- package/lib/Types/Mex.js +112 -0
- package/{src → lib}/Types/Newsletter.js +41 -72
- package/{src → lib}/Types/index.js +1 -0
- package/{src → lib}/Utils/chat-utils.js +9 -73
- 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 +42 -0
- package/lib/Utils/crypto.js +155 -0
- package/lib/Utils/curve25519-js.js +275 -0
- package/{src → lib}/Utils/decode-wa-message.js +36 -284
- package/{src → lib}/Utils/event-buffer.js +27 -6
- package/{src → lib}/Utils/generics.js +37 -114
- package/{src → lib}/Utils/index.js +5 -1
- package/lib/Utils/lt-hash.js +39 -0
- package/{src → lib}/Utils/message-retry-manager.js +39 -0
- package/{src → lib}/Utils/messages-media.js +58 -105
- package/{src → lib}/Utils/messages.js +529 -115
- package/lib/Utils/meta-ai-msmsg.js +262 -0
- package/lib/Utils/native-bridge.js +82 -0
- package/{src → lib}/Utils/noise-handler.js +15 -13
- package/{src → lib}/Utils/process-message.js +55 -54
- package/{src → lib}/Utils/reporting-utils.js +2 -2
- package/lib/Utils/session-pool.d.ts +16 -0
- package/lib/Utils/session-pool.js +94 -0
- package/{src → lib}/Utils/signal.js +51 -19
- package/{src → lib}/Utils/stanza-ack.js +2 -36
- package/lib/Utils/sticker.d.ts +17 -0
- package/lib/Utils/sticker.js +145 -0
- package/{src → lib}/Utils/tc-token-utils.js +1 -1
- package/{src → lib}/Utils/validate-connection.js +11 -40
- package/lib/Utils/view-once-cache.d.ts +9 -0
- package/lib/Utils/view-once-cache.js +79 -0
- package/{src → lib}/WABinary/decode.js +4 -38
- package/lib/WABinary/encode.js +228 -0
- package/{src → lib}/WABinary/generic-utils.js +93 -1
- package/{src → lib}/WABinary/jid-utils.js +3 -16
- package/{src → lib}/WAM/encode.js +1 -1
- package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +43 -0
- package/{src → lib}/WAUSync/Protocols/USyncContactProtocol.js +1 -7
- package/{src → lib}/WAUSync/Protocols/USyncDeviceProtocol.js +5 -13
- package/{src → lib}/WAUSync/Protocols/USyncDisappearingModeProtocol.js +4 -1
- package/{src → lib}/WAUSync/Protocols/USyncFeatureProtocol.js +2 -17
- package/{src → lib}/WAUSync/Protocols/USyncStatusProtocol.js +2 -7
- package/{src → lib}/WAUSync/Protocols/USyncUsernameProtocol.js +1 -2
- package/{src → lib}/WAUSync/Protocols/index.js +0 -1
- package/{src → lib}/WAUSync/USyncQuery.js +6 -77
- package/{src → lib}/WAUSync/USyncUser.js +8 -16
- package/{src → lib}/WAUSync/index.js +0 -1
- package/{src → lib}/antiban.js +266 -355
- package/{src → lib}/index.js +2 -2
- package/package.json +18 -15
- package/WAProto/fix-import.js +0 -38
- package/src/Socket/mex.js +0 -47
- package/src/Socket/username.js +0 -234
- package/src/Utils/crypto.js +0 -125
- package/src/Utils/lt-hash.js +0 -10
- package/src/Utils/message-inspect.js +0 -400
- package/src/Utils/meta-ai-msmsg.js +0 -133
- package/src/WABinary/encode.js +0 -58
- package/src/WAUSync/Protocols/USyncBusinessProtocol.js +0 -100
- package/src/WAUSync/USyncBackoff.js +0 -31
- /package/{src → lib}/Defaults/phonenumber-mcc.json +0 -0
- /package/{src → lib}/Signal/Group/ciphertext-message.js +0 -0
- /package/{src → lib}/Signal/Group/group-session-builder.js +0 -0
- /package/{src → lib}/Signal/Group/index.js +0 -0
- /package/{src → lib}/Signal/Group/sender-key-name.js +0 -0
- /package/{src → lib}/Signal/Group/sender-key-state.js +0 -0
- /package/{src → lib}/Signal/lid-mapping.js +0 -0
- /package/{src → lib}/Socket/Client/index.js +0 -0
- /package/{src → lib}/Socket/Client/types.js +0 -0
- /package/{src → lib}/Socket/Client/websocket.js +0 -0
- /package/{src → lib}/Socket/aigroups.js +0 -0
- /package/{src → lib}/Socket/business.js +0 -0
- /package/{src → lib}/Store/index.js +0 -0
- /package/{src → lib}/Store/make-cache-manager-store.js +0 -0
- /package/{src → lib}/Store/make-ordered-dictionary.js +0 -0
- /package/{src → lib}/Store/object-repository.js +0 -0
- /package/{src → lib}/Types/Auth.js +0 -0
- /package/{src → lib}/Types/Bussines.js +0 -0
- /package/{src → lib}/Types/Call.js +0 -0
- /package/{src → lib}/Types/Chat.js +0 -0
- /package/{src → lib}/Types/Contact.js +0 -0
- /package/{src → lib}/Types/Events.js +0 -0
- /package/{src → lib}/Types/GroupMetadata.js +0 -0
- /package/{src → lib}/Types/Label.js +0 -0
- /package/{src → lib}/Types/LabelAssociation.js +0 -0
- /package/{src → lib}/Types/Message.js +0 -0
- /package/{src → lib}/Types/Product.js +0 -0
- /package/{src → lib}/Types/Signal.js +0 -0
- /package/{src → lib}/Types/Socket.js +0 -0
- /package/{src → lib}/Types/State.js +0 -0
- /package/{src → lib}/Types/USync.js +0 -0
- /package/{src → lib}/Utils/auth-utils.js +0 -0
- /package/{src → lib}/Utils/browser-utils.js +0 -0
- /package/{src → lib}/Utils/business.js +0 -0
- /package/{src → lib}/Utils/consumer-application.js +0 -0
- /package/{src → lib}/Utils/group-history.js +0 -0
- /package/{src → lib}/Utils/history.js +0 -0
- /package/{src → lib}/Utils/identity-change-handler.js +0 -0
- /package/{src → lib}/Utils/jid-display-normalization.js +0 -0
- /package/{src → lib}/Utils/link-preview.js +0 -0
- /package/{src → lib}/Utils/logger.js +0 -0
- /package/{src → lib}/Utils/make-mutex.js +0 -0
- /package/{src → lib}/Utils/message-composer.js +0 -0
- /package/{src → lib}/Utils/offline-node-processor.js +0 -0
- /package/{src → lib}/Utils/pre-key-manager.js +0 -0
- /package/{src → lib}/Utils/sync-action-utils.js +0 -0
- /package/{src → lib}/Utils/use-multi-file-auth-state.js +0 -0
- /package/{src → lib}/Utils/voip-rekey.js +0 -0
- /package/{src → lib}/WABinary/constants.js +0 -0
- /package/{src → lib}/WABinary/index.js +0 -0
- /package/{src → lib}/WABinary/types.js +0 -0
- /package/{src → lib}/WAM/BinaryInfo.js +0 -0
- /package/{src → lib}/WAM/constants.js +0 -0
- /package/{src → lib}/WAM/index.js +0 -0
- /package/{src → lib}/WAUSync/Protocols/USyncBotProfileProtocol.js +0 -0
- /package/{src → lib}/WAUSync/Protocols/USyncLIDProtocol.js +0 -0
- /package/{src → lib}/WAUSync/Protocols/USyncPictureProtocol.js +0 -0
- /package/{src → lib}/WAUSync/Protocols/USyncSidelistProtocol.js +0 -0
- /package/{src → lib}/WAUSync/Protocols/USyncTextStatusProtocol.js +0 -0
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
Object.defineProperty(exports, '__esModule', { value: true })
|
|
3
|
-
exports.
|
|
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 =
|
|
4
15
|
exports.generateWAMessageFromContent =
|
|
5
16
|
exports.generateWAMessageContent =
|
|
6
17
|
exports.hasNonNullishProperty =
|
|
@@ -10,10 +21,12 @@ exports.generateWAMessage =
|
|
|
10
21
|
exports.generateLinkPreviewIfRequired =
|
|
11
22
|
exports.extractUrlFromText =
|
|
12
23
|
void 0
|
|
24
|
+
exports.getAggregateVotesInPollMessage = getAggregateVotesInPollMessage
|
|
25
|
+
exports.getAggregateResponsesInEventMessage = getAggregateResponsesInEventMessage
|
|
13
26
|
const boom_1 = require('@hapi/boom')
|
|
14
27
|
const crypto_1 = require('crypto')
|
|
15
28
|
const fs_1 = require('fs')
|
|
16
|
-
const
|
|
29
|
+
const index_js_1 = require('../../WAProto/index.js')
|
|
17
30
|
const WAProto_1 = require('../../WAProto/index.js')
|
|
18
31
|
const Defaults_1 = require('../Defaults')
|
|
19
32
|
const Types_1 = require('../Types')
|
|
@@ -23,12 +36,6 @@ const generics_1 = require('./generics')
|
|
|
23
36
|
const messages_media_1 = require('./messages-media')
|
|
24
37
|
const reporting_utils_1 = require('./reporting-utils')
|
|
25
38
|
const jid_display_normalization_1 = require('./jid-display-normalization')
|
|
26
|
-
const message_inspect_1 = require('./message-inspect')
|
|
27
|
-
Object.assign(exports, message_inspect_1)
|
|
28
|
-
// Group-invite thumbnails are fetched (IQ + HTTP GET) per generateWAMessage call;
|
|
29
|
-
// caching the downloaded bytes avoids redownloading the same group picture when
|
|
30
|
-
// the same invite is sent to many recipients in a burst.
|
|
31
|
-
const groupInviteThumbnailCache = new lru_cache_1.LRUCache({ max: 100, ttl: 5 * 60 * 1000 })
|
|
32
39
|
const MIMETYPE_MAP = {
|
|
33
40
|
image: 'image/jpeg',
|
|
34
41
|
video: 'video/mp4',
|
|
@@ -224,9 +231,6 @@ const assertColor = async color => {
|
|
|
224
231
|
}
|
|
225
232
|
const prepareWAMessageMedia = async (message, options) => {
|
|
226
233
|
const logger = options.logger
|
|
227
|
-
// AB props for feature-flagged media paths (passed via options.mediaAbProps).
|
|
228
|
-
const mediaAbProps = options.mediaAbProps || null
|
|
229
|
-
const getMediaProp = propName => (0, messages_media_1.getMediaProp)(mediaAbProps, propName)
|
|
230
234
|
let mediaType
|
|
231
235
|
for (const key of Defaults_1.MEDIA_KEYS) {
|
|
232
236
|
if (key in message) {
|
|
@@ -241,19 +245,6 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
241
245
|
media: message[mediaType]
|
|
242
246
|
}
|
|
243
247
|
delete uploadData[mediaType]
|
|
244
|
-
|
|
245
|
-
// Feature B: HEVC video — when hevc_video_dual_upload is enabled, allow HEVC mimetype
|
|
246
|
-
// through without forcing it to mp4. When the prop is absent we leave the existing
|
|
247
|
-
// mimetype as-is (defaults are set further below).
|
|
248
|
-
if (mediaType === 'video' && uploadData.mimetype) {
|
|
249
|
-
const isHevc = uploadData.mimetype.includes('hevc') || uploadData.mimetype.includes('x-matroska')
|
|
250
|
-
if (isHevc && !getMediaProp('hevc_video_dual_upload')) {
|
|
251
|
-
// Prop not enabled: normalise to mp4 so receivers can decode it.
|
|
252
|
-
uploadData.mimetype = MIMETYPE_MAP['video']
|
|
253
|
-
}
|
|
254
|
-
// If the prop is enabled we leave the caller-supplied HEVC mimetype intact.
|
|
255
|
-
}
|
|
256
|
-
|
|
257
248
|
// check if cacheable + generate cache key
|
|
258
249
|
const cacheableKey =
|
|
259
250
|
typeof uploadData.media === 'object' &&
|
|
@@ -271,7 +262,7 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
271
262
|
const mediaBuff = await options.mediaCache.get(cacheableKey)
|
|
272
263
|
if (mediaBuff) {
|
|
273
264
|
logger?.debug({ cacheableKey }, 'got media cache hit')
|
|
274
|
-
const obj =
|
|
265
|
+
const obj = index_js_1.proto.Message.decode(mediaBuff)
|
|
275
266
|
const key = `${mediaType}Message`
|
|
276
267
|
Object.assign(obj[key], { ...uploadData, media: undefined })
|
|
277
268
|
return obj
|
|
@@ -384,27 +375,6 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
384
375
|
logger?.warn('failed to remove tmp file')
|
|
385
376
|
}
|
|
386
377
|
})
|
|
387
|
-
|
|
388
|
-
// Feature A: HD image dual upload — set mediaHd flag when prop is enabled and caller
|
|
389
|
-
// explicitly requests HD quality via uploadData.hd === true.
|
|
390
|
-
const hdImageEnabled = mediaType === 'image' && getMediaProp('hd_image_dual_upload') && !!uploadData.hd
|
|
391
|
-
const hdVideoEnabled = mediaType === 'video' && getMediaProp('hd_video_dual_upload') && !!uploadData.hd
|
|
392
|
-
if (hdImageEnabled || hdVideoEnabled) {
|
|
393
|
-
uploadData.mediaHd = true
|
|
394
|
-
logger?.debug({ mediaType }, 'HD dual upload enabled, setting mediaHd flag')
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// Feature C: Motion photo — propagate motionPhoto field for image messages when present.
|
|
398
|
-
// The caller sets message.motionPhoto = true (or a Buffer for the motion data).
|
|
399
|
-
if (mediaType === 'image' && uploadData.motionPhoto != null) {
|
|
400
|
-
// Keep motionPhoto in uploadData; it will be spread into the proto below.
|
|
401
|
-
// If it is a boolean we coerce to 1/0 for the proto field (uint32 in WA proto).
|
|
402
|
-
if (typeof uploadData.motionPhoto === 'boolean') {
|
|
403
|
-
uploadData.motionPhoto = uploadData.motionPhoto ? 1 : 0
|
|
404
|
-
}
|
|
405
|
-
logger?.debug('motion photo field set on image message')
|
|
406
|
-
}
|
|
407
|
-
|
|
408
378
|
const obj = WAProto_1.proto.Message.fromObject({
|
|
409
379
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
410
380
|
url: mediaUrl,
|
|
@@ -456,7 +426,7 @@ const generateForwardMessageContent = (message, forceForward) => {
|
|
|
456
426
|
}
|
|
457
427
|
// hacky copy
|
|
458
428
|
content = (0, exports.normalizeMessageContent)(content)
|
|
459
|
-
content =
|
|
429
|
+
content = index_js_1.proto.Message.decode(index_js_1.proto.Message.encode(content).finish())
|
|
460
430
|
let key = Object.keys(content)[0]
|
|
461
431
|
let score = content?.[key]?.contextInfo?.forwardingScore || 0
|
|
462
432
|
score += message.key.fromMe && !forceForward ? 0 : 1
|
|
@@ -684,19 +654,15 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
684
654
|
m.groupInviteMessage.caption = message.groupInvite.text
|
|
685
655
|
m.groupInviteMessage.groupJid = message.groupInvite.jid
|
|
686
656
|
m.groupInviteMessage.groupName = message.groupInvite.subject
|
|
657
|
+
//TODO: use built-in interface and get disappearing mode info etc.
|
|
658
|
+
//TODO: cache / use store!?
|
|
687
659
|
if (options.getProfilePicUrl) {
|
|
688
|
-
const
|
|
689
|
-
if (
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
const resp = await fetch(pfpUrl, { method: 'GET', dispatcher: options?.options?.dispatcher })
|
|
695
|
-
if (resp.ok) {
|
|
696
|
-
const buf = Buffer.from(await resp.arrayBuffer())
|
|
697
|
-
m.groupInviteMessage.jpegThumbnail = buf
|
|
698
|
-
groupInviteThumbnailCache.set(message.groupInvite.jid, buf)
|
|
699
|
-
}
|
|
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
|
|
700
666
|
}
|
|
701
667
|
}
|
|
702
668
|
}
|
|
@@ -720,7 +686,7 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
720
686
|
m.buttonsResponseMessage = {
|
|
721
687
|
selectedButtonId: message.buttonReply.id,
|
|
722
688
|
selectedDisplayText: message.buttonReply.displayText,
|
|
723
|
-
type:
|
|
689
|
+
type: index_js_1.proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
|
|
724
690
|
}
|
|
725
691
|
break
|
|
726
692
|
case 'interactive':
|
|
@@ -814,12 +780,7 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
814
780
|
...(message.poll.hideParticipantName !== undefined
|
|
815
781
|
? { hideParticipantName: !!message.poll.hideParticipantName }
|
|
816
782
|
: {}),
|
|
817
|
-
...(message.poll.allowAddOption !== undefined ? { allowAddOption: !!message.poll.allowAddOption } : {})
|
|
818
|
-
// Feature D: media_poll — allow poll messages to carry a media attachment when the
|
|
819
|
-
// AB prop is enabled and the caller supplies message.poll.mediaAttachment.
|
|
820
|
-
...((0, messages_media_1.getMediaProp)(options.mediaAbProps, 'media_poll') && message.poll.mediaPoll != null
|
|
821
|
-
? { mediaPoll: !!message.poll.mediaPoll }
|
|
822
|
-
: {})
|
|
783
|
+
...(message.poll.allowAddOption !== undefined ? { allowAddOption: !!message.poll.allowAddOption } : {})
|
|
823
784
|
}
|
|
824
785
|
if (message.poll.version === 6 || message.poll.v6) {
|
|
825
786
|
m.pollCreationMessageV6 = pollCreationMessage
|
|
@@ -962,13 +923,13 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
962
923
|
}
|
|
963
924
|
} else if ((0, exports.hasNonNullishProperty)(message, 'sharePhoneNumber')) {
|
|
964
925
|
m.protocolMessage = {
|
|
965
|
-
type:
|
|
926
|
+
type: index_js_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
|
|
966
927
|
}
|
|
967
928
|
} else if ((0, exports.hasNonNullishProperty)(message, 'requestPhoneNumber')) {
|
|
968
929
|
m.requestPhoneNumberMessage = {}
|
|
969
930
|
} else if ((0, exports.hasNonNullishProperty)(message, 'limitSharing')) {
|
|
970
931
|
m.protocolMessage = {
|
|
971
|
-
type:
|
|
932
|
+
type: index_js_1.proto.Message.ProtocolMessage.Type.LIMIT_SHARING,
|
|
972
933
|
limitSharing: {
|
|
973
934
|
sharingLimited: message.limitSharing === true,
|
|
974
935
|
trigger: 1,
|
|
@@ -1071,7 +1032,7 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
1071
1032
|
m = { interactiveMessage }
|
|
1072
1033
|
} else if ('templateButtons' in message && !!message.templateButtons) {
|
|
1073
1034
|
const msg = {
|
|
1074
|
-
hydratedButtons: message.templateButtons
|
|
1035
|
+
hydratedButtons: message.hasOwnProperty('templateButtons') ? message.templateButtons : message.templateButtons
|
|
1075
1036
|
}
|
|
1076
1037
|
if ('text' in message) {
|
|
1077
1038
|
msg.hydratedContentText = message.text
|
|
@@ -1128,42 +1089,73 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
1128
1089
|
}
|
|
1129
1090
|
}
|
|
1130
1091
|
if ('interactiveButtons' in message && !!message.interactiveButtons) {
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1092
|
+
const nativeFlow = WAProto_1.proto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
|
|
1093
|
+
buttons: message.interactiveButtons,
|
|
1094
|
+
messageParamsJson: message.messageParams ?? "{}"
|
|
1095
|
+
});
|
|
1096
|
+
let interactiveMessage = { nativeFlowMessage: nativeFlow };
|
|
1097
|
+
if ('text' in message) {
|
|
1098
|
+
interactiveMessage.body = { text: message.text };
|
|
1099
|
+
} else if ('caption' in message) {
|
|
1100
|
+
interactiveMessage.body = { text: message.caption };
|
|
1101
|
+
}
|
|
1102
|
+
if ('title' in message && !!message.title) {
|
|
1103
|
+
interactiveMessage.header = {
|
|
1104
|
+
title: message.title,
|
|
1105
|
+
subtitle: message.subtitle || "",
|
|
1106
|
+
hasMediaAttachment: false
|
|
1107
|
+
};
|
|
1108
|
+
let media = null;
|
|
1109
|
+
if ('image' in message && !!message.image) {
|
|
1110
|
+
media = await prepareWAMessageMedia({ image: message.image }, options);
|
|
1111
|
+
interactiveMessage.header.imageMessage = media.imageMessage;
|
|
1112
|
+
if (message.image.caption) {
|
|
1113
|
+
interactiveMessage.header.imageMessage.caption = message.image.caption;
|
|
1114
|
+
}
|
|
1115
|
+
} else if ('video' in message && !!message.video) {
|
|
1116
|
+
media = await prepareWAMessageMedia({ video: message.video }, options);
|
|
1117
|
+
interactiveMessage.header.videoMessage = media.videoMessage;
|
|
1118
|
+
if (message.video.caption) {
|
|
1119
|
+
interactiveMessage.header.videoMessage.caption = message.video.caption;
|
|
1120
|
+
}
|
|
1121
|
+
} else if ('gif' in message && !!message.gif) {
|
|
1122
|
+
media = await prepareWAMessageMedia({ video: message.gif }, options);
|
|
1123
|
+
interactiveMessage.header.videoMessage = media.videoMessage;
|
|
1124
|
+
interactiveMessage.header.videoMessage.gifPlayback = true;
|
|
1125
|
+
if (message.gif.caption) {
|
|
1126
|
+
interactiveMessage.header.videoMessage.caption = message.gif.caption;
|
|
1127
|
+
}
|
|
1128
|
+
} else if ('document' in message && !!message.document) {
|
|
1129
|
+
media = await prepareWAMessageMedia({ document: message.document }, options);
|
|
1130
|
+
interactiveMessage.header.documentMessage = media.documentMessage;
|
|
1131
|
+
let docuR = interactiveMessage.header.documentMessage;
|
|
1132
|
+
docuR.fileName = message.document.fileName || "Document";
|
|
1133
|
+
docuR.mimetype = message.document.mimetype || docuR.mimetype;
|
|
1134
|
+
if (message.document.caption) docuR.caption = message.document.caption;
|
|
1135
|
+
if (message.document.jpegThumbnail) docuR.jpegThumbnail = message.document.jpegThumbnail;
|
|
1136
|
+
} else if ('location' in message && !!message.location) {
|
|
1137
|
+
let mLoc = message.location;
|
|
1138
|
+
interactiveMessage.header.locationMessage = {
|
|
1139
|
+
degreesLongitude: mLoc.longitude || 0,
|
|
1140
|
+
degreesLatitude: mLoc.latitude || 0,
|
|
1141
|
+
name: mLoc.name || null,
|
|
1142
|
+
address: mLoc.address || null,
|
|
1143
|
+
url: mLoc.url || null
|
|
1144
|
+
};
|
|
1145
|
+
media = true;
|
|
1146
|
+
} else if ('thumbnail' in message && !!message.thumbnail) {
|
|
1147
|
+
interactiveMessage.header.jpegThumbnail = message.thumbnail;
|
|
1148
|
+
}
|
|
1149
|
+
if (media || ('thumbnail' in message && !!message.thumbnail)) {
|
|
1150
|
+
interactiveMessage.header.hasMediaAttachment = true;
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
if ('footer' in message && !!message.footer) {
|
|
1154
|
+
interactiveMessage.footer = { text: message.footer };
|
|
1155
|
+
}
|
|
1156
|
+
applyContextInfoAndMentions(interactiveMessage, message);
|
|
1157
|
+
m = { interactiveMessage };
|
|
1158
|
+
}
|
|
1167
1159
|
if ('shop' in message && !!message.shop) {
|
|
1168
1160
|
const interactiveMessage = {
|
|
1169
1161
|
shopStorefrontMessage: WAProto_1.proto.Message.InteractiveMessage.ShopMessage.fromObject({
|
|
@@ -1240,12 +1232,22 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
1240
1232
|
}
|
|
1241
1233
|
})
|
|
1242
1234
|
}
|
|
1243
|
-
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
|
+
}
|
|
1244
1244
|
sections.push({
|
|
1245
1245
|
view_model: {
|
|
1246
1246
|
primitive: {
|
|
1247
|
-
rows:
|
|
1248
|
-
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
|
|
1249
1251
|
})),
|
|
1250
1252
|
__typename: 'GenAITableUXPrimitive'
|
|
1251
1253
|
},
|
|
@@ -1876,10 +1878,9 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
1876
1878
|
...existing,
|
|
1877
1879
|
botThreadInfo: {
|
|
1878
1880
|
clientInfo: {
|
|
1879
|
-
type:
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
: (bt.type ?? threadTypeEnum.UNKNOWN),
|
|
1881
|
+
type: typeof bt.type === 'string'
|
|
1882
|
+
? (threadTypeMap[bt.type.toLowerCase()] ?? threadTypeEnum.UNKNOWN)
|
|
1883
|
+
: (bt.type ?? threadTypeEnum.UNKNOWN),
|
|
1883
1884
|
sourceChatJid: bt.sourceChatJid || ''
|
|
1884
1885
|
}
|
|
1885
1886
|
}
|
|
@@ -2280,7 +2281,7 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
2280
2281
|
m.messageContextInfo = {
|
|
2281
2282
|
...(m.messageContextInfo || {}),
|
|
2282
2283
|
messageAddOnDurationInSecs: message.afterReadDuration,
|
|
2283
|
-
messageAddOnExpiryType:
|
|
2284
|
+
messageAddOnExpiryType: index_js_1.proto.MessageContextInfo.MessageAddonExpiryType.DEPENDENT_ON_PARENT
|
|
2284
2285
|
}
|
|
2285
2286
|
}
|
|
2286
2287
|
if ('raw' in message && !!message.raw) {
|
|
@@ -2425,7 +2426,7 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
2425
2426
|
let quotedMsg = (0, exports.normalizeMessageContent)(quoted.message)
|
|
2426
2427
|
const msgType = (0, exports.getContentType)(quotedMsg)
|
|
2427
2428
|
// strip any redundant properties
|
|
2428
|
-
quotedMsg =
|
|
2429
|
+
quotedMsg = index_js_1.proto.Message.create({ [msgType]: quotedMsg[msgType] })
|
|
2429
2430
|
const quotedContent = quotedMsg[msgType]
|
|
2430
2431
|
if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
|
|
2431
2432
|
delete quotedContent.contextInfo
|
|
@@ -2462,11 +2463,20 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
2462
2463
|
}
|
|
2463
2464
|
}
|
|
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))
|
|
2465
2475
|
const messageJSON = {
|
|
2466
2476
|
key: {
|
|
2467
2477
|
remoteJid: jid,
|
|
2468
2478
|
fromMe: true,
|
|
2469
|
-
id:
|
|
2479
|
+
id: pickedMessageId
|
|
2470
2480
|
},
|
|
2471
2481
|
message: message,
|
|
2472
2482
|
messageTimestamp: timestamp,
|
|
@@ -2488,3 +2498,407 @@ const generateWAMessage = async (jid, content, options) => {
|
|
|
2488
2498
|
)
|
|
2489
2499
|
}
|
|
2490
2500
|
exports.generateWAMessage = generateWAMessage
|
|
2501
|
+
/** Get the key to access the true type of content */
|
|
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
|
|
2510
|
+
/**
|
|
2511
|
+
* Normalizes ephemeral, view once messages to regular message content
|
|
2512
|
+
* Eg. image messages in ephemeral messages, in view once messages etc.
|
|
2513
|
+
* @param content
|
|
2514
|
+
* @returns
|
|
2515
|
+
*/
|
|
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
|
|
2565
|
+
/**
|
|
2566
|
+
* Extract the true message content from a message
|
|
2567
|
+
* Eg. extracts the inner message from a disappearing message/view once message
|
|
2568
|
+
*/
|
|
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
|
|
2602
|
+
/**
|
|
2603
|
+
* Returns the device predicted by message ID
|
|
2604
|
+
*/
|
|
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
|
|
2616
|
+
/** Upserts a receipt in the message */
|
|
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
|
|
2627
|
+
/** Update the message with a new reaction */
|
|
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
|
|
2636
|
+
/** Update the message with a new poll update */
|
|
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
|
|
2648
|
+
/** Update the message with a new event response */
|
|
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
|
|
2658
|
+
/**
|
|
2659
|
+
* Aggregates all poll updates in a poll.
|
|
2660
|
+
* @param msg the poll creation message
|
|
2661
|
+
* @param meId your jid
|
|
2662
|
+
* @returns A list of options & their voters
|
|
2663
|
+
*/
|
|
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
|
|
2774
|
+
}
|
|
2775
|
+
exports.getPollCorrectAnswer = getPollCorrectAnswer
|
|
2776
|
+
|
|
2777
|
+
/**
|
|
2778
|
+
* Aggregates all event responses in an event message.
|
|
2779
|
+
* @param msg the event creation message
|
|
2780
|
+
* @param meLid your lid
|
|
2781
|
+
* @returns A list of response types & their responders
|
|
2782
|
+
*/
|
|
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)
|
|
2802
|
+
}
|
|
2803
|
+
|
|
2804
|
+
exports.getAggregateResponsesInEventMessage = getAggregateResponsesInEventMessage
|
|
2805
|
+
|
|
2806
|
+
const REUPLOAD_REQUIRED_STATUS = [410, 404]
|
|
2807
|
+
/**
|
|
2808
|
+
* Downloads the given message. Throws an error if it's not a media message
|
|
2809
|
+
*/
|
|
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
|
|
2859
|
+
/** Checks whether the given message is a media message; if it is returns the inner content */
|
|
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
|