@hansaka02/baileys 7.3.2 → 7.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Defaults/baileys-version.json +2 -2
- package/lib/Defaults/connection.js +51 -0
- package/lib/Defaults/constants.js +74 -0
- package/lib/Defaults/history.js +19 -0
- package/lib/Defaults/index.js +36 -142
- package/lib/Defaults/media.js +48 -0
- package/lib/Defaults/prefix.js +18 -0
- package/lib/Signal/Group/group-session-builder.js +10 -42
- package/lib/Signal/Group/group_cipher.js +9 -6
- package/lib/Signal/Group/index.js +39 -53
- package/lib/Signal/Group/keyhelper.js +8 -41
- package/lib/Signal/Group/sender-chain-key.js +5 -18
- package/lib/Signal/Group/sender-key-distribution-message.js +7 -7
- package/lib/Signal/Group/sender-key-message.js +12 -8
- package/lib/Signal/Group/sender-key-record.js +7 -16
- package/lib/Signal/Group/sender-key-state.js +15 -61
- package/lib/Signal/Group/sender-message-key.js +2 -2
- package/lib/Signal/libsignal.js +237 -177
- package/lib/Signal/lid-mapping.js +128 -71
- package/lib/Socket/Client/types.js +2 -2
- package/lib/Socket/Client/websocket.js +25 -16
- package/lib/Socket/business.js +46 -33
- package/lib/Socket/chats.js +286 -170
- package/lib/Socket/community.js +215 -77
- package/lib/Socket/groups.js +77 -61
- package/lib/Socket/index.js +4 -4
- package/lib/Socket/messages-recv.js +629 -457
- package/lib/Socket/messages-send.js +645 -656
- package/lib/Socket/mex.js +61 -0
- package/lib/Socket/newsletter.js +166 -245
- package/lib/Socket/socket.js +396 -170
- package/lib/Store/index.js +27 -11
- package/lib/Store/make-cache-manager-store.js +14 -15
- package/lib/Store/make-in-memory-store.js +28 -24
- package/lib/Types/LabelAssociation.js +2 -2
- package/lib/Types/Message.js +6 -6
- package/lib/Types/MexUpdates.js +5 -5
- package/lib/Types/Newsletter.js +32 -25
- package/lib/Types/State.js +4 -4
- package/lib/Types/index.js +28 -12
- package/lib/Utils/auth-utils.js +212 -375
- package/lib/Utils/baileys-event-stream.js +68 -69
- package/lib/Utils/browser-utils.js +43 -0
- package/lib/Utils/business.js +63 -53
- package/lib/Utils/chat-utils.js +241 -106
- package/lib/Utils/crypto.js +25 -45
- package/lib/Utils/decode-wa-message.js +361 -311
- package/lib/Utils/event-buffer.js +97 -42
- package/lib/Utils/generics.js +90 -207
- package/lib/Utils/history.js +29 -27
- package/lib/Utils/index.js +28 -14
- package/lib/Utils/link-preview.js +24 -62
- package/lib/Utils/logger.js +5 -5
- package/lib/Utils/lt-hash.js +29 -23
- package/lib/Utils/make-mutex.js +26 -28
- package/lib/Utils/message-retry-manager.js +55 -7
- package/lib/Utils/messages-media.js +434 -247
- package/lib/Utils/messages.js +963 -917
- package/lib/Utils/noise-handler.js +60 -20
- package/lib/Utils/pre-key-manager.js +126 -0
- package/lib/Utils/process-message.js +216 -141
- package/lib/Utils/signal.js +75 -37
- package/lib/Utils/use-multi-file-auth-state.js +18 -22
- package/lib/Utils/validate-connection.js +96 -66
- package/lib/WABinary/constants.js +1268 -1268
- package/lib/WABinary/decode.js +62 -34
- package/lib/WABinary/encode.js +57 -36
- package/lib/WABinary/generic-utils.js +4 -4
- package/lib/WABinary/index.js +27 -11
- package/lib/WABinary/jid-utils.js +58 -11
- package/lib/WAM/constants.js +19064 -11563
- package/lib/WAM/encode.js +71 -14
- package/lib/WAM/index.js +27 -11
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +20 -16
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +2 -2
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +7 -4
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +2 -2
- package/lib/WAUSync/Protocols/USyncLIDProtocol.js +0 -2
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +2 -2
- package/lib/WAUSync/Protocols/index.js +27 -11
- package/lib/WAUSync/USyncQuery.js +51 -28
- package/lib/WAUSync/index.js +27 -11
- package/lib/index.js +60 -31
- package/package.json +12 -17
- package/WAProto/AICommon/AICommon.d.ts +0 -11702
- package/WAProto/Adv/Adv.d.ts +0 -643
- package/WAProto/BotMetadata/BotMetadata.d.ts +0 -5654
- package/WAProto/Cert/Cert.d.ts +0 -613
- package/WAProto/ChatLockSettings/ChatLockSettings.d.ts +0 -476
- package/WAProto/CompanionReg/CompanionReg.d.ts +0 -1361
- package/WAProto/DeviceCapabilities/DeviceCapabilities.d.ts +0 -577
- package/WAProto/E2E/E2E.d.ts +0 -41724
- package/WAProto/Ephemeral/Ephemeral.d.ts +0 -114
- package/WAProto/HistorySync/HistorySync.d.ts +0 -51700
- package/WAProto/LidMigrationSyncPayload/LidMigrationSyncPayload.d.ts +0 -229
- package/WAProto/MdStorageChatRowOpaqueData/MdStorageChatRowOpaqueData.d.ts +0 -583
- package/WAProto/MdStorageMsgRowOpaqueData/MdStorageMsgRowOpaqueData.d.ts +0 -42897
- package/WAProto/MmsRetry/MmsRetry.d.ts +0 -243
- package/WAProto/Protocol/Protocol.d.ts +0 -270
- package/WAProto/Reporting/Reporting.d.ts +0 -371
- package/WAProto/ServerSync/ServerSync.d.ts +0 -1285
- package/WAProto/SignalLocalStorageProtocol/SignalLocalStorageProtocol.d.ts +0 -1868
- package/WAProto/SignalWhisperTextProtocol/SignalWhisperTextProtocol.d.ts +0 -767
- package/WAProto/StatusAttributions/StatusAttributions.d.ts +0 -1027
- package/WAProto/SyncAction/SyncAction.d.ts +0 -11193
- package/WAProto/UserPassword/UserPassword.d.ts +0 -363
- package/WAProto/VnameCert/VnameCert.d.ts +0 -821
- package/WAProto/Wa6/Wa6.d.ts +0 -2128
- package/WAProto/Web/Web.d.ts +0 -46383
- package/WAProto/index.d.ts +0 -55
- package/lib/Defaults/index.d.ts +0 -77
- package/lib/Signal/Group/ciphertext-message.d.ts +0 -9
- package/lib/Signal/Group/group-session-builder.d.ts +0 -17
- package/lib/Signal/Group/group_cipher.d.ts +0 -19
- package/lib/Signal/Group/index.d.ts +0 -11
- package/lib/Signal/Group/keyhelper.d.ts +0 -16
- package/lib/Signal/Group/sender-chain-key.d.ts +0 -14
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -17
- package/lib/Signal/Group/sender-key-message.d.ts +0 -19
- package/lib/Signal/Group/sender-key-name.d.ts +0 -19
- package/lib/Signal/Group/sender-key-record.d.ts +0 -32
- package/lib/Signal/Group/sender-key-state.d.ts +0 -44
- package/lib/Signal/Group/sender-message-key.d.ts +0 -11
- package/lib/Signal/libsignal.d.ts +0 -8
- package/lib/Signal/lid-mapping.d.ts +0 -28
- package/lib/Socket/Client/index.d.ts +0 -2
- package/lib/Socket/Client/types.d.ts +0 -16
- package/lib/Socket/Client/websocket.d.ts +0 -13
- package/lib/Socket/business.d.ts +0 -187
- package/lib/Socket/chats.d.ts +0 -97
- package/lib/Socket/community.d.ts +0 -129
- package/lib/Socket/groups.d.ts +0 -129
- package/lib/Socket/index.d.ts +0 -191
- package/lib/Socket/messages-recv.d.ts +0 -174
- package/lib/Socket/messages-send.d.ts +0 -165
- package/lib/Socket/newsletter.d.ts +0 -145
- package/lib/Socket/socket.d.ts +0 -45
- package/lib/Socket/usync.d.ts +0 -37
- package/lib/Socket/usync.js +0 -83
- package/lib/Store/index.d.ts +0 -4
- package/lib/Store/make-cache-manager-store.d.ts +0 -14
- package/lib/Store/make-in-memory-store.d.ts +0 -123
- package/lib/Store/make-ordered-dictionary.d.ts +0 -12
- package/lib/Store/object-repository.d.ts +0 -10
- package/lib/Types/Auth.d.ts +0 -121
- package/lib/Types/Bussiness.d.ts +0 -28
- package/lib/Types/Call.d.ts +0 -14
- package/lib/Types/Chat.d.ts +0 -143
- package/lib/Types/Contact.d.ts +0 -23
- package/lib/Types/Events.d.ts +0 -226
- package/lib/Types/GroupMetadata.d.ts +0 -66
- package/lib/Types/Label.d.ts +0 -48
- package/lib/Types/LabelAssociation.d.ts +0 -35
- package/lib/Types/Message.d.ts +0 -484
- package/lib/Types/MexUpdates.d.ts +0 -9
- package/lib/Types/Newsletter.d.ts +0 -109
- package/lib/Types/Product.d.ts +0 -92
- package/lib/Types/Signal.d.ts +0 -98
- package/lib/Types/Socket.d.ts +0 -141
- package/lib/Types/State.d.ts +0 -41
- package/lib/Types/USync.d.ts +0 -26
- package/lib/Types/index.d.ts +0 -80
- package/lib/Utils/auth-utils.d.ts +0 -21
- package/lib/Utils/baileys-event-stream.d.ts +0 -18
- package/lib/Utils/business.d.ts +0 -29
- package/lib/Utils/chat-utils.d.ts +0 -82
- package/lib/Utils/crypto.d.ts +0 -56
- package/lib/Utils/decode-wa-message.d.ts +0 -53
- package/lib/Utils/event-buffer.d.ts +0 -39
- package/lib/Utils/generics.d.ts +0 -117
- package/lib/Utils/history.d.ts +0 -23
- package/lib/Utils/index.d.ts +0 -20
- package/lib/Utils/link-preview.d.ts +0 -23
- package/lib/Utils/logger.d.ts +0 -13
- package/lib/Utils/lt-hash.d.ts +0 -14
- package/lib/Utils/make-mutex.d.ts +0 -9
- package/lib/Utils/message-retry-manager.d.ts +0 -88
- package/lib/Utils/messages-media.d.ts +0 -135
- package/lib/Utils/messages.d.ts +0 -105
- package/lib/Utils/noise-handler.d.ts +0 -20
- package/lib/Utils/process-message.d.ts +0 -49
- package/lib/Utils/signal.d.ts +0 -42
- package/lib/Utils/use-mongo-file-auth-state.d.ts +0 -6
- package/lib/Utils/use-mongo-file-auth-state.js +0 -84
- package/lib/Utils/use-multi-file-auth-state.d.ts +0 -13
- package/lib/Utils/use-single-file-auth-state.d.ts +0 -13
- package/lib/Utils/use-single-file-auth-state.js +0 -80
- package/lib/Utils/validate-connection.d.ts +0 -13
- package/lib/WABinary/constants.d.ts +0 -30
- package/lib/WABinary/decode.d.ts +0 -9
- package/lib/WABinary/encode.d.ts +0 -3
- package/lib/WABinary/generic-utils.d.ts +0 -28
- package/lib/WABinary/index.d.ts +0 -5
- package/lib/WABinary/jid-utils.d.ts +0 -58
- package/lib/WABinary/types.d.ts +0 -22
- package/lib/WAM/BinaryInfo.d.ts +0 -16
- package/lib/WAM/constants.d.ts +0 -47
- package/lib/WAM/encode.d.ts +0 -3
- package/lib/WAM/index.d.ts +0 -3
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.d.ts +0 -28
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +0 -10
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +0 -26
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +0 -14
- package/lib/WAUSync/Protocols/USyncLIDProtocol.d.ts +0 -10
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +0 -14
- package/lib/WAUSync/Protocols/index.d.ts +0 -6
- package/lib/WAUSync/USyncQuery.d.ts +0 -31
- package/lib/WAUSync/USyncUser.d.ts +0 -12
- package/lib/WAUSync/index.d.ts +0 -3
- package/lib/index.d.ts +0 -13
package/lib/Utils/messages.js
CHANGED
|
@@ -1,22 +1,42 @@
|
|
|
1
1
|
"use strict"
|
|
2
2
|
|
|
3
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
-
return (mod && mod.__esModule) ? mod : { "default": mod }
|
|
5
|
-
}
|
|
6
|
-
|
|
7
3
|
Object.defineProperty(exports, "__esModule", { value: true })
|
|
8
4
|
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
5
|
+
const { Boom } = require("@hapi/boom")
|
|
6
|
+
const { randomBytes } = require("crypto")
|
|
7
|
+
const { promises } = require("fs")
|
|
8
|
+
const { proto } = require("../../WAProto")
|
|
9
|
+
const {
|
|
10
|
+
URL_REGEX,
|
|
11
|
+
WA_DEFAULT_EPHEMERAL
|
|
12
|
+
} = require("../Defaults/constants")
|
|
13
|
+
const { MEDIA_KEYS } = require("../Defaults/media")
|
|
14
|
+
const {
|
|
15
|
+
WAProto,
|
|
16
|
+
WAMessageStatus
|
|
17
|
+
} = require("../Types")
|
|
18
|
+
const {
|
|
19
|
+
isJidGroup,
|
|
20
|
+
isJidNewsletter,
|
|
21
|
+
isJidStatusBroadcast,
|
|
22
|
+
jidNormalizedUser
|
|
23
|
+
} = require("../WABinary")
|
|
24
|
+
const { sha256 } = require("./crypto")
|
|
25
|
+
const {
|
|
26
|
+
generateMessageID,
|
|
27
|
+
getKeyAuthor,
|
|
28
|
+
unixTimestampSeconds
|
|
29
|
+
} = require("./generics")
|
|
30
|
+
const {
|
|
31
|
+
downloadContentFromMessage,
|
|
32
|
+
encryptedStream,
|
|
33
|
+
generateThumbnail,
|
|
34
|
+
getAudioDuration,
|
|
35
|
+
getAudioWaveform,
|
|
36
|
+
getRawMediaUploadData,
|
|
37
|
+
getStream,
|
|
38
|
+
toBuffer
|
|
39
|
+
} = require("./messages-media")
|
|
20
40
|
|
|
21
41
|
const MIMETYPE_MAP = {
|
|
22
42
|
image: 'image/jpeg',
|
|
@@ -28,11 +48,11 @@ const MIMETYPE_MAP = {
|
|
|
28
48
|
}
|
|
29
49
|
|
|
30
50
|
const MessageTypeProto = {
|
|
31
|
-
'image':
|
|
32
|
-
'video':
|
|
33
|
-
'audio':
|
|
34
|
-
'sticker':
|
|
35
|
-
'document':
|
|
51
|
+
'image': WAProto.Message.ImageMessage,
|
|
52
|
+
'video': WAProto.Message.VideoMessage,
|
|
53
|
+
'audio': WAProto.Message.AudioMessage,
|
|
54
|
+
'sticker': WAProto.Message.StickerMessage,
|
|
55
|
+
'document': WAProto.Message.DocumentMessage
|
|
36
56
|
}
|
|
37
57
|
|
|
38
58
|
/**
|
|
@@ -40,7 +60,7 @@ const MessageTypeProto = {
|
|
|
40
60
|
* @param text eg. hello https://google.com
|
|
41
61
|
* @returns the URL, eg. https://google.com
|
|
42
62
|
*/
|
|
43
|
-
const extractUrlFromText = (text) => text.match(
|
|
63
|
+
const extractUrlFromText = (text) => text.match(URL_REGEX)?.[0]
|
|
44
64
|
|
|
45
65
|
const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
|
|
46
66
|
const url = extractUrlFromText(text)
|
|
@@ -76,66 +96,71 @@ const assertColor = async (color) => {
|
|
|
76
96
|
|
|
77
97
|
const prepareWAMessageMedia = async (message, options) => {
|
|
78
98
|
const logger = options.logger
|
|
99
|
+
|
|
79
100
|
let mediaType
|
|
80
|
-
|
|
81
|
-
for (const key of
|
|
101
|
+
|
|
102
|
+
for (const key of MEDIA_KEYS) {
|
|
82
103
|
if (key in message) {
|
|
83
104
|
mediaType = key
|
|
84
105
|
}
|
|
85
106
|
}
|
|
86
|
-
|
|
107
|
+
|
|
87
108
|
if (!mediaType) {
|
|
88
|
-
throw new
|
|
109
|
+
throw new Boom('Invalid media type', { statusCode: 400 })
|
|
89
110
|
}
|
|
90
|
-
|
|
111
|
+
|
|
91
112
|
const uploadData = {
|
|
92
113
|
...message,
|
|
93
114
|
media: message[mediaType]
|
|
94
115
|
}
|
|
95
|
-
|
|
116
|
+
|
|
96
117
|
delete uploadData[mediaType]
|
|
97
|
-
|
|
118
|
+
|
|
98
119
|
// check if cacheable + generate cache key
|
|
99
120
|
const cacheableKey = typeof uploadData.media === 'object' &&
|
|
100
121
|
'url' in uploadData.media &&
|
|
101
122
|
!!uploadData.media.url &&
|
|
102
123
|
!!options.mediaCache &&
|
|
103
124
|
mediaType + ':' + uploadData.media.url.toString()
|
|
104
|
-
|
|
125
|
+
|
|
105
126
|
if (mediaType === 'document' && !uploadData.fileName) {
|
|
106
127
|
uploadData.fileName = 'file'
|
|
107
128
|
}
|
|
108
|
-
|
|
129
|
+
|
|
109
130
|
if (!uploadData.mimetype) {
|
|
110
131
|
uploadData.mimetype = MIMETYPE_MAP[mediaType]
|
|
111
132
|
}
|
|
112
|
-
|
|
133
|
+
|
|
113
134
|
if (cacheableKey) {
|
|
114
135
|
const mediaBuff = await options.mediaCache.get(cacheableKey)
|
|
136
|
+
|
|
115
137
|
if (mediaBuff) {
|
|
116
138
|
logger?.debug({ cacheableKey }, 'got media cache hit')
|
|
117
|
-
|
|
139
|
+
|
|
140
|
+
const obj = proto.Message.decode(mediaBuff)
|
|
118
141
|
const key = `${mediaType}Message`
|
|
142
|
+
|
|
119
143
|
Object.assign(obj[key], { ...uploadData, media: undefined })
|
|
144
|
+
|
|
120
145
|
return obj
|
|
121
146
|
}
|
|
122
147
|
}
|
|
123
|
-
|
|
124
|
-
const isNewsletter = !!options.jid &&
|
|
125
|
-
|
|
148
|
+
|
|
149
|
+
const isNewsletter = !!options.jid && isJidNewsletter(options.jid)
|
|
150
|
+
|
|
126
151
|
if (isNewsletter) {
|
|
127
152
|
logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter')
|
|
128
|
-
const { filePath, fileSha256, fileLength } = await
|
|
129
|
-
const fileSha256B64 = fileSha256.toString('base64')
|
|
153
|
+
const { filePath, fileSha256, fileLength } = await getRawMediaUploadData(uploadData.media, options.mediaTypeOverride || mediaType, logger)
|
|
154
|
+
const fileSha256B64 = fileSha256.toString('base64');
|
|
130
155
|
const { mediaUrl, directPath } = await options.upload(filePath, {
|
|
131
156
|
fileEncSha256B64: fileSha256B64,
|
|
132
157
|
mediaType: mediaType,
|
|
133
158
|
timeoutMs: options.mediaUploadTimeoutMs
|
|
134
159
|
})
|
|
135
|
-
|
|
136
|
-
await
|
|
137
|
-
|
|
138
|
-
const obj =
|
|
160
|
+
|
|
161
|
+
await promises.unlink(filePath)
|
|
162
|
+
|
|
163
|
+
const obj = WAProto.Message.fromObject({
|
|
139
164
|
// todo: add more support here
|
|
140
165
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
141
166
|
url: mediaUrl,
|
|
@@ -146,34 +171,35 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
146
171
|
media: undefined
|
|
147
172
|
})
|
|
148
173
|
})
|
|
149
|
-
|
|
174
|
+
|
|
150
175
|
if (uploadData.ptv) {
|
|
151
176
|
obj.ptvMessage = obj.videoMessage
|
|
152
177
|
delete obj.videoMessage
|
|
153
178
|
}
|
|
154
|
-
|
|
179
|
+
|
|
180
|
+
if (obj.stickerMessage) {
|
|
181
|
+
obj.stickerMessage.stickerSentTs = Date.now()
|
|
182
|
+
}
|
|
183
|
+
|
|
155
184
|
if (cacheableKey) {
|
|
156
185
|
logger?.debug({ cacheableKey }, 'set cache');
|
|
157
|
-
await options.mediaCache.set(cacheableKey,
|
|
186
|
+
await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish())
|
|
158
187
|
}
|
|
159
|
-
|
|
188
|
+
|
|
160
189
|
return obj
|
|
161
190
|
}
|
|
162
|
-
|
|
191
|
+
|
|
163
192
|
const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined'
|
|
164
193
|
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined'
|
|
165
194
|
const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true
|
|
166
195
|
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true
|
|
167
196
|
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation
|
|
168
|
-
|
|
169
|
-
const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await messages_media_1.encryptedStream(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
197
|
+
const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await encryptedStream(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
170
198
|
logger,
|
|
171
199
|
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
172
200
|
opts: options.options
|
|
173
201
|
})
|
|
174
|
-
|
|
175
202
|
const fileEncSha256B64 = fileEncSha256.toString('base64')
|
|
176
|
-
|
|
177
203
|
const [{ mediaUrl, directPath }] = await Promise.all([
|
|
178
204
|
(async () => {
|
|
179
205
|
const result = await options.upload(encFilePath, {
|
|
@@ -184,32 +210,31 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
184
210
|
logger?.debug({ mediaType, cacheableKey }, 'uploaded media')
|
|
185
211
|
return result
|
|
186
212
|
})(),
|
|
187
|
-
|
|
188
213
|
(async () => {
|
|
189
214
|
try {
|
|
190
215
|
if (requiresThumbnailComputation) {
|
|
191
|
-
const { thumbnail, originalImageDimensions } = await
|
|
216
|
+
const { thumbnail, originalImageDimensions } = await generateThumbnail(originalFilePath, mediaType, options)
|
|
217
|
+
|
|
192
218
|
uploadData.jpegThumbnail = thumbnail
|
|
219
|
+
|
|
193
220
|
if (!uploadData.width && originalImageDimensions) {
|
|
194
221
|
uploadData.width = originalImageDimensions.width
|
|
195
222
|
uploadData.height = originalImageDimensions.height
|
|
196
|
-
|
|
197
223
|
logger?.debug('set dimensions')
|
|
198
224
|
}
|
|
199
|
-
|
|
200
|
-
logger?.debug('generated thumbnail');
|
|
225
|
+
logger?.debug('generated thumbnail')
|
|
201
226
|
}
|
|
202
|
-
|
|
227
|
+
|
|
203
228
|
if (requiresDurationComputation) {
|
|
204
|
-
uploadData.seconds = await
|
|
229
|
+
uploadData.seconds = await getAudioDuration(originalFilePath)
|
|
205
230
|
logger?.debug('computed audio duration')
|
|
206
231
|
}
|
|
207
|
-
|
|
232
|
+
|
|
208
233
|
if (requiresWaveformProcessing) {
|
|
209
|
-
uploadData.waveform = await
|
|
234
|
+
uploadData.waveform = await getAudioWaveform(originalFilePath, logger)
|
|
210
235
|
logger?.debug('processed waveform')
|
|
211
236
|
}
|
|
212
|
-
|
|
237
|
+
|
|
213
238
|
if (requiresAudioBackground) {
|
|
214
239
|
uploadData.backgroundArgb = await assertColor(options.backgroundColor)
|
|
215
240
|
logger?.debug('computed backgroundColor audio status')
|
|
@@ -221,20 +246,20 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
221
246
|
})()
|
|
222
247
|
]).finally(async () => {
|
|
223
248
|
try {
|
|
224
|
-
await
|
|
225
|
-
|
|
249
|
+
await promises.unlink(encFilePath)
|
|
250
|
+
|
|
226
251
|
if (originalFilePath) {
|
|
227
|
-
await
|
|
252
|
+
await promises.unlink(originalFilePath)
|
|
228
253
|
}
|
|
229
|
-
|
|
254
|
+
|
|
230
255
|
logger?.debug('removed tmp files')
|
|
231
256
|
}
|
|
232
257
|
catch (error) {
|
|
233
258
|
logger?.warn('failed to remove tmp file')
|
|
234
259
|
}
|
|
235
260
|
})
|
|
236
|
-
|
|
237
|
-
const obj =
|
|
261
|
+
|
|
262
|
+
const obj = WAProto.Message.fromObject({
|
|
238
263
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
239
264
|
url: mediaUrl,
|
|
240
265
|
directPath,
|
|
@@ -242,88 +267,99 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
242
267
|
fileEncSha256,
|
|
243
268
|
fileSha256,
|
|
244
269
|
fileLength,
|
|
245
|
-
mediaKeyTimestamp:
|
|
270
|
+
mediaKeyTimestamp: unixTimestampSeconds(),
|
|
246
271
|
...uploadData,
|
|
247
272
|
media: undefined
|
|
248
273
|
})
|
|
249
274
|
})
|
|
250
|
-
|
|
275
|
+
|
|
251
276
|
if (uploadData.ptv) {
|
|
252
277
|
obj.ptvMessage = obj.videoMessage
|
|
253
278
|
delete obj.videoMessage
|
|
254
279
|
}
|
|
255
|
-
|
|
280
|
+
|
|
256
281
|
if (cacheableKey) {
|
|
257
|
-
logger?.debug({ cacheableKey }, 'set cache')
|
|
258
|
-
await options.mediaCache.set(cacheableKey,
|
|
282
|
+
logger?.debug({ cacheableKey }, 'set cache')
|
|
283
|
+
await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish())
|
|
259
284
|
}
|
|
260
|
-
|
|
285
|
+
|
|
261
286
|
return obj
|
|
262
287
|
}
|
|
263
288
|
|
|
264
289
|
const prepareAlbumMessageContent = async (jid, albums, options) => {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
for (const i in albums) {
|
|
281
|
-
const media = albums[i]
|
|
282
|
-
|
|
283
|
-
if ('image' in media) {
|
|
284
|
-
mediaMsg = await generateWAMessage(jid, {
|
|
285
|
-
image: media.image,
|
|
286
|
-
...media,
|
|
287
|
-
...options
|
|
288
|
-
}, {
|
|
289
|
-
userJid: options.userJid,
|
|
290
|
-
upload: async (encFilePath, opts) => {
|
|
291
|
-
const up = await options.suki.waUploadToServer(encFilePath, { ...opts, newsletter: WABinary_1.isJidNewsletter(jid) })
|
|
292
|
-
mediaHandle = up.handle
|
|
293
|
-
return up
|
|
294
|
-
},
|
|
295
|
-
...options
|
|
296
|
-
})
|
|
297
|
-
} else if ('video' in message) {
|
|
298
|
-
mediaMsg = await generateWAMessage(jid, {
|
|
299
|
-
video: media.video,
|
|
300
|
-
...media,
|
|
301
|
-
...options
|
|
302
|
-
}, {
|
|
303
|
-
userJid: options.userJid,
|
|
304
|
-
upload: async (encFilePath, opts) => {
|
|
305
|
-
const up = await options.suki.waUploadToServer(encFilePath, { ...opts, newsletter: WABinary_1.isJidNewsletter(jid) })
|
|
306
|
-
mediaHandle = up.handle
|
|
307
|
-
return up
|
|
308
|
-
},
|
|
309
|
-
...options
|
|
310
|
-
})
|
|
311
|
-
}
|
|
290
|
+
if (!Array.isArray(albums)) {
|
|
291
|
+
throw new Error("albums must be an array containing media objects.")
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (albums.length === 0) {
|
|
295
|
+
throw new Error("albums cannot be empty. At least one media item is required.")
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const validCount = albums.filter(m => ('image' in m) || ('video' in m)).length
|
|
299
|
+
|
|
300
|
+
if (validCount === 0) {
|
|
301
|
+
throw new Error("albums contains no valid media. Use 'image' or 'video' keys.")
|
|
302
|
+
}
|
|
312
303
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
messageAssociation: {
|
|
317
|
-
associationType: 1,
|
|
318
|
-
parentMessageKey: albumMsg.key
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
304
|
+
let mediaHandle
|
|
305
|
+
let mediaMsg
|
|
306
|
+
const message = []
|
|
322
307
|
|
|
323
|
-
|
|
308
|
+
const albumMsg = generateWAMessageFromContent(jid, {
|
|
309
|
+
albumMessage: {
|
|
310
|
+
expectedImageCount: albums.filter(item => 'image' in item).length,
|
|
311
|
+
expectedVideoCount: albums.filter(item => 'video' in item).length
|
|
324
312
|
}
|
|
313
|
+
}, options)
|
|
325
314
|
|
|
326
|
-
|
|
315
|
+
await options.suki.relayMessage(jid, albumMsg.message, {
|
|
316
|
+
messageId: albumMsg.key.id
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
for (const media of albums) {
|
|
320
|
+
let content = {}
|
|
321
|
+
if ('image' in media) {
|
|
322
|
+
content = { image: media.image }
|
|
323
|
+
} else if ('video' in media) {
|
|
324
|
+
content = { video: media.video }
|
|
325
|
+
} else {
|
|
326
|
+
continue
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
mediaMsg = await generateWAMessage(
|
|
330
|
+
jid,
|
|
331
|
+
{
|
|
332
|
+
...content,
|
|
333
|
+
...media
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
userJid: options.userJid,
|
|
337
|
+
upload: async (encFilePath, opts) => {
|
|
338
|
+
const up = await options.suki.waUploadToServer(
|
|
339
|
+
encFilePath,
|
|
340
|
+
{ ...opts, newsletter: isJidNewsletter(jid) }
|
|
341
|
+
)
|
|
342
|
+
mediaHandle = up.handle
|
|
343
|
+
return up
|
|
344
|
+
},
|
|
345
|
+
...options
|
|
346
|
+
}
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
if (mediaMsg) {
|
|
350
|
+
mediaMsg.message.messageContextInfo = {
|
|
351
|
+
messageSecret: randomBytes(32),
|
|
352
|
+
messageAssociation: {
|
|
353
|
+
associationType: proto.MessageAssociation.AssociationType.MEDIA_ALBUM,
|
|
354
|
+
parentMessageKey: albumMsg.key
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
message.push(mediaMsg)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return message
|
|
327
363
|
}
|
|
328
364
|
|
|
329
365
|
const prepareDisappearingMessageSettingContent = (expiration) => {
|
|
@@ -331,14 +367,14 @@ const prepareDisappearingMessageSettingContent = (expiration) => {
|
|
|
331
367
|
ephemeralMessage: {
|
|
332
368
|
message: {
|
|
333
369
|
protocolMessage: {
|
|
334
|
-
type:
|
|
370
|
+
type: WAProto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
|
|
335
371
|
ephemeralExpiration: expiration ? expiration : 0
|
|
336
372
|
}
|
|
337
373
|
}
|
|
338
374
|
}
|
|
339
375
|
}
|
|
340
376
|
|
|
341
|
-
return
|
|
377
|
+
return WAProto.Message.fromObject(content)
|
|
342
378
|
}
|
|
343
379
|
|
|
344
380
|
/**
|
|
@@ -350,12 +386,12 @@ const generateForwardMessageContent = (message, forceForward) => {
|
|
|
350
386
|
let content = message.message
|
|
351
387
|
|
|
352
388
|
if (!content) {
|
|
353
|
-
throw new
|
|
389
|
+
throw new Boom('no content in message', { statusCode: 400 })
|
|
354
390
|
}
|
|
355
391
|
|
|
356
392
|
// hacky copy
|
|
357
393
|
content = normalizeMessageContent(content)
|
|
358
|
-
content =
|
|
394
|
+
content = proto.Message.decode(proto.Message.encode(content).finish())
|
|
359
395
|
|
|
360
396
|
let key = Object.keys(content)[0]
|
|
361
397
|
let score = content[key].contextInfo?.forwardingScore || 0
|
|
@@ -379,883 +415,920 @@ const generateForwardMessageContent = (message, forceForward) => {
|
|
|
379
415
|
return content
|
|
380
416
|
}
|
|
381
417
|
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
if (urlInfo) {
|
|
393
|
-
extContent.canonicalUrl = urlInfo['canonical-url']
|
|
394
|
-
extContent.matchedText = urlInfo['matched-text']
|
|
395
|
-
extContent.jpegThumbnail = urlInfo.jpegThumbnail
|
|
396
|
-
extContent.description = urlInfo.description
|
|
397
|
-
extContent.title = urlInfo.title
|
|
398
|
-
extContent.previewType = 0
|
|
399
|
-
const img = urlInfo.highQualityThumbnail
|
|
400
|
-
|
|
401
|
-
if (img) {
|
|
402
|
-
extContent.thumbnailDirectPath = img.directPath
|
|
403
|
-
extContent.mediaKey = img.mediaKey
|
|
404
|
-
extContent.mediaKeyTimestamp = img.mediaKeyTimestamp
|
|
405
|
-
extContent.thumbnailWidth = img.width
|
|
406
|
-
extContent.thumbnailHeight = img.height
|
|
407
|
-
extContent.thumbnailSha256 = img.fileSha256
|
|
408
|
-
extContent.thumbnailEncSha256 = img.fileEncSha256
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
if (options.backgroundColor) {
|
|
413
|
-
extContent.backgroundArgb = await assertColor(options.backgroundColor)
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (options.textColor) {
|
|
417
|
-
extContent.textArgb = await assertColor(options.textColor)
|
|
418
|
-
}
|
|
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
|
+
}
|
|
419
427
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
428
|
+
function hasOptionalProperty(obj, key) {
|
|
429
|
+
return (
|
|
430
|
+
typeof obj === 'object' &&
|
|
431
|
+
obj !== null &&
|
|
432
|
+
key in obj &&
|
|
433
|
+
obj[key] !== null
|
|
434
|
+
)
|
|
435
|
+
}
|
|
423
436
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
437
|
+
const generateWAMessageContent = async (message, options) => {
|
|
438
|
+
const hasMedia = [
|
|
439
|
+
"image",
|
|
440
|
+
"video",
|
|
441
|
+
"audio",
|
|
442
|
+
"sticker",
|
|
443
|
+
"document",
|
|
444
|
+
].some((key) => hasNonNullishProperty(message, key))
|
|
428
445
|
|
|
429
|
-
|
|
430
|
-
}
|
|
446
|
+
let m = {}
|
|
431
447
|
|
|
432
|
-
|
|
448
|
+
if (hasNonNullishProperty(message, "contacts")) {
|
|
433
449
|
const contactLen = message.contacts.contacts.length
|
|
434
450
|
|
|
435
451
|
let contactMessage
|
|
436
452
|
|
|
437
453
|
if (!contactLen) {
|
|
438
|
-
throw new
|
|
454
|
+
throw new Boom("require atleast 1 contact", { statusCode: 400 })
|
|
439
455
|
}
|
|
440
456
|
|
|
441
457
|
if (contactLen === 1) {
|
|
442
458
|
contactMessage = {
|
|
443
|
-
|
|
459
|
+
contactMessage: WAProto.Message.ContactMessage.fromObject(
|
|
460
|
+
message.contacts.contacts[0]
|
|
461
|
+
),
|
|
444
462
|
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
else {
|
|
463
|
+
} else {
|
|
448
464
|
contactMessage = {
|
|
449
|
-
|
|
465
|
+
contactsArrayMessage: WAProto.Message.ContactsArrayMessage.fromObject(
|
|
466
|
+
message.contacts
|
|
467
|
+
),
|
|
450
468
|
}
|
|
451
469
|
}
|
|
452
470
|
|
|
453
|
-
const [type] = Object.keys(contactMessage)
|
|
454
|
-
|
|
455
|
-
contactMessage[type].contextInfo = {
|
|
456
|
-
...(message.contextInfo || {}),
|
|
457
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
458
|
-
}
|
|
459
|
-
|
|
460
471
|
m = contactMessage
|
|
461
|
-
}
|
|
472
|
+
} else if (hasNonNullishProperty(message, "contacts")) {
|
|
473
|
+
const contactLen = message.contacts.contacts.length
|
|
462
474
|
|
|
463
|
-
|
|
464
|
-
let locationMessage
|
|
475
|
+
let contactMessage
|
|
465
476
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
liveLocationMessage: Types_1.WAProto.Message.LiveLocationMessage.fromObject(message.location)
|
|
469
|
-
}
|
|
477
|
+
if (!contactLen) {
|
|
478
|
+
throw new Boom("require atleast 1 contact", { statusCode: 400 })
|
|
470
479
|
}
|
|
471
480
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
481
|
+
if (contactLen === 1) {
|
|
482
|
+
contactMessage = {
|
|
483
|
+
contactMessage: WAProto.Message.ContactMessage.fromObject(
|
|
484
|
+
message.contacts.contacts[0]
|
|
485
|
+
),
|
|
486
|
+
}
|
|
487
|
+
} else {
|
|
488
|
+
contactMessage = {
|
|
489
|
+
contactsArrayMessage: WAProto.Message.ContactsArrayMessage.fromObject(
|
|
490
|
+
message.contacts
|
|
491
|
+
),
|
|
475
492
|
}
|
|
476
493
|
}
|
|
477
494
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
locationMessage
|
|
481
|
-
|
|
482
|
-
|
|
495
|
+
m = contactMessage
|
|
496
|
+
} else if (hasNonNullishProperty(message, "location")) {
|
|
497
|
+
let locationMessage
|
|
498
|
+
|
|
499
|
+
if (message.live) {
|
|
500
|
+
locationMessage = {
|
|
501
|
+
liveLocationMessage: WAProto.Message.LiveLocationMessage.fromObject(
|
|
502
|
+
message.location
|
|
503
|
+
),
|
|
504
|
+
}
|
|
505
|
+
} else {
|
|
506
|
+
locationMessage = {
|
|
507
|
+
locationMessage: WAProto.Message.LocationMessage.fromObject(
|
|
508
|
+
message.location
|
|
509
|
+
),
|
|
510
|
+
}
|
|
483
511
|
}
|
|
484
512
|
|
|
485
513
|
m = locationMessage
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
else if ('react' in message) {
|
|
514
|
+
} else if (hasNonNullishProperty(message, "react")) {
|
|
489
515
|
if (!message.react.senderTimestampMs) {
|
|
490
516
|
message.react.senderTimestampMs = Date.now()
|
|
491
517
|
}
|
|
492
518
|
|
|
493
|
-
m.reactionMessage =
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
else if (
|
|
519
|
+
m.reactionMessage = WAProto.Message.ReactionMessage.fromObject(
|
|
520
|
+
message.react
|
|
521
|
+
)
|
|
522
|
+
} else if (hasNonNullishProperty(message, "delete")) {
|
|
497
523
|
m.protocolMessage = {
|
|
498
524
|
key: message.delete,
|
|
499
|
-
type:
|
|
525
|
+
type: WAProto.Message.ProtocolMessage.Type.REVOKE,
|
|
500
526
|
}
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const mess = generateForwardMessageContent(message.forward, message.force)
|
|
505
|
-
const [type] = Object.keys(mess)
|
|
506
|
-
|
|
507
|
-
mess[type].contextInfo = {
|
|
508
|
-
...(message.contextInfo || {}),
|
|
509
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
527
|
+
} else if (hasNonNullishProperty(message, "sharePhoneNumber")) {
|
|
528
|
+
m.protocolMessage = {
|
|
529
|
+
type: WAProto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER,
|
|
510
530
|
}
|
|
511
|
-
|
|
512
|
-
m =
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
else if (
|
|
516
|
-
const exp =
|
|
517
|
-
|
|
518
|
-
|
|
531
|
+
} else if (hasNonNullishProperty(message, "requestPhoneNumber")) {
|
|
532
|
+
m.requestPhoneNumberMessage = {}
|
|
533
|
+
} else if (hasNonNullishProperty(message, "forward")) {
|
|
534
|
+
m = generateForwardMessageContent(message.forward, message.force)
|
|
535
|
+
} else if (hasNonNullishProperty(message, "disappearingMessagesInChat")) {
|
|
536
|
+
const exp =
|
|
537
|
+
typeof message.disappearingMessagesInChat === "boolean"
|
|
538
|
+
? message.disappearingMessagesInChat
|
|
539
|
+
? WA_DEFAULT_EPHEMERAL
|
|
540
|
+
: 0
|
|
541
|
+
: message.disappearingMessagesInChat
|
|
519
542
|
m = prepareDisappearingMessageSettingContent(exp)
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
else if ('groupInvite' in message) {
|
|
523
|
-
m.groupInviteMessage = {}
|
|
543
|
+
} else if (hasNonNullishProperty(message, "groupInvite")) {
|
|
544
|
+
m.groupInviteMessage = {}
|
|
524
545
|
|
|
525
546
|
m.groupInviteMessage.inviteCode = message.groupInvite.code
|
|
526
547
|
m.groupInviteMessage.inviteExpiration = message.groupInvite.expiration
|
|
527
548
|
m.groupInviteMessage.caption = message.groupInvite.caption
|
|
528
549
|
m.groupInviteMessage.groupJid = message.groupInvite.jid
|
|
529
|
-
m.groupInviteMessage.groupName = message.groupInvite.name
|
|
530
|
-
m.groupInviteMessage.contextInfo = message.contextInfo
|
|
550
|
+
m.groupInviteMessage.groupName = message.groupInvite.name
|
|
551
|
+
m.groupInviteMessage.contextInfo = message.contextInfo
|
|
531
552
|
|
|
532
553
|
if (options.getProfilePicUrl) {
|
|
533
|
-
const pfpUrl = await options.getProfilePicUrl(
|
|
534
|
-
|
|
554
|
+
const pfpUrl = await options.getProfilePicUrl(
|
|
555
|
+
message.groupInvite.jid
|
|
556
|
+
)
|
|
557
|
+
const { thumbnail } = await generateThumbnail(pfpUrl, "image")
|
|
535
558
|
m.groupInviteMessage.jpegThumbnail = thumbnail
|
|
536
559
|
}
|
|
537
|
-
|
|
538
|
-
m.
|
|
539
|
-
...(message.contextInfo || {}),
|
|
540
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
else if ('adminInvite' in message) {
|
|
545
|
-
m.newsletterAdminInviteMessage = {}
|
|
560
|
+
} else if (hasNonNullishProperty(message, "adminInvite")) {
|
|
561
|
+
m.newsletterAdminInviteMessage = {}
|
|
546
562
|
|
|
547
563
|
m.newsletterAdminInviteMessage.newsletterJid = message.adminInvite.jid
|
|
548
|
-
m.newsletterAdminInviteMessage.newsletterName=
|
|
564
|
+
m.newsletterAdminInviteMessage.newsletterName =
|
|
565
|
+
message.adminInvite.name
|
|
549
566
|
m.newsletterAdminInviteMessage.caption = message.adminInvite.caption
|
|
550
|
-
m.newsletterAdminInviteMessage.inviteExpiration =
|
|
551
|
-
|
|
567
|
+
m.newsletterAdminInviteMessage.inviteExpiration =
|
|
568
|
+
message.adminInvite.expiration
|
|
569
|
+
m.newsletterAdminInviteMessage.contextInfo = message.contextInfo
|
|
552
570
|
|
|
553
571
|
if (options.getProfilePicUrl) {
|
|
554
|
-
const pfpUrl = await options.getProfilePicUrl(
|
|
555
|
-
|
|
572
|
+
const pfpUrl = await options.getProfilePicUrl(
|
|
573
|
+
message.adminInvite.jid
|
|
574
|
+
)
|
|
575
|
+
const { thumbnail } = await generateThumbnail(pfpUrl, "image")
|
|
556
576
|
m.newsletterAdminInviteMessage.jpegThumbnail = thumbnail
|
|
557
577
|
}
|
|
558
|
-
|
|
559
|
-
m.newsletterAdminInviteMessage.contextInfo = {
|
|
560
|
-
...(message.contextInfo || {}),
|
|
561
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
else if ('pin' in message) {
|
|
566
|
-
m.pinInChatMessage = {}
|
|
567
|
-
m.messageContextInfo = {}
|
|
568
|
-
|
|
569
|
-
m.pinInChatMessage.key = message.pin.key
|
|
570
|
-
m.pinInChatMessage.type = message.pin?.type || 1
|
|
571
|
-
m.pinInChatMessage.senderTimestampMs = message.pin?.time || Date.now()
|
|
572
|
-
m.messageContextInfo.messageAddOnDurationInSecs = message.pin.type === 1 ? message.pin.time || 86400 : 0
|
|
573
|
-
m.messageContextInfo.messageAddOnExpiryType = WAProto_1.proto.MessageContextInfo.MessageAddonExpiryType.STATIC
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
else if ('keep' in message) {
|
|
578
|
+
} else if (hasNonNullishProperty(message, "keep")) {
|
|
577
579
|
m.keepInChatMessage = {}
|
|
578
580
|
|
|
579
581
|
m.keepInChatMessage.key = message.keep.key
|
|
580
582
|
m.keepInChatMessage.keepType = message.keep?.type || 1
|
|
581
583
|
m.keepInChatMessage.timestampMs = message.keep?.time || Date.now()
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
else if ('call' in message) {
|
|
584
|
+
} else if (hasNonNullishProperty(message, "call")) {
|
|
585
585
|
m.scheduledCallCreationMessage = {}
|
|
586
586
|
|
|
587
|
-
m.scheduledCallCreationMessage.scheduledTimestampMs =
|
|
587
|
+
m.scheduledCallCreationMessage.scheduledTimestampMs =
|
|
588
|
+
message.call?.time || Date.now()
|
|
588
589
|
m.scheduledCallCreationMessage.callType = message.call?.type || 1
|
|
589
|
-
m.scheduledCallCreationMessage.title =
|
|
590
|
+
m.scheduledCallCreationMessage.title =
|
|
591
|
+
message.call?.name || "Call Creation"
|
|
592
|
+
} else if (hasNonNullishProperty(message, "paymentInvite")) {
|
|
593
|
+
m.messageContextInfo = {}
|
|
594
|
+
m.paymentInviteMessage = {}
|
|
595
|
+
|
|
596
|
+
m.paymentInviteMessage.expiryTimestamp =
|
|
597
|
+
message.paymentInvite?.expiry || 0
|
|
598
|
+
m.paymentInviteMessage.serviceType = message.paymentInvite?.type || 2
|
|
599
|
+
} else if (hasNonNullishProperty(message, "ptv")) {
|
|
600
|
+
const { videoMessage } = await prepareWAMessageMedia(
|
|
601
|
+
{ video: message.video },
|
|
602
|
+
options
|
|
603
|
+
)
|
|
604
|
+
|
|
605
|
+
m.ptvMessage = videoMessage
|
|
606
|
+
} else if (hasNonNullishProperty(message, "order")) {
|
|
607
|
+
m.orderMessage = WAProto.Message.OrderMessage.fromObject(message.order)
|
|
608
|
+
} else if (hasNonNullishProperty(message, "product")) {
|
|
609
|
+
const { imageMessage } = await prepareWAMessageMedia(
|
|
610
|
+
{ image: message.product.productImage },
|
|
611
|
+
options
|
|
612
|
+
)
|
|
613
|
+
|
|
614
|
+
m.productMessage = WAProto.Message.ProductMessage.fromObject({
|
|
615
|
+
...message,
|
|
616
|
+
product: {
|
|
617
|
+
...message.product,
|
|
618
|
+
productImage: imageMessage,
|
|
619
|
+
},
|
|
620
|
+
})
|
|
621
|
+
} else if (hasNonNullishProperty(message, "album")) {
|
|
622
|
+
const imageMessages = message.album.filter((item) => "image" in item)
|
|
623
|
+
const videoMessages = message.album.filter((item) => "video" in item)
|
|
590
624
|
|
|
591
|
-
m.
|
|
592
|
-
|
|
593
|
-
|
|
625
|
+
m.albumMessage = WAProto.Message.AlbumMessage.fromObject({
|
|
626
|
+
expectedImageCount: imageMessages.length,
|
|
627
|
+
expectedVideoCount: videoMessages.length,
|
|
628
|
+
})
|
|
629
|
+
} else if (hasNonNullishProperty(message, "event")) {
|
|
630
|
+
m.eventMessage = WAProto.Message.EventMessage.fromObject(message.event)
|
|
631
|
+
|
|
632
|
+
if (!message.event.startTime) {
|
|
633
|
+
m.eventMessage.startTime = unixTimestampSeconds() + 86400
|
|
594
634
|
}
|
|
595
|
-
}
|
|
596
635
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
636
|
+
if (options.getCallLink && message.event.call) {
|
|
637
|
+
const link = await options.getCallLink(
|
|
638
|
+
message.event.call,
|
|
639
|
+
m.eventMessage.startTime
|
|
640
|
+
)
|
|
641
|
+
m.eventMessage.joinLink = link
|
|
642
|
+
}
|
|
643
|
+
} else if (hasNonNullishProperty(message, "pollResult")) {
|
|
644
|
+
if (!Array.isArray(message.pollResult.values)) {
|
|
645
|
+
throw new Boom("Invalid pollResult values", { statusCode: 400 })
|
|
646
|
+
}
|
|
600
647
|
|
|
601
|
-
|
|
602
|
-
|
|
648
|
+
const pollResultSnapshotMessage = {
|
|
649
|
+
name: message.pollResult.name,
|
|
650
|
+
pollVotes: message.pollResult.values.map(
|
|
651
|
+
([optionName, optionVoteCount]) => ({
|
|
652
|
+
optionName,
|
|
653
|
+
optionVoteCount,
|
|
654
|
+
})
|
|
655
|
+
),
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
m.pollResultSnapshotMessage = pollResultSnapshotMessage
|
|
659
|
+
} else if (hasNonNullishProperty(message, "poll")) {
|
|
660
|
+
if (!Array.isArray(message.poll.values)) {
|
|
661
|
+
throw new Boom("Invalid poll values", { statusCode: 400 })
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
if (
|
|
665
|
+
message.poll.selectableCount < 0 ||
|
|
666
|
+
message.poll.selectableCount > message.poll.values.length
|
|
667
|
+
) {
|
|
668
|
+
throw new Boom(
|
|
669
|
+
`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`,
|
|
670
|
+
{ statusCode: 400 }
|
|
671
|
+
)
|
|
672
|
+
}
|
|
603
673
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
674
|
+
const pollCreationMessage = {
|
|
675
|
+
name: message.poll.name,
|
|
676
|
+
selectableOptionsCount: message.poll?.selectableCount || 0,
|
|
677
|
+
options: message.poll.values.map((optionName) => ({ optionName })),
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
if (message.poll?.toAnnouncementGroup) {
|
|
681
|
+
m.pollCreationMessageV2 = pollCreationMessage
|
|
682
|
+
} else {
|
|
683
|
+
if (message.poll.selectableCount > 0) {
|
|
684
|
+
m.pollCreationMessageV3 = pollCreationMessage
|
|
685
|
+
} else {
|
|
686
|
+
m.pollCreationMessage = pollCreationMessage
|
|
687
|
+
}
|
|
607
688
|
}
|
|
608
|
-
|
|
689
|
+
} else if (hasNonNullishProperty(message, "payment")) {
|
|
690
|
+
const requestPaymentMessage = {
|
|
691
|
+
amount: {
|
|
692
|
+
currencyCode: message.payment?.currency || "IDR",
|
|
693
|
+
offset: message.payment?.offset || 0,
|
|
694
|
+
value: message.payment?.amount || 999999999,
|
|
695
|
+
},
|
|
696
|
+
expiryTimestamp: message.payment?.expiry || 0,
|
|
697
|
+
amount1000: message.payment?.amount || 999999999 * 1000,
|
|
698
|
+
currencyCodeIso4217: message.payment?.currency || "IDR",
|
|
699
|
+
requestFrom: message.payment?.from || "0@s.whatsapp.net",
|
|
700
|
+
noteMessage: {
|
|
701
|
+
extendedTextMessage: {
|
|
702
|
+
text: message.payment?.note || "Notes",
|
|
703
|
+
},
|
|
704
|
+
},
|
|
705
|
+
background: {
|
|
706
|
+
placeholderArgb:
|
|
707
|
+
message.payment?.image?.placeholderArgb || 4278190080,
|
|
708
|
+
textArgb: message.payment?.image?.textArgb || 4294967295,
|
|
709
|
+
subtextArgb: message.payment?.image?.subtextArgb || 4294967295,
|
|
710
|
+
type: 1,
|
|
711
|
+
},
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
m.requestPaymentMessage = requestPaymentMessage
|
|
715
|
+
} else if (hasNonNullishProperty(message, "stickerPack")) {
|
|
716
|
+
const {
|
|
717
|
+
stickers,
|
|
718
|
+
cover,
|
|
719
|
+
name,
|
|
720
|
+
publisher,
|
|
721
|
+
packId,
|
|
722
|
+
description,
|
|
723
|
+
} = message.stickerPack
|
|
724
|
+
|
|
725
|
+
const { zip } = require("fflate")
|
|
726
|
+
|
|
727
|
+
const stickerData = {}
|
|
728
|
+
const stickerPromises = stickers.map(async (s, i) => {
|
|
729
|
+
const { stream } = await getStream(s.sticker)
|
|
730
|
+
const buffer = await toBuffer(stream)
|
|
731
|
+
const hash = sha256(buffer).toString("base64url")
|
|
732
|
+
const fileName = `${i.toString().padStart(2, "0")}_${hash}.webp`
|
|
733
|
+
|
|
734
|
+
stickerData[fileName] = [new Uint8Array(buffer), { level: 0 }]
|
|
735
|
+
|
|
736
|
+
return {
|
|
737
|
+
fileName,
|
|
738
|
+
mimetype: "image/webp",
|
|
739
|
+
isAnimated: s.isAnimated || false,
|
|
740
|
+
isLottie: s.isLottie || false,
|
|
741
|
+
emojis: s.emojis || [],
|
|
742
|
+
accessibilityLabel: s.accessibilityLabel || "",
|
|
743
|
+
}
|
|
744
|
+
})
|
|
745
|
+
|
|
746
|
+
const stickerMetadata = await Promise.all(stickerPromises)
|
|
747
|
+
|
|
748
|
+
const zipBuffer = await new Promise((resolve, reject) => {
|
|
749
|
+
zip(stickerData, (err, data) => {
|
|
750
|
+
if (err) {
|
|
751
|
+
reject(err)
|
|
752
|
+
} else {
|
|
753
|
+
resolve(Buffer.from(data))
|
|
754
|
+
}
|
|
755
|
+
})
|
|
756
|
+
})
|
|
609
757
|
|
|
610
|
-
|
|
758
|
+
const coverBuffer = await toBuffer((await getStream(cover)).stream)
|
|
759
|
+
|
|
760
|
+
const [stickerPackUpload, coverUpload] = await Promise.all([
|
|
761
|
+
encryptedStream(zipBuffer, "sticker-pack", {
|
|
762
|
+
logger: options.logger,
|
|
763
|
+
opts: options.options,
|
|
764
|
+
}),
|
|
765
|
+
prepareWAMessageMedia(
|
|
766
|
+
{ image: coverBuffer },
|
|
767
|
+
{ ...options, mediaTypeOverride: "image" }
|
|
768
|
+
),
|
|
769
|
+
])
|
|
770
|
+
|
|
771
|
+
const stickerPackUploadResult = await options.upload(
|
|
772
|
+
stickerPackUpload.encFilePath,
|
|
773
|
+
{
|
|
774
|
+
fileEncSha256B64: stickerPackUpload.fileEncSha256.toString(
|
|
775
|
+
"base64"
|
|
776
|
+
),
|
|
777
|
+
mediaType: "sticker-pack",
|
|
778
|
+
timeoutMs: options.mediaUploadTimeoutMs,
|
|
779
|
+
}
|
|
780
|
+
)
|
|
781
|
+
|
|
782
|
+
const coverImage = coverUpload.imageMessage
|
|
783
|
+
const imageDataHash = sha256(coverBuffer).toString("base64")
|
|
784
|
+
const stickerPackId = packId || generateMessageID()
|
|
785
|
+
|
|
786
|
+
m.stickerPackMessage = {
|
|
787
|
+
name,
|
|
788
|
+
publisher,
|
|
789
|
+
stickerPackId,
|
|
790
|
+
packDescription: description,
|
|
791
|
+
stickerPackOrigin:
|
|
792
|
+
proto.Message.StickerPackMessage.StickerPackOrigin.THIRD_PARTY,
|
|
793
|
+
stickerPackSize: stickerPackUpload.fileLength,
|
|
794
|
+
stickers: stickerMetadata,
|
|
795
|
+
fileSha256: stickerPackUpload.fileSha256,
|
|
796
|
+
fileEncSha256: stickerPackUpload.fileEncSha256,
|
|
797
|
+
mediaKey: stickerPackUpload.mediaKey,
|
|
798
|
+
directPath: stickerPackUploadResult.directPath,
|
|
799
|
+
fileLength: stickerPackUpload.fileLength,
|
|
800
|
+
mediaKeyTimestamp: unixTimestampSeconds(),
|
|
801
|
+
trayIconFileName: `${stickerPackId}.png`,
|
|
802
|
+
imageDataHash,
|
|
803
|
+
thumbnailDirectPath: coverImage.directPath,
|
|
804
|
+
thumbnailFileSha256: coverImage.fileSha256,
|
|
805
|
+
thumbnailFileEncSha256: coverImage.fileEncSha256,
|
|
806
|
+
thumbnailHeight: coverImage.height,
|
|
807
|
+
thumbnailWidth: coverImage.width,
|
|
808
|
+
}
|
|
809
|
+
} else if (hasNonNullishProperty(message, "buttonReply")) {
|
|
611
810
|
switch (message.type) {
|
|
612
|
-
|
|
811
|
+
case "list":
|
|
613
812
|
m.listResponseMessage = {
|
|
614
813
|
title: message.buttonReply.title,
|
|
615
814
|
description: message.buttonReply.description,
|
|
616
815
|
singleSelectReply: {
|
|
617
|
-
|
|
618
|
-
},
|
|
619
|
-
lisType:
|
|
816
|
+
selectedRowId: message.buttonReply.rowId,
|
|
817
|
+
},
|
|
818
|
+
lisType:
|
|
819
|
+
proto.Message.ListResponseMessage.ListType
|
|
820
|
+
.SINGLE_SELECT,
|
|
620
821
|
}
|
|
621
822
|
break
|
|
622
|
-
case
|
|
823
|
+
case "template":
|
|
623
824
|
m.templateButtonReplyMessage = {
|
|
624
825
|
selectedDisplayText: message.buttonReply.displayText,
|
|
625
826
|
selectedId: message.buttonReply.id,
|
|
626
|
-
selectedIndex: message.buttonReply.index
|
|
827
|
+
selectedIndex: message.buttonReply.index,
|
|
627
828
|
}
|
|
628
829
|
break
|
|
629
|
-
case
|
|
830
|
+
case "plain":
|
|
630
831
|
m.buttonsResponseMessage = {
|
|
631
832
|
selectedButtonId: message.buttonReply.id,
|
|
632
833
|
selectedDisplayText: message.buttonReply.displayText,
|
|
633
|
-
type:
|
|
834
|
+
type:
|
|
835
|
+
proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT,
|
|
634
836
|
}
|
|
635
837
|
break
|
|
636
|
-
case
|
|
838
|
+
case "interactive":
|
|
637
839
|
m.interactiveResponseMessage = {
|
|
638
840
|
body: {
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
841
|
+
text: message.buttonReply.displayText,
|
|
842
|
+
format:
|
|
843
|
+
proto.Message.InteractiveResponseMessage.Body.Format
|
|
844
|
+
.EXTENSIONS_1,
|
|
845
|
+
},
|
|
642
846
|
nativeFlowResponseMessage: {
|
|
643
|
-
|
|
644
|
-
paramsJson: message.buttonReply.nativeFlows.paramsJson,
|
|
645
|
-
version: message.buttonReply.nativeFlows.version
|
|
646
|
-
}
|
|
847
|
+
name: message.buttonReply.nativeFlows.name,
|
|
848
|
+
paramsJson: message.buttonReply.nativeFlows.paramsJson,
|
|
849
|
+
version: message.buttonReply.nativeFlows.version,
|
|
850
|
+
},
|
|
647
851
|
}
|
|
648
|
-
break
|
|
852
|
+
break
|
|
853
|
+
}
|
|
854
|
+
} else if (hasNonNullishProperty(message, "sections")) {
|
|
855
|
+
m.listMessage = {
|
|
856
|
+
title: message.title,
|
|
857
|
+
buttonText: message.buttonText,
|
|
858
|
+
footerText: message.footer,
|
|
859
|
+
description: message.text,
|
|
860
|
+
sections: message.sections,
|
|
861
|
+
listType: proto.Message.ListMessage.ListType.SINGLE_SELECT,
|
|
862
|
+
}
|
|
863
|
+
} else if (hasNonNullishProperty(message, "productList")) {
|
|
864
|
+
const thumbnail = message.thumbnail
|
|
865
|
+
? await generateThumbnail(message.thumbnail, "image")
|
|
866
|
+
: null
|
|
867
|
+
|
|
868
|
+
m.listMessage = {
|
|
869
|
+
title: message.title,
|
|
870
|
+
buttonText: message.buttonText,
|
|
871
|
+
footerText: message.footer,
|
|
872
|
+
description: message.text,
|
|
873
|
+
productListInfo: {
|
|
874
|
+
productSections: message.productList,
|
|
875
|
+
headerImage: {
|
|
876
|
+
productId: message.productList[0].products[0].productId,
|
|
877
|
+
jpegThumbnail: thumbnail?.thumbnail || null,
|
|
878
|
+
},
|
|
879
|
+
businessOwnerJid: message.businessOwnerJid,
|
|
880
|
+
},
|
|
881
|
+
listType: proto.Message.ListMessage.ListType.PRODUCT_LIST,
|
|
882
|
+
}
|
|
883
|
+
} else if (hasNonNullishProperty(message, "buttons")) {
|
|
884
|
+
const buttonsMessage = {
|
|
885
|
+
buttons: message.buttons.map((b) => ({
|
|
886
|
+
...b,
|
|
887
|
+
type: proto.Message.ButtonsMessage.Button.Type.RESPONSE,
|
|
888
|
+
})),
|
|
649
889
|
}
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
else if ('ptv' in message && message.ptv) {
|
|
653
|
-
const { videoMessage } = await prepareWAMessageMedia({ video: message.video }, options)
|
|
654
|
-
|
|
655
|
-
m.ptvMessage = videoMessage
|
|
656
|
-
}
|
|
657
890
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
891
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
892
|
+
buttonsMessage.contentText = message.text
|
|
893
|
+
buttonsMessage.headerType =
|
|
894
|
+
proto.Message.ButtonsMessage.HeaderType.EMPTY
|
|
895
|
+
} else {
|
|
896
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
897
|
+
buttonsMessage.contentText = message.caption
|
|
898
|
+
}
|
|
661
899
|
|
|
662
|
-
|
|
663
|
-
expectedImageCount: imageMessages.length,
|
|
664
|
-
expectedVideoCount: videoMessages.length
|
|
665
|
-
})
|
|
666
|
-
}
|
|
900
|
+
const type = Object.keys(m)[0].replace("Message", "").toUpperCase()
|
|
667
901
|
|
|
668
|
-
|
|
669
|
-
|
|
902
|
+
buttonsMessage.headerType =
|
|
903
|
+
proto.Message.ButtonsMessage.HeaderType[type]
|
|
670
904
|
|
|
671
|
-
|
|
672
|
-
...(message.contextInfo || {}),
|
|
673
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
905
|
+
Object.assign(buttonsMessage, m)
|
|
674
906
|
}
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
else if ('event' in message) {
|
|
678
|
-
m.eventMessage = Types_1.WAProto.Message.EventMessage.fromObject(message.event)
|
|
679
|
-
|
|
680
|
-
if (!message.event.startTime) {
|
|
681
|
-
m.eventMessage.startTime = generics_1.unixTimestampSeconds() + 86400
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
if (options.getCallLink && message.event.call) {
|
|
685
|
-
const link = await options.getCallLink(message.event.call, m.eventMessage.startTime)
|
|
686
|
-
m.eventMessage.joinLink = link
|
|
687
|
-
}
|
|
688
907
|
|
|
908
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
909
|
+
buttonsMessage.text = message.title
|
|
910
|
+
buttonsMessage.headerType =
|
|
911
|
+
proto.Message.ButtonsMessage.HeaderType.TEXT
|
|
912
|
+
}
|
|
689
913
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
914
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
915
|
+
buttonsMessage.footerText = message.footer
|
|
693
916
|
}
|
|
694
|
-
}
|
|
695
917
|
|
|
696
|
-
|
|
697
|
-
|
|
918
|
+
m = { buttonsMessage }
|
|
919
|
+
} else if (hasNonNullishProperty(message, "templateButtons")) {
|
|
920
|
+
const hydratedTemplate = {
|
|
921
|
+
hydratedButtons: message.templateButtons,
|
|
922
|
+
}
|
|
698
923
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
924
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
925
|
+
hydratedTemplate.hydratedContentText = message.text
|
|
926
|
+
} else {
|
|
927
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
928
|
+
hydratedTemplate.hydratedContentText = message.caption
|
|
704
929
|
}
|
|
705
|
-
})
|
|
706
930
|
|
|
707
|
-
|
|
708
|
-
...(message.contextInfo || {}),
|
|
709
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
931
|
+
Object.assign(msg, m)
|
|
710
932
|
}
|
|
711
|
-
}
|
|
712
933
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
throw new boom_1.Boom('Invalid pollResult values', { statusCode: 400 })
|
|
934
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
935
|
+
hydratedTemplate.hydratedFooterText = message.footer
|
|
716
936
|
}
|
|
717
937
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
pollResultSnapshotMessage.contextInfo = {
|
|
727
|
-
...(message.contextInfo || {}),
|
|
728
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
938
|
+
m = { templateMessage: { hydratedTemplate } }
|
|
939
|
+
} else if (hasNonNullishProperty(message, "interactiveButtons")) {
|
|
940
|
+
const interactiveMessage = {
|
|
941
|
+
nativeFlowMessage: {
|
|
942
|
+
buttons: message.interactiveButtons,
|
|
943
|
+
},
|
|
729
944
|
}
|
|
730
945
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
if (!Array.isArray(message.poll.values)) {
|
|
736
|
-
throw new boom_1.Boom('Invalid poll values', { statusCode: 400 })
|
|
946
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
947
|
+
interactiveMessage.body = {
|
|
948
|
+
text: message.text,
|
|
949
|
+
}
|
|
737
950
|
}
|
|
738
951
|
|
|
739
|
-
if (message
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
952
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
953
|
+
interactiveMessage.header = {
|
|
954
|
+
title: message.title,
|
|
955
|
+
subtitle: null,
|
|
956
|
+
hasMediaAttachment: false,
|
|
957
|
+
}
|
|
743
958
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
959
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
960
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
961
|
+
}
|
|
962
|
+
} else {
|
|
963
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
964
|
+
interactiveMessage.body = {
|
|
965
|
+
text: message.caption,
|
|
966
|
+
}
|
|
749
967
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
968
|
+
interactiveMessage.header = {
|
|
969
|
+
title: null,
|
|
970
|
+
subtitle: null,
|
|
971
|
+
hasMediaAttachment: false,
|
|
972
|
+
...Object.assign(interactiveMessage, m),
|
|
973
|
+
}
|
|
754
974
|
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
} else {
|
|
758
|
-
if(message.poll.selectableCount > 0) {
|
|
759
|
-
m.pollCreationMessageV3 = pollCreationMessage
|
|
760
|
-
} else {
|
|
761
|
-
m.pollCreationMessage = pollCreationMessage
|
|
762
|
-
}
|
|
975
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
976
|
+
interactiveMessage.header.title = message.title
|
|
763
977
|
}
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
else if ('payment' in message) {
|
|
767
|
-
const requestPaymentMessage = {
|
|
768
|
-
amount: {
|
|
769
|
-
currencyCode: message.payment?.currency || 'IDR',
|
|
770
|
-
offset: message.payment?.offset || 0,
|
|
771
|
-
value: message.payment?.amount || 999999999
|
|
772
|
-
},
|
|
773
|
-
expiryTimestamp: message.payment?.expiry || 0,
|
|
774
|
-
amount1000: message.payment?.amount || 999999999 * 1000,
|
|
775
|
-
currencyCodeIso4217: message.payment?.currency || 'IDR',
|
|
776
|
-
requestFrom: message.payment?.from || '0@s.whatsapp.net',
|
|
777
|
-
noteMessage: {
|
|
778
|
-
extendedTextMessage: {
|
|
779
|
-
text: message.payment?.note || 'Notes'
|
|
780
|
-
}
|
|
781
|
-
},
|
|
782
|
-
background: {
|
|
783
|
-
placeholderArgb: message.payment?.image?.placeholderArgb || 4278190080,
|
|
784
|
-
textArgb: message.payment?.image?.textArgb || 4294967295,
|
|
785
|
-
subtextArgb: message.payment?.image?.subtextArgb || 4294967295,
|
|
786
|
-
type: 1
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
978
|
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
}
|
|
979
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
980
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
981
|
+
}
|
|
794
982
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
const { zip } = require('fflate')
|
|
802
|
-
|
|
803
|
-
const stickerData = {}
|
|
804
|
-
const stickerPromises = stickers.map(async (s, i) => {
|
|
805
|
-
const { stream } = await messages_media_1.getStream(s.sticker)
|
|
806
|
-
const buffer = await messages_media_1.toBuffer(stream)
|
|
807
|
-
const hash = crypto_2.sha256(buffer).toString('base64url')
|
|
808
|
-
const fileName = `${i.toString().padStart(2, '0')}_${hash}.webp`
|
|
809
|
-
stickerData[fileName] = [new Uint8Array(buffer), { level: 0 }]
|
|
810
|
-
|
|
811
|
-
return {
|
|
812
|
-
fileName,
|
|
813
|
-
mimetype: 'image/webp',
|
|
814
|
-
isAnimated: s.isAnimated || false,
|
|
815
|
-
isLottie: s.isLottie || false,
|
|
816
|
-
emojis: s.emojis || [],
|
|
817
|
-
accessibilityLabel: s.accessibilityLabel || ''
|
|
818
|
-
}
|
|
819
|
-
})
|
|
820
|
-
|
|
821
|
-
const stickerMetadata = await Promise.all(stickerPromises)
|
|
822
|
-
|
|
823
|
-
const zipBuffer = await new Promise((resolve, reject) => {
|
|
824
|
-
zip(stickerData, (err, data) => {
|
|
825
|
-
if (err) {
|
|
826
|
-
reject(err)
|
|
827
|
-
} else {
|
|
828
|
-
resolve(Buffer.from(data))
|
|
829
|
-
}
|
|
830
|
-
})
|
|
831
|
-
})
|
|
832
|
-
|
|
833
|
-
const coverBuffer = await messages_media_1.toBuffer((await messages_media_1.getStream(cover)).stream)
|
|
834
|
-
|
|
835
|
-
const [stickerPackUpload, coverUpload] = await Promise.all([
|
|
836
|
-
messages_media_1.encryptedStream(zipBuffer, 'sticker-pack', { logger: options.logger, opts: options.options }),
|
|
837
|
-
prepareWAMessageMedia({ image: coverBuffer }, { ...options, mediaTypeOverride: 'image' })
|
|
838
|
-
])
|
|
839
|
-
|
|
840
|
-
const stickerPackUploadResult = await options.upload(stickerPackUpload.encFilePath, {
|
|
841
|
-
fileEncSha256B64: stickerPackUpload.fileEncSha256.toString('base64'),
|
|
842
|
-
mediaType: 'sticker-pack',
|
|
843
|
-
timeoutMs: options.mediaUploadTimeoutMs
|
|
844
|
-
})
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
const coverImage = coverUpload.imageMessage
|
|
848
|
-
const imageDataHash = crypto_2.sha256(coverBuffer).toString('base64')
|
|
849
|
-
const stickerPackId = packId || generics_1.generateMessageID()
|
|
850
|
-
|
|
851
|
-
m.stickerPackMessage = {
|
|
852
|
-
name,
|
|
853
|
-
publisher,
|
|
854
|
-
stickerPackId,
|
|
855
|
-
packDescription: description,
|
|
856
|
-
stickerPackOrigin: WAProto_1.proto.Message.StickerPackMessage.StickerPackOrigin.THIRD_PARTY,
|
|
857
|
-
stickerPackSize: stickerPackUpload.fileLength,
|
|
858
|
-
stickers: stickerMetadata,
|
|
859
|
-
fileSha256: stickerPackUpload.fileSha256,
|
|
860
|
-
fileEncSha256: stickerPackUpload.fileEncSha256,
|
|
861
|
-
mediaKey: stickerPackUpload.mediaKey,
|
|
862
|
-
directPath: stickerPackUploadResult.directPath,
|
|
863
|
-
fileLength: stickerPackUpload.fileLength,
|
|
864
|
-
mediaKeyTimestamp: generics_1.unixTimestampSeconds(),
|
|
865
|
-
trayIconFileName: `${stickerPackId}.png`,
|
|
866
|
-
imageDataHash,
|
|
867
|
-
thumbnailDirectPath: coverImage.directPath,
|
|
868
|
-
thumbnailFileSha256: coverImage.fileSha256,
|
|
869
|
-
thumbnailFileEncSha256: coverImage.fileEncSha256,
|
|
870
|
-
thumbnailHeight: coverImage.height,
|
|
871
|
-
thumbnailWidth: coverImage.width
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
m.stickerPackMessage.contextInfo = {
|
|
875
|
-
...(message.contextInfo || {}),
|
|
876
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
else if ('sharePhoneNumber' in message) {
|
|
881
|
-
m.protocolMessage = {
|
|
882
|
-
type: Types_1.WAProto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
|
|
983
|
+
if (hasNonNullishProperty(message, "hasMediaAttachment")) {
|
|
984
|
+
interactiveMessage.header.hasMediaAttachment = Boolean(
|
|
985
|
+
message.hasMediaAttachment
|
|
986
|
+
)
|
|
987
|
+
}
|
|
988
|
+
}
|
|
883
989
|
}
|
|
884
|
-
}
|
|
885
990
|
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
991
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
992
|
+
interactiveMessage.footer = {
|
|
993
|
+
text: message.footer,
|
|
994
|
+
}
|
|
995
|
+
}
|
|
889
996
|
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
const
|
|
997
|
+
m = { interactiveMessage }
|
|
998
|
+
} else if (hasNonNullishProperty(message, "shop")) {
|
|
999
|
+
const interactiveMessage = {
|
|
1000
|
+
shopStorefrontMessage: {
|
|
1001
|
+
surface: message.shop.surface,
|
|
1002
|
+
id: message.shop.id,
|
|
1003
|
+
},
|
|
1004
|
+
}
|
|
893
1005
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
1006
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
1007
|
+
interactiveMessage.body = {
|
|
1008
|
+
text: message.text,
|
|
1009
|
+
}
|
|
897
1010
|
}
|
|
898
1011
|
|
|
899
|
-
|
|
900
|
-
|
|
1012
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1013
|
+
interactiveMessage.header = {
|
|
1014
|
+
title: message.title,
|
|
1015
|
+
subtitle: null,
|
|
1016
|
+
hasMediaAttachment: false,
|
|
1017
|
+
}
|
|
901
1018
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
}
|
|
1019
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1020
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1021
|
+
}
|
|
1022
|
+
} else {
|
|
1023
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
1024
|
+
interactiveMessage.body = {
|
|
1025
|
+
text: message.caption,
|
|
1026
|
+
}
|
|
911
1027
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
1028
|
+
interactiveMessage.header = {
|
|
1029
|
+
title: null,
|
|
1030
|
+
subtitle: null,
|
|
1031
|
+
hasMediaAttachment: false,
|
|
1032
|
+
...Object.assign(interactiveMessage, m),
|
|
1033
|
+
}
|
|
916
1034
|
|
|
917
|
-
|
|
918
|
-
|
|
1035
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1036
|
+
interactiveMessage.header.title = message.title
|
|
1037
|
+
}
|
|
919
1038
|
|
|
920
|
-
|
|
921
|
-
|
|
1039
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1040
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1041
|
+
}
|
|
922
1042
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
productSections: message.productList,
|
|
930
|
-
headerImage: {
|
|
931
|
-
productId: message.productList[0].products[0].productId,
|
|
932
|
-
jpegThumbnail: thumbnail?.thumbnail || null
|
|
933
|
-
},
|
|
934
|
-
businessOwnerJid: message.businessOwnerJid
|
|
935
|
-
},
|
|
936
|
-
listType: WAProto_1.proto.Message.ListMessage.ListType.PRODUCT_LIST
|
|
1043
|
+
if (hasNonNullishProperty(message, "hasMediaAttachment")) {
|
|
1044
|
+
interactiveMessage.header.hasMediaAttachment = Boolean(
|
|
1045
|
+
message.hasMediaAttachment
|
|
1046
|
+
)
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
937
1049
|
}
|
|
938
1050
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
1051
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
1052
|
+
interactiveMessage.footer = {
|
|
1053
|
+
text: message.footer,
|
|
1054
|
+
}
|
|
942
1055
|
}
|
|
943
1056
|
|
|
944
|
-
m = {
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
1057
|
+
m = { interactiveMessage }
|
|
1058
|
+
} else if (hasNonNullishProperty(message, "collection")) {
|
|
1059
|
+
const interactiveMessage = {
|
|
1060
|
+
collectionMessage: {
|
|
1061
|
+
bizJid: message.collection.bizJid,
|
|
1062
|
+
id: message.collection.id,
|
|
1063
|
+
messageVersion: message?.collection?.version,
|
|
1064
|
+
},
|
|
950
1065
|
}
|
|
951
1066
|
|
|
952
|
-
if (
|
|
953
|
-
|
|
954
|
-
|
|
1067
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
1068
|
+
interactiveMessage.body = {
|
|
1069
|
+
text: message.text,
|
|
1070
|
+
}
|
|
955
1071
|
}
|
|
956
1072
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1073
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1074
|
+
interactiveMessage.header = {
|
|
1075
|
+
title: message.title,
|
|
1076
|
+
subtitle: null,
|
|
1077
|
+
hasMediaAttachment: false,
|
|
960
1078
|
}
|
|
961
1079
|
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1080
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1081
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1082
|
+
}
|
|
1083
|
+
} else {
|
|
1084
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
1085
|
+
interactiveMessage.body = {
|
|
1086
|
+
text: message.caption,
|
|
1087
|
+
}
|
|
965
1088
|
|
|
966
|
-
|
|
967
|
-
|
|
1089
|
+
interactiveMessage.header = {
|
|
1090
|
+
title: null,
|
|
1091
|
+
subtitle: null,
|
|
1092
|
+
hasMediaAttachment: false,
|
|
1093
|
+
...Object.assign(interactiveMessage, m),
|
|
1094
|
+
}
|
|
968
1095
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1096
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1097
|
+
interactiveMessage.header.title = message.title
|
|
1098
|
+
}
|
|
972
1099
|
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
}
|
|
1100
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1101
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1102
|
+
}
|
|
977
1103
|
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1104
|
+
if (hasNonNullishProperty(message, "hasMediaAttachment")) {
|
|
1105
|
+
interactiveMessage.header.hasMediaAttachment = Boolean(
|
|
1106
|
+
message.hasMediaAttachment
|
|
1107
|
+
)
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
981
1110
|
}
|
|
982
1111
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
const hydratedTemplate = {
|
|
988
|
-
hydratedButtons: message.templateButtons
|
|
1112
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
1113
|
+
interactiveMessage.footer = {
|
|
1114
|
+
text: message.footer,
|
|
1115
|
+
}
|
|
989
1116
|
}
|
|
990
1117
|
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1118
|
+
m = { interactiveMessage }
|
|
1119
|
+
} else if (hasNonNullishProperty(message, "cards")) {
|
|
1120
|
+
const slides = await Promise.all(
|
|
1121
|
+
message.cards.map(async (slide) => {
|
|
1122
|
+
const {
|
|
1123
|
+
image,
|
|
1124
|
+
video,
|
|
1125
|
+
product,
|
|
1126
|
+
title,
|
|
1127
|
+
body,
|
|
1128
|
+
footer,
|
|
1129
|
+
buttons,
|
|
1130
|
+
} = slide
|
|
1131
|
+
|
|
1132
|
+
let header
|
|
1133
|
+
|
|
1134
|
+
if (product) {
|
|
1135
|
+
const { imageMessage } = await prepareWAMessageMedia(
|
|
1136
|
+
{ image: product.productImage, ...options },
|
|
1137
|
+
options
|
|
1138
|
+
)
|
|
1139
|
+
header = {
|
|
1140
|
+
productMessage: {
|
|
1141
|
+
product: {
|
|
1142
|
+
...product,
|
|
1143
|
+
productImage: imageMessage,
|
|
1144
|
+
},
|
|
1145
|
+
...slide,
|
|
1146
|
+
},
|
|
1147
|
+
}
|
|
1148
|
+
} else if (image) {
|
|
1149
|
+
header = await prepareWAMessageMedia(
|
|
1150
|
+
{ image: image, ...options },
|
|
1151
|
+
options
|
|
1152
|
+
)
|
|
1153
|
+
} else if (video) {
|
|
1154
|
+
header = await prepareWAMessageMedia(
|
|
1155
|
+
{ video: video, ...options },
|
|
1156
|
+
options
|
|
1157
|
+
)
|
|
1158
|
+
}
|
|
994
1159
|
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
1160
|
+
const msg = {
|
|
1161
|
+
header: {
|
|
1162
|
+
title,
|
|
1163
|
+
hasMediaAttachment: true,
|
|
1164
|
+
...header,
|
|
1165
|
+
},
|
|
1166
|
+
body: {
|
|
1167
|
+
text: body,
|
|
1168
|
+
},
|
|
1169
|
+
footer: {
|
|
1170
|
+
text: footer,
|
|
1171
|
+
},
|
|
1172
|
+
nativeFlowMessage: {
|
|
1173
|
+
buttons,
|
|
1174
|
+
},
|
|
1175
|
+
}
|
|
999
1176
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1177
|
+
return msg
|
|
1178
|
+
})
|
|
1179
|
+
)
|
|
1002
1180
|
|
|
1003
|
-
|
|
1004
|
-
|
|
1181
|
+
const interactiveMessage = {
|
|
1182
|
+
carouselMessage: {
|
|
1183
|
+
cards: slides,
|
|
1184
|
+
},
|
|
1005
1185
|
}
|
|
1006
1186
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1187
|
+
if (hasNonNullishProperty(message, "text")) {
|
|
1188
|
+
interactiveMessage.body = {
|
|
1189
|
+
text: message.text,
|
|
1190
|
+
}
|
|
1010
1191
|
}
|
|
1011
1192
|
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
nativeFlowMessage: {
|
|
1018
|
-
buttons: message.interactiveButtons
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
if ('text' in message) {
|
|
1023
|
-
interactiveMessage.body = {
|
|
1024
|
-
text: message.text
|
|
1025
|
-
},
|
|
1026
|
-
interactiveMessage.header = {
|
|
1027
|
-
title: message.title,
|
|
1028
|
-
subtitle: message.subtitle,
|
|
1029
|
-
hasMediaAttachment: false
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
else {
|
|
1034
|
-
if ('caption' in message) {
|
|
1035
|
-
interactiveMessage.body = {
|
|
1036
|
-
text: message.caption
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
interactiveMessage.header = {
|
|
1040
|
-
title: message.title,
|
|
1041
|
-
subtitle: message.subtitle,
|
|
1042
|
-
hasMediaAttachment: message.hasMediaAttachment ? message.hasMediaAttachment : false,
|
|
1043
|
-
...Object.assign(interactiveMessage, m)
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
if ('footer' in message && !!message.footer) {
|
|
1049
|
-
interactiveMessage.footer = {
|
|
1050
|
-
text: message.footer
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
interactiveMessage.contextInfo = {
|
|
1055
|
-
...(message.contextInfo || {}),
|
|
1056
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
m = { interactiveMessage }
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
else if ('shop' in message && !!message.shop) {
|
|
1063
|
-
const interactiveMessage = {
|
|
1064
|
-
shopStorefrontMessage: {
|
|
1065
|
-
surface: message.shop.surface,
|
|
1066
|
-
id: message.shop.id
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
if ('text' in message) {
|
|
1071
|
-
interactiveMessage.body = {
|
|
1072
|
-
text: message.text
|
|
1073
|
-
},
|
|
1074
|
-
interactiveMessage.header = {
|
|
1075
|
-
title: message.title,
|
|
1076
|
-
subtitle: message.subtitle,
|
|
1077
|
-
hasMediaAttachment: false
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
else {
|
|
1082
|
-
if ('caption' in message) {
|
|
1083
|
-
interactiveMessage.body = {
|
|
1084
|
-
text: message.caption
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
|
-
interactiveMessage.header = {
|
|
1088
|
-
title: message.title,
|
|
1089
|
-
subtitle: message.subtitle,
|
|
1090
|
-
hasMediaAttachment: message.hasMediaAttachment ? message.hasMediaAttachment : false,
|
|
1091
|
-
...Object.assign(interactiveMessage, m)
|
|
1193
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1194
|
+
interactiveMessage.header = {
|
|
1195
|
+
title: message.title,
|
|
1196
|
+
subtitle: null,
|
|
1197
|
+
hasMediaAttachment: false,
|
|
1092
1198
|
}
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
if ('footer' in message && !!message.footer) {
|
|
1097
|
-
interactiveMessage.footer = {
|
|
1098
|
-
text: message.footer
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
interactiveMessage.contextInfo = {
|
|
1103
|
-
...(message.contextInfo || {}),
|
|
1104
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
m = { interactiveMessage }
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
else if ('collection' in message && !!message.collection) {
|
|
1111
|
-
const interactiveMessage = {
|
|
1112
|
-
collectionMessage: {
|
|
1113
|
-
bizJid: message.collection.bizJid,
|
|
1114
|
-
id: message.collection.id,
|
|
1115
|
-
messageVersion: message?.collection?.version
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
if ('text' in message) {
|
|
1120
|
-
interactiveMessage.body = {
|
|
1121
|
-
text: message.text
|
|
1122
|
-
},
|
|
1123
|
-
interactiveMessage.header = {
|
|
1124
|
-
title: message.title,
|
|
1125
|
-
subtitle: message.subtitle,
|
|
1126
|
-
hasMediaAttachment: false
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
else {
|
|
1131
|
-
if ('caption' in message) {
|
|
1132
|
-
interactiveMessage.body = {
|
|
1133
|
-
text: message.caption
|
|
1134
|
-
}
|
|
1135
|
-
interactiveMessage.header = {
|
|
1136
|
-
title: message.title,
|
|
1137
|
-
subtitle: message.subtitle,
|
|
1138
|
-
hasMediaAttachment: message.hasMediaAttachment ? message.hasMediaAttachment : false,
|
|
1139
|
-
...Object.assign(interactiveMessage, m)
|
|
1199
|
+
|
|
1200
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1201
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1140
1202
|
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1203
|
+
} else {
|
|
1204
|
+
if (hasNonNullishProperty(message, "caption")) {
|
|
1205
|
+
interactiveMessage.body = {
|
|
1206
|
+
text: message.caption,
|
|
1207
|
+
}
|
|
1143
1208
|
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1209
|
+
interactiveMessage.header = {
|
|
1210
|
+
title: null,
|
|
1211
|
+
subtitle: null,
|
|
1212
|
+
hasMediaAttachment: false,
|
|
1213
|
+
...Object.assign(interactiveMessage, m),
|
|
1214
|
+
}
|
|
1149
1215
|
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
}
|
|
1216
|
+
if (hasNonNullishProperty(message, "title")) {
|
|
1217
|
+
interactiveMessage.header.title = message.title
|
|
1218
|
+
}
|
|
1154
1219
|
|
|
1155
|
-
|
|
1156
|
-
|
|
1220
|
+
if (hasNonNullishProperty(message, "subtitle")) {
|
|
1221
|
+
interactiveMessage.header.subtitle = message.subtitle
|
|
1222
|
+
}
|
|
1157
1223
|
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
if (product) {
|
|
1164
|
-
const { imageMessage } = await prepareWAMessageMedia({ image: product.productImage, ...options }, options)
|
|
1165
|
-
header = {
|
|
1166
|
-
productMessage: {
|
|
1167
|
-
product: {
|
|
1168
|
-
...product,
|
|
1169
|
-
productImage: imageMessage,
|
|
1170
|
-
},
|
|
1171
|
-
...slide
|
|
1172
|
-
}
|
|
1224
|
+
if (hasNonNullishProperty(message, "hasMediaAttachment")) {
|
|
1225
|
+
interactiveMessage.header.hasMediaAttachment = Boolean(
|
|
1226
|
+
message.hasMediaAttachment
|
|
1227
|
+
)
|
|
1173
1228
|
}
|
|
1174
1229
|
}
|
|
1230
|
+
}
|
|
1175
1231
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1232
|
+
if (hasNonNullishProperty(message, "footer")) {
|
|
1233
|
+
interactiveMessage.footer = {
|
|
1234
|
+
text: message.footer,
|
|
1178
1235
|
}
|
|
1236
|
+
}
|
|
1179
1237
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1238
|
+
m = { interactiveMessage }
|
|
1239
|
+
} else if (hasNonNullishProperty(message, "text")) {
|
|
1240
|
+
const extContent = { text: message.text }
|
|
1183
1241
|
|
|
1184
|
-
|
|
1185
|
-
header: {
|
|
1186
|
-
title,
|
|
1187
|
-
hasMediaAttachment: true,
|
|
1188
|
-
...header
|
|
1189
|
-
},
|
|
1190
|
-
body: {
|
|
1191
|
-
text: body
|
|
1192
|
-
},
|
|
1193
|
-
footer: {
|
|
1194
|
-
text: footer
|
|
1195
|
-
},
|
|
1196
|
-
nativeFlowMessage: {
|
|
1197
|
-
buttons,
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1242
|
+
let urlInfo = message.linkPreview
|
|
1200
1243
|
|
|
1201
|
-
|
|
1202
|
-
|
|
1244
|
+
if (typeof urlInfo === "undefined") {
|
|
1245
|
+
urlInfo = await generateLinkPreviewIfRequired(
|
|
1246
|
+
message.text,
|
|
1247
|
+
options.getUrlInfo,
|
|
1248
|
+
options.logger
|
|
1249
|
+
)
|
|
1250
|
+
}
|
|
1203
1251
|
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1252
|
+
if (urlInfo) {
|
|
1253
|
+
extContent.canonicalUrl = urlInfo["canonical-url"]
|
|
1254
|
+
extContent.matchedText = urlInfo["matched-text"]
|
|
1255
|
+
extContent.jpegThumbnail = urlInfo.jpegThumbnail
|
|
1256
|
+
extContent.description = urlInfo.description
|
|
1257
|
+
extContent.title = urlInfo.title
|
|
1258
|
+
extContent.previewType = 0
|
|
1259
|
+
|
|
1260
|
+
const img = urlInfo.highQualityThumbnail
|
|
1261
|
+
|
|
1262
|
+
if (img) {
|
|
1263
|
+
extContent.thumbnailDirectPath = img.directPath
|
|
1264
|
+
extContent.mediaKey = img.mediaKey
|
|
1265
|
+
extContent.mediaKeyTimestamp = img.mediaKeyTimestamp
|
|
1266
|
+
extContent.thumbnailWidth = img.width
|
|
1267
|
+
extContent.thumbnailHeight = img.height
|
|
1268
|
+
extContent.thumbnailSha256 = img.fileSha256
|
|
1269
|
+
extContent.thumbnailEncSha256 = img.fileEncSha256
|
|
1207
1270
|
}
|
|
1208
1271
|
}
|
|
1209
1272
|
|
|
1210
|
-
if (
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
interactiveMessage.header = {
|
|
1215
|
-
title: message.title,
|
|
1216
|
-
subtitle: message.subtitle,
|
|
1217
|
-
hasMediaAttachment: false
|
|
1218
|
-
}
|
|
1273
|
+
if (options.backgroundColor) {
|
|
1274
|
+
extContent.backgroundArgb = await assertColor(
|
|
1275
|
+
options.backgroundColor
|
|
1276
|
+
)
|
|
1219
1277
|
}
|
|
1220
1278
|
|
|
1221
|
-
if (
|
|
1222
|
-
|
|
1223
|
-
text: message.footer
|
|
1224
|
-
}
|
|
1279
|
+
if (options.textColor) {
|
|
1280
|
+
extContent.textArgb = await assertColor(options.textColor)
|
|
1225
1281
|
}
|
|
1226
1282
|
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
...(message.mentions ? { mentionedJid: message.mentions } : {})
|
|
1283
|
+
if (options.font) {
|
|
1284
|
+
extContent.font = options.font
|
|
1230
1285
|
}
|
|
1231
1286
|
|
|
1232
|
-
m =
|
|
1287
|
+
m.extendedTextMessage = extContent
|
|
1288
|
+
} else if (hasMedia) {
|
|
1289
|
+
m = await prepareWAMessageMedia(message, options)
|
|
1233
1290
|
}
|
|
1234
1291
|
|
|
1235
|
-
if (
|
|
1236
|
-
|
|
1237
|
-
}
|
|
1292
|
+
if (hasOptionalProperty(message, "ephemeral")) {
|
|
1293
|
+
m = { ephemeralMessage: { message: m } }
|
|
1294
|
+
}
|
|
1238
1295
|
|
|
1239
|
-
if (
|
|
1240
|
-
|
|
1296
|
+
if (hasOptionalProperty(message, "mentions") && message.mentions?.length) {
|
|
1297
|
+
const messageType = Object.keys(m)[0]
|
|
1298
|
+
const key = m[messageType]
|
|
1299
|
+
|
|
1300
|
+
if ("contextInfo" in key && !!key.contextInfo) {
|
|
1301
|
+
key.contextInfo.mentionedJid = message.mentions
|
|
1302
|
+
} else if (key) {
|
|
1303
|
+
key.contextInfo = {
|
|
1304
|
+
mentionedJid: message.mentions,
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1241
1307
|
}
|
|
1242
1308
|
|
|
1243
|
-
if (
|
|
1244
|
-
|
|
1309
|
+
if (hasOptionalProperty(message, "contextInfo") && !!message.contextInfo) {
|
|
1310
|
+
const messageType = Object.keys(m)[0]
|
|
1311
|
+
const key = m[messageType]
|
|
1312
|
+
|
|
1313
|
+
if ("contextInfo" in key && !!key.contextInfo) {
|
|
1314
|
+
key.contextInfo = { ...key.contextInfo, ...message.contextInfo }
|
|
1315
|
+
} else if (key) {
|
|
1316
|
+
key.contextInfo = message.contextInfo
|
|
1317
|
+
}
|
|
1245
1318
|
}
|
|
1246
1319
|
|
|
1247
|
-
if (
|
|
1320
|
+
if (hasOptionalProperty(message, "edit")) {
|
|
1248
1321
|
m = {
|
|
1249
1322
|
protocolMessage: {
|
|
1250
1323
|
key: message.edit,
|
|
1251
1324
|
editedMessage: m,
|
|
1252
1325
|
timestampMs: Date.now(),
|
|
1253
|
-
type:
|
|
1254
|
-
}
|
|
1326
|
+
type: WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT,
|
|
1327
|
+
},
|
|
1255
1328
|
}
|
|
1256
1329
|
}
|
|
1257
1330
|
|
|
1258
|
-
return
|
|
1331
|
+
return WAProto.Message.fromObject(m)
|
|
1259
1332
|
}
|
|
1260
1333
|
|
|
1261
1334
|
const generateWAMessageFromContent = (jid, message, options) => {
|
|
@@ -1265,11 +1338,11 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1265
1338
|
|
|
1266
1339
|
const innerMessage = normalizeMessageContent(message)
|
|
1267
1340
|
const key = getContentType(innerMessage)
|
|
1268
|
-
const timestamp =
|
|
1341
|
+
const timestamp = unixTimestampSeconds(options.timestamp)
|
|
1269
1342
|
const threadId = []
|
|
1270
1343
|
const { quoted, userJid } = options
|
|
1271
1344
|
|
|
1272
|
-
if (quoted && !
|
|
1345
|
+
if (quoted && !isJidNewsletter(jid)) {
|
|
1273
1346
|
const participant = quoted.key.fromMe
|
|
1274
1347
|
? userJid
|
|
1275
1348
|
: quoted.participant || quoted.key.participant || quoted.key.remoteJid
|
|
@@ -1277,7 +1350,7 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1277
1350
|
let quotedMsg = normalizeMessageContent(quoted.message)
|
|
1278
1351
|
const msgType = getContentType(quotedMsg)
|
|
1279
1352
|
|
|
1280
|
-
quotedMsg =
|
|
1353
|
+
quotedMsg = proto.Message.fromObject({ [msgType]: quotedMsg[msgType] })
|
|
1281
1354
|
|
|
1282
1355
|
const quotedContent = quotedMsg[msgType]
|
|
1283
1356
|
|
|
@@ -1297,7 +1370,7 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1297
1370
|
|
|
1298
1371
|
const contextInfo = (key === 'requestPaymentMessage' ? requestPayment?.contextInfo : innerMessage[key].contextInfo) || {}
|
|
1299
1372
|
|
|
1300
|
-
contextInfo.participant =
|
|
1373
|
+
contextInfo.participant = jidNormalizedUser(participant)
|
|
1301
1374
|
contextInfo.stanzaId = quoted.key.id
|
|
1302
1375
|
contextInfo.quotedMessage = quotedMsg
|
|
1303
1376
|
|
|
@@ -1306,16 +1379,16 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1306
1379
|
}
|
|
1307
1380
|
|
|
1308
1381
|
if (contextInfo.quotedMessage) {
|
|
1309
|
-
contextInfo.quotedType =
|
|
1382
|
+
contextInfo.quotedType = proto.ContextInfo.QuotedType.EXPLICIT
|
|
1310
1383
|
}
|
|
1311
1384
|
|
|
1312
|
-
if (contextInfo.quotedMessage &&
|
|
1385
|
+
if (contextInfo.quotedMessage && isJidGroup(jid)) {
|
|
1313
1386
|
threadId.push({
|
|
1314
|
-
threadType:
|
|
1387
|
+
threadType: proto.ThreadID.ThreadType.VIEW_REPLIES,
|
|
1315
1388
|
threadKey: {
|
|
1316
1389
|
remoteJid: quoted?.key?.remoteJid,
|
|
1317
1390
|
fromMe: quoted?.key?.fromMe,
|
|
1318
|
-
id:
|
|
1391
|
+
id: generateMessageID(),
|
|
1319
1392
|
...(quoted?.key?.fromMe ? {} : { participant: quoted?.key?.participant })
|
|
1320
1393
|
}
|
|
1321
1394
|
})
|
|
@@ -1330,10 +1403,10 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1330
1403
|
|
|
1331
1404
|
if (key !== 'protocolMessage' &&
|
|
1332
1405
|
key !== 'ephemeralMessage' &&
|
|
1333
|
-
!
|
|
1406
|
+
!isJidNewsletter(jid)) {
|
|
1334
1407
|
message.messageContextInfo = {
|
|
1335
1408
|
threadId: threadId.length > 0 ? threadId : [],
|
|
1336
|
-
messageSecret:
|
|
1409
|
+
messageSecret: randomBytes(32),
|
|
1337
1410
|
...message.messageContextInfo
|
|
1338
1411
|
}
|
|
1339
1412
|
innerMessage[key].contextInfo = {
|
|
@@ -1342,34 +1415,34 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1342
1415
|
}
|
|
1343
1416
|
}
|
|
1344
1417
|
|
|
1345
|
-
message =
|
|
1418
|
+
message = WAProto.Message.fromObject(message)
|
|
1346
1419
|
|
|
1347
1420
|
const messageJSON = {
|
|
1348
1421
|
key: {
|
|
1349
1422
|
remoteJid: jid,
|
|
1350
1423
|
fromMe: true,
|
|
1351
|
-
id: options?.messageId ||
|
|
1424
|
+
id: options?.messageId || generateMessageID()
|
|
1352
1425
|
},
|
|
1353
1426
|
message: message,
|
|
1354
1427
|
messageTimestamp: timestamp,
|
|
1355
1428
|
messageStubParameters: [],
|
|
1356
|
-
participant:
|
|
1357
|
-
status:
|
|
1429
|
+
participant: isJidGroup(jid) || isJidStatusBroadcast(jid) ? userJid : undefined,
|
|
1430
|
+
status: WAMessageStatus.PENDING
|
|
1358
1431
|
}
|
|
1359
1432
|
|
|
1360
|
-
return
|
|
1433
|
+
return WAProto.WebMessageInfo.fromObject(messageJSON)
|
|
1361
1434
|
}
|
|
1362
1435
|
|
|
1363
1436
|
const generateWAMessage = async (jid, content, options) => {
|
|
1364
1437
|
options.logger = options?.logger?.child({ msgId: options.messageId })
|
|
1365
1438
|
|
|
1366
|
-
return generateWAMessageFromContent(jid, await generateWAMessageContent(content, { newsletter:
|
|
1439
|
+
return generateWAMessageFromContent(jid, await generateWAMessageContent(content, { newsletter: isJidNewsletter(jid), ...options }), options)
|
|
1367
1440
|
}
|
|
1368
1441
|
|
|
1369
1442
|
const getContentType = (content) => {
|
|
1370
1443
|
if (content) {
|
|
1371
1444
|
const keys = Object.keys(content)
|
|
1372
|
-
const key = keys.find(k => (k === 'conversation' || k.endsWith('Message') || k.endsWith('V2') || k.endsWith('V3') || k.endsWith('V4')
|
|
1445
|
+
const key = keys.find(k => (k === 'conversation' || k.endsWith('Message') || k.endsWith('V2') || k.endsWith('V3') || k.endsWith('V4')) && k !== 'senderKeyDistributionMessage' && k !== 'messageContextInfo')
|
|
1373
1446
|
|
|
1374
1447
|
return key
|
|
1375
1448
|
}
|
|
@@ -1416,7 +1489,6 @@ const normalizeMessageContent = (content) => {
|
|
|
1416
1489
|
|| (message?.statusMentionMessage)
|
|
1417
1490
|
|| (message?.groupStatusMessageV2)
|
|
1418
1491
|
|| (message?.pollCreationMessageV4)
|
|
1419
|
-
|| (message?.pollCreationMessageV5)
|
|
1420
1492
|
|| (message?.associatedChildMessage)
|
|
1421
1493
|
|| (message?.groupMentionedMessage)
|
|
1422
1494
|
|| (message?.groupStatusMentionMessage)
|
|
@@ -1517,9 +1589,9 @@ const updateMessageWithReceipt = (msg, receipt) => {
|
|
|
1517
1589
|
|
|
1518
1590
|
/** Update the message with a new reaction */
|
|
1519
1591
|
const updateMessageWithReaction = (msg, reaction) => {
|
|
1520
|
-
const authorID =
|
|
1592
|
+
const authorID = getKeyAuthor(reaction.key)
|
|
1521
1593
|
const reactions = (msg.reactions || [])
|
|
1522
|
-
.filter(r =>
|
|
1594
|
+
.filter(r => getKeyAuthor(r.key) !== authorID)
|
|
1523
1595
|
|
|
1524
1596
|
reaction.text = reaction.text || ''
|
|
1525
1597
|
reactions.push(reaction)
|
|
@@ -1528,9 +1600,9 @@ const updateMessageWithReaction = (msg, reaction) => {
|
|
|
1528
1600
|
|
|
1529
1601
|
/** Update the message with a new poll update */
|
|
1530
1602
|
const updateMessageWithPollUpdate = (msg, update) => {
|
|
1531
|
-
const authorID =
|
|
1603
|
+
const authorID = getKeyAuthor(update.pollUpdateMessageKey)
|
|
1532
1604
|
const votes = (msg.pollUpdates || [])
|
|
1533
|
-
.filter(r =>
|
|
1605
|
+
.filter(r => getKeyAuthor(r.pollUpdateMessageKey) !== authorID)
|
|
1534
1606
|
|
|
1535
1607
|
if (update.vote?.selectedOptions?.length) {
|
|
1536
1608
|
votes.push(update)
|
|
@@ -1541,10 +1613,10 @@ const updateMessageWithPollUpdate = (msg, update) => {
|
|
|
1541
1613
|
|
|
1542
1614
|
/** Update the message with a new event response*/
|
|
1543
1615
|
const updateMessageWithEventResponse = (msg, update) => {
|
|
1544
|
-
const authorID =
|
|
1616
|
+
const authorID = getKeyAuthor(update.eventResponseMessageKey)
|
|
1545
1617
|
const responses = (msg.eventResponses || [])
|
|
1546
|
-
|
|
1547
|
-
|
|
1618
|
+
.filter(r => getKeyAuthor(r.eventResponseMessageKey) !== authorID)
|
|
1619
|
+
|
|
1548
1620
|
responses.push(update)
|
|
1549
1621
|
msg.eventResponses = responses
|
|
1550
1622
|
}
|
|
@@ -1561,7 +1633,7 @@ function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
|
1561
1633
|
const opts = message?.pollCreationMessage?.options || message?.pollCreationMessageV2?.options || message?.pollCreationMessageV3?.options || []
|
|
1562
1634
|
|
|
1563
1635
|
const voteHashMap = opts.reduce((acc, opt) => {
|
|
1564
|
-
const hash =
|
|
1636
|
+
const hash = sha256(Buffer.from(opt.optionName || '')).toString()
|
|
1565
1637
|
acc[hash] = {
|
|
1566
1638
|
name: opt.optionName || '',
|
|
1567
1639
|
voters: []
|
|
@@ -1590,7 +1662,7 @@ function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
|
1590
1662
|
data = voteHashMap[hash]
|
|
1591
1663
|
}
|
|
1592
1664
|
|
|
1593
|
-
voteHashMap[hash].voters.push(
|
|
1665
|
+
voteHashMap[hash].voters.push(getKeyAuthor(update.pollUpdateMessageKey, meId))
|
|
1594
1666
|
}
|
|
1595
1667
|
}
|
|
1596
1668
|
|
|
@@ -1608,18 +1680,18 @@ function getAggregateResponsesInEventMessage({ eventResponses }, meLid) {
|
|
|
1608
1680
|
const responseMap = {}
|
|
1609
1681
|
|
|
1610
1682
|
for (const type of responseTypes) {
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1683
|
+
responseMap[type] = {
|
|
1684
|
+
response: type,
|
|
1685
|
+
responders: []
|
|
1686
|
+
}
|
|
1615
1687
|
}
|
|
1616
|
-
|
|
1688
|
+
|
|
1617
1689
|
for (const update of eventResponses) {
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1690
|
+
const { response } = update.response || 0
|
|
1691
|
+
const responseType = proto.Message.EventResponseMessage.EventResponseType[response]
|
|
1692
|
+
if (responseType !== 'UNKNOWN' && responseMap[responseType]) {
|
|
1693
|
+
responseMap[responseType].responders.push(getKeyAuthor(update.eventResponseMessageKey, meLid))
|
|
1694
|
+
}
|
|
1623
1695
|
}
|
|
1624
1696
|
|
|
1625
1697
|
return Object.values(responseMap)
|
|
@@ -1655,40 +1727,42 @@ const REUPLOAD_REQUIRED_STATUS = [410, 404]
|
|
|
1655
1727
|
*/
|
|
1656
1728
|
const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
1657
1729
|
const result = await downloadMsg().catch(async (error) => {
|
|
1658
|
-
if (ctx &&
|
|
1659
|
-
|
|
1730
|
+
if (ctx &&
|
|
1731
|
+
typeof error?.status === 'number' && // treat errors with status as HTTP failures requiring reupload
|
|
1732
|
+
REUPLOAD_REQUIRED_STATUS.includes(error.status)) {
|
|
1660
1733
|
ctx.logger.info({ key: message.key }, 'sending reupload media request...')
|
|
1661
|
-
|
|
1734
|
+
|
|
1662
1735
|
// request reupload
|
|
1663
1736
|
message = await ctx.reuploadRequest(message)
|
|
1664
|
-
|
|
1737
|
+
|
|
1665
1738
|
const result = await downloadMsg()
|
|
1666
|
-
|
|
1667
1739
|
return result
|
|
1668
1740
|
}
|
|
1669
|
-
|
|
1741
|
+
|
|
1670
1742
|
throw error
|
|
1671
1743
|
})
|
|
1672
|
-
|
|
1744
|
+
|
|
1673
1745
|
return result
|
|
1674
|
-
|
|
1746
|
+
|
|
1675
1747
|
async function downloadMsg() {
|
|
1676
1748
|
const mContent = extractMessageContent(message.message)
|
|
1677
|
-
|
|
1749
|
+
|
|
1678
1750
|
if (!mContent) {
|
|
1679
|
-
throw new
|
|
1751
|
+
throw new Boom('No message present', { statusCode: 400, data: message })
|
|
1680
1752
|
}
|
|
1681
|
-
|
|
1753
|
+
|
|
1682
1754
|
const contentType = getContentType(mContent)
|
|
1755
|
+
|
|
1683
1756
|
let mediaType = contentType?.replace('Message', '')
|
|
1757
|
+
|
|
1684
1758
|
const media = contentType === 'productMessage' ? mContent[contentType]?.product?.productImage : mContent[contentType]
|
|
1685
|
-
|
|
1759
|
+
|
|
1686
1760
|
if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
|
|
1687
|
-
throw new
|
|
1761
|
+
throw new Boom(`"${contentType}" message is not a media message`)
|
|
1688
1762
|
}
|
|
1689
|
-
|
|
1763
|
+
|
|
1690
1764
|
let download
|
|
1691
|
-
|
|
1765
|
+
|
|
1692
1766
|
if ('thumbnailDirectPath' in media && !('url' in media)) {
|
|
1693
1767
|
download = {
|
|
1694
1768
|
directPath: media.thumbnailDirectPath,
|
|
@@ -1696,68 +1770,40 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
|
1696
1770
|
}
|
|
1697
1771
|
mediaType = 'thumbnail-link'
|
|
1698
1772
|
}
|
|
1699
|
-
|
|
1700
1773
|
else {
|
|
1701
1774
|
download = media
|
|
1702
1775
|
}
|
|
1703
|
-
|
|
1704
|
-
const stream = await
|
|
1705
|
-
|
|
1776
|
+
|
|
1777
|
+
const stream = await downloadContentFromMessage(download, mediaType, options)
|
|
1778
|
+
|
|
1706
1779
|
if (type === 'buffer') {
|
|
1707
1780
|
const bufferArray = []
|
|
1708
|
-
|
|
1709
1781
|
for await (const chunk of stream) {
|
|
1710
|
-
bufferArray.push(chunk)
|
|
1782
|
+
bufferArray.push(chunk);
|
|
1711
1783
|
}
|
|
1712
|
-
|
|
1713
|
-
return Buffer.concat(bufferArray)
|
|
1784
|
+
return Buffer.concat(bufferArray);
|
|
1714
1785
|
}
|
|
1715
|
-
|
|
1716
1786
|
return stream
|
|
1717
1787
|
}
|
|
1718
1788
|
}
|
|
1719
1789
|
|
|
1720
|
-
/** Checks whether the given message is a media message if it is returns the inner content */
|
|
1790
|
+
/** Checks whether the given message is a media message; if it is returns the inner content */
|
|
1721
1791
|
const assertMediaContent = (content) => {
|
|
1722
1792
|
content = extractMessageContent(content)
|
|
1723
|
-
|
|
1724
|
-
const mediaContent = content?.documentMessage
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1793
|
+
|
|
1794
|
+
const mediaContent = content?.documentMessage ||
|
|
1795
|
+
content?.imageMessage ||
|
|
1796
|
+
content?.videoMessage ||
|
|
1797
|
+
content?.audioMessage ||
|
|
1798
|
+
content?.stickerMessage
|
|
1799
|
+
|
|
1730
1800
|
if (!mediaContent) {
|
|
1731
|
-
throw new
|
|
1801
|
+
throw new Boom('given message is not a media message', { statusCode: 400, data: content });
|
|
1732
1802
|
}
|
|
1803
|
+
|
|
1733
1804
|
return mediaContent
|
|
1734
1805
|
}
|
|
1735
1806
|
|
|
1736
|
-
/**
|
|
1737
|
-
* this is an experimental patch to make buttons work
|
|
1738
|
-
* Don't know how it works, but it does for now
|
|
1739
|
-
*/
|
|
1740
|
-
const patchMessageForMdIfRequired = (message) => {
|
|
1741
|
-
if (message?.buttonsMessage ||
|
|
1742
|
-
message?.templateMessage ||
|
|
1743
|
-
message?.listMessage ||
|
|
1744
|
-
message?.interactiveMessage?.nativeFlowMesaage
|
|
1745
|
-
) {
|
|
1746
|
-
message = {
|
|
1747
|
-
viewOnceMessageV2Extension: {
|
|
1748
|
-
message: {
|
|
1749
|
-
messageContextInfo: {
|
|
1750
|
-
deviceListMetadataVersion: 2,
|
|
1751
|
-
deviceListMetadata: {}
|
|
1752
|
-
},
|
|
1753
|
-
...message
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
return message
|
|
1759
|
-
}
|
|
1760
|
-
|
|
1761
1807
|
module.exports = {
|
|
1762
1808
|
extractUrlFromText,
|
|
1763
1809
|
generateLinkPreviewIfRequired,
|
|
@@ -1769,6 +1815,7 @@ module.exports = {
|
|
|
1769
1815
|
generateWAMessageFromContent,
|
|
1770
1816
|
generateWAMessage,
|
|
1771
1817
|
getContentType,
|
|
1818
|
+
hasNonNullishProperty,
|
|
1772
1819
|
normalizeMessageContent,
|
|
1773
1820
|
extractMessageContent,
|
|
1774
1821
|
getDevice,
|
|
@@ -1780,6 +1827,5 @@ module.exports = {
|
|
|
1780
1827
|
getAggregateResponsesInEventMessage,
|
|
1781
1828
|
aggregateMessageKeysNotFromMe,
|
|
1782
1829
|
downloadMediaMessage,
|
|
1783
|
-
assertMediaContent
|
|
1784
|
-
patchMessageForMdIfRequired
|
|
1830
|
+
assertMediaContent
|
|
1785
1831
|
}
|