@crysnovax/baileys 2.6.4 → 2.6.6
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 +37 -0
- package/lib/Socket/messages-send.js +118 -62
- package/lib/Socket/messages-send.js[failed] +1589 -0
- package/lib/Socket/messages-send.js[old] +134 -1
- package/lib/Utils/messages-media.js +90 -0
- package/lib/Utils/{messages-media.js[past] → messages-media.js[old]} +74 -0
- package/lib/Utils/messages.js +2 -2
- package/lib/Utils/messages.js[old] +38 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -732,6 +732,42 @@ await sock.sendMessage(jid, {
|
|
|
732
732
|
})
|
|
733
733
|
```
|
|
734
734
|
|
|
735
|
+
### Rich preview for group status
|
|
736
|
+
```
|
|
737
|
+
// Fully auto — fetches title, description, image from the URL
|
|
738
|
+
await sock.sendMessage(jid, {
|
|
739
|
+
text: 'https://facebook.com/share/v/14i...',
|
|
740
|
+
richPreview: true
|
|
741
|
+
})
|
|
742
|
+
|
|
743
|
+
// Group status with auto-fetched preview
|
|
744
|
+
await sock.sendMessage(jid, {
|
|
745
|
+
text: 'https://chat.whatsapp.com/CODE',
|
|
746
|
+
richPreview: true,
|
|
747
|
+
groupStatus: true
|
|
748
|
+
})
|
|
749
|
+
```
|
|
750
|
+
### SEND MESSAGES EXACTLY AS IS NO PROCESSING
|
|
751
|
+
```
|
|
752
|
+
// Relay a received message exactly as-is
|
|
753
|
+
await sock.sendMessage(jid, {
|
|
754
|
+
likeThis: true,
|
|
755
|
+
...m.message // spread the captured message directly
|
|
756
|
+
})
|
|
757
|
+
|
|
758
|
+
// Send a manually constructed proto without normalization
|
|
759
|
+
await sock.sendMessage(jid, {
|
|
760
|
+
likeThis: true,
|
|
761
|
+
imageMessage: { ...rawFields }
|
|
762
|
+
})
|
|
763
|
+
|
|
764
|
+
// Re-forward with original quality intact
|
|
765
|
+
await sock.sendMessage(jid, {
|
|
766
|
+
likeThis: true,
|
|
767
|
+
...capturedMsg.message
|
|
768
|
+
})
|
|
769
|
+
```
|
|
770
|
+
|
|
735
771
|
### WHATSAPP VERIFIED ☑️ ⚉
|
|
736
772
|
send Media messages with verified WhatsApp check ✔️
|
|
737
773
|
```
|
|
@@ -741,6 +777,7 @@ await sock.sendMessage(jid, {
|
|
|
741
777
|
verifiedMe: true
|
|
742
778
|
})
|
|
743
779
|
```
|
|
780
|
+
|
|
744
781
|
---
|
|
745
782
|
|
|
746
783
|
## Meta AI Features
|
|
@@ -3,7 +3,7 @@ import { Boom } from '@hapi/boom';
|
|
|
3
3
|
import { randomBytes } from 'crypto';
|
|
4
4
|
import { proto } from '../../WAProto/index.js';
|
|
5
5
|
import { BIZ_BOT_SUPPORT_PAYLOAD, DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
|
|
6
|
-
import { aggregateMessageKeysNotFromMe, assertMediaContent, assertMeId, bindWaitForEvent, decryptMediaRetryData, DEF_MEDIA_HOST, delay, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, extractImageThumb, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, generateWAMessageFromContent, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, hasValidAlbumMedia, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, prepareWAMessageMedia, shouldIncludeBizBinaryNode, unixTimestampSeconds } from '../Utils/index.js';
|
|
6
|
+
import { aggregateMessageKeysNotFromMe, assertMediaContent, assertMeId, bindWaitForEvent, buildLinkPreview, decryptMediaRetryData, DEF_MEDIA_HOST, delay, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, extractImageThumb, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, generateWAMessageFromContent, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, hasValidAlbumMedia, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, prepareWAMessageMedia, shouldIncludeBizBinaryNode, unixTimestampSeconds } from '../Utils/index.js';
|
|
7
7
|
import { AssociationType } from '../Types/index.js';
|
|
8
8
|
import { getUrlInfo } from '../Utils/link-preview.js';
|
|
9
9
|
import { makeKeyedMutex, makeMutex } from '../Utils/make-mutex.js';
|
|
@@ -1269,6 +1269,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
1269
1269
|
previewTitle,
|
|
1270
1270
|
previewDescription,
|
|
1271
1271
|
previewImage,
|
|
1272
|
+
groupStatus: isGroupStatus,
|
|
1272
1273
|
quoted,
|
|
1273
1274
|
...restContent
|
|
1274
1275
|
} = content;
|
|
@@ -1277,24 +1278,35 @@ export const makeMessagesSocket = (config) => {
|
|
|
1277
1278
|
throw new Boom('richPreview requires a `text` field containing the URL', { statusCode: 400 });
|
|
1278
1279
|
}
|
|
1279
1280
|
|
|
1280
|
-
//
|
|
1281
|
-
//
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1281
|
+
// Auto-fetch metadata (title, description, image) when not provided.
|
|
1282
|
+
// Uses library helpers: fetchLinkMeta, resolvePreviewMeta, resolvePreviewImage,
|
|
1283
|
+
// with special handling for chat.whatsapp.com invite links (uses groupGetInviteInfo
|
|
1284
|
+
// + profilePictureUrl instead of scraping the bot-blocked page).
|
|
1285
|
+
const _preview = await buildLinkPreview(
|
|
1286
|
+
previewLink,
|
|
1287
|
+
sock,
|
|
1288
|
+
{
|
|
1289
|
+
customTitle: previewTitle || '',
|
|
1290
|
+
customDesc: previewDescription || '',
|
|
1291
|
+
customImage: Buffer.isBuffer(previewImage) ? previewImage : null
|
|
1286
1292
|
}
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1293
|
+
);
|
|
1294
|
+
|
|
1295
|
+
let imageBuffer = _preview.imageBuffer;
|
|
1296
|
+
|
|
1297
|
+
// If previewImage was a URL string, fetch it (overrides auto-fetch)
|
|
1298
|
+
if (!imageBuffer && typeof previewImage === 'string') {
|
|
1299
|
+
try {
|
|
1300
|
+
const res = await fetch(previewImage);
|
|
1301
|
+
imageBuffer = Buffer.from(await res.arrayBuffer());
|
|
1302
|
+
} catch (err) {
|
|
1303
|
+
logger?.warn({ err }, 'richPreview: failed to fetch previewImage URL');
|
|
1295
1304
|
}
|
|
1296
1305
|
}
|
|
1297
1306
|
|
|
1307
|
+
const resolvedTitle = previewTitle || _preview.title || '';
|
|
1308
|
+
const resolvedDescription = previewDescription || _preview.description || '';
|
|
1309
|
+
|
|
1298
1310
|
// Small embedded jpegThumbnail — kept under the ~7KB ceiling
|
|
1299
1311
|
// that causes WA clients to render a blank/black preview if exceeded.
|
|
1300
1312
|
// 296px @ quality 50 (fixed internally by extractImageThumb) sits
|
|
@@ -1323,41 +1335,48 @@ export const makeMessagesSocket = (config) => {
|
|
|
1323
1335
|
}
|
|
1324
1336
|
}
|
|
1325
1337
|
|
|
1326
|
-
const
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
...restContent
|
|
1347
|
-
}
|
|
1338
|
+
const extendedText = {
|
|
1339
|
+
text: previewLink,
|
|
1340
|
+
matchedText: previewLink,
|
|
1341
|
+
canonicalUrl: previewLink,
|
|
1342
|
+
title: resolvedTitle,
|
|
1343
|
+
description: resolvedDescription,
|
|
1344
|
+
previewType: 5, // IMAGE
|
|
1345
|
+
jpegThumbnail: smallThumb || undefined,
|
|
1346
|
+
...(hq
|
|
1347
|
+
? {
|
|
1348
|
+
thumbnailDirectPath: hq.directPath,
|
|
1349
|
+
mediaKey: hq.mediaKey,
|
|
1350
|
+
mediaKeyTimestamp: hq.mediaKeyTimestamp,
|
|
1351
|
+
thumbnailWidth: hq.width,
|
|
1352
|
+
thumbnailHeight: hq.height,
|
|
1353
|
+
thumbnailSha256: hq.fileSha256,
|
|
1354
|
+
thumbnailEncSha256: hq.fileEncSha256
|
|
1355
|
+
}
|
|
1356
|
+
: {}),
|
|
1357
|
+
...restContent
|
|
1348
1358
|
};
|
|
1349
1359
|
|
|
1350
|
-
const msgId = options.messageId || generateMessageIDV2(userJid);
|
|
1351
|
-
|
|
1352
1360
|
if (quoted) {
|
|
1353
|
-
|
|
1354
|
-
...(
|
|
1361
|
+
extendedText.contextInfo = {
|
|
1362
|
+
...(extendedText.contextInfo || {}),
|
|
1355
1363
|
stanzaId: quoted.key.id,
|
|
1356
1364
|
participant: jidNormalizedUser(quoted.key.fromMe ? userJid : (quoted.key.participant || quoted.key.remoteJid)),
|
|
1357
1365
|
quotedMessage: quoted.message
|
|
1358
1366
|
};
|
|
1359
1367
|
}
|
|
1360
1368
|
|
|
1369
|
+
// Support groupStatus:true alongside richPreview:true
|
|
1370
|
+
if (isGroupStatus) {
|
|
1371
|
+
extendedText.contextInfo = { ...(extendedText.contextInfo || {}), isGroupStatus: true };
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
const previewMessage = isGroupStatus
|
|
1375
|
+
? { groupStatusMessageV2: { message: { extendedTextMessage: extendedText } } }
|
|
1376
|
+
: { extendedTextMessage: extendedText };
|
|
1377
|
+
|
|
1378
|
+
const msgId = options.messageId || generateMessageIDV2(userJid);
|
|
1379
|
+
|
|
1361
1380
|
await relayMessage(jid, previewMessage, {
|
|
1362
1381
|
messageId: msgId,
|
|
1363
1382
|
additionalAttributes: options.additionalAttributes || {},
|
|
@@ -1381,28 +1400,66 @@ export const makeMessagesSocket = (config) => {
|
|
|
1381
1400
|
}
|
|
1382
1401
|
return fullMsg;
|
|
1383
1402
|
}
|
|
1403
|
+
// crysnovax@LikeThis --- likeThis:true relays the message object exactly as-is,
|
|
1404
|
+
// bypassing generateWAMessage/generateWAMessageContent entirely.
|
|
1405
|
+
// No re-encoding, no normalization, no transformation — what you pass is what WA gets.
|
|
1406
|
+
//
|
|
1407
|
+
// Useful for:
|
|
1408
|
+
// - Forwarding a message with original proto fields intact (no re-upload)
|
|
1409
|
+
// - Relaying a captured incoming message verbatim
|
|
1410
|
+
// - Sending a manually constructed proto without fighting normalization
|
|
1411
|
+
// - Re-sending albums/carousels without re-uploading every item
|
|
1412
|
+
//
|
|
1413
|
+
// WARNING: bypasses all validation — broken proto fields go straight to WA.
|
|
1414
|
+
//
|
|
1415
|
+
// Usage:
|
|
1416
|
+
// sock.sendMessage(jid, {
|
|
1417
|
+
// likeThis: true,
|
|
1418
|
+
// imageMessage: { ...rawProtoFields }
|
|
1419
|
+
// })
|
|
1420
|
+
// sock.sendMessage(jid, {
|
|
1421
|
+
// likeThis: true,
|
|
1422
|
+
// ...capturedMessage.message // spread a received message directly
|
|
1423
|
+
// })
|
|
1424
|
+
else if ('likeThis' in content && content.likeThis === true) {
|
|
1425
|
+
const { likeThis: _, ...rawMessage } = content;
|
|
1426
|
+
const msgId = options.messageId || generateMessageIDV2(userJid);
|
|
1427
|
+
|
|
1428
|
+
await relayMessage(jid, rawMessage, {
|
|
1429
|
+
messageId: msgId,
|
|
1430
|
+
additionalAttributes: options.additionalAttributes || {},
|
|
1431
|
+
additionalNodes: options.additionalNodes || []
|
|
1432
|
+
});
|
|
1433
|
+
|
|
1434
|
+
const fullMsg = {
|
|
1435
|
+
key: {
|
|
1436
|
+
remoteJid: jid,
|
|
1437
|
+
fromMe: true,
|
|
1438
|
+
id: msgId
|
|
1439
|
+
},
|
|
1440
|
+
message: rawMessage,
|
|
1441
|
+
messageTimestamp: unixTimestampSeconds()
|
|
1442
|
+
};
|
|
1443
|
+
|
|
1444
|
+
if (config.emitOwnEvents) {
|
|
1445
|
+
process.nextTick(async () => {
|
|
1446
|
+
await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
return fullMsg;
|
|
1450
|
+
}
|
|
1451
|
+
// ── NORMAL MESSAGE HANDLING ──
|
|
1384
1452
|
else {
|
|
1385
1453
|
const fullMsg = await generateWAMessage(jid, content, {
|
|
1386
1454
|
logger,
|
|
1387
1455
|
userJid,
|
|
1388
|
-
getUrlInfo: text => getUrlInfo(text, {
|
|
1389
|
-
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
1390
|
-
fetchOpts: {
|
|
1391
|
-
timeout: 3000,
|
|
1392
|
-
...(httpRequestOptions || {})
|
|
1393
|
-
},
|
|
1394
|
-
logger,
|
|
1395
|
-
uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
|
|
1396
|
-
}),
|
|
1397
|
-
//TODO: CACHE
|
|
1398
|
-
getProfilePicUrl: sock.profilePictureUrl,
|
|
1399
|
-
getCallLink: sock.createCallLink,
|
|
1400
1456
|
upload: waUploadToServer,
|
|
1401
1457
|
mediaCache: config.mediaCache,
|
|
1402
1458
|
options: config.options,
|
|
1403
1459
|
...options,
|
|
1404
1460
|
messageId: generateMessageIDV2(userJid)
|
|
1405
1461
|
});
|
|
1462
|
+
|
|
1406
1463
|
const isNewsletter = isJidNewsletter(jid);
|
|
1407
1464
|
const isEventMsg = 'event' in content && !!content.event;
|
|
1408
1465
|
const isDeleteMsg = 'delete' in content && !!content.delete;
|
|
@@ -1415,9 +1472,8 @@ export const makeMessagesSocket = (config) => {
|
|
|
1415
1472
|
const isNeedBizAttrs = 'secureMetaServiceLabel' in content && !!content.secureMetaServiceLabel;
|
|
1416
1473
|
const additionalAttributes = options.additionalAttributes || {};
|
|
1417
1474
|
const additionalNodes = options.additionalNodes || [];
|
|
1418
|
-
|
|
1475
|
+
|
|
1419
1476
|
if (isDeleteMsg || isKeepMsg) {
|
|
1420
|
-
// if the chat is a group, and I am not the author, then delete the message as an admin
|
|
1421
1477
|
if (isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) {
|
|
1422
1478
|
additionalAttributes.edit = '8';
|
|
1423
1479
|
}
|
|
@@ -1438,7 +1494,6 @@ export const makeMessagesSocket = (config) => {
|
|
|
1438
1494
|
additionalNodes.push({
|
|
1439
1495
|
tag: 'meta',
|
|
1440
1496
|
attrs: {
|
|
1441
|
-
// Lia@Note 08-02-26 --- Still a hypothesis regarding PollResult ༎ຶ‿༎ຶ
|
|
1442
1497
|
polltype: isQuizMsg ? 'quiz_creation' : 'creation',
|
|
1443
1498
|
contenttype: isPollMsg && isNewsletter ? 'text' : undefined
|
|
1444
1499
|
},
|
|
@@ -1454,7 +1509,6 @@ export const makeMessagesSocket = (config) => {
|
|
|
1454
1509
|
content: undefined
|
|
1455
1510
|
});
|
|
1456
1511
|
}
|
|
1457
|
-
// Lia@Changes 30-01-26 --- Add support for AI label in message when "ai" is true, but works only in private chat
|
|
1458
1512
|
else if (isAiMsg) {
|
|
1459
1513
|
if (!(isPnUser(jid) || isLidUser(jid))) {
|
|
1460
1514
|
throw new Boom('AI icon on message are only allowed in private chat', { statusCode: 400 });
|
|
@@ -1462,7 +1516,6 @@ export const makeMessagesSocket = (config) => {
|
|
|
1462
1516
|
if ('messageContextInfo' in fullMsg.message && !!fullMsg.message.messageContextInfo) {
|
|
1463
1517
|
fullMsg.message.messageContextInfo.supportPayload = BIZ_BOT_SUPPORT_PAYLOAD;
|
|
1464
1518
|
}
|
|
1465
|
-
;
|
|
1466
1519
|
additionalNodes.push({
|
|
1467
1520
|
tag: 'bot',
|
|
1468
1521
|
attrs: {
|
|
@@ -1472,6 +1525,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
1472
1525
|
});
|
|
1473
1526
|
delete content.ai;
|
|
1474
1527
|
}
|
|
1528
|
+
|
|
1475
1529
|
await relayMessage(jid, fullMsg.message, {
|
|
1476
1530
|
messageId: fullMsg.key.id,
|
|
1477
1531
|
useCachedGroupMetadata: options.useCachedGroupMetadata,
|
|
@@ -1480,13 +1534,14 @@ export const makeMessagesSocket = (config) => {
|
|
|
1480
1534
|
additionalAttributes,
|
|
1481
1535
|
additionalNodes
|
|
1482
1536
|
});
|
|
1537
|
+
|
|
1483
1538
|
if (config.emitOwnEvents) {
|
|
1484
1539
|
process.nextTick(async () => {
|
|
1485
1540
|
await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
1486
1541
|
});
|
|
1487
1542
|
}
|
|
1488
|
-
|
|
1489
|
-
//
|
|
1543
|
+
|
|
1544
|
+
// ── ALBUM MESSAGES ──
|
|
1490
1545
|
if ('album' in content) {
|
|
1491
1546
|
const { delayMs = 1500 } = options;
|
|
1492
1547
|
for (const albumMedia of content.album) {
|
|
@@ -1523,8 +1578,9 @@ export const makeMessagesSocket = (config) => {
|
|
|
1523
1578
|
await delay(delayMs);
|
|
1524
1579
|
}
|
|
1525
1580
|
}
|
|
1581
|
+
|
|
1526
1582
|
return fullMsg;
|
|
1527
1583
|
}
|
|
1528
1584
|
}
|
|
1529
|
-
}
|
|
1530
|
-
};
|
|
1585
|
+
}
|
|
1586
|
+
};
|