@heavstaltech/baileys 2.3.4 → 3.2.4
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 +226 -53
- package/WAProto/index.js +14270 -302
- package/engine-requirements.js +10 -0
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/index.js +118 -79
- package/lib/Defaults/phonenumber-mcc.json +223 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
- package/lib/Signal/Group/ciphertext-message.js +15 -0
- package/lib/Signal/Group/group-session-builder.d.ts +14 -0
- package/lib/Signal/Group/group-session-builder.js +64 -0
- package/lib/Signal/Group/group_cipher.d.ts +17 -0
- package/lib/Signal/Group/group_cipher.js +96 -0
- package/lib/Signal/Group/index.d.ts +11 -0
- package/lib/Signal/Group/index.js +57 -0
- package/lib/Signal/Group/keyhelper.d.ts +10 -0
- package/lib/Signal/Group/keyhelper.js +55 -0
- package/lib/Signal/Group/queue-job.d.ts +1 -0
- package/lib/Signal/Group/queue-job.js +57 -0
- package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
- package/lib/Signal/Group/sender-chain-key.js +34 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
- package/lib/Signal/Group/sender-key-message.d.ts +18 -0
- package/lib/Signal/Group/sender-key-message.js +69 -0
- package/lib/Signal/Group/sender-key-name.d.ts +17 -0
- package/lib/Signal/Group/sender-key-name.js +51 -0
- package/lib/Signal/Group/sender-key-record.d.ts +30 -0
- package/lib/Signal/Group/sender-key-record.js +53 -0
- package/lib/Signal/Group/sender-key-state.d.ts +38 -0
- package/lib/Signal/Group/sender-key-state.js +99 -0
- package/lib/Signal/Group/sender-message-key.d.ts +11 -0
- package/{WASignalGroup/sender_message_key.js → lib/Signal/Group/sender-message-key.js} +6 -16
- package/lib/Signal/libsignal.js +51 -29
- package/lib/Socket/business.d.ts +43 -42
- package/lib/Socket/chats.d.ts +222 -36
- package/lib/Socket/chats.js +186 -153
- package/lib/Socket/dugong.d.ts +254 -0
- package/lib/Socket/dugong.js +484 -0
- package/lib/Socket/groups.d.ts +7 -7
- package/lib/Socket/groups.js +37 -35
- package/lib/Socket/index.d.ts +52 -51
- package/lib/Socket/index.js +1 -0
- package/lib/Socket/messages-recv.d.ts +37 -34
- package/lib/Socket/messages-recv.js +175 -37
- package/lib/Socket/messages-send.d.ts +12 -18
- package/lib/Socket/messages-send.js +396 -574
- package/lib/Socket/newsletter.d.ts +28 -26
- package/lib/Socket/newsletter.js +140 -25
- package/lib/Socket/registration.d.ts +52 -49
- package/lib/Socket/registration.js +7 -7
- package/lib/Socket/socket.d.ts +0 -1
- package/lib/Socket/socket.js +47 -198
- package/lib/Socket/usync.d.ts +10 -11
- package/lib/Store/make-cache-manager-store.d.ts +1 -2
- package/lib/Store/make-in-memory-store.d.ts +2 -2
- package/lib/Store/make-in-memory-store.js +1 -5
- package/lib/Store/make-ordered-dictionary.js +2 -2
- package/lib/Types/Auth.d.ts +1 -0
- package/lib/Types/Call.d.ts +1 -1
- package/lib/Types/Chat.d.ts +7 -12
- package/lib/Types/Events.d.ts +2 -17
- package/lib/Types/GroupMetadata.d.ts +2 -3
- package/lib/Types/Label.d.ts +0 -11
- package/lib/Types/Label.js +1 -1
- package/lib/Types/LabelAssociation.js +1 -1
- package/lib/Types/Message.d.ts +10 -170
- package/lib/Types/Newsletter.d.ts +97 -86
- package/lib/Types/Newsletter.js +38 -32
- package/lib/Types/Socket.d.ts +2 -7
- package/lib/Types/index.d.ts +0 -9
- package/lib/Types/index.js +1 -1
- package/lib/Utils/auth-utils.js +14 -35
- package/lib/Utils/business.d.ts +1 -1
- package/lib/Utils/business.js +2 -2
- package/lib/Utils/chat-utils.d.ts +12 -11
- package/lib/Utils/chat-utils.js +36 -52
- package/lib/Utils/crypto.d.ts +16 -15
- package/lib/Utils/crypto.js +26 -74
- package/lib/Utils/decode-wa-message.d.ts +0 -17
- package/lib/Utils/decode-wa-message.js +17 -53
- package/lib/Utils/event-buffer.js +7 -10
- package/lib/Utils/generics.d.ts +17 -13
- package/lib/Utils/generics.js +79 -58
- package/lib/Utils/history.d.ts +2 -6
- package/lib/Utils/history.js +6 -4
- package/lib/Utils/logger.d.ts +3 -1
- package/lib/Utils/lt-hash.js +12 -12
- package/lib/Utils/make-mutex.d.ts +2 -2
- package/lib/Utils/messages-media.d.ts +28 -25
- package/lib/Utils/messages-media.js +201 -103
- package/lib/Utils/messages.js +36 -473
- package/lib/Utils/noise-handler.d.ts +5 -4
- package/lib/Utils/noise-handler.js +14 -19
- package/lib/Utils/process-message.d.ts +5 -5
- package/lib/Utils/process-message.js +23 -75
- package/lib/Utils/signal.d.ts +1 -2
- package/lib/Utils/signal.js +26 -32
- package/lib/Utils/use-multi-file-auth-state.d.ts +1 -0
- package/lib/Utils/use-multi-file-auth-state.js +66 -242
- package/lib/Utils/validate-connection.d.ts +1 -1
- package/lib/Utils/validate-connection.js +88 -64
- package/lib/WABinary/constants.d.ts +27 -24
- package/lib/WABinary/decode.d.ts +2 -1
- package/lib/WABinary/decode.js +11 -23
- package/lib/WABinary/encode.d.ts +2 -1
- package/lib/WABinary/encode.js +147 -134
- package/lib/WABinary/generic-utils.d.ts +5 -2
- package/lib/WABinary/generic-utils.js +125 -37
- package/lib/WABinary/jid-utils.d.ts +1 -1
- package/lib/WAM/BinaryInfo.d.ts +11 -2
- package/lib/WAM/encode.d.ts +2 -1
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +3 -3
- package/lib/WAUSync/USyncUser.d.ts +2 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.js +12 -0
- package/package.json +102 -98
- package/WAProto/index.d.ts +0 -50383
- 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_name.js +0 -70
- package/WASignalGroup/sender_key_record.js +0 -56
- package/WASignalGroup/sender_key_state.js +0 -129
- package/lib/Utils/use-single-file-auth-state.d.ts +0 -12
- package/lib/Utils/use-single-file-auth-state.js +0 -75
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
/// <reference types="node" />
|
|
1
4
|
import { Boom } from '@hapi/boom';
|
|
2
5
|
import { AxiosRequestConfig } from 'axios';
|
|
3
6
|
import type { Logger } from 'pino';
|
|
4
|
-
import { Readable } from 'stream';
|
|
7
|
+
import { Readable, Transform } from 'stream';
|
|
5
8
|
import { URL } from 'url';
|
|
6
9
|
import { proto } from '../../WAProto';
|
|
7
10
|
import { DownloadableMessage, MediaConnInfo, MediaDecryptionKeyInfo, MediaType, SocketConfig, WAMediaUpload, WAMediaUploadFunction, WAMessageContent } from '../Types';
|
|
@@ -10,10 +13,10 @@ export declare const hkdfInfoKey: (type: MediaType) => string;
|
|
|
10
13
|
/** generates all the keys required to encrypt/decrypt & sign a media message */
|
|
11
14
|
export declare function getMediaKeys(buffer: Uint8Array | string | null | undefined, mediaType: MediaType): MediaDecryptionKeyInfo;
|
|
12
15
|
export declare const extractImageThumb: (bufferOrFilePath: Readable | Buffer | string, width?: number) => Promise<{
|
|
13
|
-
buffer:
|
|
16
|
+
buffer: Buffer;
|
|
14
17
|
original: {
|
|
15
|
-
width:
|
|
16
|
-
height:
|
|
18
|
+
width: number | undefined;
|
|
19
|
+
height: number | undefined;
|
|
17
20
|
};
|
|
18
21
|
}>;
|
|
19
22
|
export declare const encodeBase64EncodedStringForUpload: (b64: string) => string;
|
|
@@ -21,25 +24,25 @@ export declare const generateProfilePicture: (mediaUpload: WAMediaUpload) => Pro
|
|
|
21
24
|
img: Buffer;
|
|
22
25
|
}>;
|
|
23
26
|
/** gets the SHA256 of the given media message */
|
|
24
|
-
export declare const mediaMessageSHA256B64: (message: WAMessageContent) =>
|
|
25
|
-
export declare function getAudioDuration(buffer: Buffer | string | Readable): Promise<
|
|
27
|
+
export declare const mediaMessageSHA256B64: (message: WAMessageContent) => string | null | undefined;
|
|
28
|
+
export declare function getAudioDuration(buffer: Buffer | string | Readable): Promise<number | undefined>;
|
|
26
29
|
/**
|
|
27
30
|
referenced from and modifying https://github.com/wppconnect-team/wa-js/blob/main/src/chat/functions/prepareAudioWaveform.ts
|
|
28
31
|
*/
|
|
29
|
-
export declare function getAudioWaveform(buffer: Buffer | string | Readable, logger?: Logger): Promise<Uint8Array
|
|
30
|
-
export declare const toReadable: (buffer: Buffer) =>
|
|
31
|
-
export declare const toBuffer: (stream: Readable) => Promise<
|
|
32
|
+
export declare function getAudioWaveform(buffer: Buffer | string | Readable, logger?: Logger): Promise<Uint8Array | undefined>;
|
|
33
|
+
export declare const toReadable: (buffer: Buffer) => Readable;
|
|
34
|
+
export declare const toBuffer: (stream: Readable) => Promise<Buffer>;
|
|
32
35
|
export declare const getStream: (item: WAMediaUpload, opts?: AxiosRequestConfig) => Promise<{
|
|
33
|
-
readonly stream:
|
|
36
|
+
readonly stream: Readable;
|
|
34
37
|
readonly type: "buffer";
|
|
35
38
|
} | {
|
|
36
|
-
readonly stream:
|
|
39
|
+
readonly stream: Readable;
|
|
37
40
|
readonly type: "readable";
|
|
38
41
|
} | {
|
|
39
42
|
readonly stream: Readable;
|
|
40
43
|
readonly type: "remote";
|
|
41
44
|
} | {
|
|
42
|
-
readonly stream:
|
|
45
|
+
readonly stream: import("fs").ReadStream;
|
|
43
46
|
readonly type: "file";
|
|
44
47
|
}>;
|
|
45
48
|
/** generates a thumbnail for a given media, if required */
|
|
@@ -62,20 +65,20 @@ type EncryptedStreamOptions = {
|
|
|
62
65
|
};
|
|
63
66
|
export declare const prepareStream: (media: WAMediaUpload, mediaType: MediaType, { logger, saveOriginalFileIfRequired, opts }?: EncryptedStreamOptions) => Promise<{
|
|
64
67
|
mediaKey: undefined;
|
|
65
|
-
encWriteStream:
|
|
66
|
-
fileLength:
|
|
67
|
-
fileSha256:
|
|
68
|
+
encWriteStream: Buffer;
|
|
69
|
+
fileLength: number;
|
|
70
|
+
fileSha256: Buffer;
|
|
68
71
|
fileEncSha256: undefined;
|
|
69
72
|
bodyPath: string | undefined;
|
|
70
73
|
didSaveToTmpPath: boolean;
|
|
71
74
|
}>;
|
|
72
75
|
export declare const encryptedStream: (media: WAMediaUpload, mediaType: MediaType, { logger, saveOriginalFileIfRequired, opts }?: EncryptedStreamOptions) => Promise<{
|
|
73
|
-
mediaKey:
|
|
74
|
-
encWriteStream:
|
|
76
|
+
mediaKey: Buffer;
|
|
77
|
+
encWriteStream: Readable;
|
|
75
78
|
bodyPath: string | undefined;
|
|
76
|
-
mac:
|
|
77
|
-
fileEncSha256:
|
|
78
|
-
fileSha256:
|
|
79
|
+
mac: Buffer;
|
|
80
|
+
fileEncSha256: Buffer;
|
|
81
|
+
fileSha256: Buffer;
|
|
79
82
|
fileLength: number;
|
|
80
83
|
didSaveToTmpPath: boolean;
|
|
81
84
|
}>;
|
|
@@ -85,12 +88,12 @@ export type MediaDownloadOptions = {
|
|
|
85
88
|
options?: AxiosRequestConfig<any>;
|
|
86
89
|
};
|
|
87
90
|
export declare const getUrlFromDirectPath: (directPath: string) => string;
|
|
88
|
-
export declare const downloadContentFromMessage: ({ mediaKey, directPath, url }: DownloadableMessage, type: MediaType, opts?: MediaDownloadOptions) => Promise<
|
|
91
|
+
export declare const downloadContentFromMessage: ({ mediaKey, directPath, url }: DownloadableMessage, type: MediaType, opts?: MediaDownloadOptions) => Promise<Transform>;
|
|
89
92
|
/**
|
|
90
93
|
* Decrypts and downloads an AES256-CBC encrypted file given the keys.
|
|
91
94
|
* Assumes the SHA256 of the plaintext is appended to the end of the ciphertext
|
|
92
95
|
* */
|
|
93
|
-
export declare const downloadEncryptedContent: (downloadUrl: string, { cipherKey, iv }: MediaDecryptionKeyInfo, { startByte, endByte, options }?: MediaDownloadOptions) => Promise<
|
|
96
|
+
export declare const downloadEncryptedContent: (downloadUrl: string, { cipherKey, iv }: MediaDecryptionKeyInfo, { startByte, endByte, options }?: MediaDownloadOptions) => Promise<Transform>;
|
|
94
97
|
export declare function extensionForMediaMessage(message: WAMessageContent): string;
|
|
95
98
|
export declare const getWAUploadToServer: ({ customUploadHosts, fetchAgent, logger, options }: SocketConfig, refreshMediaConn: (force: boolean) => Promise<MediaConnInfo>) => WAMediaUploadFunction;
|
|
96
99
|
/**
|
|
@@ -98,12 +101,12 @@ export declare const getWAUploadToServer: ({ customUploadHosts, fetchAgent, logg
|
|
|
98
101
|
*/
|
|
99
102
|
export declare const encryptMediaRetryRequest: (key: proto.IMessageKey, mediaKey: Buffer | Uint8Array, meId: string) => BinaryNode;
|
|
100
103
|
export declare const decodeMediaRetryNode: (node: BinaryNode) => {
|
|
101
|
-
key:
|
|
104
|
+
key: proto.IMessageKey;
|
|
102
105
|
media?: {
|
|
103
106
|
ciphertext: Uint8Array;
|
|
104
107
|
iv: Uint8Array;
|
|
105
|
-
};
|
|
106
|
-
error?: Boom;
|
|
108
|
+
} | undefined;
|
|
109
|
+
error?: Boom<any> | undefined;
|
|
107
110
|
};
|
|
108
111
|
export declare const decryptMediaRetryData: ({ ciphertext, iv }: {
|
|
109
112
|
ciphertext: Uint8Array;
|
|
@@ -15,30 +15,15 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
35
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.prepareStream = exports.getHttpStream = exports.getStream = exports.toBuffer = exports.toReadable = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.hkdfInfoKey = void 0;
|
|
37
|
-
exports.getMediaKeys = getMediaKeys;
|
|
38
|
-
exports.getAudioDuration = getAudioDuration;
|
|
39
|
-
exports.getAudioWaveform = getAudioWaveform;
|
|
40
|
-
exports.generateThumbnail = generateThumbnail;
|
|
41
|
-
exports.extensionForMediaMessage = extensionForMediaMessage;
|
|
26
|
+
exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.extensionForMediaMessage = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.prepareStream = exports.getHttpStream = exports.generateThumbnail = exports.getStream = exports.toBuffer = exports.toReadable = exports.getAudioWaveform = exports.getAudioDuration = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.getMediaKeys = exports.hkdfInfoKey = void 0;
|
|
42
27
|
const boom_1 = require("@hapi/boom");
|
|
43
28
|
const child_process_1 = require("child_process");
|
|
44
29
|
const Crypto = __importStar(require("crypto"));
|
|
@@ -81,7 +66,7 @@ const hkdfInfoKey = (type) => {
|
|
|
81
66
|
};
|
|
82
67
|
exports.hkdfInfoKey = hkdfInfoKey;
|
|
83
68
|
/** generates all the keys required to encrypt/decrypt & sign a media message */
|
|
84
|
-
|
|
69
|
+
function getMediaKeys(buffer, mediaType) {
|
|
85
70
|
if (!buffer) {
|
|
86
71
|
throw new boom_1.Boom('Cannot derive from empty media key');
|
|
87
72
|
}
|
|
@@ -89,13 +74,14 @@ async function getMediaKeys(buffer, mediaType) {
|
|
|
89
74
|
buffer = Buffer.from(buffer.replace('data:;base64,', ''), 'base64');
|
|
90
75
|
}
|
|
91
76
|
// expand using HKDF to 112 bytes, also pass in the relevant app info
|
|
92
|
-
const expandedMediaKey =
|
|
77
|
+
const expandedMediaKey = (0, crypto_1.hkdf)(buffer, 112, { info: (0, exports.hkdfInfoKey)(mediaType) });
|
|
93
78
|
return {
|
|
94
79
|
iv: expandedMediaKey.slice(0, 16),
|
|
95
80
|
cipherKey: expandedMediaKey.slice(16, 48),
|
|
96
81
|
macKey: expandedMediaKey.slice(48, 80),
|
|
97
82
|
};
|
|
98
83
|
}
|
|
84
|
+
exports.getMediaKeys = getMediaKeys;
|
|
99
85
|
/** Extracts video thumb using FFMPEG */
|
|
100
86
|
const extractVideoThumb = async (path, destPath, time, size) => new Promise((resolve, reject) => {
|
|
101
87
|
const cmd = `ffmpeg -ss ${time} -i ${path} -y -vf scale=${size.width}:-1 -vframes 1 -f image2 ${destPath}`;
|
|
@@ -156,23 +142,42 @@ const encodeBase64EncodedStringForUpload = (b64) => (encodeURIComponent(b64
|
|
|
156
142
|
.replace(/\=+$/, '')));
|
|
157
143
|
exports.encodeBase64EncodedStringForUpload = encodeBase64EncodedStringForUpload;
|
|
158
144
|
const generateProfilePicture = async (mediaUpload) => {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
145
|
+
var _a, _b;
|
|
146
|
+
let bufferOrFilePath;
|
|
147
|
+
if (Buffer.isBuffer(mediaUpload)) {
|
|
148
|
+
bufferOrFilePath = mediaUpload;
|
|
149
|
+
}
|
|
150
|
+
else if ('url' in mediaUpload) {
|
|
151
|
+
bufferOrFilePath = mediaUpload.url.toString();
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
bufferOrFilePath = await (0, exports.toBuffer)(mediaUpload.stream);
|
|
155
|
+
}
|
|
156
|
+
const lib = await getImageProcessingLibrary();
|
|
164
157
|
let img;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
158
|
+
if ('sharp' in lib && typeof ((_a = lib.sharp) === null || _a === void 0 ? void 0 : _a.default) === 'function') {
|
|
159
|
+
img = lib.sharp.default(bufferOrFilePath)
|
|
160
|
+
.resize(640, 640)
|
|
161
|
+
.jpeg({
|
|
162
|
+
quality: 50,
|
|
163
|
+
})
|
|
164
|
+
.toBuffer();
|
|
165
|
+
}
|
|
166
|
+
else if ('jimp' in lib && typeof ((_b = lib.jimp) === null || _b === void 0 ? void 0 : _b.read) === 'function') {
|
|
167
|
+
const { read, MIME_JPEG, RESIZE_BILINEAR } = lib.jimp;
|
|
168
|
+
const jimp = await read(bufferOrFilePath);
|
|
169
|
+
const min = Math.min(jimp.getWidth(), jimp.getHeight());
|
|
170
|
+
const cropped = jimp.crop(0, 0, min, min);
|
|
171
|
+
img = cropped
|
|
172
|
+
.quality(50)
|
|
173
|
+
.resize(640, 640, RESIZE_BILINEAR)
|
|
174
|
+
.getBufferAsync(MIME_JPEG);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
throw new boom_1.Boom('No image processing library available');
|
|
178
|
+
}
|
|
174
179
|
return {
|
|
175
|
-
img: await img
|
|
180
|
+
img: await img,
|
|
176
181
|
};
|
|
177
182
|
};
|
|
178
183
|
exports.generateProfilePicture = generateProfilePicture;
|
|
@@ -183,66 +188,138 @@ const mediaMessageSHA256B64 = (message) => {
|
|
|
183
188
|
};
|
|
184
189
|
exports.mediaMessageSHA256B64 = mediaMessageSHA256B64;
|
|
185
190
|
async function getAudioDuration(buffer) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
191
|
+
try {
|
|
192
|
+
const { PassThrough } = require('stream');
|
|
193
|
+
const ff = require('fluent-ffmpeg');
|
|
194
|
+
|
|
195
|
+
return await new Promise((resolve, reject) => {
|
|
196
|
+
const inputStream = new PassThrough();
|
|
197
|
+
inputStream.end(buffer);
|
|
198
|
+
|
|
199
|
+
ff(inputStream)
|
|
200
|
+
.ffprobe((err, data) => {
|
|
201
|
+
if (err) reject(err);
|
|
202
|
+
else resolve(data.format.duration);
|
|
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
|
+
});
|
|
198
225
|
}
|
|
226
|
+
return metadata.format.duration;
|
|
199
227
|
}
|
|
200
|
-
else {
|
|
201
|
-
metadata = await musicMetadata.parseStream(buffer, undefined, { duration: true });
|
|
202
|
-
}
|
|
203
|
-
return metadata.format.duration;
|
|
204
228
|
}
|
|
205
|
-
|
|
206
|
-
referenced from and modifying https://github.com/wppconnect-team/wa-js/blob/main/src/chat/functions/prepareAudioWaveform.ts
|
|
207
|
-
*/
|
|
229
|
+
exports.getAudioDuration = getAudioDuration;
|
|
208
230
|
async function getAudioWaveform(buffer, logger) {
|
|
209
231
|
try {
|
|
210
|
-
const
|
|
232
|
+
const { PassThrough } = require('stream');
|
|
233
|
+
const ff = require('fluent-ffmpeg');
|
|
234
|
+
|
|
211
235
|
let audioData;
|
|
212
236
|
if (Buffer.isBuffer(buffer)) {
|
|
213
237
|
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);
|
|
214
243
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
244
|
+
|
|
245
|
+
return await new Promise((resolve, reject) => {
|
|
246
|
+
const inputStream = new PassThrough();
|
|
247
|
+
inputStream.end(audioData);
|
|
248
|
+
const chunks = [];
|
|
249
|
+
const bars = 64;
|
|
250
|
+
|
|
251
|
+
ff(inputStream)
|
|
252
|
+
.audioChannels(1)
|
|
253
|
+
.audioFrequency(16000)
|
|
254
|
+
.format('s16le')
|
|
255
|
+
.on('error', reject)
|
|
256
|
+
.on('end', () => {
|
|
257
|
+
const rawData = Buffer.concat(chunks);
|
|
258
|
+
const samples = rawData.length / 2;
|
|
259
|
+
const amplitudes = [];
|
|
260
|
+
|
|
261
|
+
for (let i = 0; i < samples; i++) {
|
|
262
|
+
amplitudes.push(Math.abs(rawData.readInt16LE(i * 2)) / 32768);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const blockSize = Math.floor(amplitudes.length / bars);
|
|
266
|
+
const avg = [];
|
|
267
|
+
for (let i = 0; i < bars; i++) {
|
|
268
|
+
const block = amplitudes.slice(i * blockSize, (i + 1) * blockSize);
|
|
269
|
+
avg.push(block.reduce((a, b) => a + b, 0) / block.length);
|
|
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);
|
|
241
281
|
}
|
|
242
|
-
|
|
243
|
-
|
|
282
|
+
}
|
|
283
|
+
exports.getAudioWaveform = getAudioWaveform;
|
|
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;
|
|
244
320
|
}
|
|
245
321
|
}
|
|
322
|
+
exports.convertToOpusBuffer = convertToOpusBuffer;
|
|
246
323
|
const toReadable = (buffer) => {
|
|
247
324
|
const readable = new stream_1.Readable({ read: () => { } });
|
|
248
325
|
readable.push(buffer);
|
|
@@ -304,6 +381,7 @@ async function generateThumbnail(file, mediaType, options) {
|
|
|
304
381
|
originalImageDimensions
|
|
305
382
|
};
|
|
306
383
|
}
|
|
384
|
+
exports.generateThumbnail = generateThumbnail;
|
|
307
385
|
const getHttpStream = async (url, options = {}) => {
|
|
308
386
|
const { default: axios } = await import('axios');
|
|
309
387
|
const fetched = await axios.get(url.toString(), { ...options, responseType: 'stream' });
|
|
@@ -354,15 +432,28 @@ const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequi
|
|
|
354
432
|
}
|
|
355
433
|
};
|
|
356
434
|
exports.prepareStream = prepareStream;
|
|
357
|
-
const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
|
|
435
|
+
const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts, isPtt, forceOpus } = {}) => {
|
|
358
436
|
const { stream, type } = await (0, exports.getStream)(media, opts);
|
|
359
|
-
|
|
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
|
+
|
|
360
450
|
const mediaKey = Crypto.randomBytes(32);
|
|
361
|
-
const { cipherKey, iv, macKey } =
|
|
451
|
+
const { cipherKey, iv, macKey } = getMediaKeys(mediaKey, mediaType);
|
|
362
452
|
const encWriteStream = new stream_1.Readable({ read: () => { } });
|
|
363
453
|
let bodyPath;
|
|
364
454
|
let writeStream;
|
|
365
455
|
let didSaveToTmpPath = false;
|
|
456
|
+
|
|
366
457
|
if (type === 'file') {
|
|
367
458
|
bodyPath = media.url;
|
|
368
459
|
}
|
|
@@ -371,13 +462,15 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
|
|
|
371
462
|
writeStream = (0, fs_1.createWriteStream)(bodyPath);
|
|
372
463
|
didSaveToTmpPath = true;
|
|
373
464
|
}
|
|
465
|
+
|
|
374
466
|
let fileLength = 0;
|
|
375
467
|
const aes = Crypto.createCipheriv('aes-256-cbc', cipherKey, iv);
|
|
376
468
|
let hmac = Crypto.createHmac('sha256', macKey).update(iv);
|
|
377
469
|
let sha256Plain = Crypto.createHash('sha256');
|
|
378
470
|
let sha256Enc = Crypto.createHash('sha256');
|
|
471
|
+
|
|
379
472
|
try {
|
|
380
|
-
for await (const data of
|
|
473
|
+
for await (const data of finalStream) {
|
|
381
474
|
fileLength += data.length;
|
|
382
475
|
if (type === 'remote'
|
|
383
476
|
&& (opts === null || opts === void 0 ? void 0 : opts.maxContentLength)
|
|
@@ -386,6 +479,7 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
|
|
|
386
479
|
data: { media, type }
|
|
387
480
|
});
|
|
388
481
|
}
|
|
482
|
+
|
|
389
483
|
sha256Plain = sha256Plain.update(data);
|
|
390
484
|
if (writeStream) {
|
|
391
485
|
if (!writeStream.write(data)) {
|
|
@@ -394,16 +488,18 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
|
|
|
394
488
|
}
|
|
395
489
|
onChunk(aes.update(data));
|
|
396
490
|
}
|
|
491
|
+
|
|
397
492
|
onChunk(aes.final());
|
|
398
493
|
const mac = hmac.digest().slice(0, 10);
|
|
399
494
|
sha256Enc = sha256Enc.update(mac);
|
|
400
495
|
const fileSha256 = sha256Plain.digest();
|
|
401
496
|
const fileEncSha256 = sha256Enc.digest();
|
|
497
|
+
|
|
402
498
|
encWriteStream.push(mac);
|
|
403
499
|
encWriteStream.push(null);
|
|
404
500
|
writeStream === null || writeStream === void 0 ? void 0 : writeStream.end();
|
|
405
|
-
|
|
406
|
-
|
|
501
|
+
finalStream.destroy();
|
|
502
|
+
|
|
407
503
|
return {
|
|
408
504
|
mediaKey,
|
|
409
505
|
encWriteStream,
|
|
@@ -416,24 +512,24 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
|
|
|
416
512
|
};
|
|
417
513
|
}
|
|
418
514
|
catch (error) {
|
|
419
|
-
// destroy all streams with error
|
|
420
515
|
encWriteStream.destroy();
|
|
421
516
|
writeStream === null || writeStream === void 0 ? void 0 : writeStream.destroy();
|
|
422
517
|
aes.destroy();
|
|
423
518
|
hmac.destroy();
|
|
424
519
|
sha256Plain.destroy();
|
|
425
520
|
sha256Enc.destroy();
|
|
426
|
-
|
|
521
|
+
finalStream.destroy();
|
|
522
|
+
|
|
427
523
|
if (didSaveToTmpPath) {
|
|
428
524
|
try {
|
|
429
525
|
await fs_1.promises.unlink(bodyPath);
|
|
430
526
|
}
|
|
431
527
|
catch (err) {
|
|
432
|
-
logger === null || logger === void 0 ? void 0 : logger.error({ err }, 'failed to save to tmp path');
|
|
433
528
|
}
|
|
434
529
|
}
|
|
435
530
|
throw error;
|
|
436
531
|
}
|
|
532
|
+
|
|
437
533
|
function onChunk(buff) {
|
|
438
534
|
sha256Enc = sha256Enc.update(buff);
|
|
439
535
|
hmac = hmac.update(buff);
|
|
@@ -448,9 +544,9 @@ const toSmallestChunkSize = (num) => {
|
|
|
448
544
|
};
|
|
449
545
|
const getUrlFromDirectPath = (directPath) => `https://${DEF_HOST}${directPath}`;
|
|
450
546
|
exports.getUrlFromDirectPath = getUrlFromDirectPath;
|
|
451
|
-
const downloadContentFromMessage =
|
|
547
|
+
const downloadContentFromMessage = ({ mediaKey, directPath, url }, type, opts = {}) => {
|
|
452
548
|
const downloadUrl = url || (0, exports.getUrlFromDirectPath)(directPath);
|
|
453
|
-
const keys =
|
|
549
|
+
const keys = getMediaKeys(mediaKey, type);
|
|
454
550
|
return (0, exports.downloadEncryptedContent)(downloadUrl, keys, opts);
|
|
455
551
|
};
|
|
456
552
|
exports.downloadContentFromMessage = downloadContentFromMessage;
|
|
@@ -557,6 +653,7 @@ function extensionForMediaMessage(message) {
|
|
|
557
653
|
}
|
|
558
654
|
return extension;
|
|
559
655
|
}
|
|
656
|
+
exports.extensionForMediaMessage = extensionForMediaMessage;
|
|
560
657
|
const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options }, refreshMediaConn) => {
|
|
561
658
|
return async (stream, { mediaType, fileEncSha256B64, newsletter, timeoutMs }) => {
|
|
562
659
|
var _a, _b;
|
|
@@ -634,11 +731,11 @@ const getMediaRetryKey = (mediaKey) => {
|
|
|
634
731
|
/**
|
|
635
732
|
* Generate a binary node that will request the phone to re-upload the media & return the newly uploaded URL
|
|
636
733
|
*/
|
|
637
|
-
const encryptMediaRetryRequest =
|
|
734
|
+
const encryptMediaRetryRequest = (key, mediaKey, meId) => {
|
|
638
735
|
const recp = { stanzaId: key.id };
|
|
639
736
|
const recpBuffer = WAProto_1.proto.ServerErrorReceipt.encode(recp).finish();
|
|
640
737
|
const iv = Crypto.randomBytes(12);
|
|
641
|
-
const retryKey =
|
|
738
|
+
const retryKey = getMediaRetryKey(mediaKey);
|
|
642
739
|
const ciphertext = (0, crypto_1.aesEncryptGCM)(recpBuffer, retryKey, iv, Buffer.from(key.id));
|
|
643
740
|
const req = {
|
|
644
741
|
tag: 'receipt',
|
|
@@ -702,8 +799,8 @@ const decodeMediaRetryNode = (node) => {
|
|
|
702
799
|
return event;
|
|
703
800
|
};
|
|
704
801
|
exports.decodeMediaRetryNode = decodeMediaRetryNode;
|
|
705
|
-
const decryptMediaRetryData =
|
|
706
|
-
const retryKey =
|
|
802
|
+
const decryptMediaRetryData = ({ ciphertext, iv }, mediaKey, msgId) => {
|
|
803
|
+
const retryKey = getMediaRetryKey(mediaKey);
|
|
707
804
|
const plaintext = (0, crypto_1.aesDecryptGCM)(ciphertext, retryKey, iv, Buffer.from(msgId));
|
|
708
805
|
return WAProto_1.proto.MediaRetryNotification.decode(plaintext);
|
|
709
806
|
};
|
|
@@ -716,6 +813,7 @@ const MEDIA_RETRY_STATUS_MAP = {
|
|
|
716
813
|
[WAProto_1.proto.MediaRetryNotification.ResultType.NOT_FOUND]: 404,
|
|
717
814
|
[WAProto_1.proto.MediaRetryNotification.ResultType.GENERAL_ERROR]: 418,
|
|
718
815
|
};
|
|
816
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
719
817
|
function __importStar(arg0) {
|
|
720
818
|
throw new Error('Function not implemented.');
|
|
721
819
|
}
|