@areumtecnologia/wasockets 2.0.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1987 -1649
- package/lib/Client/Builders/Buttons.js +127 -0
- package/lib/Client/Builders/EventBuilder.js +122 -0
- package/lib/Client/Builders/InteractiveMessage.js +150 -0
- package/lib/Client/Builders/Lists.js +78 -0
- package/lib/Client/Builders/PollBuilder.js +84 -0
- package/lib/Client/Builders/index.js +21 -0
- package/lib/Client/Constants.js +54 -0
- package/lib/Client/Context/CallContext.js +96 -0
- package/lib/Client/Context/MediaObject.js +155 -0
- package/lib/Client/Context/MessageContext.js +146 -0
- package/lib/Client/Modules/BusinessManager.js +155 -0
- package/lib/Client/Modules/ChannelManager.js +144 -0
- package/lib/Client/Modules/ChatManager.js +113 -0
- package/lib/Client/Modules/CommunityManager.js +136 -0
- package/lib/Client/Modules/GroupManager.js +194 -0
- package/lib/Client/Modules/LabelManager.js +123 -0
- package/lib/Client/Modules/MessageManager.js +198 -0
- package/lib/Client/Modules/PresenceManager.js +68 -0
- package/lib/Client/Modules/PrivacyManager.js +98 -0
- package/lib/Client/Modules/ProfileManager.js +92 -0
- package/lib/Client/Modules/UserManager.js +92 -0
- package/lib/Client/Modules/VoipManager.js +117 -0
- package/lib/Client/Modules/index.js +29 -0
- package/lib/Client/Normalizers/EventNormalizer.js +82 -0
- package/lib/Client/Normalizers/JidNormalizer.js +93 -0
- package/lib/Client/Normalizers/MessageNormalizer.js +134 -0
- package/lib/Client/WaClient.js +438 -0
- package/lib/Client/index.d.ts +464 -0
- package/lib/Client/index.js +76 -0
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/connection.js +14 -1
- package/lib/Socket/index.js +51 -48
- package/lib/Socket/messages-recv.js +74 -13
- package/lib/Socket/messages-send.js +50 -25
- package/lib/Socket/socket.js +13 -0
- package/lib/Socket/voip.js +123 -0
- package/lib/Store/make-cache-manager-store.js +14 -5
- package/lib/Types/index.d.ts +4 -0
- package/lib/Utils/auth-utils.js +16 -1
- package/lib/Utils/browser-utils.js +6 -2
- package/lib/Utils/generics.js +47 -8
- package/lib/Utils/index.d.ts +1 -0
- package/lib/Utils/messages-media.js +44 -21
- package/lib/Utils/pre-key-manager.js +16 -1
- package/lib/Utils/validate-connection.js +10 -11
- package/lib/VoIP/VoIPCrypto.js +150 -0
- package/lib/VoIP/VoIPManager.js +469 -0
- package/lib/VoIP/VoIPMediaEngine.js +224 -0
- package/lib/VoIP/VoIPProtocol.js +354 -0
- package/lib/VoIP/VoIPRelayTransport.js +173 -0
- package/lib/VoIP/VoIPSession.js +314 -0
- package/lib/VoIP/assets/wasm/loader.js +5 -0
- package/lib/VoIP/assets/wasm/whatsapp.wasm +0 -0
- package/lib/VoIP/assets/wasm/worker-modules.js +305 -0
- package/lib/VoIP/engine/audio-feeder.d.mts +15 -0
- package/lib/VoIP/engine/audio-feeder.mjs +243 -0
- package/lib/VoIP/engine/index.d.mts +91 -0
- package/lib/VoIP/engine/index.mjs +1683 -0
- package/lib/VoIP/engine/relay-transport.d.mts +43 -0
- package/lib/VoIP/engine/relay-transport.mjs +607 -0
- package/lib/VoIP/engine/signaling.d.mts +44 -0
- package/lib/VoIP/engine/signaling.mjs +893 -0
- package/lib/VoIP/engine/types.d.mts +183 -0
- package/lib/VoIP/engine/types.mjs +17 -0
- package/lib/VoIP/engine/wasm-engine.d.mts +103 -0
- package/lib/VoIP/engine/wasm-engine.mjs +1397 -0
- package/lib/VoIP/engine/worker-bootstrap.mjs +1049 -0
- package/lib/VoIP/index.js +51 -0
- package/lib/VoIP/utils/audio.d.ts +28 -0
- package/lib/VoIP/utils/audio.js +148 -0
- package/lib/WABinary/generic-utils.js +22 -6
- package/lib/index.d.ts +382 -274
- package/lib/index.js +5 -0
- package/package.json +51 -49
|
@@ -17,11 +17,17 @@ const {
|
|
|
17
17
|
createReadStream,
|
|
18
18
|
createWriteStream
|
|
19
19
|
} = require("fs")
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
let _musicMetadata;
|
|
21
|
+
const getMusicMetadata = async () => {
|
|
22
|
+
if (!_musicMetadata) {
|
|
23
|
+
try {
|
|
24
|
+
_musicMetadata = require('music-metadata');
|
|
25
|
+
} catch {
|
|
26
|
+
_musicMetadata = await import('music-metadata');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return _musicMetadata;
|
|
30
|
+
};
|
|
25
31
|
const { tmpdir } = require("os")
|
|
26
32
|
const { join } = require("path")
|
|
27
33
|
const {
|
|
@@ -175,21 +181,28 @@ const extractImageThumb = async (bufferOrFilePath, width = 32, quality = 50) =>
|
|
|
175
181
|
}
|
|
176
182
|
}
|
|
177
183
|
}
|
|
178
|
-
else if ('jimp' in lib && typeof lib.jimp.read === 'function') {
|
|
179
|
-
|
|
180
|
-
const jimp = await read(bufferOrFilePath)
|
|
184
|
+
else if ('jimp' in lib && (typeof lib.jimp.read === 'function' || typeof lib.jimp.Jimp?.read === 'function')) {
|
|
185
|
+
const JimpClass = lib.jimp.Jimp || lib.jimp;
|
|
186
|
+
const jimp = await JimpClass.read(bufferOrFilePath);
|
|
181
187
|
const dimensions = {
|
|
182
|
-
width: jimp.getWidth(),
|
|
183
|
-
height: jimp.getHeight()
|
|
188
|
+
width: typeof jimp.getWidth === 'function' ? jimp.getWidth() : jimp.width,
|
|
189
|
+
height: typeof jimp.getHeight === 'function' ? jimp.getHeight() : jimp.height
|
|
190
|
+
};
|
|
191
|
+
let buffer;
|
|
192
|
+
if (typeof jimp.getBufferAsync === 'function') {
|
|
193
|
+
const { MIME_JPEG, RESIZE_BEZIER, AUTO } = lib.jimp;
|
|
194
|
+
buffer = await jimp
|
|
195
|
+
.quality(quality)
|
|
196
|
+
.resize(width, AUTO, RESIZE_BEZIER)
|
|
197
|
+
.getBufferAsync(MIME_JPEG);
|
|
198
|
+
} else {
|
|
199
|
+
jimp.resize({ w: width });
|
|
200
|
+
buffer = await jimp.getBuffer(lib.jimp.JimpMime?.jpeg || 'image/jpeg', { quality });
|
|
184
201
|
}
|
|
185
|
-
const buffer = await jimp
|
|
186
|
-
.quality(quality)
|
|
187
|
-
.resize(width, AUTO, RESIZE_BEZIER)
|
|
188
|
-
.getBufferAsync(MIME_JPEG)
|
|
189
202
|
return {
|
|
190
203
|
buffer,
|
|
191
204
|
original: dimensions
|
|
192
|
-
}
|
|
205
|
+
};
|
|
193
206
|
}
|
|
194
207
|
else {
|
|
195
208
|
throw new Boom('No image processing library available')
|
|
@@ -227,11 +240,21 @@ const generateProfilePicture = async (mediaUpload, dimensions) => {
|
|
|
227
240
|
quality: 50
|
|
228
241
|
}).toBuffer()
|
|
229
242
|
}
|
|
230
|
-
else if ('jimp' in lib && typeof lib.jimp?.read === 'function') {
|
|
231
|
-
const
|
|
232
|
-
const
|
|
233
|
-
const
|
|
234
|
-
|
|
243
|
+
else if ('jimp' in lib && (typeof lib.jimp?.read === 'function' || typeof lib.jimp?.Jimp?.read === 'function')) {
|
|
244
|
+
const JimpClass = lib.jimp.Jimp || lib.jimp;
|
|
245
|
+
const jimp = await JimpClass.read(buffer);
|
|
246
|
+
const imgWidth = typeof jimp.getWidth === 'function' ? jimp.getWidth() : jimp.width;
|
|
247
|
+
const imgHeight = typeof jimp.getHeight === 'function' ? jimp.getHeight() : jimp.height;
|
|
248
|
+
const min = Math.min(imgWidth, imgHeight);
|
|
249
|
+
const cropped = typeof jimp.crop === 'function' && jimp.crop.length > 1
|
|
250
|
+
? jimp.crop(0, 0, min, min)
|
|
251
|
+
: jimp.crop({ x: 0, y: 0, w: min, h: min });
|
|
252
|
+
const mode = lib.jimp.ResizeStrategy?.BILINEAR || lib.jimp.RESIZE_BILINEAR;
|
|
253
|
+
if (typeof cropped.getBufferAsync === 'function') {
|
|
254
|
+
img = cropped.resize(w, h, mode).getBufferAsync(lib.jimp.MIME_JPEG);
|
|
255
|
+
} else {
|
|
256
|
+
img = cropped.resize({ w, h, mode }).getBuffer(lib.jimp.JimpMime?.jpeg || 'image/jpeg', { quality: 50 });
|
|
257
|
+
}
|
|
235
258
|
}
|
|
236
259
|
else {
|
|
237
260
|
throw new Boom('No image processing library available');
|
|
@@ -251,7 +274,7 @@ async function getAudioDuration(buffer) {
|
|
|
251
274
|
const options = {
|
|
252
275
|
duration: true
|
|
253
276
|
}
|
|
254
|
-
|
|
277
|
+
const { parseBuffer, parseFile, parseStream } = await getMusicMetadata();
|
|
255
278
|
let metadata
|
|
256
279
|
|
|
257
280
|
if (Buffer.isBuffer(buffer)) {
|
|
@@ -2,7 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true })
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
let PQueue
|
|
6
|
+
try {
|
|
7
|
+
const pq = require("p-queue")
|
|
8
|
+
PQueue = pq.default || pq
|
|
9
|
+
} catch {
|
|
10
|
+
PQueue = class SimpleQueue {
|
|
11
|
+
constructor() {
|
|
12
|
+
this._chain = Promise.resolve()
|
|
13
|
+
}
|
|
14
|
+
add(fn) {
|
|
15
|
+
const result = this._chain.then(() => fn())
|
|
16
|
+
this._chain = result.catch(() => {})
|
|
17
|
+
return result
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
6
21
|
|
|
7
22
|
/**
|
|
8
23
|
* Manages pre-key operations with proper concurrency control
|
|
@@ -30,9 +30,9 @@ const getUserAgent = (config) => {
|
|
|
30
30
|
secondary: config.version[1],
|
|
31
31
|
tertiary: config.version[2],
|
|
32
32
|
},
|
|
33
|
-
platform:
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
platform: config.browser?.[1]?.toLowerCase().includes('android')
|
|
34
|
+
? proto.ClientPayload.UserAgent.Platform.ANDROID
|
|
35
|
+
: proto.ClientPayload.UserAgent.Platform.WEB,
|
|
36
36
|
releaseChannel: proto.ClientPayload.UserAgent.ReleaseChannel.RELEASE,
|
|
37
37
|
osVersion: config.browser?.[2] || '10.0.22631',
|
|
38
38
|
device: 'Desktop',
|
|
@@ -46,7 +46,7 @@ const getUserAgent = (config) => {
|
|
|
46
46
|
|
|
47
47
|
const PLATFORM_MAP = {
|
|
48
48
|
'Mac OS': proto.ClientPayload.WebInfo.WebSubPlatform.DARWIN,
|
|
49
|
-
'Windows': proto.ClientPayload.WebInfo.WebSubPlatform.
|
|
49
|
+
'Windows': proto.ClientPayload.WebInfo.WebSubPlatform.WIN_HYBRID
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
const getWebInfo = (config) => {
|
|
@@ -66,10 +66,9 @@ const getClientPayload = (config) => {
|
|
|
66
66
|
userAgent: getUserAgent(config),
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
payload.webInfo = getWebInfo(config)
|
|
69
|
+
if (!config.browser?.[1]?.toLowerCase().includes('android')) {
|
|
70
|
+
payload.webInfo = getWebInfo(config)
|
|
71
|
+
}
|
|
73
72
|
|
|
74
73
|
return payload
|
|
75
74
|
}
|
|
@@ -91,9 +90,9 @@ const generateLoginNode = (userJid, config) => {
|
|
|
91
90
|
const getPlatformType = (platform) => {
|
|
92
91
|
const platformType = platform.toUpperCase()
|
|
93
92
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
if (platformType === 'ANDROID') {
|
|
94
|
+
return proto.DeviceProps.PlatformType.ANDROID_PHONE
|
|
95
|
+
}
|
|
97
96
|
|
|
98
97
|
return (proto.DeviceProps.PlatformType[platformType] ||
|
|
99
98
|
proto.DeviceProps.PlatformType.CHROME)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
|
|
5
|
+
const crypto = require("crypto");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* WhatsApp VoIP SRTP Key Derivation & Packet Protection
|
|
9
|
+
* Conforms to WhatsApp VoIP specifications (wacrg / AstraCalls / RFC 3711)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const SRTP_LABEL = {
|
|
13
|
+
CALLER_AUDIO_KEY: "WhatsApp VoIP Master Key Caller Audio",
|
|
14
|
+
CALLER_AUDIO_SALT: "WhatsApp VoIP Master Salt Caller Audio",
|
|
15
|
+
CALLEE_AUDIO_KEY: "WhatsApp VoIP Master Key Callee Audio",
|
|
16
|
+
CALLEE_AUDIO_SALT: "WhatsApp VoIP Master Salt Callee Audio",
|
|
17
|
+
CALLER_VIDEO_KEY: "WhatsApp VoIP Master Key Caller Video",
|
|
18
|
+
CALLER_VIDEO_SALT: "WhatsApp VoIP Master Salt Caller Video",
|
|
19
|
+
CALLEE_VIDEO_KEY: "WhatsApp VoIP Master Key Callee Video",
|
|
20
|
+
CALLEE_VIDEO_SALT: "WhatsApp VoIP Master Salt Callee Video",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Standard HKDF extraction & expansion using SHA-256
|
|
25
|
+
*/
|
|
26
|
+
function hkdfDerive(ikm, salt, info, length) {
|
|
27
|
+
const actualSalt = salt && salt.length > 0 ? salt : Buffer.alloc(32, 0);
|
|
28
|
+
const prk = crypto.createHmac("sha256", actualSalt).update(ikm).digest();
|
|
29
|
+
|
|
30
|
+
let prev = Buffer.alloc(0);
|
|
31
|
+
const buffers = [];
|
|
32
|
+
let currentLen = 0;
|
|
33
|
+
let counter = 1;
|
|
34
|
+
|
|
35
|
+
while (currentLen < length) {
|
|
36
|
+
const hmac = crypto.createHmac("sha256", prk);
|
|
37
|
+
hmac.update(prev);
|
|
38
|
+
if (info) {
|
|
39
|
+
hmac.update(Buffer.isBuffer(info) ? info : Buffer.from(info, "utf8"));
|
|
40
|
+
}
|
|
41
|
+
hmac.update(Buffer.from([counter]));
|
|
42
|
+
prev = hmac.digest();
|
|
43
|
+
buffers.push(prev);
|
|
44
|
+
currentLen += prev.length;
|
|
45
|
+
counter++;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return Buffer.concat(buffers).subarray(0, length);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Derives all SRTP Master Keys and Salts from the 32-byte callKey
|
|
53
|
+
* @param {Buffer|Uint8Array} callKey 32-byte master call key negotiated via Signal
|
|
54
|
+
* @param {Buffer|Uint8Array} [salt] Optional salt (defaults to 32 zero bytes)
|
|
55
|
+
*/
|
|
56
|
+
function deriveVoIPKeys(callKey, salt = null) {
|
|
57
|
+
const keyBuf = Buffer.isBuffer(callKey) ? callKey : Buffer.from(callKey);
|
|
58
|
+
const saltBuf = salt ? (Buffer.isBuffer(salt) ? salt : Buffer.from(salt)) : Buffer.alloc(32, 0);
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
// Caller (TX if caller, RX if callee)
|
|
62
|
+
callerAudio: {
|
|
63
|
+
masterKey: hkdfDerive(keyBuf, saltBuf, SRTP_LABEL.CALLER_AUDIO_KEY, 16),
|
|
64
|
+
masterSalt: hkdfDerive(keyBuf, saltBuf, SRTP_LABEL.CALLER_AUDIO_SALT, 14),
|
|
65
|
+
},
|
|
66
|
+
// Callee (RX if caller, TX if callee)
|
|
67
|
+
calleeAudio: {
|
|
68
|
+
masterKey: hkdfDerive(keyBuf, saltBuf, SRTP_LABEL.CALLEE_AUDIO_KEY, 16),
|
|
69
|
+
masterSalt: hkdfDerive(keyBuf, saltBuf, SRTP_LABEL.CALLEE_AUDIO_SALT, 14),
|
|
70
|
+
},
|
|
71
|
+
// Video Caller
|
|
72
|
+
callerVideo: {
|
|
73
|
+
masterKey: hkdfDerive(keyBuf, saltBuf, SRTP_LABEL.CALLER_VIDEO_KEY, 16),
|
|
74
|
+
masterSalt: hkdfDerive(keyBuf, saltBuf, SRTP_LABEL.CALLER_VIDEO_SALT, 14),
|
|
75
|
+
},
|
|
76
|
+
// Video Callee
|
|
77
|
+
calleeVideo: {
|
|
78
|
+
masterKey: hkdfDerive(keyBuf, saltBuf, SRTP_LABEL.CALLEE_VIDEO_KEY, 16),
|
|
79
|
+
masterSalt: hkdfDerive(keyBuf, saltBuf, SRTP_LABEL.CALLEE_VIDEO_SALT, 14),
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Generates an SRTP Initialization Vector (IV) from SSRC, Sequence Number, and Master Salt
|
|
86
|
+
* Conforms to RFC 3711 Section 4.1.1
|
|
87
|
+
*/
|
|
88
|
+
function computeSRTPIV(masterSalt, ssrc, seqNo, roc = 0) {
|
|
89
|
+
const iv = Buffer.alloc(16, 0);
|
|
90
|
+
|
|
91
|
+
// 48-bit index: (roc << 16) | seqNo
|
|
92
|
+
const indexBuf = Buffer.alloc(8, 0);
|
|
93
|
+
indexBuf.writeUInt32BE(roc, 0);
|
|
94
|
+
indexBuf.writeUInt16BE(seqNo, 4);
|
|
95
|
+
|
|
96
|
+
// IV = (ssrc << 64) ^ (index << 16) ^ (masterSalt << 16)
|
|
97
|
+
masterSalt.copy(iv, 0, 0, 14);
|
|
98
|
+
|
|
99
|
+
// XOR SSRC at bytes 4-7
|
|
100
|
+
iv[4] ^= (ssrc >>> 24) & 0xff;
|
|
101
|
+
iv[5] ^= (ssrc >>> 16) & 0xff;
|
|
102
|
+
iv[6] ^= (ssrc >>> 8) & 0xff;
|
|
103
|
+
iv[7] ^= ssrc & 0xff;
|
|
104
|
+
|
|
105
|
+
// XOR index at bytes 6-13
|
|
106
|
+
for (let i = 0; i < 6; i++) {
|
|
107
|
+
iv[8 + i] ^= indexBuf[2 + i];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return iv;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Encrypts an RTP payload using AES-128-CTR (SRTP Default)
|
|
115
|
+
*/
|
|
116
|
+
function encryptRTPPayload(payload, key, iv) {
|
|
117
|
+
const cipher = crypto.createCipheriv("aes-128-ctr", key, iv);
|
|
118
|
+
return Buffer.concat([cipher.update(payload), cipher.final()]);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Decrypts an SRTP payload using AES-128-CTR
|
|
123
|
+
*/
|
|
124
|
+
function decryptRTPPayload(encryptedPayload, key, iv) {
|
|
125
|
+
const decipher = crypto.createDecipheriv("aes-128-ctr", key, iv);
|
|
126
|
+
return Buffer.concat([decipher.update(encryptedPayload), decipher.final()]);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Computes HMAC-SHA1-80 authentication tag (10 bytes) for SRTP packet
|
|
131
|
+
*/
|
|
132
|
+
function computeAuthTag(authKey, packetData, roc = 0) {
|
|
133
|
+
const rocBuf = Buffer.alloc(4);
|
|
134
|
+
rocBuf.writeUInt32BE(roc, 0);
|
|
135
|
+
|
|
136
|
+
const hmac = crypto.createHmac("sha1", authKey);
|
|
137
|
+
hmac.update(packetData);
|
|
138
|
+
hmac.update(rocBuf);
|
|
139
|
+
return hmac.digest().subarray(0, 10);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
module.exports = {
|
|
143
|
+
SRTP_LABEL,
|
|
144
|
+
hkdfDerive,
|
|
145
|
+
deriveVoIPKeys,
|
|
146
|
+
computeSRTPIV,
|
|
147
|
+
encryptRTPPayload,
|
|
148
|
+
decryptRTPPayload,
|
|
149
|
+
computeAuthTag,
|
|
150
|
+
};
|