@baileys-md/baileys 11.2.4 → 12.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/WAProto/WAProto.proto +5311 -0
- package/WAProto/index.js +70084 -131686
- package/lib/Defaults/index.js +118 -117
- package/lib/KeyDB/BinarySearch.js +20 -0
- package/lib/KeyDB/KeyedDB.js +167 -0
- package/lib/KeyDB/index.js +4 -0
- package/lib/Signal/Group/ciphertext-message.js +13 -0
- package/lib/Signal/Group/group-session-builder.js +32 -0
- package/lib/Signal/Group/group_cipher.js +84 -0
- package/lib/Signal/Group/index.js +13 -0
- package/lib/Signal/Group/keyhelper.js +20 -0
- package/lib/Signal/Group/sender-chain-key.js +28 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +65 -0
- package/lib/Signal/Group/sender-key-message.js +68 -0
- package/{WASignalGroup/sender_key_name.js → lib/Signal/Group/sender-key-name.js} +10 -28
- package/lib/Signal/Group/sender-key-record.js +43 -0
- package/lib/Signal/Group/sender-key-state.js +86 -0
- package/lib/Signal/Group/sender-message-key.js +28 -0
- package/lib/Signal/libsignal.js +314 -151
- package/lib/Signal/lid-mapping.js +155 -0
- package/lib/Socket/Client/index.js +4 -19
- package/lib/Socket/Client/types.js +13 -0
- package/lib/Socket/Client/websocket.js +52 -0
- package/lib/Socket/business.js +359 -242
- package/lib/Socket/chats.js +847 -844
- package/lib/Socket/communities.js +413 -0
- package/lib/Socket/groups.js +304 -319
- package/lib/Socket/index.js +15 -9
- package/lib/Socket/messages-recv.js +1109 -989
- package/lib/Socket/messages-send.js +611 -347
- package/lib/Socket/mex.js +45 -0
- package/lib/Socket/newsletter.js +230 -231
- package/lib/Socket/socket.js +795 -616
- package/lib/Store/index.js +6 -8
- package/lib/Store/make-cache-manager-store.js +73 -81
- package/lib/Store/make-in-memory-store.js +286 -427
- package/lib/Store/make-ordered-dictionary.js +77 -79
- package/lib/Store/object-repository.js +24 -26
- package/lib/Types/Auth.js +3 -2
- package/lib/Types/Bussines.js +3 -0
- package/lib/Types/Call.js +3 -2
- package/lib/Types/Chat.js +9 -4
- package/lib/Types/Contact.js +3 -2
- package/lib/Types/Events.js +3 -2
- package/lib/Types/GroupMetadata.js +3 -2
- package/lib/Types/Label.js +24 -26
- package/lib/Types/LabelAssociation.js +6 -8
- package/lib/Types/Message.js +12 -7
- package/lib/Types/Newsletter.js +32 -17
- package/lib/Types/Product.js +3 -2
- package/lib/Types/Signal.js +3 -2
- package/lib/Types/Socket.js +4 -2
- package/lib/Types/State.js +11 -2
- package/lib/Types/USync.js +3 -2
- package/lib/Types/index.js +27 -41
- package/lib/Utils/auth-utils.js +211 -198
- package/lib/Utils/baileys-event-stream.js +42 -61
- package/lib/Utils/browser-utils.js +25 -0
- package/lib/Utils/business.js +213 -214
- package/lib/Utils/chat-utils.js +711 -689
- package/lib/Utils/crypto.js +112 -133
- package/lib/Utils/decode-wa-message.js +254 -186
- package/lib/Utils/event-buffer.js +510 -502
- package/lib/Utils/generics.js +318 -408
- package/lib/Utils/history.js +83 -90
- package/lib/Utils/index.js +21 -33
- package/lib/Utils/link-preview.js +71 -116
- package/lib/Utils/logger.js +5 -7
- package/lib/Utils/lt-hash.js +40 -46
- package/lib/Utils/make-mutex.js +34 -41
- package/lib/Utils/message-retry-manager.js +113 -0
- package/lib/Utils/messages-media.js +575 -671
- package/lib/Utils/messages.js +354 -462
- package/lib/Utils/noise-handler.js +138 -149
- package/lib/Utils/pre-key-manager.js +85 -0
- package/lib/Utils/process-message.js +323 -354
- package/lib/Utils/signal.js +148 -130
- package/lib/Utils/use-multi-file-auth-state.js +109 -91
- package/lib/Utils/validate-connection.js +183 -190
- package/lib/WABinary/constants.js +1298 -35
- package/lib/WABinary/decode.js +231 -256
- package/lib/WABinary/encode.js +207 -239
- package/lib/WABinary/generic-utils.js +119 -40
- package/lib/WABinary/index.js +7 -21
- package/lib/WABinary/jid-utils.js +88 -64
- package/lib/WABinary/types.js +3 -2
- package/lib/WAM/BinaryInfo.js +10 -12
- package/lib/WAM/constants.js +22851 -15348
- package/lib/WAM/encode.js +135 -136
- package/lib/WAM/index.js +5 -19
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +28 -30
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +49 -53
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -28
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +36 -39
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -50
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +26 -20
- package/lib/WAUSync/Protocols/index.js +6 -20
- package/lib/WAUSync/USyncQuery.js +86 -85
- package/lib/WAUSync/USyncUser.js +23 -25
- package/lib/WAUSync/index.js +5 -19
- package/lib/index.js +18 -33
- package/package.json +52 -57
- package/README.md +0 -2
- package/WASignalGroup/GroupProtocol.js +0 -1697
- package/WASignalGroup/ciphertext_message.js +0 -16
- package/WASignalGroup/group_cipher.js +0 -120
- package/WASignalGroup/group_session_builder.js +0 -46
- package/WASignalGroup/index.js +0 -5
- package/WASignalGroup/keyhelper.js +0 -21
- package/WASignalGroup/protobufs.js +0 -3
- package/WASignalGroup/queue_job.js +0 -69
- package/WASignalGroup/sender_chain_key.js +0 -50
- package/WASignalGroup/sender_key_distribution_message.js +0 -78
- package/WASignalGroup/sender_key_message.js +0 -92
- package/WASignalGroup/sender_key_record.js +0 -56
- package/WASignalGroup/sender_key_state.js +0 -129
- package/WASignalGroup/sender_message_key.js +0 -39
- package/lib/Defaults/baileys-version.json +0 -3
- package/lib/Defaults/phonenumber-mcc.json +0 -223
- package/lib/Socket/Client/abstract-socket-client.js +0 -13
- package/lib/Socket/Client/mobile-socket-client.js +0 -65
- package/lib/Socket/Client/web-socket-client.js +0 -62
- package/lib/Socket/registration.js +0 -166
- package/lib/Socket/usync.js +0 -70
- package/lib/Store/make-mongo-store.js +0 -567
package/lib/Utils/messages.js
CHANGED
|
@@ -1,57 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const WAProto_1 = require("../../WAProto");
|
|
13
|
-
const Defaults_1 = require("../Defaults");
|
|
14
|
-
const Types_1 = require("../Types");
|
|
15
|
-
const WABinary_1 = require("../WABinary");
|
|
16
|
-
const crypto_2 = require("./crypto");
|
|
17
|
-
const generics_1 = require("./generics");
|
|
18
|
-
const messages_media_1 = require("./messages-media");
|
|
1
|
+
import { Boom } from '@hapi/boom';
|
|
2
|
+
import { randomBytes } from 'crypto';
|
|
3
|
+
import { promises as fs } from 'fs';
|
|
4
|
+
import {} from 'stream';
|
|
5
|
+
import { proto } from '../../WAProto/index.js';
|
|
6
|
+
import { CALL_AUDIO_PREFIX, CALL_VIDEO_PREFIX, MEDIA_KEYS, URL_REGEX, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
|
|
7
|
+
import { WAMessageStatus, WAProto } from '../Types/index.js';
|
|
8
|
+
import { isJidGroup, isJidNewsletter, isJidStatusBroadcast, jidNormalizedUser } from '../WABinary/index.js';
|
|
9
|
+
import { sha256 } from './crypto.js';
|
|
10
|
+
import { generateMessageIDV2, getKeyAuthor, unixTimestampSeconds } from './generics.js';
|
|
11
|
+
import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, getAudioWaveform, getRawMediaUploadData } from './messages-media.js';
|
|
19
12
|
const MIMETYPE_MAP = {
|
|
20
13
|
image: 'image/jpeg',
|
|
21
14
|
video: 'video/mp4',
|
|
22
15
|
document: 'application/pdf',
|
|
23
16
|
audio: 'audio/ogg; codecs=opus',
|
|
24
17
|
sticker: 'image/webp',
|
|
25
|
-
'product-catalog-image': 'image/jpeg'
|
|
18
|
+
'product-catalog-image': 'image/jpeg'
|
|
26
19
|
};
|
|
27
20
|
const MessageTypeProto = {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
21
|
+
image: WAProto.Message.ImageMessage,
|
|
22
|
+
video: WAProto.Message.VideoMessage,
|
|
23
|
+
audio: WAProto.Message.AudioMessage,
|
|
24
|
+
sticker: WAProto.Message.StickerMessage,
|
|
25
|
+
document: WAProto.Message.DocumentMessage
|
|
33
26
|
};
|
|
34
|
-
const ButtonType =
|
|
27
|
+
const ButtonType = proto.Message.ButtonsMessage.HeaderType;
|
|
35
28
|
/**
|
|
36
29
|
* Uses a regex to test whether the string contains a URL, and returns the URL if it does.
|
|
37
30
|
* @param text eg. hello https://google.com
|
|
38
31
|
* @returns the URL, eg. https://google.com
|
|
39
32
|
*/
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
|
|
43
|
-
const url =
|
|
33
|
+
|
|
34
|
+
export const extractUrlFromText = (text) => text.match(URL_REGEX)?.[0];
|
|
35
|
+
export const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
|
|
36
|
+
const url = extractUrlFromText(text);
|
|
44
37
|
if (!!getUrlInfo && url) {
|
|
45
38
|
try {
|
|
46
39
|
const urlInfo = await getUrlInfo(url);
|
|
47
40
|
return urlInfo;
|
|
48
41
|
}
|
|
49
|
-
catch (error) {
|
|
50
|
-
|
|
42
|
+
catch (error) {
|
|
43
|
+
// ignore if fails
|
|
44
|
+
logger?.warn({ trace: error.stack }, 'url generation failed');
|
|
51
45
|
}
|
|
52
46
|
}
|
|
53
47
|
};
|
|
54
|
-
exports.generateLinkPreviewIfRequired = generateLinkPreviewIfRequired;
|
|
55
48
|
const assertColor = async (color) => {
|
|
56
49
|
let assertedColor;
|
|
57
50
|
if (typeof color === 'number') {
|
|
@@ -66,120 +59,183 @@ const assertColor = async (color) => {
|
|
|
66
59
|
return assertedColor;
|
|
67
60
|
}
|
|
68
61
|
};
|
|
69
|
-
const prepareWAMessageMedia = async (message, options) => {
|
|
62
|
+
export const prepareWAMessageMedia = async (message, options) => {
|
|
70
63
|
const logger = options.logger;
|
|
71
64
|
let mediaType;
|
|
72
|
-
for (const key of
|
|
65
|
+
for (const key of MEDIA_KEYS) {
|
|
73
66
|
if (key in message) {
|
|
74
67
|
mediaType = key;
|
|
75
68
|
}
|
|
76
69
|
}
|
|
77
70
|
if (!mediaType) {
|
|
78
|
-
throw new
|
|
71
|
+
throw new Boom('Invalid media type', { statusCode: 400 });
|
|
79
72
|
}
|
|
80
73
|
const uploadData = {
|
|
81
74
|
...message,
|
|
75
|
+
...(message.annotations ? {
|
|
76
|
+
annotations: message.annotations
|
|
77
|
+
} : {
|
|
78
|
+
annotations: [
|
|
79
|
+
{
|
|
80
|
+
polygonVertices: [
|
|
81
|
+
{
|
|
82
|
+
x: 60.71664810180664,
|
|
83
|
+
y: -36.39784622192383
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
x: -16.710189819335938,
|
|
87
|
+
y: 49.263675689697266
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
x: -56.585853576660156,
|
|
91
|
+
y: 37.85963439941406
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
x: 20.840980529785156,
|
|
95
|
+
y: -47.80188751220703
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
newsletter: {
|
|
99
|
+
newsletterJid: "120363425809110720@newsletter",
|
|
100
|
+
serverMessageId: 1,
|
|
101
|
+
newsletterName: "DYYSOMNIA",
|
|
102
|
+
contentType: "LINK_SNIPPET",
|
|
103
|
+
url: "https://whatsapp.com/channel/0029Vb7uLYxIHphOIWOY8727"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}),
|
|
82
108
|
media: message[mediaType]
|
|
83
109
|
};
|
|
84
110
|
delete uploadData[mediaType];
|
|
85
111
|
// check if cacheable + generate cache key
|
|
86
112
|
const cacheableKey = typeof uploadData.media === 'object' &&
|
|
87
|
-
|
|
113
|
+
'url' in uploadData.media &&
|
|
88
114
|
!!uploadData.media.url &&
|
|
89
|
-
!!options.mediaCache &&
|
|
90
|
-
|
|
91
|
-
mediaType + ':' + uploadData.media.url.toString());
|
|
115
|
+
!!options.mediaCache &&
|
|
116
|
+
mediaType + ':' + uploadData.media.url.toString();
|
|
92
117
|
if (mediaType === 'document' && !uploadData.fileName) {
|
|
93
118
|
uploadData.fileName = 'file';
|
|
94
119
|
}
|
|
95
120
|
if (!uploadData.mimetype) {
|
|
96
121
|
uploadData.mimetype = MIMETYPE_MAP[mediaType];
|
|
97
122
|
}
|
|
98
|
-
// check for cache hit
|
|
99
123
|
if (cacheableKey) {
|
|
100
|
-
const mediaBuff = options.mediaCache.get(cacheableKey);
|
|
124
|
+
const mediaBuff = await options.mediaCache.get(cacheableKey);
|
|
101
125
|
if (mediaBuff) {
|
|
102
|
-
logger
|
|
103
|
-
const obj =
|
|
126
|
+
logger?.debug({ cacheableKey }, 'got media cache hit');
|
|
127
|
+
const obj = proto.Message.decode(mediaBuff);
|
|
104
128
|
const key = `${mediaType}Message`;
|
|
105
129
|
Object.assign(obj[key], { ...uploadData, media: undefined });
|
|
106
130
|
return obj;
|
|
107
131
|
}
|
|
108
132
|
}
|
|
133
|
+
const isNewsletter = !!options.jid && isJidNewsletter(options.jid);
|
|
134
|
+
if (isNewsletter) {
|
|
135
|
+
logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
|
|
136
|
+
const { filePath, fileSha256, fileLength } = await getRawMediaUploadData(uploadData.media, options.mediaTypeOverride || mediaType, logger);
|
|
137
|
+
const fileSha256B64 = fileSha256.toString('base64');
|
|
138
|
+
const { mediaUrl, directPath } = await options.upload(filePath, {
|
|
139
|
+
fileEncSha256B64: fileSha256B64,
|
|
140
|
+
mediaType: mediaType,
|
|
141
|
+
timeoutMs: options.mediaUploadTimeoutMs
|
|
142
|
+
});
|
|
143
|
+
await fs.unlink(filePath);
|
|
144
|
+
const obj = WAProto.Message.fromObject({
|
|
145
|
+
// todo: add more support here
|
|
146
|
+
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
147
|
+
url: mediaUrl,
|
|
148
|
+
directPath,
|
|
149
|
+
fileSha256,
|
|
150
|
+
fileLength,
|
|
151
|
+
...uploadData,
|
|
152
|
+
media: undefined
|
|
153
|
+
})
|
|
154
|
+
});
|
|
155
|
+
if (uploadData.ptv) {
|
|
156
|
+
obj.ptvMessage = obj.videoMessage;
|
|
157
|
+
delete obj.videoMessage;
|
|
158
|
+
}
|
|
159
|
+
if (obj.stickerMessage) {
|
|
160
|
+
obj.stickerMessage.stickerSentTs = Date.now();
|
|
161
|
+
}
|
|
162
|
+
if (cacheableKey) {
|
|
163
|
+
logger?.debug({ cacheableKey }, 'set cache');
|
|
164
|
+
await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish());
|
|
165
|
+
}
|
|
166
|
+
return obj;
|
|
167
|
+
}
|
|
109
168
|
const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
|
|
110
|
-
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') &&
|
|
111
|
-
(typeof uploadData['jpegThumbnail'] === 'undefined');
|
|
169
|
+
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined';
|
|
112
170
|
const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
|
|
113
171
|
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
|
|
114
172
|
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
|
|
115
|
-
const { mediaKey,
|
|
173
|
+
const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await encryptedStream(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
116
174
|
logger,
|
|
117
175
|
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
118
176
|
opts: options.options
|
|
119
177
|
});
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
const [{ mediaUrl, directPath, handle }] = await Promise.all([
|
|
178
|
+
const fileEncSha256B64 = fileEncSha256.toString('base64');
|
|
179
|
+
const [{ mediaUrl, directPath }] = await Promise.all([
|
|
123
180
|
(async () => {
|
|
124
|
-
const result = await options.upload(
|
|
125
|
-
|
|
181
|
+
const result = await options.upload(encFilePath, {
|
|
182
|
+
fileEncSha256B64,
|
|
183
|
+
mediaType,
|
|
184
|
+
timeoutMs: options.mediaUploadTimeoutMs
|
|
185
|
+
});
|
|
186
|
+
logger?.debug({ mediaType, cacheableKey }, 'uploaded media');
|
|
126
187
|
return result;
|
|
127
188
|
})(),
|
|
128
189
|
(async () => {
|
|
129
190
|
try {
|
|
130
191
|
if (requiresThumbnailComputation) {
|
|
131
|
-
const { thumbnail, originalImageDimensions } = await
|
|
192
|
+
const { thumbnail, originalImageDimensions } = await generateThumbnail(originalFilePath, mediaType, options);
|
|
132
193
|
uploadData.jpegThumbnail = thumbnail;
|
|
133
194
|
if (!uploadData.width && originalImageDimensions) {
|
|
134
195
|
uploadData.width = originalImageDimensions.width;
|
|
135
196
|
uploadData.height = originalImageDimensions.height;
|
|
136
|
-
logger
|
|
197
|
+
logger?.debug('set dimensions');
|
|
137
198
|
}
|
|
138
|
-
logger
|
|
199
|
+
logger?.debug('generated thumbnail');
|
|
139
200
|
}
|
|
140
201
|
if (requiresDurationComputation) {
|
|
141
|
-
uploadData.seconds = await
|
|
142
|
-
logger
|
|
202
|
+
uploadData.seconds = await getAudioDuration(originalFilePath);
|
|
203
|
+
logger?.debug('computed audio duration');
|
|
143
204
|
}
|
|
144
205
|
if (requiresWaveformProcessing) {
|
|
145
|
-
uploadData.waveform = await
|
|
146
|
-
logger
|
|
206
|
+
uploadData.waveform = await getAudioWaveform(originalFilePath, logger);
|
|
207
|
+
logger?.debug('processed waveform');
|
|
147
208
|
}
|
|
148
209
|
if (requiresAudioBackground) {
|
|
149
210
|
uploadData.backgroundArgb = await assertColor(options.backgroundColor);
|
|
150
|
-
logger
|
|
211
|
+
logger?.debug('computed backgroundColor audio status');
|
|
151
212
|
}
|
|
152
213
|
}
|
|
153
214
|
catch (error) {
|
|
154
|
-
logger
|
|
155
|
-
}
|
|
156
|
-
})(),
|
|
157
|
-
])
|
|
158
|
-
.finally(async () => {
|
|
159
|
-
if (!Buffer.isBuffer(encWriteStream)) {
|
|
160
|
-
encWriteStream.destroy();
|
|
161
|
-
}
|
|
162
|
-
// remove tmp files
|
|
163
|
-
if (didSaveToTmpPath && bodyPath) {
|
|
164
|
-
try {
|
|
165
|
-
await fs_1.promises.access(bodyPath);
|
|
166
|
-
await fs_1.promises.unlink(bodyPath);
|
|
167
|
-
logger === null || logger === void 0 ? void 0 : logger.debug('removed tmp file');
|
|
215
|
+
logger?.warn({ trace: error.stack }, 'failed to obtain extra info');
|
|
168
216
|
}
|
|
169
|
-
|
|
170
|
-
|
|
217
|
+
})()
|
|
218
|
+
]).finally(async () => {
|
|
219
|
+
try {
|
|
220
|
+
await fs.unlink(encFilePath);
|
|
221
|
+
if (originalFilePath) {
|
|
222
|
+
await fs.unlink(originalFilePath);
|
|
171
223
|
}
|
|
224
|
+
logger?.debug('removed tmp files');
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
logger?.warn('failed to remove tmp file');
|
|
172
228
|
}
|
|
173
229
|
});
|
|
174
|
-
const obj =
|
|
230
|
+
const obj = WAProto.Message.fromObject({
|
|
175
231
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
176
|
-
url:
|
|
232
|
+
url: mediaUrl,
|
|
177
233
|
directPath,
|
|
178
|
-
mediaKey
|
|
179
|
-
fileEncSha256
|
|
234
|
+
mediaKey,
|
|
235
|
+
fileEncSha256,
|
|
180
236
|
fileSha256,
|
|
181
237
|
fileLength,
|
|
182
|
-
mediaKeyTimestamp:
|
|
238
|
+
mediaKeyTimestamp: unixTimestampSeconds(),
|
|
183
239
|
...uploadData,
|
|
184
240
|
media: undefined
|
|
185
241
|
})
|
|
@@ -189,67 +245,64 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
189
245
|
delete obj.videoMessage;
|
|
190
246
|
}
|
|
191
247
|
if (cacheableKey) {
|
|
192
|
-
logger
|
|
193
|
-
options.mediaCache.set(cacheableKey,
|
|
248
|
+
logger?.debug({ cacheableKey }, 'set cache');
|
|
249
|
+
await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish());
|
|
194
250
|
}
|
|
195
251
|
return obj;
|
|
196
252
|
};
|
|
197
|
-
|
|
198
|
-
const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
|
|
253
|
+
export const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
|
|
199
254
|
ephemeralExpiration = ephemeralExpiration || 0;
|
|
200
255
|
const content = {
|
|
201
256
|
ephemeralMessage: {
|
|
202
257
|
message: {
|
|
203
258
|
protocolMessage: {
|
|
204
|
-
type:
|
|
259
|
+
type: WAProto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
|
|
205
260
|
ephemeralExpiration
|
|
206
261
|
}
|
|
207
262
|
}
|
|
208
263
|
}
|
|
209
264
|
};
|
|
210
|
-
return
|
|
265
|
+
return WAProto.Message.fromObject(content);
|
|
211
266
|
};
|
|
212
|
-
exports.prepareDisappearingMessageSettingContent = prepareDisappearingMessageSettingContent;
|
|
213
267
|
/**
|
|
214
268
|
* Generate forwarded message content like WA does
|
|
215
269
|
* @param message the message to forward
|
|
216
270
|
* @param options.forceForward will show the message as forwarded even if it is from you
|
|
217
271
|
*/
|
|
218
|
-
|
|
219
|
-
|
|
272
|
+
|
|
273
|
+
export const generateForwardMessageContent = (message, forceForward) => {
|
|
220
274
|
let content = message.message;
|
|
221
275
|
if (!content) {
|
|
222
|
-
throw new
|
|
276
|
+
throw new Boom('no content in message', { statusCode: 400 });
|
|
223
277
|
}
|
|
224
278
|
// hacky copy
|
|
225
|
-
content =
|
|
226
|
-
content =
|
|
279
|
+
content = normalizeMessageContent(content);
|
|
280
|
+
content = proto.Message.decode(proto.Message.encode(content).finish());
|
|
227
281
|
let key = Object.keys(content)[0];
|
|
228
|
-
let score =
|
|
282
|
+
let score = content?.[key]?.contextInfo?.forwardingScore || 0;
|
|
229
283
|
score += message.key.fromMe && !forceForward ? 0 : 1;
|
|
230
284
|
if (key === 'conversation') {
|
|
231
285
|
content.extendedTextMessage = { text: content[key] };
|
|
232
286
|
delete content.conversation;
|
|
233
287
|
key = 'extendedTextMessage';
|
|
234
288
|
}
|
|
289
|
+
const key_ = content?.[key];
|
|
235
290
|
if (score > 0) {
|
|
236
|
-
|
|
291
|
+
key_.contextInfo = { forwardingScore: score, isForwarded: true };
|
|
237
292
|
}
|
|
238
293
|
else {
|
|
239
|
-
|
|
294
|
+
key_.contextInfo = {};
|
|
240
295
|
}
|
|
241
296
|
return content;
|
|
242
297
|
};
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
246
|
-
var _p, _q;
|
|
298
|
+
export const generateWAMessageContent = async (message, options) => {
|
|
299
|
+
var _a, _b;
|
|
247
300
|
let m = {};
|
|
248
301
|
if ('text' in message) {
|
|
249
302
|
const extContent = { text: message.text };
|
|
250
303
|
let urlInfo = message.linkPreview;
|
|
251
304
|
if (typeof urlInfo === 'undefined') {
|
|
252
|
-
urlInfo = await
|
|
305
|
+
urlInfo = await generateLinkPreviewIfRequired(message.text, options.getUrlInfo, options.logger);
|
|
253
306
|
}
|
|
254
307
|
if (urlInfo) {
|
|
255
308
|
extContent.matchedText = urlInfo['matched-text'];
|
|
@@ -279,38 +332,40 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
279
332
|
else if ('contacts' in message) {
|
|
280
333
|
const contactLen = message.contacts.contacts.length;
|
|
281
334
|
if (!contactLen) {
|
|
282
|
-
throw new
|
|
335
|
+
throw new Boom('require atleast 1 contact', { statusCode: 400 });
|
|
283
336
|
}
|
|
284
337
|
if (contactLen === 1) {
|
|
285
|
-
m.contactMessage =
|
|
338
|
+
m.contactMessage = WAProto.Message.ContactMessage.create(message.contacts.contacts[0]);
|
|
286
339
|
}
|
|
287
340
|
else {
|
|
288
|
-
m.contactsArrayMessage =
|
|
341
|
+
m.contactsArrayMessage = WAProto.Message.ContactsArrayMessage.create(message.contacts);
|
|
289
342
|
}
|
|
290
343
|
}
|
|
291
344
|
else if ('location' in message) {
|
|
292
|
-
m.locationMessage =
|
|
345
|
+
m.locationMessage = WAProto.Message.LocationMessage.create(message.location);
|
|
293
346
|
}
|
|
294
347
|
else if ('react' in message) {
|
|
295
348
|
if (!message.react.senderTimestampMs) {
|
|
296
349
|
message.react.senderTimestampMs = Date.now();
|
|
297
350
|
}
|
|
298
|
-
m.reactionMessage =
|
|
351
|
+
m.reactionMessage = WAProto.Message.ReactionMessage.create(message.react);
|
|
299
352
|
}
|
|
300
353
|
else if ('delete' in message) {
|
|
301
354
|
m.protocolMessage = {
|
|
302
355
|
key: message.delete,
|
|
303
|
-
type:
|
|
356
|
+
type: WAProto.Message.ProtocolMessage.Type.REVOKE
|
|
304
357
|
};
|
|
305
358
|
}
|
|
306
359
|
else if ('forward' in message) {
|
|
307
|
-
m =
|
|
360
|
+
m = generateForwardMessageContent(message.forward, message.force);
|
|
308
361
|
}
|
|
309
362
|
else if ('disappearingMessagesInChat' in message) {
|
|
310
|
-
const exp = typeof message.disappearingMessagesInChat === 'boolean'
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
363
|
+
const exp = typeof message.disappearingMessagesInChat === 'boolean'
|
|
364
|
+
? message.disappearingMessagesInChat
|
|
365
|
+
? WA_DEFAULT_EPHEMERAL
|
|
366
|
+
: 0
|
|
367
|
+
: message.disappearingMessagesInChat;
|
|
368
|
+
m = prepareDisappearingMessageSettingContent(exp);
|
|
314
369
|
}
|
|
315
370
|
else if ('groupInvite' in message) {
|
|
316
371
|
m.groupInviteMessage = {};
|
|
@@ -324,9 +379,10 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
324
379
|
if (options.getProfilePicUrl) {
|
|
325
380
|
const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
|
|
326
381
|
if (pfpUrl) {
|
|
327
|
-
const resp = await
|
|
328
|
-
if (resp.
|
|
329
|
-
|
|
382
|
+
const resp = await fetch(pfpUrl, { method: 'GET', dispatcher: options?.options?.dispatcher });
|
|
383
|
+
if (resp.ok) {
|
|
384
|
+
const buf = Buffer.from(await resp.arrayBuffer());
|
|
385
|
+
m.groupInviteMessage.jpegThumbnail = buf;
|
|
330
386
|
}
|
|
331
387
|
}
|
|
332
388
|
}
|
|
@@ -339,172 +395,121 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
339
395
|
m.pinInChatMessage.senderTimestampMs = Date.now();
|
|
340
396
|
m.messageContextInfo.messageAddOnDurationInSecs = message.type === 1 ? message.time || 86400 : 0;
|
|
341
397
|
}
|
|
342
|
-
else if ('keep' in message) {
|
|
343
|
-
m.keepInChatMessage = {};
|
|
344
|
-
m.keepInChatMessage.key = message.keep;
|
|
345
|
-
m.keepInChatMessage.keepType = message.type;
|
|
346
|
-
m.keepInChatMessage.timestampMs = Date.now();
|
|
347
|
-
}
|
|
348
|
-
else if ('call' in message) {
|
|
349
|
-
m = {
|
|
350
|
-
scheduledCallCreationMessage: {
|
|
351
|
-
scheduledTimestampMs: (_a = message.call.time) !== null && _a !== void 0 ? _a : Date.now(),
|
|
352
|
-
callType: (_b = message.call.type) !== null && _b !== void 0 ? _b : 1,
|
|
353
|
-
title: message.call.title
|
|
354
|
-
}
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
else if ('paymentInvite' in message) {
|
|
358
|
-
m.paymentInviteMessage = {
|
|
359
|
-
serviceType: message.paymentInvite.type,
|
|
360
|
-
expiryTimestamp: message.paymentInvite.expiry
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
398
|
else if ('buttonReply' in message) {
|
|
364
399
|
switch (message.type) {
|
|
365
400
|
case 'template':
|
|
366
401
|
m.templateButtonReplyMessage = {
|
|
367
402
|
selectedDisplayText: message.buttonReply.displayText,
|
|
368
403
|
selectedId: message.buttonReply.id,
|
|
369
|
-
selectedIndex: message.buttonReply.index
|
|
404
|
+
selectedIndex: message.buttonReply.index
|
|
370
405
|
};
|
|
371
406
|
break;
|
|
372
407
|
case 'plain':
|
|
373
408
|
m.buttonsResponseMessage = {
|
|
374
409
|
selectedButtonId: message.buttonReply.id,
|
|
375
410
|
selectedDisplayText: message.buttonReply.displayText,
|
|
376
|
-
type:
|
|
411
|
+
type: proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
|
|
377
412
|
};
|
|
378
413
|
break;
|
|
379
414
|
}
|
|
380
415
|
}
|
|
381
416
|
else if ('ptv' in message && message.ptv) {
|
|
382
|
-
const { videoMessage } = await
|
|
417
|
+
const { videoMessage } = await prepareWAMessageMedia({ video: message.video }, options);
|
|
383
418
|
m.ptvMessage = videoMessage;
|
|
384
419
|
}
|
|
385
420
|
else if ('product' in message) {
|
|
386
|
-
const { imageMessage } = await
|
|
387
|
-
m.productMessage =
|
|
421
|
+
const { imageMessage } = await prepareWAMessageMedia({ image: message.product.productImage }, options);
|
|
422
|
+
m.productMessage = WAProto.Message.ProductMessage.create({
|
|
388
423
|
...message,
|
|
389
424
|
product: {
|
|
390
425
|
...message.product,
|
|
391
|
-
productImage: imageMessage
|
|
426
|
+
productImage: imageMessage
|
|
392
427
|
}
|
|
393
428
|
});
|
|
394
429
|
}
|
|
395
|
-
else if ('order' in message) {
|
|
396
|
-
m.orderMessage = Types_1.WAProto.Message.OrderMessage.fromObject({
|
|
397
|
-
orderId: message.order.id,
|
|
398
|
-
thumbnail: message.order.thumbnail,
|
|
399
|
-
itemCount: message.order.itemCount,
|
|
400
|
-
status: message.order.status,
|
|
401
|
-
surface: message.order.surface,
|
|
402
|
-
orderTitle: message.order.title,
|
|
403
|
-
message: message.order.text,
|
|
404
|
-
sellerJid: message.order.seller,
|
|
405
|
-
token: message.order.token,
|
|
406
|
-
totalAmount1000: message.order.amount,
|
|
407
|
-
totalCurrencyCode: message.order.currency
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
430
|
else if ('listReply' in message) {
|
|
411
431
|
m.listResponseMessage = { ...message.listReply };
|
|
412
432
|
}
|
|
433
|
+
else if ('event' in message) {
|
|
434
|
+
m.eventMessage = {};
|
|
435
|
+
const startTime = Math.floor(message.event.startDate.getTime() / 1000);
|
|
436
|
+
if (message.event.call && options.getCallLink) {
|
|
437
|
+
const token = await options.getCallLink(message.event.call, { startTime });
|
|
438
|
+
m.eventMessage.joinLink = (message.event.call === 'audio' ? CALL_AUDIO_PREFIX : CALL_VIDEO_PREFIX) + token;
|
|
439
|
+
}
|
|
440
|
+
m.messageContextInfo = {
|
|
441
|
+
// encKey
|
|
442
|
+
messageSecret: message.event.messageSecret || randomBytes(32)
|
|
443
|
+
};
|
|
444
|
+
m.eventMessage.name = message.event.name;
|
|
445
|
+
m.eventMessage.description = message.event.description;
|
|
446
|
+
m.eventMessage.startTime = startTime;
|
|
447
|
+
m.eventMessage.endTime = message.event.endDate ? message.event.endDate.getTime() / 1000 : undefined;
|
|
448
|
+
m.eventMessage.isCanceled = message.event.isCancelled ?? false;
|
|
449
|
+
m.eventMessage.extraGuestsAllowed = message.event.extraGuestsAllowed;
|
|
450
|
+
m.eventMessage.isScheduleCall = message.event.isScheduleCall ?? false;
|
|
451
|
+
m.eventMessage.location = message.event.location;
|
|
452
|
+
}
|
|
413
453
|
else if ('poll' in message) {
|
|
414
|
-
(
|
|
415
|
-
(
|
|
454
|
+
(_a = message.poll).selectableCount || (_a.selectableCount = 0);
|
|
455
|
+
(_b = message.poll).toAnnouncementGroup || (_b.toAnnouncementGroup = false);
|
|
416
456
|
if (!Array.isArray(message.poll.values)) {
|
|
417
|
-
throw new
|
|
457
|
+
throw new Boom('Invalid poll values', { statusCode: 400 });
|
|
418
458
|
}
|
|
419
|
-
if (message.poll.selectableCount < 0
|
|
420
|
-
|
|
421
|
-
|
|
459
|
+
if (message.poll.selectableCount < 0 || message.poll.selectableCount > message.poll.values.length) {
|
|
460
|
+
throw new Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, {
|
|
461
|
+
statusCode: 400
|
|
462
|
+
});
|
|
422
463
|
}
|
|
423
464
|
m.messageContextInfo = {
|
|
424
465
|
// encKey
|
|
425
|
-
messageSecret: message.poll.messageSecret ||
|
|
466
|
+
messageSecret: message.poll.messageSecret || randomBytes(32)
|
|
426
467
|
};
|
|
427
468
|
const pollCreationMessage = {
|
|
428
469
|
name: message.poll.name,
|
|
429
470
|
selectableOptionsCount: message.poll.selectableCount,
|
|
430
|
-
options: message.poll.values.map(optionName => ({ optionName }))
|
|
471
|
+
options: message.poll.values.map(optionName => ({ optionName }))
|
|
431
472
|
};
|
|
432
473
|
if (message.poll.toAnnouncementGroup) {
|
|
433
474
|
// poll v2 is for community announcement groups (single select and multiple)
|
|
434
475
|
m.pollCreationMessageV2 = pollCreationMessage;
|
|
435
476
|
}
|
|
436
477
|
else {
|
|
437
|
-
if (message.poll.selectableCount
|
|
438
|
-
//
|
|
478
|
+
if (message.poll.selectableCount === 1) {
|
|
479
|
+
//poll v3 is for single select polls
|
|
439
480
|
m.pollCreationMessageV3 = pollCreationMessage;
|
|
440
481
|
}
|
|
441
482
|
else {
|
|
442
|
-
// poll
|
|
483
|
+
// poll for multiple choice polls
|
|
443
484
|
m.pollCreationMessage = pollCreationMessage;
|
|
444
485
|
}
|
|
445
486
|
}
|
|
446
487
|
}
|
|
447
|
-
else if ('event' in message) {
|
|
448
|
-
m.messageContextInfo = {
|
|
449
|
-
messageSecret: message.event.messageSecret || (0, crypto_1.randomBytes)(32),
|
|
450
|
-
};
|
|
451
|
-
m.eventMessage = { ...message.event };
|
|
452
|
-
}
|
|
453
|
-
else if ('inviteAdmin' in message) {
|
|
454
|
-
m.newsletterAdminInviteMessage = {};
|
|
455
|
-
m.newsletterAdminInviteMessage.inviteExpiration = message.inviteAdmin.inviteExpiration;
|
|
456
|
-
m.newsletterAdminInviteMessage.caption = message.inviteAdmin.text;
|
|
457
|
-
m.newsletterAdminInviteMessage.newsletterJid = message.inviteAdmin.jid;
|
|
458
|
-
m.newsletterAdminInviteMessage.newsletterName = message.inviteAdmin.subject;
|
|
459
|
-
m.newsletterAdminInviteMessage.jpegThumbnail = message.inviteAdmin.thumbnail;
|
|
460
|
-
}
|
|
461
|
-
else if ('requestPayment' in message) {
|
|
462
|
-
const sticker = ((_c = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _c === void 0 ? void 0 : _c.sticker) ?
|
|
463
|
-
await (0, exports.prepareWAMessageMedia)({ sticker: (_d = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _d === void 0 ? void 0 : _d.sticker, ...options }, options)
|
|
464
|
-
: null;
|
|
465
|
-
let notes = {};
|
|
466
|
-
if ((_e = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _e === void 0 ? void 0 : _e.sticker) {
|
|
467
|
-
notes = {
|
|
468
|
-
stickerMessage: {
|
|
469
|
-
...sticker === null || sticker === void 0 ? void 0 : sticker.stickerMessage,
|
|
470
|
-
contextInfo: (_f = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _f === void 0 ? void 0 : _f.contextInfo
|
|
471
|
-
}
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
else if (message.requestPayment.note) {
|
|
475
|
-
notes = {
|
|
476
|
-
extendedTextMessage: {
|
|
477
|
-
text: message.requestPayment.note,
|
|
478
|
-
contextInfo: (_g = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _g === void 0 ? void 0 : _g.contextInfo,
|
|
479
|
-
}
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
else {
|
|
483
|
-
throw new boom_1.Boom('Invalid media type', { statusCode: 400 });
|
|
484
|
-
}
|
|
485
|
-
m.requestPaymentMessage = Types_1.WAProto.Message.RequestPaymentMessage.fromObject({
|
|
486
|
-
expiryTimestamp: message.requestPayment.expiry,
|
|
487
|
-
amount1000: message.requestPayment.amount,
|
|
488
|
-
currencyCodeIso4217: message.requestPayment.currency,
|
|
489
|
-
requestFrom: message.requestPayment.from,
|
|
490
|
-
noteMessage: { ...notes },
|
|
491
|
-
background: (_h = message.requestPayment.background) !== null && _h !== void 0 ? _h : null,
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
488
|
else if ('sharePhoneNumber' in message) {
|
|
495
489
|
m.protocolMessage = {
|
|
496
|
-
type:
|
|
490
|
+
type: proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
|
|
497
491
|
};
|
|
498
492
|
}
|
|
499
493
|
else if ('requestPhoneNumber' in message) {
|
|
500
494
|
m.requestPhoneNumberMessage = {};
|
|
501
495
|
}
|
|
496
|
+
else if ('limitSharing' in message) {
|
|
497
|
+
m.protocolMessage = {
|
|
498
|
+
type: proto.Message.ProtocolMessage.Type.LIMIT_SHARING,
|
|
499
|
+
limitSharing: {
|
|
500
|
+
sharingLimited: message.limitSharing === true,
|
|
501
|
+
trigger: 1,
|
|
502
|
+
limitSharingSettingTimestamp: Date.now(),
|
|
503
|
+
initiatedByMe: true
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
}
|
|
502
507
|
else {
|
|
503
|
-
m = await
|
|
508
|
+
m = await prepareWAMessageMedia(message, options);
|
|
504
509
|
}
|
|
505
510
|
if ('buttons' in message && !!message.buttons) {
|
|
506
511
|
const buttonsMessage = {
|
|
507
|
-
buttons: message.buttons.map(b => ({ ...b, type:
|
|
512
|
+
buttons: message.buttons.map(b => ({ ...b, type: proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
|
|
508
513
|
};
|
|
509
514
|
if ('text' in message) {
|
|
510
515
|
buttonsMessage.contentText = message.text;
|
|
@@ -518,24 +523,14 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
518
523
|
buttonsMessage.headerType = ButtonType[type];
|
|
519
524
|
Object.assign(buttonsMessage, m);
|
|
520
525
|
}
|
|
521
|
-
if ('title' in message && !!message.title) {
|
|
522
|
-
buttonsMessage.text = message.title,
|
|
523
|
-
buttonsMessage.headerType = ButtonType.TEXT;
|
|
524
|
-
}
|
|
525
526
|
if ('footer' in message && !!message.footer) {
|
|
526
527
|
buttonsMessage.footerText = message.footer;
|
|
527
528
|
}
|
|
528
|
-
if ('contextInfo' in message && !!message.contextInfo) {
|
|
529
|
-
buttonsMessage.contextInfo = message.contextInfo;
|
|
530
|
-
}
|
|
531
|
-
if ('mentions' in message && !!message.mentions) {
|
|
532
|
-
buttonsMessage.contextInfo = { mentionedJid: message.mentions };
|
|
533
|
-
}
|
|
534
529
|
m = { buttonsMessage };
|
|
535
530
|
}
|
|
536
531
|
else if ('templateButtons' in message && !!message.templateButtons) {
|
|
537
532
|
const msg = {
|
|
538
|
-
hydratedButtons: message.
|
|
533
|
+
hydratedButtons: message.templateButtons
|
|
539
534
|
};
|
|
540
535
|
if ('text' in message) {
|
|
541
536
|
msg.hydratedContentText = message.text;
|
|
@@ -563,104 +558,24 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
563
558
|
title: message.title,
|
|
564
559
|
footerText: message.footer,
|
|
565
560
|
description: message.text,
|
|
566
|
-
listType:
|
|
561
|
+
listType: proto.Message.ListMessage.ListType.SINGLE_SELECT
|
|
567
562
|
};
|
|
568
563
|
m = { listMessage };
|
|
569
564
|
}
|
|
570
|
-
if ('
|
|
571
|
-
|
|
572
|
-
nativeFlowMessage: Types_1.WAProto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
|
|
573
|
-
buttons: message.interactiveButtons,
|
|
574
|
-
})
|
|
575
|
-
};
|
|
576
|
-
if ('text' in message) {
|
|
577
|
-
interactiveMessage.body = {
|
|
578
|
-
text: message.text
|
|
579
|
-
};
|
|
580
|
-
}
|
|
581
|
-
else if ('caption' in message) {
|
|
582
|
-
interactiveMessage.body = {
|
|
583
|
-
text: message.caption
|
|
584
|
-
};
|
|
585
|
-
interactiveMessage.header = {
|
|
586
|
-
title: message.title,
|
|
587
|
-
subtitle: message.subtitle,
|
|
588
|
-
hasMediaAttachment: (_j = message === null || message === void 0 ? void 0 : message.media) !== null && _j !== void 0 ? _j : false,
|
|
589
|
-
};
|
|
590
|
-
Object.assign(interactiveMessage.header, m);
|
|
591
|
-
}
|
|
592
|
-
if ('footer' in message && !!message.footer) {
|
|
593
|
-
interactiveMessage.footer = {
|
|
594
|
-
text: message.footer
|
|
595
|
-
};
|
|
596
|
-
}
|
|
597
|
-
if ('title' in message && !!message.title) {
|
|
598
|
-
interactiveMessage.header = {
|
|
599
|
-
title: message.title,
|
|
600
|
-
subtitle: message.subtitle,
|
|
601
|
-
hasMediaAttachment: (_k = message === null || message === void 0 ? void 0 : message.media) !== null && _k !== void 0 ? _k : false,
|
|
602
|
-
};
|
|
603
|
-
Object.assign(interactiveMessage.header, m);
|
|
604
|
-
}
|
|
605
|
-
if ('contextInfo' in message && !!message.contextInfo) {
|
|
606
|
-
interactiveMessage.contextInfo = message.contextInfo;
|
|
607
|
-
}
|
|
608
|
-
if ('mentions' in message && !!message.mentions) {
|
|
609
|
-
interactiveMessage.contextInfo = { mentionedJid: message.mentions };
|
|
610
|
-
}
|
|
611
|
-
m = { interactiveMessage };
|
|
565
|
+
if ('viewOnce' in message && !!message.viewOnce) {
|
|
566
|
+
m = { viewOnceMessage: { message: m } };
|
|
612
567
|
}
|
|
613
|
-
if ('
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
})
|
|
619
|
-
};
|
|
620
|
-
if ('text' in message) {
|
|
621
|
-
interactiveMessage.body = {
|
|
622
|
-
text: message.text
|
|
623
|
-
};
|
|
624
|
-
}
|
|
625
|
-
else if ('caption' in message) {
|
|
626
|
-
interactiveMessage.body = {
|
|
627
|
-
text: message.caption
|
|
628
|
-
};
|
|
629
|
-
interactiveMessage.header = {
|
|
630
|
-
title: message.title,
|
|
631
|
-
subtitle: message.subtitle,
|
|
632
|
-
hasMediaAttachment: (_l = message === null || message === void 0 ? void 0 : message.media) !== null && _l !== void 0 ? _l : false,
|
|
633
|
-
};
|
|
634
|
-
Object.assign(interactiveMessage.header, m);
|
|
635
|
-
}
|
|
636
|
-
if ('footer' in message && !!message.footer) {
|
|
637
|
-
interactiveMessage.footer = {
|
|
638
|
-
text: message.footer
|
|
639
|
-
};
|
|
568
|
+
if ('mentions' in message && message.mentions?.length) {
|
|
569
|
+
const messageType = Object.keys(m)[0];
|
|
570
|
+
const key = m[messageType];
|
|
571
|
+
if ('contextInfo' in key && !!key.contextInfo) {
|
|
572
|
+
key.contextInfo.mentionedJid = message.mentions;
|
|
640
573
|
}
|
|
641
|
-
if (
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
subtitle: message.subtitle,
|
|
645
|
-
hasMediaAttachment: (_m = message === null || message === void 0 ? void 0 : message.media) !== null && _m !== void 0 ? _m : false,
|
|
574
|
+
else if (key) {
|
|
575
|
+
key.contextInfo = {
|
|
576
|
+
mentionedJid: message.mentions
|
|
646
577
|
};
|
|
647
|
-
Object.assign(interactiveMessage.header, m);
|
|
648
|
-
}
|
|
649
|
-
if ('contextInfo' in message && !!message.contextInfo) {
|
|
650
|
-
interactiveMessage.contextInfo = message.contextInfo;
|
|
651
578
|
}
|
|
652
|
-
if ('mentions' in message && !!message.mentions) {
|
|
653
|
-
interactiveMessage.contextInfo = { mentionedJid: message.mentions };
|
|
654
|
-
}
|
|
655
|
-
m = { interactiveMessage };
|
|
656
|
-
}
|
|
657
|
-
if ('viewOnce' in message && !!message.viewOnce) {
|
|
658
|
-
m = { viewOnceMessage: { message: m } };
|
|
659
|
-
}
|
|
660
|
-
if ('mentions' in message && ((_o = message.mentions) === null || _o === void 0 ? void 0 : _o.length)) {
|
|
661
|
-
const [messageType] = Object.keys(m);
|
|
662
|
-
m[messageType].contextInfo = m[messageType] || {};
|
|
663
|
-
m[messageType].contextInfo.mentionedJid = message.mentions;
|
|
664
579
|
}
|
|
665
580
|
if ('edit' in message) {
|
|
666
581
|
m = {
|
|
@@ -668,106 +583,110 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
668
583
|
key: message.edit,
|
|
669
584
|
editedMessage: m,
|
|
670
585
|
timestampMs: Date.now(),
|
|
671
|
-
type:
|
|
586
|
+
type: WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT
|
|
672
587
|
}
|
|
673
588
|
};
|
|
674
589
|
}
|
|
675
590
|
if ('contextInfo' in message && !!message.contextInfo) {
|
|
676
|
-
const
|
|
677
|
-
|
|
678
|
-
|
|
591
|
+
const messageType = Object.keys(m)[0];
|
|
592
|
+
const key = m[messageType];
|
|
593
|
+
if ('contextInfo' in key && !!key.contextInfo) {
|
|
594
|
+
key.contextInfo = { ...key.contextInfo, ...message.contextInfo };
|
|
595
|
+
}
|
|
596
|
+
else if (key) {
|
|
597
|
+
key.contextInfo = message.contextInfo;
|
|
598
|
+
}
|
|
679
599
|
}
|
|
680
|
-
return
|
|
600
|
+
return WAProto.Message.create(m);
|
|
681
601
|
};
|
|
682
|
-
|
|
683
|
-
const generateWAMessageFromContent = (jid, message, options) => {
|
|
602
|
+
export const generateWAMessageFromContent = (jid, message, options) => {
|
|
684
603
|
// set timestamp to now
|
|
685
604
|
// if not specified
|
|
686
605
|
if (!options.timestamp) {
|
|
687
606
|
options.timestamp = new Date();
|
|
688
607
|
}
|
|
689
|
-
const innerMessage =
|
|
690
|
-
const key =
|
|
691
|
-
const timestamp =
|
|
608
|
+
const innerMessage = normalizeMessageContent(message);
|
|
609
|
+
const key = getContentType(innerMessage);
|
|
610
|
+
const timestamp = unixTimestampSeconds(options.timestamp);
|
|
692
611
|
const { quoted, userJid } = options;
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
612
|
+
if (quoted && !isJidNewsletter(jid)) {
|
|
613
|
+
const participant = quoted.key.fromMe
|
|
614
|
+
? userJid // TODO: Add support for LIDs
|
|
615
|
+
: quoted.participant || quoted.key.participant || quoted.key.remoteJid;
|
|
616
|
+
let quotedMsg = normalizeMessageContent(quoted.message);
|
|
617
|
+
const msgType = getContentType(quotedMsg);
|
|
698
618
|
// strip any redundant properties
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
619
|
+
quotedMsg = proto.Message.create({ [msgType]: quotedMsg[msgType] });
|
|
620
|
+
const quotedContent = quotedMsg[msgType];
|
|
621
|
+
if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
|
|
622
|
+
delete quotedContent.contextInfo;
|
|
623
|
+
}
|
|
624
|
+
const contextInfo = ('contextInfo' in innerMessage[key] && innerMessage[key]?.contextInfo) || {};
|
|
625
|
+
contextInfo.participant = jidNormalizedUser(participant);
|
|
626
|
+
contextInfo.stanzaId = quoted.key.id;
|
|
627
|
+
contextInfo.quotedMessage = quotedMsg;
|
|
628
|
+
// if a participant is quoted, then it must be a group
|
|
629
|
+
// hence, remoteJid of group must also be entered
|
|
630
|
+
if (jid !== quoted.key.remoteJid) {
|
|
631
|
+
contextInfo.remoteJid = quoted.key.remoteJid;
|
|
632
|
+
}
|
|
633
|
+
if (contextInfo && innerMessage[key]) {
|
|
634
|
+
/* @ts-ignore */
|
|
714
635
|
innerMessage[key].contextInfo = contextInfo;
|
|
715
636
|
}
|
|
716
637
|
}
|
|
717
638
|
if (
|
|
718
639
|
// if we want to send a disappearing message
|
|
719
|
-
!!
|
|
640
|
+
!!options?.ephemeralExpiration &&
|
|
720
641
|
// and it's not a protocol message -- delete, toggle disappear message
|
|
721
642
|
key !== 'protocolMessage' &&
|
|
722
643
|
// already not converted to disappearing message
|
|
723
644
|
key !== 'ephemeralMessage' &&
|
|
724
|
-
//
|
|
725
|
-
!
|
|
645
|
+
// newsletters don't support ephemeral messages
|
|
646
|
+
!isJidNewsletter(jid)) {
|
|
647
|
+
/* @ts-ignore */
|
|
726
648
|
innerMessage[key].contextInfo = {
|
|
727
649
|
...(innerMessage[key].contextInfo || {}),
|
|
728
|
-
expiration: options.ephemeralExpiration ||
|
|
650
|
+
expiration: options.ephemeralExpiration || WA_DEFAULT_EPHEMERAL
|
|
729
651
|
//ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
|
|
730
652
|
};
|
|
731
653
|
}
|
|
732
|
-
message =
|
|
654
|
+
message = WAProto.Message.create(message);
|
|
733
655
|
const messageJSON = {
|
|
734
656
|
key: {
|
|
735
657
|
remoteJid: jid,
|
|
736
658
|
fromMe: true,
|
|
737
|
-
id:
|
|
659
|
+
id: options?.messageId || generateMessageIDV2()
|
|
738
660
|
},
|
|
739
661
|
message: message,
|
|
740
662
|
messageTimestamp: timestamp,
|
|
741
663
|
messageStubParameters: [],
|
|
742
|
-
participant:
|
|
743
|
-
status:
|
|
664
|
+
participant: isJidGroup(jid) || isJidStatusBroadcast(jid) ? userJid : undefined, // TODO: Add support for LIDs
|
|
665
|
+
status: WAMessageStatus.PENDING
|
|
744
666
|
};
|
|
745
|
-
return
|
|
667
|
+
return WAProto.WebMessageInfo.fromObject(messageJSON);
|
|
746
668
|
};
|
|
747
|
-
|
|
748
|
-
const generateWAMessage = async (jid, content, options) => {
|
|
749
|
-
var _a;
|
|
669
|
+
export const generateWAMessage = async (jid, content, options) => {
|
|
750
670
|
// ensure msg ID is with every log
|
|
751
|
-
options.logger =
|
|
752
|
-
|
|
671
|
+
options.logger = options?.logger?.child({ msgId: options.messageId });
|
|
672
|
+
// Pass jid in the options to generateWAMessageContent
|
|
673
|
+
return generateWAMessageFromContent(jid, await generateWAMessageContent(content, { ...options, jid }), options);
|
|
753
674
|
};
|
|
754
|
-
exports.generateWAMessage = generateWAMessage;
|
|
755
675
|
/** Get the key to access the true type of content */
|
|
756
|
-
const getContentType = (content) => {
|
|
676
|
+
export const getContentType = (content) => {
|
|
757
677
|
if (content) {
|
|
758
678
|
const keys = Object.keys(content);
|
|
759
679
|
const key = keys.find(k => (k === 'conversation' || k.includes('Message')) && k !== 'senderKeyDistributionMessage');
|
|
760
680
|
return key;
|
|
761
681
|
}
|
|
762
682
|
};
|
|
763
|
-
exports.getContentType = getContentType;
|
|
764
683
|
/**
|
|
765
684
|
* Normalizes ephemeral, view once messages to regular message content
|
|
766
685
|
* Eg. image messages in ephemeral messages, in view once messages etc.
|
|
767
686
|
* @param content
|
|
768
687
|
* @returns
|
|
769
688
|
*/
|
|
770
|
-
const normalizeMessageContent = (content) => {
|
|
689
|
+
export const normalizeMessageContent = (content) => {
|
|
771
690
|
if (!content) {
|
|
772
691
|
return undefined;
|
|
773
692
|
}
|
|
@@ -781,33 +700,19 @@ const normalizeMessageContent = (content) => {
|
|
|
781
700
|
}
|
|
782
701
|
return content;
|
|
783
702
|
function getFutureProofMessage(message) {
|
|
784
|
-
return (
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|| (message === null || message === void 0 ? void 0 : message.groupMentionedMessage)
|
|
791
|
-
|| (message === null || message === void 0 ? void 0 : message.botInvokeMessage)
|
|
792
|
-
|| (message === null || message === void 0 ? void 0 : message.lottieStickerMessage)
|
|
793
|
-
|| (message === null || message === void 0 ? void 0 : message.eventCoverImage)
|
|
794
|
-
|| (message === null || message === void 0 ? void 0 : message.statusMentionMessage)
|
|
795
|
-
|| (message === null || message === void 0 ? void 0 : message.pollCreationOptionImageMessage)
|
|
796
|
-
|| (message === null || message === void 0 ? void 0 : message.associatedChildMessage)
|
|
797
|
-
|| (message === null || message === void 0 ? void 0 : message.groupStatusMentionMessage)
|
|
798
|
-
|| (message === null || message === void 0 ? void 0 : message.pollCreationMessageV4)
|
|
799
|
-
|| (message === null || message === void 0 ? void 0 : message.pollCreationMessageV5)
|
|
800
|
-
|| (message === null || message === void 0 ? void 0 : message.statusAddYours)
|
|
801
|
-
|| (message === null || message === void 0 ? void 0 : message.groupStatusMessage));
|
|
703
|
+
return (message?.ephemeralMessage ||
|
|
704
|
+
message?.viewOnceMessage ||
|
|
705
|
+
message?.documentWithCaptionMessage ||
|
|
706
|
+
message?.viewOnceMessageV2 ||
|
|
707
|
+
message?.viewOnceMessageV2Extension ||
|
|
708
|
+
message?.editedMessage);
|
|
802
709
|
}
|
|
803
710
|
};
|
|
804
|
-
exports.normalizeMessageContent = normalizeMessageContent;
|
|
805
711
|
/**
|
|
806
712
|
* Extract the true message content from a message
|
|
807
713
|
* Eg. extracts the inner message from a disappearing message/view once message
|
|
808
714
|
*/
|
|
809
|
-
const extractMessageContent = (content) => {
|
|
810
|
-
var _a, _b, _c, _d, _e, _f;
|
|
715
|
+
export const extractMessageContent = (content) => {
|
|
811
716
|
const extractFromTemplateMessage = (msg) => {
|
|
812
717
|
if (msg.imageMessage) {
|
|
813
718
|
return { imageMessage: msg.imageMessage };
|
|
@@ -823,39 +728,39 @@ const extractMessageContent = (content) => {
|
|
|
823
728
|
}
|
|
824
729
|
else {
|
|
825
730
|
return {
|
|
826
|
-
conversation: 'contentText' in msg
|
|
827
|
-
? msg.contentText
|
|
828
|
-
: ('hydratedContentText' in msg ? msg.hydratedContentText : '')
|
|
731
|
+
conversation: 'contentText' in msg ? msg.contentText : 'hydratedContentText' in msg ? msg.hydratedContentText : ''
|
|
829
732
|
};
|
|
830
733
|
}
|
|
831
734
|
};
|
|
832
|
-
content =
|
|
833
|
-
if (content
|
|
735
|
+
content = normalizeMessageContent(content);
|
|
736
|
+
if (content?.buttonsMessage) {
|
|
834
737
|
return extractFromTemplateMessage(content.buttonsMessage);
|
|
835
738
|
}
|
|
836
|
-
if (
|
|
837
|
-
return extractFromTemplateMessage(
|
|
739
|
+
if (content?.templateMessage?.hydratedFourRowTemplate) {
|
|
740
|
+
return extractFromTemplateMessage(content?.templateMessage?.hydratedFourRowTemplate);
|
|
838
741
|
}
|
|
839
|
-
if (
|
|
840
|
-
return extractFromTemplateMessage(
|
|
742
|
+
if (content?.templateMessage?.hydratedTemplate) {
|
|
743
|
+
return extractFromTemplateMessage(content?.templateMessage?.hydratedTemplate);
|
|
841
744
|
}
|
|
842
|
-
if (
|
|
843
|
-
return extractFromTemplateMessage(
|
|
745
|
+
if (content?.templateMessage?.fourRowTemplate) {
|
|
746
|
+
return extractFromTemplateMessage(content?.templateMessage?.fourRowTemplate);
|
|
844
747
|
}
|
|
845
748
|
return content;
|
|
846
749
|
};
|
|
847
|
-
exports.extractMessageContent = extractMessageContent;
|
|
848
750
|
/**
|
|
849
751
|
* Returns the device predicted by message ID
|
|
850
752
|
*/
|
|
851
|
-
const getDevice = (id) => /^3A.{18}$/.test(id)
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
753
|
+
export const getDevice = (id) => /^3A.{18}$/.test(id)
|
|
754
|
+
? 'ios'
|
|
755
|
+
: /^3E.{20}$/.test(id)
|
|
756
|
+
? 'web'
|
|
757
|
+
: /^(.{21}|.{32})$/.test(id)
|
|
758
|
+
? 'android'
|
|
759
|
+
: /^(3F|.{18}$)/.test(id)
|
|
760
|
+
? 'desktop'
|
|
761
|
+
: 'unknown';
|
|
857
762
|
/** Upserts a receipt in the message */
|
|
858
|
-
const updateMessageWithReceipt = (msg, receipt) => {
|
|
763
|
+
export const updateMessageWithReceipt = (msg, receipt) => {
|
|
859
764
|
msg.userReceipt = msg.userReceipt || [];
|
|
860
765
|
const recp = msg.userReceipt.find(m => m.userJid === receipt.userJid);
|
|
861
766
|
if (recp) {
|
|
@@ -865,41 +770,36 @@ const updateMessageWithReceipt = (msg, receipt) => {
|
|
|
865
770
|
msg.userReceipt.push(receipt);
|
|
866
771
|
}
|
|
867
772
|
};
|
|
868
|
-
exports.updateMessageWithReceipt = updateMessageWithReceipt;
|
|
869
773
|
/** Update the message with a new reaction */
|
|
870
|
-
const updateMessageWithReaction = (msg, reaction) => {
|
|
871
|
-
const authorID =
|
|
872
|
-
const reactions = (msg.reactions || [])
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
reactions.push(reaction);
|
|
876
|
-
}
|
|
774
|
+
export const updateMessageWithReaction = (msg, reaction) => {
|
|
775
|
+
const authorID = getKeyAuthor(reaction.key);
|
|
776
|
+
const reactions = (msg.reactions || []).filter(r => getKeyAuthor(r.key) !== authorID);
|
|
777
|
+
reaction.text = reaction.text || '';
|
|
778
|
+
reactions.push(reaction);
|
|
877
779
|
msg.reactions = reactions;
|
|
878
780
|
};
|
|
879
|
-
exports.updateMessageWithReaction = updateMessageWithReaction;
|
|
880
781
|
/** Update the message with a new poll update */
|
|
881
|
-
const updateMessageWithPollUpdate = (msg, update) => {
|
|
882
|
-
|
|
883
|
-
const
|
|
884
|
-
|
|
885
|
-
.filter(r => (0, generics_1.getKeyAuthor)(r.pollUpdateMessageKey) !== authorID);
|
|
886
|
-
if ((_b = (_a = update.vote) === null || _a === void 0 ? void 0 : _a.selectedOptions) === null || _b === void 0 ? void 0 : _b.length) {
|
|
782
|
+
export const updateMessageWithPollUpdate = (msg, update) => {
|
|
783
|
+
const authorID = getKeyAuthor(update.pollUpdateMessageKey);
|
|
784
|
+
const reactions = (msg.pollUpdates || []).filter(r => getKeyAuthor(r.pollUpdateMessageKey) !== authorID);
|
|
785
|
+
if (update.vote?.selectedOptions?.length) {
|
|
887
786
|
reactions.push(update);
|
|
888
787
|
}
|
|
889
788
|
msg.pollUpdates = reactions;
|
|
890
789
|
};
|
|
891
|
-
exports.updateMessageWithPollUpdate = updateMessageWithPollUpdate;
|
|
892
790
|
/**
|
|
893
791
|
* Aggregates all poll updates in a poll.
|
|
894
792
|
* @param msg the poll creation message
|
|
895
793
|
* @param meId your jid
|
|
896
794
|
* @returns A list of options & their voters
|
|
897
795
|
*/
|
|
898
|
-
function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
899
|
-
|
|
900
|
-
|
|
796
|
+
export function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
797
|
+
const opts = message?.pollCreationMessage?.options ||
|
|
798
|
+
message?.pollCreationMessageV2?.options ||
|
|
799
|
+
message?.pollCreationMessageV3?.options ||
|
|
800
|
+
[];
|
|
901
801
|
const voteHashMap = opts.reduce((acc, opt) => {
|
|
902
|
-
const hash =
|
|
802
|
+
const hash = sha256(Buffer.from(opt.optionName || '')).toString();
|
|
903
803
|
acc[hash] = {
|
|
904
804
|
name: opt.optionName || '',
|
|
905
805
|
voters: []
|
|
@@ -921,13 +821,13 @@ function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
|
921
821
|
};
|
|
922
822
|
data = voteHashMap[hash];
|
|
923
823
|
}
|
|
924
|
-
voteHashMap[hash].voters.push(
|
|
824
|
+
voteHashMap[hash].voters.push(getKeyAuthor(update.pollUpdateMessageKey, meId));
|
|
925
825
|
}
|
|
926
826
|
}
|
|
927
827
|
return Object.values(voteHashMap);
|
|
928
828
|
}
|
|
929
829
|
/** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
|
|
930
|
-
const aggregateMessageKeysNotFromMe = (keys) => {
|
|
830
|
+
export const aggregateMessageKeysNotFromMe = (keys) => {
|
|
931
831
|
const keyMap = {};
|
|
932
832
|
for (const { remoteJid, id, participant, fromMe } of keys) {
|
|
933
833
|
if (!fromMe) {
|
|
@@ -944,40 +844,34 @@ const aggregateMessageKeysNotFromMe = (keys) => {
|
|
|
944
844
|
}
|
|
945
845
|
return Object.values(keyMap);
|
|
946
846
|
};
|
|
947
|
-
exports.aggregateMessageKeysNotFromMe = aggregateMessageKeysNotFromMe;
|
|
948
847
|
const REUPLOAD_REQUIRED_STATUS = [410, 404];
|
|
949
848
|
/**
|
|
950
849
|
* Downloads the given message. Throws an error if it's not a media message
|
|
951
850
|
*/
|
|
952
|
-
const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
953
|
-
const result = await downloadMsg()
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
message = await ctx.reuploadRequest(message);
|
|
963
|
-
const result = await downloadMsg();
|
|
964
|
-
return result;
|
|
965
|
-
}
|
|
966
|
-
}
|
|
851
|
+
export const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
852
|
+
const result = await downloadMsg().catch(async (error) => {
|
|
853
|
+
if (ctx &&
|
|
854
|
+
typeof error?.status === 'number' && // treat errors with status as HTTP failures requiring reupload
|
|
855
|
+
REUPLOAD_REQUIRED_STATUS.includes(error.status)) {
|
|
856
|
+
ctx.logger.info({ key: message.key }, 'sending reupload media request...');
|
|
857
|
+
// request reupload
|
|
858
|
+
message = await ctx.reuploadRequest(message);
|
|
859
|
+
const result = await downloadMsg();
|
|
860
|
+
return result;
|
|
967
861
|
}
|
|
968
862
|
throw error;
|
|
969
863
|
});
|
|
970
864
|
return result;
|
|
971
865
|
async function downloadMsg() {
|
|
972
|
-
const mContent =
|
|
866
|
+
const mContent = extractMessageContent(message.message);
|
|
973
867
|
if (!mContent) {
|
|
974
|
-
throw new
|
|
868
|
+
throw new Boom('No message present', { statusCode: 400, data: message });
|
|
975
869
|
}
|
|
976
|
-
const contentType =
|
|
977
|
-
let mediaType = contentType
|
|
870
|
+
const contentType = getContentType(mContent);
|
|
871
|
+
let mediaType = contentType?.replace('Message', '');
|
|
978
872
|
const media = mContent[contentType];
|
|
979
873
|
if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
|
|
980
|
-
throw new
|
|
874
|
+
throw new Boom(`"${contentType}" message is not a media message`);
|
|
981
875
|
}
|
|
982
876
|
let download;
|
|
983
877
|
if ('thumbnailDirectPath' in media && !('url' in media)) {
|
|
@@ -990,7 +884,7 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
|
990
884
|
else {
|
|
991
885
|
download = media;
|
|
992
886
|
}
|
|
993
|
-
const stream = await
|
|
887
|
+
const stream = await downloadContentFromMessage(download, mediaType, options);
|
|
994
888
|
if (type === 'buffer') {
|
|
995
889
|
const bufferArray = [];
|
|
996
890
|
for await (const chunk of stream) {
|
|
@@ -1001,18 +895,16 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
|
1001
895
|
return stream;
|
|
1002
896
|
}
|
|
1003
897
|
};
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|| (content === null || content === void 0 ? void 0 : content.stickerMessage);
|
|
898
|
+
|
|
899
|
+
export const assertMediaContent = (content) => {
|
|
900
|
+
content = extractMessageContent(content);
|
|
901
|
+
const mediaContent = content?.documentMessage ||
|
|
902
|
+
content?.imageMessage ||
|
|
903
|
+
content?.videoMessage ||
|
|
904
|
+
content?.audioMessage ||
|
|
905
|
+
content?.stickerMessage;
|
|
1013
906
|
if (!mediaContent) {
|
|
1014
|
-
throw new
|
|
907
|
+
throw new Boom('given message is not a media message', { statusCode: 400, data: content });
|
|
1015
908
|
}
|
|
1016
909
|
return mediaContent;
|
|
1017
910
|
};
|
|
1018
|
-
exports.assertMediaContent = assertMediaContent;
|