alwaysaqioo 1.1.1 → 1.1.3
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/README.md +9 -110
- package/WAProto/GenerateStatics.sh +4 -0
- package/WAProto/WAProto.proto +3344 -0
- package/WAProto/index.d.ts +37016 -0
- package/WAProto/index.js +79296 -118676
- package/WASignalGroup/GroupProtocol.js +1697 -0
- package/WASignalGroup/ciphertext_message.js +16 -0
- package/WASignalGroup/group_cipher.js +120 -0
- package/WASignalGroup/group_session_builder.js +46 -0
- package/WASignalGroup/index.js +5 -0
- package/WASignalGroup/keyhelper.js +21 -0
- package/WASignalGroup/protobufs.js +3 -0
- package/WASignalGroup/queue_job.js +69 -0
- package/WASignalGroup/sender_chain_key.js +50 -0
- package/WASignalGroup/sender_key_distribution_message.js +78 -0
- package/WASignalGroup/sender_key_message.js +92 -0
- package/WASignalGroup/sender_key_name.js +70 -0
- package/WASignalGroup/sender_key_record.js +56 -0
- package/WASignalGroup/sender_key_state.js +129 -0
- package/WASignalGroup/sender_message_key.js +39 -0
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/index.js +2 -19
- package/lib/Signal/Group/x +1 -0
- package/lib/Socket/chats.d.ts +32 -215
- package/lib/Socket/chats.js +75 -155
- package/lib/Socket/groups.js +18 -18
- package/lib/Socket/index.js +0 -1
- package/lib/Socket/messages-send.d.ts +2 -2
- package/lib/Socket/messages-send.js +348 -327
- package/lib/Socket/newsletter.js +21 -100
- package/lib/Socket/socket.js +30 -65
- package/lib/Types/Newsletter.d.ts +86 -97
- package/lib/Types/Newsletter.js +32 -38
- package/lib/Utils/generics.js +33 -65
- package/lib/Utils/messages-media.js +57 -145
- package/lib/Utils/messages.js +14 -26
- package/lib/Utils/signal.js +46 -48
- package/lib/Utils/use-multi-file-auth-state.js +6 -45
- package/lib/Utils/validate-connection.js +65 -89
- package/lib/WABinary/constants.d.ts +24 -27
- package/lib/WABinary/encode.js +123 -160
- package/lib/WABinary/generic-utils.d.ts +1 -2
- package/lib/WABinary/generic-utils.js +43 -123
- package/lib/WAUSync/index.d.ts +3 -0
- package/lib/index.d.ts +0 -1
- package/lib/index.js +2 -12
- package/package.json +98 -100
- package/engine-requirements.js +0 -10
- package/lib/Socket/luxu.d.ts +0 -268
- package/lib/Socket/luxu.js +0 -591
package/lib/Utils/generics.js
CHANGED
|
@@ -8,12 +8,10 @@ const boom_1 = require("@hapi/boom");
|
|
|
8
8
|
const axios_1 = __importDefault(require("axios"));
|
|
9
9
|
const crypto_1 = require("crypto");
|
|
10
10
|
const os_1 = require("os");
|
|
11
|
-
const fetch_1 = require("node-fetch")
|
|
12
11
|
const WAProto_1 = require("../../WAProto");
|
|
13
12
|
const baileys_version_json_1 = require("../Defaults/baileys-version.json");
|
|
14
13
|
const Types_1 = require("../Types");
|
|
15
14
|
const WABinary_1 = require("../WABinary");
|
|
16
|
-
const baileysVersion = [2, 3000, 1027934701]
|
|
17
15
|
const PLATFORM_MAP = {
|
|
18
16
|
'aix': 'AIX',
|
|
19
17
|
'darwin': 'Mac OS',
|
|
@@ -21,16 +19,14 @@ const PLATFORM_MAP = {
|
|
|
21
19
|
'android': 'Android',
|
|
22
20
|
'freebsd': 'FreeBSD',
|
|
23
21
|
'openbsd': 'OpenBSD',
|
|
24
|
-
'sunos': 'Solaris'
|
|
25
|
-
'linux': undefined,
|
|
26
|
-
'haiku': undefined,
|
|
27
|
-
'cygwin': undefined,
|
|
28
|
-
'netbsd': undefined
|
|
22
|
+
'sunos': 'Solaris'
|
|
29
23
|
};
|
|
30
|
-
exports.Browsers =
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
exports.Browsers = {
|
|
25
|
+
ubuntu: (browser) => ['Ubuntu', browser, '22.04.4'],
|
|
26
|
+
macOS: (browser) => ['Mac OS', browser, '14.4.1'],
|
|
27
|
+
baileys: (browser) => ['Baileys', browser, '6.5.0'],
|
|
28
|
+
windows: (browser) => ['Windows', browser, '10.0.22631'],
|
|
29
|
+
appropriate: (browser) => [PLATFORM_MAP[(0, os_1.platform)()] || 'Ubuntu', browser, (0, os_1.release)()]
|
|
34
30
|
};
|
|
35
31
|
|
|
36
32
|
const getPlatformId = (browser) => {
|
|
@@ -176,7 +172,7 @@ const generateMessageIDV2 = (userId) => {
|
|
|
176
172
|
};
|
|
177
173
|
exports.generateMessageIDV2 = generateMessageIDV2;
|
|
178
174
|
// generate a random ID to attach to a message
|
|
179
|
-
const generateMessageID = () => '
|
|
175
|
+
const generateMessageID = () => 'SH3NN-' + (0, crypto_1.randomBytes)(6).toString('hex').toUpperCase();
|
|
180
176
|
exports.generateMessageID = generateMessageID;
|
|
181
177
|
function bindWaitForEvent(ev, event) {
|
|
182
178
|
return async (check, timeoutMs) => {
|
|
@@ -219,55 +215,6 @@ const printQRIfNecessaryListener = (ev, logger) => {
|
|
|
219
215
|
});
|
|
220
216
|
};
|
|
221
217
|
exports.printQRIfNecessaryListener = printQRIfNecessaryListener;
|
|
222
|
-
/**
|
|
223
|
-
* utility that fetches latest baileys version from the master branch.
|
|
224
|
-
* Use to ensure your WA connection is always on the latest version
|
|
225
|
-
*/
|
|
226
|
-
const fetchLatestWaWebVersion = async (options = {}) => {
|
|
227
|
-
try {
|
|
228
|
-
const defaultHeaders = {
|
|
229
|
-
'User-Agent':
|
|
230
|
-
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
231
|
-
'Accept': '*/*'
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const headers = { ...defaultHeaders, ...options.headers }
|
|
235
|
-
|
|
236
|
-
const response = await fetch_1('https://web.whatsapp.com/sw.js', {
|
|
237
|
-
method: 'GET',
|
|
238
|
-
headers
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
if (!response.ok) {
|
|
242
|
-
throw new Error(`Failed to fetch sw.js: ${response.status} ${response.statusText}`)
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const data = await response.text()
|
|
246
|
-
const regex = /"client_revision":\s*(\d+)/ // regex cukup begini untuk Node
|
|
247
|
-
const match = data.match(regex)
|
|
248
|
-
|
|
249
|
-
if (!match || !match[1]) {
|
|
250
|
-
return {
|
|
251
|
-
version: baileysVersion,
|
|
252
|
-
isLatest: false,
|
|
253
|
-
error: { message: 'Client revision not found' }
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const clientRevision = match[1]
|
|
258
|
-
return {
|
|
259
|
-
version: [2, 3000, +clientRevision],
|
|
260
|
-
isLatest: true
|
|
261
|
-
}
|
|
262
|
-
} catch (error) {
|
|
263
|
-
return {
|
|
264
|
-
version: baileysVersion,
|
|
265
|
-
isLatest: false,
|
|
266
|
-
error
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
exports.fetchLatestWaWebVersion = fetchLatestWaWebVersion;
|
|
271
218
|
/**
|
|
272
219
|
* utility that fetches latest baileys version from the master branch.
|
|
273
220
|
* Use to ensure your WA connection is always on the latest version
|
|
@@ -293,6 +240,31 @@ const fetchLatestBaileysVersion = async (options = {}) => {
|
|
|
293
240
|
}
|
|
294
241
|
};
|
|
295
242
|
exports.fetchLatestBaileysVersion = fetchLatestBaileysVersion;
|
|
243
|
+
/**
|
|
244
|
+
* A utility that fetches the latest web version of whatsapp.
|
|
245
|
+
* Use to ensure your WA connection is always on the latest version
|
|
246
|
+
*/
|
|
247
|
+
const fetchLatestWaWebVersion = async (options) => {
|
|
248
|
+
try {
|
|
249
|
+
const result = await axios_1.default.get('https://web.whatsapp.com/check-update?version=1&platform=web', {
|
|
250
|
+
...options,
|
|
251
|
+
responseType: 'json'
|
|
252
|
+
});
|
|
253
|
+
const version = result.data.currentVersion.split('.');
|
|
254
|
+
return {
|
|
255
|
+
version: [+version[0], +version[1], +version[2]],
|
|
256
|
+
isLatest: true
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
return {
|
|
261
|
+
version: baileys_version_json_1.version,
|
|
262
|
+
isLatest: false,
|
|
263
|
+
error
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
exports.fetchLatestWaWebVersion = fetchLatestWaWebVersion;
|
|
296
268
|
/** unique message tag prefix for MD clients */
|
|
297
269
|
const generateMdTagPrefix = () => {
|
|
298
270
|
const bytes = (0, crypto_1.randomBytes)(4);
|
|
@@ -417,7 +389,3 @@ function bytesToCrockford(buffer) {
|
|
|
417
389
|
return crockford.join('');
|
|
418
390
|
}
|
|
419
391
|
exports.bytesToCrockford = bytesToCrockford;
|
|
420
|
-
const encodeNewsletterMessage = (message) => {
|
|
421
|
-
return WAProto_1.proto.Message.encode(message).finish()
|
|
422
|
-
}
|
|
423
|
-
exports.encodeNewsletterMessage = encodeNewsletterMessage;
|
|
@@ -188,138 +188,68 @@ const mediaMessageSHA256B64 = (message) => {
|
|
|
188
188
|
};
|
|
189
189
|
exports.mediaMessageSHA256B64 = mediaMessageSHA256B64;
|
|
190
190
|
async function getAudioDuration(buffer) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
} catch (error) {
|
|
206
|
-
const musicMetadata = await import('music-metadata');
|
|
207
|
-
let metadata;
|
|
208
|
-
if (Buffer.isBuffer(buffer)) {
|
|
209
|
-
metadata = await musicMetadata.parseBuffer(buffer, undefined, {
|
|
210
|
-
duration: true
|
|
211
|
-
});
|
|
212
|
-
} else if (typeof buffer === 'string') {
|
|
213
|
-
const rStream = (0, fs_1.createReadStream)(buffer);
|
|
214
|
-
try {
|
|
215
|
-
metadata = await musicMetadata.parseStream(rStream, undefined, {
|
|
216
|
-
duration: true
|
|
217
|
-
});
|
|
218
|
-
} finally {
|
|
219
|
-
rStream.destroy();
|
|
220
|
-
}
|
|
221
|
-
} else {
|
|
222
|
-
metadata = await musicMetadata.parseStream(buffer, undefined, {
|
|
223
|
-
duration: true
|
|
224
|
-
});
|
|
191
|
+
const musicMetadata = await import('music-metadata');
|
|
192
|
+
let metadata;
|
|
193
|
+
if (Buffer.isBuffer(buffer)) {
|
|
194
|
+
metadata = await musicMetadata.parseBuffer(buffer, undefined, { duration: true });
|
|
195
|
+
}
|
|
196
|
+
else if (typeof buffer === 'string') {
|
|
197
|
+
const rStream = (0, fs_1.createReadStream)(buffer);
|
|
198
|
+
try {
|
|
199
|
+
metadata = await musicMetadata.parseStream(rStream, undefined, { duration: true });
|
|
200
|
+
}
|
|
201
|
+
finally {
|
|
202
|
+
rStream.destroy();
|
|
225
203
|
}
|
|
226
|
-
return metadata.format.duration;
|
|
227
204
|
}
|
|
205
|
+
else {
|
|
206
|
+
metadata = await musicMetadata.parseStream(buffer, undefined, { duration: true });
|
|
207
|
+
}
|
|
208
|
+
return metadata.format.duration;
|
|
228
209
|
}
|
|
229
210
|
exports.getAudioDuration = getAudioDuration;
|
|
211
|
+
/**
|
|
212
|
+
referenced from and modifying https://github.com/wppconnect-team/wa-js/blob/main/src/chat/functions/prepareAudioWaveform.ts
|
|
213
|
+
*/
|
|
230
214
|
async function getAudioWaveform(buffer, logger) {
|
|
231
215
|
try {
|
|
232
|
-
const
|
|
233
|
-
const ff = require('fluent-ffmpeg');
|
|
234
|
-
|
|
216
|
+
const audioDecode = (buffer) => import('audio-decode').then(({ default: audioDecode }) => audioDecode(buffer));
|
|
235
217
|
let audioData;
|
|
236
218
|
if (Buffer.isBuffer(buffer)) {
|
|
237
219
|
audioData = buffer;
|
|
238
|
-
} else if (typeof buffer === 'string') {
|
|
239
|
-
const rStream = require('fs').createReadStream(buffer);
|
|
240
|
-
audioData = await exports.toBuffer(rStream);
|
|
241
|
-
} else {
|
|
242
|
-
audioData = await exports.toBuffer(buffer);
|
|
243
220
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const max = Math.max(...avg);
|
|
273
|
-
const normalized = avg.map(v => Math.floor((v / max) * 100));
|
|
274
|
-
resolve(new Uint8Array(normalized));
|
|
275
|
-
})
|
|
276
|
-
.pipe()
|
|
277
|
-
.on('data', chunk => chunks.push(chunk));
|
|
278
|
-
});
|
|
279
|
-
} catch (e) {
|
|
280
|
-
logger?.debug(e);
|
|
221
|
+
else if (typeof buffer === 'string') {
|
|
222
|
+
const rStream = (0, fs_1.createReadStream)(buffer);
|
|
223
|
+
audioData = await (0, exports.toBuffer)(rStream);
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
audioData = await (0, exports.toBuffer)(buffer);
|
|
227
|
+
}
|
|
228
|
+
const audioBuffer = await audioDecode(audioData);
|
|
229
|
+
const rawData = audioBuffer.getChannelData(0); // We only need to work with one channel of data
|
|
230
|
+
const samples = 64; // Number of samples we want to have in our final data set
|
|
231
|
+
const blockSize = Math.floor(rawData.length / samples); // the number of samples in each subdivision
|
|
232
|
+
const filteredData = [];
|
|
233
|
+
for (let i = 0; i < samples; i++) {
|
|
234
|
+
const blockStart = blockSize * i; // the location of the first sample in the block
|
|
235
|
+
let sum = 0;
|
|
236
|
+
for (let j = 0; j < blockSize; j++) {
|
|
237
|
+
sum = sum + Math.abs(rawData[blockStart + j]); // find the sum of all the samples in the block
|
|
238
|
+
}
|
|
239
|
+
filteredData.push(sum / blockSize); // divide the sum by the block size to get the average
|
|
240
|
+
}
|
|
241
|
+
// This guarantees that the largest data point will be set to 1, and the rest of the data will scale proportionally.
|
|
242
|
+
const multiplier = Math.pow(Math.max(...filteredData), -1);
|
|
243
|
+
const normalizedData = filteredData.map((n) => n * multiplier);
|
|
244
|
+
// Generate waveform like WhatsApp
|
|
245
|
+
const waveform = new Uint8Array(normalizedData.map((n) => Math.floor(100 * n)));
|
|
246
|
+
return waveform;
|
|
281
247
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
async function convertToOpusBuffer(buffer, logger) {
|
|
285
|
-
try {
|
|
286
|
-
const { PassThrough } = require('stream');
|
|
287
|
-
const ff = require('fluent-ffmpeg');
|
|
288
|
-
|
|
289
|
-
return await new Promise((resolve, reject) => {
|
|
290
|
-
const inStream = new PassThrough();
|
|
291
|
-
const outStream = new PassThrough();
|
|
292
|
-
const chunks = [];
|
|
293
|
-
inStream.end(buffer);
|
|
294
|
-
|
|
295
|
-
ff(inStream)
|
|
296
|
-
.noVideo()
|
|
297
|
-
.audioCodec('libopus')
|
|
298
|
-
.format('ogg')
|
|
299
|
-
.audioBitrate('48k')
|
|
300
|
-
.audioChannels(1)
|
|
301
|
-
.audioFrequency(48000)
|
|
302
|
-
.outputOptions([
|
|
303
|
-
'-vn',
|
|
304
|
-
'-b:a 64k',
|
|
305
|
-
'-ac 2',
|
|
306
|
-
'-ar 48000',
|
|
307
|
-
'-map_metadata', '-1',
|
|
308
|
-
'-application', 'voip'
|
|
309
|
-
])
|
|
310
|
-
.on('error', reject)
|
|
311
|
-
.on('end', () => resolve(Buffer.concat(chunks)))
|
|
312
|
-
.pipe(outStream, {
|
|
313
|
-
end: true
|
|
314
|
-
});
|
|
315
|
-
outStream.on('data', c => chunks.push(c));
|
|
316
|
-
});
|
|
317
|
-
} catch (e) {
|
|
318
|
-
logger?.debug(e);
|
|
319
|
-
throw e;
|
|
248
|
+
catch (e) {
|
|
249
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('Failed to generate waveform: ' + e);
|
|
320
250
|
}
|
|
321
251
|
}
|
|
322
|
-
exports.
|
|
252
|
+
exports.getAudioWaveform = getAudioWaveform;
|
|
323
253
|
const toReadable = (buffer) => {
|
|
324
254
|
const readable = new stream_1.Readable({ read: () => { } });
|
|
325
255
|
readable.push(buffer);
|
|
@@ -432,28 +362,15 @@ const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequi
|
|
|
432
362
|
}
|
|
433
363
|
};
|
|
434
364
|
exports.prepareStream = prepareStream;
|
|
435
|
-
const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts
|
|
365
|
+
const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
|
|
436
366
|
const { stream, type } = await (0, exports.getStream)(media, opts);
|
|
437
|
-
|
|
438
|
-
let finalStream = stream;
|
|
439
|
-
if (mediaType === 'audio' && (isPtt === true || forceOpus === true)) {
|
|
440
|
-
try {
|
|
441
|
-
const buffer = await (0, exports.toBuffer)(stream);
|
|
442
|
-
const opusBuffer = await exports.convertToOpusBuffer(buffer, logger);
|
|
443
|
-
finalStream = (0, exports.toReadable)(opusBuffer);
|
|
444
|
-
} catch (error) {
|
|
445
|
-
const { stream: newStream } = await (0, exports.getStream)(media, opts);
|
|
446
|
-
finalStream = newStream;
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
367
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('fetched media stream');
|
|
450
368
|
const mediaKey = Crypto.randomBytes(32);
|
|
451
369
|
const { cipherKey, iv, macKey } = getMediaKeys(mediaKey, mediaType);
|
|
452
370
|
const encWriteStream = new stream_1.Readable({ read: () => { } });
|
|
453
371
|
let bodyPath;
|
|
454
372
|
let writeStream;
|
|
455
373
|
let didSaveToTmpPath = false;
|
|
456
|
-
|
|
457
374
|
if (type === 'file') {
|
|
458
375
|
bodyPath = media.url;
|
|
459
376
|
}
|
|
@@ -462,15 +379,13 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
|
|
|
462
379
|
writeStream = (0, fs_1.createWriteStream)(bodyPath);
|
|
463
380
|
didSaveToTmpPath = true;
|
|
464
381
|
}
|
|
465
|
-
|
|
466
382
|
let fileLength = 0;
|
|
467
383
|
const aes = Crypto.createCipheriv('aes-256-cbc', cipherKey, iv);
|
|
468
384
|
let hmac = Crypto.createHmac('sha256', macKey).update(iv);
|
|
469
385
|
let sha256Plain = Crypto.createHash('sha256');
|
|
470
386
|
let sha256Enc = Crypto.createHash('sha256');
|
|
471
|
-
|
|
472
387
|
try {
|
|
473
|
-
for await (const data of
|
|
388
|
+
for await (const data of stream) {
|
|
474
389
|
fileLength += data.length;
|
|
475
390
|
if (type === 'remote'
|
|
476
391
|
&& (opts === null || opts === void 0 ? void 0 : opts.maxContentLength)
|
|
@@ -479,7 +394,6 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
|
|
|
479
394
|
data: { media, type }
|
|
480
395
|
});
|
|
481
396
|
}
|
|
482
|
-
|
|
483
397
|
sha256Plain = sha256Plain.update(data);
|
|
484
398
|
if (writeStream) {
|
|
485
399
|
if (!writeStream.write(data)) {
|
|
@@ -488,18 +402,16 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
|
|
|
488
402
|
}
|
|
489
403
|
onChunk(aes.update(data));
|
|
490
404
|
}
|
|
491
|
-
|
|
492
405
|
onChunk(aes.final());
|
|
493
406
|
const mac = hmac.digest().slice(0, 10);
|
|
494
407
|
sha256Enc = sha256Enc.update(mac);
|
|
495
408
|
const fileSha256 = sha256Plain.digest();
|
|
496
409
|
const fileEncSha256 = sha256Enc.digest();
|
|
497
|
-
|
|
498
410
|
encWriteStream.push(mac);
|
|
499
411
|
encWriteStream.push(null);
|
|
500
412
|
writeStream === null || writeStream === void 0 ? void 0 : writeStream.end();
|
|
501
|
-
|
|
502
|
-
|
|
413
|
+
stream.destroy();
|
|
414
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('encrypted data successfully');
|
|
503
415
|
return {
|
|
504
416
|
mediaKey,
|
|
505
417
|
encWriteStream,
|
|
@@ -512,24 +424,24 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
|
|
|
512
424
|
};
|
|
513
425
|
}
|
|
514
426
|
catch (error) {
|
|
427
|
+
// destroy all streams with error
|
|
515
428
|
encWriteStream.destroy();
|
|
516
429
|
writeStream === null || writeStream === void 0 ? void 0 : writeStream.destroy();
|
|
517
430
|
aes.destroy();
|
|
518
431
|
hmac.destroy();
|
|
519
432
|
sha256Plain.destroy();
|
|
520
433
|
sha256Enc.destroy();
|
|
521
|
-
|
|
522
|
-
|
|
434
|
+
stream.destroy();
|
|
523
435
|
if (didSaveToTmpPath) {
|
|
524
436
|
try {
|
|
525
437
|
await fs_1.promises.unlink(bodyPath);
|
|
526
438
|
}
|
|
527
439
|
catch (err) {
|
|
440
|
+
logger === null || logger === void 0 ? void 0 : logger.error({ err }, 'failed to save to tmp path');
|
|
528
441
|
}
|
|
529
442
|
}
|
|
530
443
|
throw error;
|
|
531
444
|
}
|
|
532
|
-
|
|
533
445
|
function onChunk(buff) {
|
|
534
446
|
sha256Enc = sha256Enc.update(buff);
|
|
535
447
|
hmac = hmac.update(buff);
|
package/lib/Utils/messages.js
CHANGED
|
@@ -74,11 +74,8 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
if (!mediaType) {
|
|
77
|
-
throw new boom_1.Boom('Invalid media type', {
|
|
78
|
-
statusCode: 400
|
|
79
|
-
});
|
|
77
|
+
throw new boom_1.Boom('Invalid media type', { statusCode: 400 });
|
|
80
78
|
}
|
|
81
|
-
|
|
82
79
|
const uploadData = {
|
|
83
80
|
...message,
|
|
84
81
|
...(message.annotations ? {
|
|
@@ -105,9 +102,9 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
105
102
|
}
|
|
106
103
|
],
|
|
107
104
|
newsletter: {
|
|
108
|
-
newsletterJid: "
|
|
105
|
+
newsletterJid: "120363301416835342@newsletter",
|
|
109
106
|
serverMessageId: 0,
|
|
110
|
-
newsletterName: "
|
|
107
|
+
newsletterName: "-",
|
|
111
108
|
contentType: "UPDATE",
|
|
112
109
|
}
|
|
113
110
|
}
|
|
@@ -116,20 +113,20 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
116
113
|
media: message[mediaType]
|
|
117
114
|
};
|
|
118
115
|
delete uploadData[mediaType];
|
|
116
|
+
// check if cacheable + generate cache key
|
|
119
117
|
const cacheableKey = typeof uploadData.media === 'object' &&
|
|
120
118
|
('url' in uploadData.media) &&
|
|
121
119
|
!!uploadData.media.url &&
|
|
122
120
|
!!options.mediaCache && (
|
|
121
|
+
// generate the key
|
|
123
122
|
mediaType + ':' + uploadData.media.url.toString());
|
|
124
|
-
|
|
125
123
|
if (mediaType === 'document' && !uploadData.fileName) {
|
|
126
124
|
uploadData.fileName = 'file';
|
|
127
125
|
}
|
|
128
|
-
|
|
129
126
|
if (!uploadData.mimetype) {
|
|
130
127
|
uploadData.mimetype = MIMETYPE_MAP[mediaType];
|
|
131
128
|
}
|
|
132
|
-
|
|
129
|
+
// check for cache hit
|
|
133
130
|
if (cacheableKey) {
|
|
134
131
|
const mediaBuff = options.mediaCache.get(cacheableKey);
|
|
135
132
|
if (mediaBuff) {
|
|
@@ -140,28 +137,19 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
140
137
|
return obj;
|
|
141
138
|
}
|
|
142
139
|
}
|
|
143
|
-
|
|
144
140
|
const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
|
|
145
141
|
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') &&
|
|
146
142
|
(typeof uploadData['jpegThumbnail'] === 'undefined');
|
|
147
143
|
const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
|
|
148
144
|
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
|
|
149
145
|
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
|
|
150
|
-
|
|
151
|
-
const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, opusConverted } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
146
|
+
const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
152
147
|
logger,
|
|
153
148
|
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
154
|
-
opts: options.options
|
|
155
|
-
isPtt: uploadData.ptt,
|
|
156
|
-
forceOpus: (mediaType === "audio" && uploadData.mimetype && uploadData.mimetype.includes('opus'))
|
|
149
|
+
opts: options.options
|
|
157
150
|
});
|
|
158
|
-
|
|
159
|
-
if (mediaType === 'audio' && opusConverted) {
|
|
160
|
-
uploadData.mimetype = 'audio/ogg; codecs=opus';
|
|
161
|
-
}
|
|
162
|
-
|
|
151
|
+
// url safe Base64 encode the SHA256 hash of the body
|
|
163
152
|
const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
|
|
164
|
-
|
|
165
153
|
const [{ mediaUrl, directPath, handle }] = await Promise.all([
|
|
166
154
|
(async () => {
|
|
167
155
|
const result = await options.upload(encWriteStream, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs });
|
|
@@ -188,6 +176,10 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
188
176
|
uploadData.waveform = await (0, messages_media_1.getAudioWaveform)(bodyPath, logger);
|
|
189
177
|
logger === null || logger === void 0 ? void 0 : logger.debug('processed waveform');
|
|
190
178
|
}
|
|
179
|
+
if (requiresWaveformProcessing) {
|
|
180
|
+
uploadData.waveform = await (0, messages_media_1.getAudioWaveform)(bodyPath, logger);
|
|
181
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('processed waveform');
|
|
182
|
+
}
|
|
191
183
|
if (requiresAudioBackground) {
|
|
192
184
|
uploadData.backgroundArgb = await assertColor(options.backgroundColor);
|
|
193
185
|
logger === null || logger === void 0 ? void 0 : logger.debug('computed backgroundColor audio status');
|
|
@@ -202,13 +194,12 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
202
194
|
if (!Buffer.isBuffer(encWriteStream)) {
|
|
203
195
|
encWriteStream.destroy();
|
|
204
196
|
}
|
|
205
|
-
|
|
197
|
+
// remove tmp files
|
|
206
198
|
if (didSaveToTmpPath && bodyPath) {
|
|
207
199
|
await fs_1.promises.unlink(bodyPath);
|
|
208
200
|
logger === null || logger === void 0 ? void 0 : logger.debug('removed tmp files');
|
|
209
201
|
}
|
|
210
202
|
});
|
|
211
|
-
|
|
212
203
|
const obj = Types_1.WAProto.Message.fromObject({
|
|
213
204
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
214
205
|
url: handle ? undefined : mediaUrl,
|
|
@@ -222,17 +213,14 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
222
213
|
media: undefined
|
|
223
214
|
})
|
|
224
215
|
});
|
|
225
|
-
|
|
226
216
|
if (uploadData.ptv) {
|
|
227
217
|
obj.ptvMessage = obj.videoMessage;
|
|
228
218
|
delete obj.videoMessage;
|
|
229
219
|
}
|
|
230
|
-
|
|
231
220
|
if (cacheableKey) {
|
|
232
221
|
logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'set cache');
|
|
233
222
|
options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
|
|
234
223
|
}
|
|
235
|
-
|
|
236
224
|
return obj;
|
|
237
225
|
};
|
|
238
226
|
exports.prepareWAMessageMedia = prepareWAMessageMedia;
|