@nexustechpro/baileys 1.1.9 → 2.0.2
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/lib/Socket/messages-send.js +629 -345
- package/lib/Utils/link-preview.js +46 -36
- package/lib/Utils/messages-media.js +155 -311
- package/lib/Utils/messages.js +43 -43
- package/lib/index.js +2 -2
- package/package.json +20 -20
package/lib/Utils/messages.js
CHANGED
|
@@ -22,7 +22,7 @@ export const extractUrlFromText = (text) => text.match(URL_REGEX)?.[0];
|
|
|
22
22
|
export const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
|
|
23
23
|
const url = extractUrlFromText(text);
|
|
24
24
|
if (!getUrlInfo || !url) return;
|
|
25
|
-
try { return await getUrlInfo(url); }
|
|
25
|
+
try { return await getUrlInfo(url); }
|
|
26
26
|
catch (e) { logger?.warn({ trace: e.stack }, 'url generation failed'); }
|
|
27
27
|
};
|
|
28
28
|
|
|
@@ -122,7 +122,7 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
122
122
|
uploadData.waveform = await getAudioWaveform(bodyPath, options.logger)
|
|
123
123
|
} catch (err) {
|
|
124
124
|
options.logger?.warn('Failed to generate waveform, using fallback')
|
|
125
|
-
uploadData.waveform = new Uint8Array([0,99,0,99,0,99,0,99,88,99,0,99,0,55,0,99,0,99,0,99,0,99,0,99,88,99,0,99,0,55,0,99])
|
|
125
|
+
uploadData.waveform = new Uint8Array([0, 99, 0, 99, 0, 99, 0, 99, 88, 99, 0, 99, 0, 55, 0, 99, 0, 99, 0, 99, 0, 99, 0, 99, 88, 99, 0, 99, 0, 55, 0, 99])
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
if (options.backgroundColor && mediaType === 'audio') uploadData.backgroundArgb = assertColor(options.backgroundColor)
|
|
@@ -134,7 +134,7 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
134
134
|
if (encFilePath && typeof encFilePath === 'string') {
|
|
135
135
|
try {
|
|
136
136
|
await fs.unlink(encFilePath)
|
|
137
|
-
} catch {}
|
|
137
|
+
} catch { }
|
|
138
138
|
}
|
|
139
139
|
if (didSaveToTmpPath && bodyPath) {
|
|
140
140
|
try {
|
|
@@ -164,13 +164,13 @@ export const generateForwardMessageContent = (message, forceForward) => {
|
|
|
164
164
|
const content = proto.Message.decode(proto.Message.encode(normalizeMessageContent(message.message)).finish());
|
|
165
165
|
let key = Object.keys(content)[0];
|
|
166
166
|
let score = (content?.[key]?.contextInfo?.forwardingScore || 0) + (message.key.fromMe && !forceForward ? 0 : 1);
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
if (key === 'conversation') {
|
|
169
169
|
content.extendedTextMessage = { text: content[key] };
|
|
170
170
|
delete content.conversation;
|
|
171
171
|
key = 'extendedTextMessage';
|
|
172
172
|
}
|
|
173
|
-
|
|
173
|
+
|
|
174
174
|
content[key].contextInfo = score > 0 ? { forwardingScore: score, isForwarded: true } : {};
|
|
175
175
|
return content;
|
|
176
176
|
};
|
|
@@ -179,7 +179,7 @@ export const generateForwardMessageContent = (message, forceForward) => {
|
|
|
179
179
|
const handleTextMessage = async (message, options) => {
|
|
180
180
|
const extContent = { text: message.text };
|
|
181
181
|
let urlInfo = message.linkPreview || await generateLinkPreviewIfRequired(message.text, options.getUrlInfo, options.logger);
|
|
182
|
-
|
|
182
|
+
|
|
183
183
|
if (urlInfo) {
|
|
184
184
|
Object.assign(extContent, {
|
|
185
185
|
matchedText: urlInfo['matched-text'], jpegThumbnail: urlInfo.jpegThumbnail,
|
|
@@ -193,7 +193,7 @@ const handleTextMessage = async (message, options) => {
|
|
|
193
193
|
});
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
|
-
|
|
196
|
+
|
|
197
197
|
if (options.backgroundColor) extContent.backgroundArgb = assertColor(options.backgroundColor);
|
|
198
198
|
if (options.font) extContent.font = options.font;
|
|
199
199
|
return { extendedTextMessage: extContent };
|
|
@@ -226,7 +226,7 @@ const handleGroupInvite = async (message, options) => {
|
|
|
226
226
|
caption: message.groupInvite.text, groupJid: message.groupInvite.jid, groupName: message.groupInvite.subject
|
|
227
227
|
}
|
|
228
228
|
};
|
|
229
|
-
|
|
229
|
+
|
|
230
230
|
if (options.getProfilePicUrl) {
|
|
231
231
|
const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
|
|
232
232
|
if (pfpUrl) {
|
|
@@ -248,7 +248,7 @@ const handleEventMessage = (message, options) => {
|
|
|
248
248
|
},
|
|
249
249
|
messageContextInfo: { messageSecret: message.event.messageSecret || randomBytes(32) }
|
|
250
250
|
};
|
|
251
|
-
|
|
251
|
+
|
|
252
252
|
if (message.event.call && options.getCallLink) {
|
|
253
253
|
options.getCallLink(message.event.call, { startTime }).then(token => {
|
|
254
254
|
m.eventMessage.joinLink = (message.event.call === 'audio' ? CALL_AUDIO_PREFIX : CALL_VIDEO_PREFIX) + token;
|
|
@@ -260,7 +260,7 @@ const handleEventMessage = (message, options) => {
|
|
|
260
260
|
const handlePollMessage = (message) => {
|
|
261
261
|
message.poll.selectableCount ||= 0;
|
|
262
262
|
message.poll.toAnnouncementGroup ||= false;
|
|
263
|
-
|
|
263
|
+
|
|
264
264
|
if (!Array.isArray(message.poll.values)) throw new Boom('Invalid poll values', { statusCode: 400 });
|
|
265
265
|
if (message.poll.selectableCount < 0 || message.poll.selectableCount > message.poll.values.length)
|
|
266
266
|
throw new Boom(`poll.selectableCount should be >= 0 and <= ${message.poll.values.length}`, { statusCode: 400 });
|
|
@@ -308,21 +308,21 @@ const handleRequestPayment = async (message, options) => {
|
|
|
308
308
|
// ===== MAIN GENERATOR =====
|
|
309
309
|
export const generateWAMessageContent = async (message, options = {}) => {
|
|
310
310
|
const messageKeys = Object.keys(message);
|
|
311
|
-
|
|
311
|
+
|
|
312
312
|
// ===== SMART DETECTION =====
|
|
313
|
-
const isRawProtoMessage = messageKeys.some(key =>
|
|
314
|
-
key.endsWith('Message') &&
|
|
313
|
+
const isRawProtoMessage = messageKeys.some(key =>
|
|
314
|
+
key.endsWith('Message') &&
|
|
315
315
|
typeof message[key] === 'object' &&
|
|
316
316
|
!HIGH_LEVEL_KEYS.includes(key)
|
|
317
317
|
);
|
|
318
|
-
|
|
318
|
+
|
|
319
319
|
const isWrapperMessage = ['viewOnceMessage', 'ephemeralMessage', 'viewOnceMessageV2', 'documentWithCaptionMessage'].some(k => k in message);
|
|
320
|
-
|
|
320
|
+
|
|
321
321
|
// Pass through raw protocol messages directly
|
|
322
322
|
if ((isRawProtoMessage || isWrapperMessage) && messageKeys.length === 1) {
|
|
323
323
|
return WAProto.Message.create(message);
|
|
324
324
|
}
|
|
325
|
-
|
|
325
|
+
|
|
326
326
|
// If no high-level keys AND has proto message keys, pass through
|
|
327
327
|
if (!messageKeys.some(k => HIGH_LEVEL_KEYS.includes(k)) && isRawProtoMessage) {
|
|
328
328
|
return WAProto.Message.create(message);
|
|
@@ -334,7 +334,7 @@ export const generateWAMessageContent = async (message, options = {}) => {
|
|
|
334
334
|
if ('text' in message && !('buttons' in message) && !('templateButtons' in message) && !('sections' in message) && !('interactiveButtons' in message) && !('shop' in message)) {
|
|
335
335
|
m = await handleTextMessage(message, options);
|
|
336
336
|
}
|
|
337
|
-
|
|
337
|
+
|
|
338
338
|
// ===== HANDLE SPECIAL MESSAGES =====
|
|
339
339
|
else {
|
|
340
340
|
const special = await handleSpecialMessages(message, options);
|
|
@@ -379,7 +379,7 @@ export const generateWAMessageContent = async (message, options = {}) => {
|
|
|
379
379
|
// ===== SMART BUTTON HANDLING =====
|
|
380
380
|
if ('buttons' in message && Array.isArray(message.buttons) && message.buttons.length > 0) {
|
|
381
381
|
const hasNativeFlow = message.buttons.some(b => b.nativeFlowInfo || b.name || b.buttonParamsJson);
|
|
382
|
-
|
|
382
|
+
|
|
383
383
|
if (hasNativeFlow) {
|
|
384
384
|
// Convert to interactiveMessage
|
|
385
385
|
const interactive = {
|
|
@@ -393,25 +393,25 @@ export const generateWAMessageContent = async (message, options = {}) => {
|
|
|
393
393
|
})
|
|
394
394
|
}
|
|
395
395
|
};
|
|
396
|
-
|
|
396
|
+
|
|
397
397
|
if (message.title) interactive.header = { title: message.title, subtitle: message.subtitle, hasMediaAttachment: message.hasMediaAttachment || false };
|
|
398
398
|
if (Object.keys(m).length > 0) {
|
|
399
399
|
interactive.header = interactive.header || { title: message.title || '', hasMediaAttachment: true };
|
|
400
400
|
Object.assign(interactive.header, m);
|
|
401
401
|
}
|
|
402
|
-
|
|
402
|
+
|
|
403
403
|
m = { interactiveMessage: interactive };
|
|
404
404
|
} else {
|
|
405
405
|
// Old-style buttons
|
|
406
406
|
const buttonsMessage = { buttons: message.buttons.map(b => ({ ...b, type: proto.Message.ButtonsMessage.Button.Type.RESPONSE })) };
|
|
407
|
-
if ('text' in message) { buttonsMessage.contentText = message.text; buttonsMessage.headerType = proto.Message.ButtonsMessage.HeaderType.EMPTY; }
|
|
407
|
+
if ('text' in message) { buttonsMessage.contentText = message.text; buttonsMessage.headerType = proto.Message.ButtonsMessage.HeaderType.EMPTY; }
|
|
408
408
|
else { if ('caption' in message) buttonsMessage.contentText = message.caption; const type = Object.keys(m)[0]?.replace('Message', '').toUpperCase(); buttonsMessage.headerType = proto.Message.ButtonsMessage.HeaderType[type] || proto.Message.ButtonsMessage.HeaderType.EMPTY; Object.assign(buttonsMessage, m); }
|
|
409
409
|
if (message.title) { buttonsMessage.text = message.title; buttonsMessage.headerType = proto.Message.ButtonsMessage.HeaderType.TEXT; }
|
|
410
410
|
if (message.footer) buttonsMessage.footerText = message.footer;
|
|
411
411
|
m = { buttonsMessage };
|
|
412
412
|
}
|
|
413
413
|
}
|
|
414
|
-
|
|
414
|
+
|
|
415
415
|
// ===== TEMPLATE BUTTONS =====
|
|
416
416
|
else if ('templateButtons' in message && !!message.templateButtons) {
|
|
417
417
|
const msg = { hydratedButtons: message.templateButtons };
|
|
@@ -420,12 +420,12 @@ export const generateWAMessageContent = async (message, options = {}) => {
|
|
|
420
420
|
if ('footer' in message && !!message.footer) msg.hydratedFooterText = message.footer;
|
|
421
421
|
m = { templateMessage: { fourRowTemplate: msg, hydratedTemplate: msg } };
|
|
422
422
|
}
|
|
423
|
-
|
|
423
|
+
|
|
424
424
|
// ===== LIST MESSAGE =====
|
|
425
425
|
else if ('sections' in message && !!message.sections) {
|
|
426
426
|
m = { listMessage: { sections: message.sections, buttonText: message.buttonText, title: message.title, footerText: message.footer, description: message.text, listType: proto.Message.ListMessage.ListType.SINGLE_SELECT } };
|
|
427
427
|
}
|
|
428
|
-
|
|
428
|
+
|
|
429
429
|
// ===== INTERACTIVE BUTTONS =====
|
|
430
430
|
else if ('interactiveButtons' in message && !!message.interactiveButtons) {
|
|
431
431
|
const interactiveMessage = { nativeFlowMessage: WAProto.Message.InteractiveMessage.NativeFlowMessage.fromObject({ buttons: message.interactiveButtons }) };
|
|
@@ -435,50 +435,50 @@ export const generateWAMessageContent = async (message, options = {}) => {
|
|
|
435
435
|
if ('title' in message && !!message.title) { interactiveMessage.header = { title: message.title, subtitle: message.subtitle, hasMediaAttachment: message?.media ?? false }; Object.assign(interactiveMessage.header, m); }
|
|
436
436
|
m = { interactiveMessage };
|
|
437
437
|
}
|
|
438
|
-
|
|
438
|
+
|
|
439
439
|
// ===== SHOP MESSAGE (YOUR EXAMPLE) =====
|
|
440
440
|
else if ('shop' in message && !!message.shop) {
|
|
441
|
-
const interactiveMessage = {
|
|
442
|
-
shopStorefrontMessage: WAProto.Message.InteractiveMessage.ShopMessage.fromObject({
|
|
443
|
-
surface: message.shop.surface || 1,
|
|
444
|
-
id: message.shop.id || message.id
|
|
445
|
-
})
|
|
441
|
+
const interactiveMessage = {
|
|
442
|
+
shopStorefrontMessage: WAProto.Message.InteractiveMessage.ShopMessage.fromObject({
|
|
443
|
+
surface: message.shop.surface || 1,
|
|
444
|
+
id: message.shop.id || message.id
|
|
445
|
+
})
|
|
446
446
|
};
|
|
447
|
-
|
|
447
|
+
|
|
448
448
|
// Handle body text
|
|
449
449
|
if ('text' in message) interactiveMessage.body = { text: message.text };
|
|
450
450
|
else if ('caption' in message) interactiveMessage.body = { text: message.caption };
|
|
451
|
-
|
|
451
|
+
|
|
452
452
|
// Handle header with media
|
|
453
453
|
if (message.title || message.subtitle || Object.keys(m).length > 0) {
|
|
454
|
-
interactiveMessage.header = {
|
|
455
|
-
title: message.title || '',
|
|
456
|
-
subtitle: message.subtitle || '',
|
|
454
|
+
interactiveMessage.header = {
|
|
455
|
+
title: message.title || '',
|
|
456
|
+
subtitle: message.subtitle || '',
|
|
457
457
|
hasMediaAttachment: message.hasMediaAttachment ?? (Object.keys(m).length > 0)
|
|
458
458
|
};
|
|
459
459
|
if (Object.keys(m).length > 0) Object.assign(interactiveMessage.header, m);
|
|
460
460
|
}
|
|
461
|
-
|
|
461
|
+
|
|
462
462
|
if ('footer' in message && !!message.footer) interactiveMessage.footer = { text: message.footer };
|
|
463
|
-
|
|
463
|
+
|
|
464
464
|
m = { interactiveMessage };
|
|
465
465
|
}
|
|
466
466
|
|
|
467
467
|
// ===== AUTO-APPLY CONTEXT & WRAPPERS =====
|
|
468
468
|
const finalKey = Object.keys(m)[0];
|
|
469
|
-
|
|
469
|
+
|
|
470
470
|
// Auto-merge contextInfo and mentions
|
|
471
471
|
if ((message.contextInfo || message.mentions) && finalKey && m[finalKey]) {
|
|
472
|
-
m[finalKey].contextInfo = {
|
|
473
|
-
...(m[finalKey].contextInfo || {}),
|
|
472
|
+
m[finalKey].contextInfo = {
|
|
473
|
+
...(m[finalKey].contextInfo || {}),
|
|
474
474
|
...(message.contextInfo || {}),
|
|
475
475
|
mentionedJid: message.mentions || message.contextInfo?.mentionedJid || []
|
|
476
476
|
};
|
|
477
477
|
}
|
|
478
|
-
|
|
478
|
+
|
|
479
479
|
// ViewOnce wrapper
|
|
480
480
|
if (message.viewOnce === true) m = { viewOnceMessage: { message: m } };
|
|
481
|
-
|
|
481
|
+
|
|
482
482
|
// Edit wrapper
|
|
483
483
|
if (message.edit) m = { protocolMessage: { key: message.edit, editedMessage: m, timestampMs: Date.now(), type: WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT } };
|
|
484
484
|
|
|
@@ -509,7 +509,7 @@ export const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
509
509
|
}
|
|
510
510
|
|
|
511
511
|
return WAProto.WebMessageInfo.fromObject({
|
|
512
|
-
key: { remoteJid: jid, fromMe: true, id: options?.messageId || generateMessageIDV2() },
|
|
512
|
+
key: { remoteJid: jid, fromMe: true, id: options?.messageId || generateMessageIDV2(), participant: (isJidGroup(jid) || isJidStatusBroadcast(jid)) ? userJid : undefined },
|
|
513
513
|
message: WAProto.Message.create(message),
|
|
514
514
|
messageTimestamp: timestamp,
|
|
515
515
|
messageStubParameters: [],
|
package/lib/index.js
CHANGED
|
@@ -32,7 +32,7 @@ const banner = `
|
|
|
32
32
|
const info = `
|
|
33
33
|
┌───────────────────────────────────────────────────────────────────────┐
|
|
34
34
|
│ 📦 Package: @nexustechpro/baileys │
|
|
35
|
-
│ 🔖 Version:
|
|
35
|
+
│ 🔖 Version: 2.0.2 │
|
|
36
36
|
│ ⚡ Status: Production Ready │
|
|
37
37
|
├───────────────────────────────────────────────────────────────────────┤
|
|
38
38
|
│ 🚀 Advanced WhatsApp Web API Client │
|
|
@@ -41,7 +41,7 @@ const info = `
|
|
|
41
41
|
│ 📱 Business API • Channels • Status Updates │
|
|
42
42
|
├───────────────────────────────────────────────────────────────────────┤
|
|
43
43
|
│ 💡 Built by NexusTech Pro Team │
|
|
44
|
-
│ 📚 Docs: github.com/
|
|
44
|
+
│ 📚 Docs: github.com/nexustechpro2/baileys │
|
|
45
45
|
│ 💬 Support: Join our community for updates & assistance │
|
|
46
46
|
└───────────────────────────────────────────────────────────────────────┘
|
|
47
47
|
`;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@nexustechpro/baileys",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "2.0.2",
|
|
6
6
|
"description": "Advanced WhatsApp Web API client with interactive messages, product catalogs, carousels, events, payments, and polls.",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"whatsapp",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"payments",
|
|
32
32
|
"multi-device"
|
|
33
33
|
],
|
|
34
|
-
"homepage": "https://github.com/
|
|
34
|
+
"homepage": "https://github.com/nexustechpro2/baileys/",
|
|
35
35
|
"repository": {
|
|
36
|
-
"url": "git+ssh://git@github.com/
|
|
36
|
+
"url": "git+ssh://git@github.com/nexustechpro2/baileys.git"
|
|
37
37
|
},
|
|
38
38
|
"license": "MIT",
|
|
39
|
-
"author": "
|
|
39
|
+
"author": "nexustechpro2",
|
|
40
40
|
"main": "lib/index.js",
|
|
41
41
|
"types": "lib/index.d.ts",
|
|
42
42
|
"scripts": {
|
|
@@ -57,17 +57,17 @@
|
|
|
57
57
|
"release": "release-it",
|
|
58
58
|
"test": "jest"
|
|
59
59
|
},
|
|
60
|
-
"files": [
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
],
|
|
60
|
+
"files": [
|
|
61
|
+
"lib/**/*.js",
|
|
62
|
+
"lib/**/*.json",
|
|
63
|
+
"lib/**/*.d.ts",
|
|
64
|
+
"lib/**/*.map",
|
|
65
|
+
"WAProto/**/*.js",
|
|
66
|
+
"WAProto/**/*.json",
|
|
67
|
+
"WAProto/**/*.d.ts",
|
|
68
|
+
"WAProto/**/*.sh",
|
|
69
|
+
"engine-requirements.js"
|
|
70
|
+
],
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@cacheable/node-cache": "^1.4.0",
|
|
73
73
|
"@hapi/boom": "^9.1.3",
|
|
@@ -83,9 +83,10 @@
|
|
|
83
83
|
"p-queue": "^9.0.0",
|
|
84
84
|
"pino": "^9.6",
|
|
85
85
|
"protobufjs": "^7.2.4",
|
|
86
|
+
"sharp": "^0.32.0",
|
|
87
|
+
"whatsapp-rust-bridge": "^0.5.2",
|
|
86
88
|
"ws": "^8.13.0",
|
|
87
|
-
"yarn": "^1.22.22"
|
|
88
|
-
"whatsapp-rust-bridge": "^0.5.2"
|
|
89
|
+
"yarn": "^1.22.22"
|
|
89
90
|
},
|
|
90
91
|
"devDependencies": {
|
|
91
92
|
"@eslint/eslintrc": "^3.3.1",
|
|
@@ -106,7 +107,7 @@
|
|
|
106
107
|
"jimp": "^1.6.0",
|
|
107
108
|
"jiti": "^2.4.2",
|
|
108
109
|
"json": "^11.0.0",
|
|
109
|
-
"link-preview-js": "^
|
|
110
|
+
"link-preview-js": "^4.0.0",
|
|
110
111
|
"lru-cache": "^11.1.0",
|
|
111
112
|
"open": "^8.4.2",
|
|
112
113
|
"pino-pretty": "^13.1.1",
|
|
@@ -123,8 +124,7 @@
|
|
|
123
124
|
"peerDependencies": {
|
|
124
125
|
"audio-decode": "^2.1.3",
|
|
125
126
|
"jimp": "^1.6.0",
|
|
126
|
-
"link-preview-js": "^3.0.0"
|
|
127
|
-
"sharp": "*"
|
|
127
|
+
"link-preview-js": "^3.0.0"
|
|
128
128
|
},
|
|
129
129
|
"peerDependenciesMeta": {
|
|
130
130
|
"audio-decode": {
|