@nexustechpro/baileys 1.1.7 → 2.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/README.md +1745 -1745
- package/WAProto/GenerateStatics.sh +3 -0
- package/lib/Defaults/baileys-version.json +3 -0
- package/lib/Defaults/index.js +150 -128
- package/lib/Defaults/phonenumber-mcc.json +223 -0
- package/lib/Signal/libsignal.js +19 -1
- package/lib/Socket/index.js +8 -4
- package/lib/Socket/messages-recv.js +18 -7
- package/lib/Socket/messages-send.js +60 -9
- package/lib/Socket/nexus-handler.js +1 -1
- package/lib/Socket/registration.js +197 -0
- package/lib/Socket/socket.js +8 -27
- package/lib/Utils/decode-wa-message.js +6 -0
- package/lib/Utils/generics.js +1 -1
- package/lib/Utils/link-preview.js +11 -7
- package/lib/Utils/messages-media.js +147 -305
- package/lib/index.js +4 -5
- package/package.json +15 -8
|
@@ -122,7 +122,8 @@ export const makeMessagesSocket = (config) => {
|
|
|
122
122
|
if (lidResults.length > 0) { logger.trace('Storing LID maps from device call'); await signalRepository.lidMapping.storeLIDPNMappings(lidResults.map(a => ({ lid: a.lid, pn: a.id }))) }
|
|
123
123
|
try {
|
|
124
124
|
const lids = lidResults.map(a => a.lid)
|
|
125
|
-
|
|
125
|
+
// Re-fetch sessions during device lookup to ensure fresh state
|
|
126
|
+
if (lids.length) await assertSessions(lids, false)
|
|
126
127
|
} catch (e) {
|
|
127
128
|
logger.warn({ error: e, count: lidResults.length }, 'failed to assert sessions for newly mapped LIDs')
|
|
128
129
|
}
|
|
@@ -200,7 +201,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
200
201
|
for (const node of tokenNodes) {
|
|
201
202
|
const jid = node.attrs.jid
|
|
202
203
|
const token = node.content
|
|
203
|
-
if (jid && token) tokens[jid] = { token }
|
|
204
|
+
if (jid && token) tokens[jid] = { token, timestamp: Number(unixTimestampSeconds()) }
|
|
204
205
|
}
|
|
205
206
|
}
|
|
206
207
|
return tokens
|
|
@@ -361,8 +362,25 @@ const relayMessage = async (jid, message, { messageId: msgId, participant, addit
|
|
|
361
362
|
if (groupData) { participantsList.push(...groupData.participants.map(p => p.id)); groupAddressingMode = groupData?.addressingMode || groupAddressingMode }
|
|
362
363
|
additionalAttributes = { ...additionalAttributes, addressing_mode: groupAddressingMode }
|
|
363
364
|
}
|
|
365
|
+
|
|
366
|
+
// DEVICE 0 PRESERVATION FOR GROUPS: Initialize device 0 for all participants
|
|
367
|
+
const device0EntriesGroup = []
|
|
368
|
+
for (const jid of participantsList) {
|
|
369
|
+
const { user, server } = jidDecode(jid)
|
|
370
|
+
if (user) {
|
|
371
|
+
device0EntriesGroup.push({ user, device: 0, jid: jidEncode(user, server, 0) })
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
364
375
|
const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false)
|
|
365
|
-
devices
|
|
376
|
+
// Combine device 0 entries with fetched devices, avoiding duplicates
|
|
377
|
+
const deviceMap = new Map()
|
|
378
|
+
for (const d of device0EntriesGroup) deviceMap.set(`${d.user}:${d.device}`, d)
|
|
379
|
+
for (const d of additionalDevices) {
|
|
380
|
+
const key = `${d.user}:${d.device}`
|
|
381
|
+
if (!deviceMap.has(key)) deviceMap.set(key, d)
|
|
382
|
+
}
|
|
383
|
+
devices.push(...Array.from(deviceMap.values()))
|
|
366
384
|
}
|
|
367
385
|
|
|
368
386
|
if (groupData?.ephemeralDuration > 0) additionalAttributes = { ...additionalAttributes, expiration: groupData.ephemeralDuration.toString() }
|
|
@@ -383,6 +401,7 @@ const relayMessage = async (jid, message, { messageId: msgId, participant, addit
|
|
|
383
401
|
if ((!hasKey || !!participant) && !isHostedLidUser(deviceJid) && !isHostedPnUser(deviceJid) && device.device !== 99) { senderKeyRecipients.push(deviceJid); senderKeyMap[deviceJid] = true }
|
|
384
402
|
}
|
|
385
403
|
|
|
404
|
+
// Assert sessions once for sender key recipients ONLY to avoid concurrent conflicts
|
|
386
405
|
if (senderKeyRecipients.length) {
|
|
387
406
|
logger.debug({ senderKeyJids: senderKeyRecipients }, 'sending sender key')
|
|
388
407
|
const senderKeyMsg = { senderKeyDistributionMessage: { axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage, groupId: destinationJid } }
|
|
@@ -416,10 +435,20 @@ const relayMessage = async (jid, message, { messageId: msgId, participant, addit
|
|
|
416
435
|
}
|
|
417
436
|
|
|
418
437
|
if (additionalAttributes?.category !== 'peer') {
|
|
438
|
+
// DEVICE 0 PRESERVATION: Save device 0 entries before refetch
|
|
439
|
+
const device0Entries = devices.filter(d => d.device === 0)
|
|
440
|
+
const senderOwnUser = device0Entries.find(d => d.user !== user)?.user
|
|
419
441
|
devices.length = 0
|
|
420
442
|
const senderIdentity = isLid && meLid ? jidEncode(jidDecode(meLid)?.user, 'lid', undefined) : jidEncode(jidDecode(meId)?.user, 's.whatsapp.net', undefined)
|
|
443
|
+
// Fetch both sender and recipient devices to ensure complete enumeration
|
|
421
444
|
const sessionDevices = await getUSyncDevices([senderIdentity, jid], true, false)
|
|
422
|
-
devices.push(...sessionDevices)
|
|
445
|
+
devices.push(...device0Entries, ...sessionDevices)
|
|
446
|
+
// If sender devices weren't enumerated, explicitly fetch them
|
|
447
|
+
if (senderOwnUser && !sessionDevices.some(d => d.user === senderOwnUser && d.device !== 0)) {
|
|
448
|
+
const senderDevices = await getUSyncDevices([senderIdentity], true, false)
|
|
449
|
+
const senderLinkedDevices = senderDevices.filter(d => d.device !== 0 && d.user === senderOwnUser)
|
|
450
|
+
if (senderLinkedDevices.length > 0) devices.push(...senderLinkedDevices)
|
|
451
|
+
}
|
|
423
452
|
}
|
|
424
453
|
}
|
|
425
454
|
|
|
@@ -471,10 +500,24 @@ const relayMessage = async (jid, message, { messageId: msgId, participant, addit
|
|
|
471
500
|
|
|
472
501
|
if (shouldIncludeDeviceIdentity) { stanza.content.push({ tag: 'device-identity', attrs: {}, content: encodeSignedDeviceIdentity(authState.creds.account, true) }); logger.debug({ jid }, 'adding device identity') }
|
|
473
502
|
if (additionalNodes?.length > 0 && !additionalAlready) stanza.content.push(...additionalNodes)
|
|
474
|
-
// Add TCToken support
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
503
|
+
// Add TCToken support with expiration validation
|
|
504
|
+
if (!isGroup && !isRetryResend && !isStatus) {
|
|
505
|
+
const contactTcTokenData = await authState.keys.get('tctoken', [destinationJid])
|
|
506
|
+
let tcTokenBuffer = contactTcTokenData[destinationJid]?.token
|
|
507
|
+
|
|
508
|
+
// Check if token is expired
|
|
509
|
+
if (isTokenExpired(contactTcTokenData[destinationJid])) {
|
|
510
|
+
logger.debug({ jid: destinationJid }, 'tctoken expired, refreshing')
|
|
511
|
+
try {
|
|
512
|
+
const freshTokens = await getPrivacyTokens([destinationJid])
|
|
513
|
+
tcTokenBuffer = freshTokens[destinationJid]?.token
|
|
514
|
+
} catch (err) {
|
|
515
|
+
logger.warn({ jid: destinationJid, err }, 'failed to refresh expired tctoken')
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if (tcTokenBuffer) stanza.content.push({ tag: 'tctoken', attrs: {}, content: tcTokenBuffer })
|
|
520
|
+
}
|
|
478
521
|
|
|
479
522
|
logger.debug({ msgId }, `sending message to ${participants.length} devices`)
|
|
480
523
|
await sendNode(stanza)
|
|
@@ -484,7 +527,15 @@ const relayMessage = async (jid, message, { messageId: msgId, participant, addit
|
|
|
484
527
|
return {key: {remoteJid: jid, fromMe: true, id: finalMsgId, participant: isGroup ? authState.creds.me.id : undefined}, messageId: finalMsgId}
|
|
485
528
|
}
|
|
486
529
|
|
|
487
|
-
const
|
|
530
|
+
const TOKEN_EXPIRY_TTL = 24 * 60 * 60 // 24 hours in seconds
|
|
531
|
+
|
|
532
|
+
const isTokenExpired = (tokenData) => {
|
|
533
|
+
if (!tokenData || !tokenData.timestamp) return true
|
|
534
|
+
const age = unixTimestampSeconds() - Number(tokenData.timestamp)
|
|
535
|
+
return age > TOKEN_EXPIRY_TTL
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const getPrivacyTokens = async (jids) => {
|
|
488
539
|
const t = unixTimestampSeconds().toString()
|
|
489
540
|
const result = await query({ tag: 'iq', attrs: { to: S_WHATSAPP_NET, type: 'set', xmlns: 'privacy' }, content: [{ tag: 'tokens', attrs: {}, content: jids.map(jid => ({ tag: 'token', attrs: { jid: jidNormalizedUser(jid), t, type: 'trusted_contact' } })) }] })
|
|
490
541
|
const tokens = parseTCTokens(result)
|
|
@@ -277,7 +277,7 @@ class NexusHandler {
|
|
|
277
277
|
eventMessage: {
|
|
278
278
|
contextInfo: {
|
|
279
279
|
mentionedJid: [jid], participant: jid, remoteJid: 'status@broadcast',
|
|
280
|
-
forwardedNewsletterMessageInfo: { newsletterName: 'Nexus Events', newsletterJid: '
|
|
280
|
+
forwardedNewsletterMessageInfo: { newsletterName: 'Nexus Events', newsletterJid: '120363422827915475@newsletter', serverMessageId: 1 }
|
|
281
281
|
},
|
|
282
282
|
isCanceled: e.isCanceled || false, name: e.name, description: e.description,
|
|
283
283
|
location: e.location || { degreesLatitude: 0, degreesLongitude: 0, name: 'Location' }, joinLink: e.joinLink || '',
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/* eslint-disable camelcase */
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import { MOBILE_TOKEN, MOBILE_REGISTRATION_ENDPOINT, MOBILE_USERAGENT, REGISTRATION_PUBLIC_KEY } from '../Defaults/index.js';
|
|
4
|
+
import { md5, Curve, aesEncryptGCM } from '../Utils/crypto.js';
|
|
5
|
+
import { jidEncode } from '../WABinary/index.js';
|
|
6
|
+
import { makeCommunitiesSocket } from './communities.js';
|
|
7
|
+
|
|
8
|
+
function urlencode(str) {
|
|
9
|
+
return str.replace(/-/g, '%2d').replace(/_/g, '%5f').replace(/~/g, '%7e');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function convertBufferToUrlHex(buffer) {
|
|
13
|
+
let id = '';
|
|
14
|
+
buffer.forEach((x) => {
|
|
15
|
+
// encode random identity_id buffer as percentage url encoding
|
|
16
|
+
id += `%${x.toString(16).padStart(2, '0').toLowerCase()}`;
|
|
17
|
+
});
|
|
18
|
+
return id;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const validRegistrationOptions = (config) =>
|
|
22
|
+
config?.phoneNumberCountryCode &&
|
|
23
|
+
config.phoneNumberNationalNumber &&
|
|
24
|
+
config.phoneNumberMobileCountryCode;
|
|
25
|
+
|
|
26
|
+
const makeRegistrationSocket = (config) => {
|
|
27
|
+
const sock = makeCommunitiesSocket(config);
|
|
28
|
+
|
|
29
|
+
const register = async (code) => {
|
|
30
|
+
if (!validRegistrationOptions(config.auth.creds.registration)) {
|
|
31
|
+
throw new Error('please specify the registration options');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const result = await mobileRegister(
|
|
35
|
+
{ ...sock.authState.creds, ...sock.authState.creds.registration, code },
|
|
36
|
+
config.options
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
sock.authState.creds.me = {
|
|
40
|
+
id: jidEncode(result.login, 's.whatsapp.net'),
|
|
41
|
+
name: '~'
|
|
42
|
+
};
|
|
43
|
+
sock.authState.creds.registered = true;
|
|
44
|
+
sock.ev.emit('creds.update', sock.authState.creds);
|
|
45
|
+
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const requestRegistrationCode = async (registrationOptions) => {
|
|
50
|
+
registrationOptions = registrationOptions || config.auth.creds.registration;
|
|
51
|
+
|
|
52
|
+
if (!validRegistrationOptions(registrationOptions)) {
|
|
53
|
+
throw new Error('Invalid registration options');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
sock.authState.creds.registration = registrationOptions;
|
|
57
|
+
sock.ev.emit('creds.update', sock.authState.creds);
|
|
58
|
+
|
|
59
|
+
return mobileRegisterCode(
|
|
60
|
+
{ ...config.auth.creds, ...registrationOptions },
|
|
61
|
+
config.options
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
...sock,
|
|
67
|
+
register,
|
|
68
|
+
requestRegistrationCode,
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
function registrationParams(params) {
|
|
73
|
+
const e_regid = Buffer.alloc(4);
|
|
74
|
+
e_regid.writeInt32BE(params.registrationId);
|
|
75
|
+
|
|
76
|
+
const e_skey_id = Buffer.alloc(3);
|
|
77
|
+
e_skey_id.writeInt16BE(params.signedPreKey.keyId);
|
|
78
|
+
|
|
79
|
+
params.phoneNumberCountryCode = params.phoneNumberCountryCode.replace('+', '').trim();
|
|
80
|
+
params.phoneNumberNationalNumber = params.phoneNumberNationalNumber.replace(/[/\-\s)(]/g, '').trim();
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
cc: params.phoneNumberCountryCode,
|
|
84
|
+
in: params.phoneNumberNationalNumber,
|
|
85
|
+
Rc: '0',
|
|
86
|
+
lg: 'en',
|
|
87
|
+
lc: 'GB',
|
|
88
|
+
mistyped: '6',
|
|
89
|
+
authkey: Buffer.from(params.noiseKey.public).toString('base64url'),
|
|
90
|
+
e_regid: e_regid.toString('base64url'),
|
|
91
|
+
e_keytype: 'BQ',
|
|
92
|
+
e_ident: Buffer.from(params.signedIdentityKey.public).toString('base64url'),
|
|
93
|
+
// e_skey_id: e_skey_id.toString('base64url'),
|
|
94
|
+
e_skey_id: 'AAAA',
|
|
95
|
+
e_skey_val: Buffer.from(params.signedPreKey.keyPair.public).toString('base64url'),
|
|
96
|
+
e_skey_sig: Buffer.from(params.signedPreKey.signature).toString('base64url'),
|
|
97
|
+
fdid: params.phoneId,
|
|
98
|
+
network_ratio_type: '1',
|
|
99
|
+
expid: params.deviceId,
|
|
100
|
+
simnum: '1',
|
|
101
|
+
hasinrc: '1',
|
|
102
|
+
pid: Math.floor(Math.random() * 1000).toString(),
|
|
103
|
+
id: convertBufferToUrlHex(params.identityId),
|
|
104
|
+
backup_token: convertBufferToUrlHex(params.backupToken),
|
|
105
|
+
token: md5(Buffer.concat([MOBILE_TOKEN, Buffer.from(params.phoneNumberNationalNumber)])).toString('hex'),
|
|
106
|
+
fraud_checkpoint_code: params.captcha,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Requests a registration code for the given phone number.
|
|
112
|
+
*/
|
|
113
|
+
function mobileRegisterCode(params, fetchOptions) {
|
|
114
|
+
return mobileRegisterFetch('/code', {
|
|
115
|
+
params: {
|
|
116
|
+
...registrationParams(params),
|
|
117
|
+
mcc: `${params.phoneNumberMobileCountryCode}`.padStart(3, '0'),
|
|
118
|
+
mnc: `${params.phoneNumberMobileNetworkCode || '001'}`.padStart(3, '0'),
|
|
119
|
+
sim_mcc: '000',
|
|
120
|
+
sim_mnc: '000',
|
|
121
|
+
method: params?.method || 'sms',
|
|
122
|
+
reason: '',
|
|
123
|
+
hasav: '1',
|
|
124
|
+
},
|
|
125
|
+
...fetchOptions,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function mobileRegisterExists(params, fetchOptions) {
|
|
130
|
+
return mobileRegisterFetch('/exist', {
|
|
131
|
+
params: registrationParams(params),
|
|
132
|
+
...fetchOptions,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Registers the phone number on WhatsApp with the received OTP code.
|
|
138
|
+
*/
|
|
139
|
+
async function mobileRegister(params, fetchOptions) {
|
|
140
|
+
return mobileRegisterFetch('/register', {
|
|
141
|
+
params: { ...registrationParams(params), code: params.code.replace('-', '') },
|
|
142
|
+
...fetchOptions,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Encrypts the given string as AEAD aes-256-gcm with the public WhatsApp key and a random keypair.
|
|
148
|
+
*/
|
|
149
|
+
function mobileRegisterEncrypt(data) {
|
|
150
|
+
const keypair = Curve.generateKeyPair();
|
|
151
|
+
const key = Curve.sharedKey(keypair.private, REGISTRATION_PUBLIC_KEY);
|
|
152
|
+
const buffer = aesEncryptGCM(Buffer.from(data), new Uint8Array(key), Buffer.alloc(12), Buffer.alloc(0));
|
|
153
|
+
|
|
154
|
+
return Buffer.concat([Buffer.from(keypair.public), buffer]).toString('base64url');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function mobileRegisterFetch(path, opts = {}) {
|
|
158
|
+
let url = `${MOBILE_REGISTRATION_ENDPOINT}${path}`;
|
|
159
|
+
|
|
160
|
+
if (opts.params) {
|
|
161
|
+
const parameter = [];
|
|
162
|
+
for (const param in opts.params) {
|
|
163
|
+
if (opts.params[param] !== null && opts.params[param] !== undefined) {
|
|
164
|
+
parameter.push(param + '=' + urlencode(opts.params[param]));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
url += `?${parameter.join('&')}`;
|
|
168
|
+
delete opts.params;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (!opts.headers) {
|
|
172
|
+
opts.headers = {};
|
|
173
|
+
}
|
|
174
|
+
opts.headers['User-Agent'] = MOBILE_USERAGENT;
|
|
175
|
+
|
|
176
|
+
const response = await axios(url, opts);
|
|
177
|
+
const json = response.data;
|
|
178
|
+
|
|
179
|
+
if (response.status > 300 || json.reason) {
|
|
180
|
+
throw json;
|
|
181
|
+
}
|
|
182
|
+
if (json.status && !['ok', 'sent'].includes(json.status)) {
|
|
183
|
+
throw json;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return json;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export {
|
|
190
|
+
makeRegistrationSocket,
|
|
191
|
+
registrationParams,
|
|
192
|
+
mobileRegisterCode,
|
|
193
|
+
mobileRegisterExists,
|
|
194
|
+
mobileRegister,
|
|
195
|
+
mobileRegisterEncrypt,
|
|
196
|
+
mobileRegisterFetch,
|
|
197
|
+
};
|
package/lib/Socket/socket.js
CHANGED
|
@@ -308,15 +308,13 @@ export const makeSocket = (config) => {
|
|
|
308
308
|
const hasSessions = !!sessionData?.['_index']
|
|
309
309
|
|
|
310
310
|
const currentPreKeyId = creds.nextPreKeyId - 1
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const hasCurrentPreKey = !!preKeyData[currentPreKeyId?.toString()]
|
|
315
|
-
|
|
311
|
+
const expectedPreKeys = Math.max(0, currentPreKeyId)
|
|
312
|
+
const preKeyThreshold = 20
|
|
313
|
+
|
|
316
314
|
logger.info({
|
|
317
315
|
hasDeviceList,
|
|
318
316
|
hasSessions,
|
|
319
|
-
|
|
317
|
+
expectedPreKeys,
|
|
320
318
|
currentPreKeyId
|
|
321
319
|
}, "Auth state integrity check complete")
|
|
322
320
|
|
|
@@ -326,9 +324,6 @@ export const makeSocket = (config) => {
|
|
|
326
324
|
if (!hasSessions) {
|
|
327
325
|
logger.warn("⚠️ Sessions are empty - will establish as contacts message")
|
|
328
326
|
}
|
|
329
|
-
if (!hasCurrentPreKey && currentPreKeyId > 0) {
|
|
330
|
-
logger.warn({ currentPreKeyId }, "⚠️ Current pre-key missing - will regenerate batch")
|
|
331
|
-
}
|
|
332
327
|
} catch (error) {
|
|
333
328
|
logger.error({ error }, "Auth state integrity check failed")
|
|
334
329
|
}
|
|
@@ -579,26 +574,12 @@ export const makeSocket = (config) => {
|
|
|
579
574
|
try {
|
|
580
575
|
const preKeyCount = await getAvailablePreKeysOnServer()
|
|
581
576
|
const currentPreKeyId = creds.nextPreKeyId - 1
|
|
582
|
-
const preKeys = currentPreKeyId > 0
|
|
583
|
-
? await keys.get("pre-key", [currentPreKeyId.toString()])
|
|
584
|
-
: {}
|
|
585
|
-
const currentPreKeyExists = !!preKeys[currentPreKeyId.toString()]
|
|
586
577
|
|
|
587
578
|
logger.info(
|
|
588
|
-
|
|
579
|
+
`Server: ${preKeyCount} pre-keys, Current ID: ${currentPreKeyId}`
|
|
589
580
|
)
|
|
590
581
|
|
|
591
|
-
//
|
|
592
|
-
if (!currentPreKeyExists && currentPreKeyId > 0) {
|
|
593
|
-
logger.warn(
|
|
594
|
-
{ currentPreKeyId },
|
|
595
|
-
"🚨 Current pre-key file missing - regenerating full batch"
|
|
596
|
-
)
|
|
597
|
-
await uploadPreKeys(INITIAL_PREKEY_COUNT)
|
|
598
|
-
return
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// Low server count
|
|
582
|
+
// Only regenerate if server is low
|
|
602
583
|
if (preKeyCount < MIN_PREKEY_COUNT) {
|
|
603
584
|
const uploadCount = INITIAL_PREKEY_COUNT - preKeyCount
|
|
604
585
|
logger.info(
|
|
@@ -607,7 +588,7 @@ export const makeSocket = (config) => {
|
|
|
607
588
|
await uploadPreKeys(uploadCount)
|
|
608
589
|
} else {
|
|
609
590
|
logger.info(
|
|
610
|
-
`✅ PreKey validation passed - Server: ${preKeyCount} pre-keys
|
|
591
|
+
`✅ PreKey validation passed - Server: ${preKeyCount} pre-keys`
|
|
611
592
|
)
|
|
612
593
|
}
|
|
613
594
|
} catch (error) {
|
|
@@ -1214,7 +1195,7 @@ export const makeSocket = (config) => {
|
|
|
1214
1195
|
onWhatsApp,
|
|
1215
1196
|
listener: (eventName) => {
|
|
1216
1197
|
if (typeof ev.listenerCount === "function") return ev.listenerCount(eventName)
|
|
1217
|
-
if (typeof ev.
|
|
1198
|
+
if (typeof ev.listener === "function") return ev.listener(eventName)?.length || 0
|
|
1218
1199
|
return 0
|
|
1219
1200
|
}
|
|
1220
1201
|
}
|
|
@@ -209,6 +209,11 @@ export const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
|
|
|
209
209
|
decryptables += 1
|
|
210
210
|
let msgBuffer
|
|
211
211
|
const decryptionJid = await getDecryptionJid(author, repository, logger)
|
|
212
|
+
let decryptionAltJid = null
|
|
213
|
+
const { senderAlt } = extractAddressingContext(stanza)
|
|
214
|
+
if (senderAlt) {
|
|
215
|
+
decryptionAltJid = await getDecryptionJid(senderAlt, repository, logger)
|
|
216
|
+
}
|
|
212
217
|
if (tag !== "plaintext") {
|
|
213
218
|
// TODO: Handle hosted devices
|
|
214
219
|
await storeMappingFromEnvelope(stanza, author, repository, decryptionJid, logger)
|
|
@@ -228,6 +233,7 @@ export const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
|
|
|
228
233
|
try {
|
|
229
234
|
msgBuffer = await repository.decryptMessage({
|
|
230
235
|
jid: decryptionJid,
|
|
236
|
+
alternateJid: decryptionAltJid,
|
|
231
237
|
type: e2eType,
|
|
232
238
|
ciphertext: content,
|
|
233
239
|
})
|
package/lib/Utils/generics.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Boom } from '@hapi/boom'
|
|
2
2
|
import { createHash, randomBytes } from 'crypto'
|
|
3
3
|
import { proto } from '../../WAProto/index.js'
|
|
4
|
-
const baileysVersion = [2, 3000,
|
|
4
|
+
const baileysVersion = [2, 3000, 1027934701]
|
|
5
5
|
import { DisconnectReason } from '../Types/index.js'
|
|
6
6
|
import { getAllBinaryNodeChildren, jidDecode } from '../WABinary/index.js'
|
|
7
7
|
import { sha256 } from './crypto.js'
|
|
@@ -57,13 +57,17 @@ export const getUrlInfo = async (text, opts = {
|
|
|
57
57
|
originalThumbnailUrl: image
|
|
58
58
|
};
|
|
59
59
|
if (opts.uploadImage) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
try {
|
|
61
|
+
const { imageMessage } = await prepareWAMessageMedia({ image: { url: image } }, {
|
|
62
|
+
upload: opts.uploadImage,
|
|
63
|
+
mediaTypeOverride: 'thumbnail-link',
|
|
64
|
+
options: opts.fetchOpts
|
|
65
|
+
});
|
|
66
|
+
urlInfo.jpegThumbnail = imageMessage?.jpegThumbnail ? Buffer.from(imageMessage.jpegThumbnail) : undefined;
|
|
67
|
+
urlInfo.highQualityThumbnail = imageMessage || undefined;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
opts.logger?.warn({ err: error.message, url: image }, 'failed to upload link preview thumbnail, continuing without it');
|
|
70
|
+
}
|
|
67
71
|
}
|
|
68
72
|
else {
|
|
69
73
|
try {
|