innovators-bot2 2.0.5 → 2.0.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.
Files changed (5) hide show
  1. package/README.md +161 -10
  2. package/example.js +405 -202
  3. package/example.mp4 +0 -0
  4. package/index.js +176 -34
  5. package/package.json +3 -3
package/example.mp4 ADDED
Binary file
package/index.js CHANGED
@@ -21,7 +21,10 @@ const {
21
21
  generateCombinedButtons,
22
22
  generateCopyCodeButton,
23
23
  generateUrlButtonMessage,
24
- generateQuickReplyButtons
24
+ generateQuickReplyButtons,
25
+ StatusHelper,
26
+ STATUS_BACKGROUNDS,
27
+ STATUS_FONTS,
25
28
  } = require('@innovatorssoft/baileys');
26
29
 
27
30
  const { Sticker, StickerTypes } = require('wa-sticker-formatter');
@@ -124,6 +127,32 @@ class WhatsAppClient extends EventEmitter {
124
127
  return jid.replace(/:\d+@/, '@');
125
128
  }
126
129
 
130
+ /**
131
+ * Internal helper to handle mentions and the "mention all" flag
132
+ * @param {string[]} mentions - Array of JIDs or keywords like 'all'/'@all'
133
+ * @param {boolean} mentionAll - Explicit mentionAll flag
134
+ * @returns {object} Object containing processed mentions and mentionAll flag
135
+ * @private
136
+ */
137
+ _handleMentions(mentions, mentionAll) {
138
+ let processedMentions = mentions;
139
+ let finalMentionAll = mentionAll;
140
+
141
+ if (mentions && Array.isArray(mentions)) {
142
+ processedMentions = mentions
143
+ .filter(jid => jid !== 'all' && jid !== '@all')
144
+ .map(jid => this._normalizeJid(jid));
145
+ if (mentions.includes('all') || mentions.includes('@all')) {
146
+ finalMentionAll = true;
147
+ }
148
+ }
149
+
150
+ return {
151
+ mentions: processedMentions,
152
+ mentionAll: finalMentionAll
153
+ };
154
+ }
155
+
127
156
  async connect() {
128
157
  try {
129
158
  if (this._connectionState === 'connecting' && this.sock) {
@@ -148,13 +177,13 @@ class WhatsAppClient extends EventEmitter {
148
177
  auth: state,
149
178
  logger,
150
179
  markOnlineOnConnect: false,
151
- syncFullHistory: true,
180
+ syncFullHistory: false,
152
181
  getMessage: async (key) => (this.messageStore.getOriginalMessage(key))?.message,
153
182
  generateHighQualityLinkPreview: true,
154
183
  linkPreviewImageThumbnailWidth: 192,
155
184
  emitOwnEvents: true,
156
185
  browser: Browsers.android('Innovators Soft'),
157
- version: waWebVersion,
186
+ version: baileysVersion,
158
187
  cachedGroupMetadata: async (jid) => {
159
188
  const cached = this.groupMetadataCache.get(jid);
160
189
  if (cached) {
@@ -291,6 +320,10 @@ class WhatsAppClient extends EventEmitter {
291
320
  // Save message store to file immediately
292
321
  await this.saveMessageStore();
293
322
 
323
+ /*console.log('-'.repeat(50));
324
+ console.dir(update, { depth: null });
325
+ console.log('-'.repeat(50));*/
326
+
294
327
  try {
295
328
  if (update.type !== 'notify' || !update.messages?.length) return;
296
329
  const [message] = update.messages;
@@ -301,19 +334,14 @@ class WhatsAppClient extends EventEmitter {
301
334
 
302
335
  const msg = message.message || {};
303
336
 
337
+ let jid = this._normalizeJid(message.key.remoteJid);
304
338
 
305
- let jid = message.key.remoteJid;
306
-
307
- // Prefer PN (Phone Number) JID over LID for better compatibility
308
- // remoteJidAlt contains the alternate JID (PN if primary is LID, or vice versa)
309
- if (typeof message.key.remoteJidAlt === 'string' &&
310
- message.key.remoteJidAlt.endsWith('@s.whatsapp.net')
311
- ) {
312
- jid = message.key.remoteJidAlt;
313
- }
339
+ // Keep the original technical JID as the primary identifier for Signal sessions
340
+ // remoteJidAlt can be used if needed, but not to replace the primary jid for technical replies
341
+ const jidAlt = this._normalizeJid(message.key.remoteJidAlt) || null;
314
342
  // Resolve the actual sender (preferring PN over LID)
315
- const participant = message.key.participant || message.participant || null;
316
- const participantAlt = message.key.participantAlt || null;
343
+ const participant = this._normalizeJid(message.key.participant || message.participant) || null;
344
+ const participantAlt = this._normalizeJid(message.key.participantAlt) || null;
317
345
 
318
346
  let sender = jid;
319
347
  if (jid.endsWith('@g.us') || jid === 'status@broadcast') {
@@ -401,6 +429,7 @@ class WhatsAppClient extends EventEmitter {
401
429
 
402
430
  this.emit('message', {
403
431
  from: jid,
432
+ fromAlt: jidAlt,
404
433
  sender,
405
434
  participant,
406
435
  participantAlt,
@@ -427,13 +456,13 @@ class WhatsAppClient extends EventEmitter {
427
456
  this.sock.ev.on('messages.update', (updates) => {
428
457
  const deletedMessages = antiDeleteHandler(updates);
429
458
  for (const info of deletedMessages) {
430
- let jid = info.key.remoteJid;
431
- if (typeof info.key.remoteJidAlt === 'string' && info.key.remoteJidAlt.endsWith('@s.whatsapp.net')) {
432
- jid = info.key.remoteJidAlt;
433
- }
459
+ let jid = this._normalizeJid(info.key.remoteJid);
460
+ // Use original remoteJid for technical identification
461
+ const jidAlt = this._normalizeJid(info.key.remoteJidAlt) || null;
434
462
 
435
463
  this.emit('message-deleted', {
436
464
  jid: jid,
465
+ jidAlt: jidAlt,
437
466
  originalMessage: info.originalMessage,
438
467
  key: info.key
439
468
  });
@@ -446,17 +475,16 @@ class WhatsAppClient extends EventEmitter {
446
475
 
447
476
  try {
448
477
  for (const reaction of reactions) {
478
+ if (reaction.key?.fromMe) continue;
449
479
 
450
480
  // Get the chat JID, preferring PN over LID
451
- let jid = reaction.key.remoteJid;
452
- if (typeof reaction.key.remoteJidAlt === 'string' &&
453
- reaction.key.remoteJidAlt.endsWith('@s.whatsapp.net')) {
454
- jid = reaction.key.remoteJidAlt;
455
- }
481
+ let jid = this._normalizeJid(reaction.key.remoteJid);
482
+ // Use original remoteJid for technical identification
483
+ const jidAlt = this._normalizeJid(reaction.key.remoteJidAlt) || null;
456
484
 
457
485
  // Resolve the sender (who reacted), preferring PN over LID
458
- const participant = reaction.key.participant || null;
459
- const participantAlt = reaction.key.participantAlt || null;
486
+ const participant = this._normalizeJid(reaction.key.participant) || null;
487
+ const participantAlt = this._normalizeJid(reaction.key.participantAlt) || null;
460
488
 
461
489
  let sender = jid;
462
490
  if (jid.endsWith('@g.us') || jid === 'status@broadcast') {
@@ -471,6 +499,7 @@ class WhatsAppClient extends EventEmitter {
471
499
  // Emit the reaction event
472
500
  this.emit('message-reaction', {
473
501
  from: jid,
502
+ fromAlt: jidAlt,
474
503
  sender: sender,
475
504
  participant: participant,
476
505
  participantAlt: participantAlt,
@@ -611,6 +640,7 @@ class WhatsAppClient extends EventEmitter {
611
640
  * @throws {Error} If client is not connected or message sending fails
612
641
  */
613
642
  async sendMessage(chatId, message, options = {}) {
643
+ chatId = this._normalizeJid(chatId);
614
644
  if (!this.isConnected) {
615
645
  throw new Error('Client is not connected');
616
646
  }
@@ -625,9 +655,9 @@ class WhatsAppClient extends EventEmitter {
625
655
  switch (message.type) {
626
656
  case 'text':
627
657
  messageContent = { text: message.text };
628
- if (message.mentions) {
629
- messageContent.mentions = message.mentions;
630
- }
658
+ const { mentions: textMentions, mentionAll: textMentionAll } = this._handleMentions(message.mentions, message.mentionAll);
659
+ if (textMentions) messageContent.mentions = textMentions;
660
+ if (textMentionAll !== undefined) messageContent.mentionAll = textMentionAll;
631
661
  break;
632
662
 
633
663
  case 'location':
@@ -689,6 +719,7 @@ class WhatsAppClient extends EventEmitter {
689
719
  * @throws {Error} If client is not connected or file not found
690
720
  */
691
721
  async sendMedia(chatId, filePath, options = {}) {
722
+ chatId = this._normalizeJid(chatId);
692
723
  if (!this.isConnected) {
693
724
  throw new Error('Client is not connected');
694
725
  }
@@ -740,9 +771,9 @@ class WhatsAppClient extends EventEmitter {
740
771
  throw new Error('Unsupported file type: ' + fileExtension);
741
772
  }
742
773
 
743
- if (options.mentions) {
744
- mediaMessage.mentions = options.mentions;
745
- }
774
+ const { mentions: mediaMentions, mentionAll: mediaMentionAll } = this._handleMentions(options.mentions, options.mentionAll);
775
+ if (mediaMentions) mediaMessage.mentions = mediaMentions;
776
+ if (mediaMentionAll !== undefined) mediaMessage.mentionAll = mediaMentionAll;
746
777
 
747
778
  return await this.sock.sendMessage(chatId, mediaMessage, { ai: true });
748
779
  } catch (error) {
@@ -760,6 +791,7 @@ class WhatsAppClient extends EventEmitter {
760
791
  * @throws {Error} If client is not connected or file not found
761
792
  */
762
793
  async sendDocument(chatId, filePath, caption = '') {
794
+ chatId = this._normalizeJid(chatId);
763
795
  if (!this.isConnected) {
764
796
  throw new Error('Client is not connected');
765
797
  }
@@ -783,7 +815,10 @@ class WhatsAppClient extends EventEmitter {
783
815
 
784
816
  if (typeof caption === 'object' && caption !== null) {
785
817
  if (caption.caption) messageContent.caption = caption.caption;
786
- if (caption.mentions) messageContent.mentions = caption.mentions;
818
+
819
+ const { mentions: docMentions, mentionAll: docMentionAll } = this._handleMentions(caption.mentions, caption.mentionAll);
820
+ if (docMentions) messageContent.mentions = docMentions;
821
+ if (docMentionAll !== undefined) messageContent.mentionAll = docMentionAll;
787
822
  }
788
823
 
789
824
  return await this.sock.sendMessage(chatId, {
@@ -811,6 +846,7 @@ class WhatsAppClient extends EventEmitter {
811
846
  * @throws {Error} If client is not connected or message sending fails
812
847
  */
813
848
  async sendButtons(chatId, options = {}, extraOptions = {}) {
849
+ chatId = this._normalizeJid(chatId);
814
850
  if (!this.isConnected) {
815
851
  throw new Error('Client is not connected');
816
852
  }
@@ -893,7 +929,9 @@ class WhatsAppClient extends EventEmitter {
893
929
  * @returns {Promise<object>} The sent message info
894
930
  * @throws {Error} If client is not connected or message sending fails
895
931
  */
932
+
896
933
  async SendList(chatId, listOptions) {
934
+ chatId = this._normalizeJid(chatId);
897
935
  if (!this.isConnected) {
898
936
  throw new Error('Client is not connected');
899
937
  }
@@ -929,6 +967,7 @@ class WhatsAppClient extends EventEmitter {
929
967
  * @param {object} options - { footer }
930
968
  */
931
969
  async sendQuickReplyV2(jid, text, buttons, options = {}) {
970
+ jid = this._normalizeJid(jid);
932
971
  if (!this.isConnected) throw new Error('Client is not connected');
933
972
  const message = generateQuickReplyButtons(text, buttons, options);
934
973
  return await this.sock.sendMessage(jid, message, { ai: true });
@@ -940,6 +979,7 @@ class WhatsAppClient extends EventEmitter {
940
979
  * @param {object} options - Button options
941
980
  */
942
981
  async sendInteractiveButtonV2(jid, options) {
982
+ jid = this._normalizeJid(jid);
943
983
  if (!this.isConnected) throw new Error('Client is not connected');
944
984
  const message = generateInteractiveButtonMessage(options);
945
985
  return await this.sock.sendMessage(jid, message, { ai: true });
@@ -953,6 +993,7 @@ class WhatsAppClient extends EventEmitter {
953
993
  * @param {object} options - { title, footer }
954
994
  */
955
995
  async sendUrlButtonV2(jid, text, buttons, options = {}) {
996
+ jid = this._normalizeJid(jid);
956
997
  if (!this.isConnected) throw new Error('Client is not connected');
957
998
  const message = generateUrlButtonMessage(text, buttons, options);
958
999
  return await this.sock.sendMessage(jid, message, { ai: true });
@@ -966,6 +1007,7 @@ class WhatsAppClient extends EventEmitter {
966
1007
  * @param {string} buttonText - Text on the copy button
967
1008
  */
968
1009
  async sendCopyCodeV2(jid, text, code, buttonText) {
1010
+ jid = this._normalizeJid(jid);
969
1011
  if (!this.isConnected) throw new Error('Client is not connected');
970
1012
  const message = generateCopyCodeButton(text, code, buttonText);
971
1013
  return await this.sock.sendMessage(jid, message, { ai: true });
@@ -979,6 +1021,7 @@ class WhatsAppClient extends EventEmitter {
979
1021
  * @param {object} options - { title, footer }
980
1022
  */
981
1023
  async sendCombinedButtonsV2(jid, text, buttons, options = {}) {
1024
+ jid = this._normalizeJid(jid);
982
1025
  if (!this.isConnected) throw new Error('Client is not connected');
983
1026
  const message = generateCombinedButtons(text, buttons, options);
984
1027
  return await this.sock.sendMessage(jid, message, { ai: true });
@@ -990,9 +1033,21 @@ class WhatsAppClient extends EventEmitter {
990
1033
  * @param {object} options - List options (title, buttonText, description, footer, sections)
991
1034
  */
992
1035
  async sendListV2(jid, options) {
1036
+ jid = this._normalizeJid(jid);
993
1037
  if (!this.isConnected) throw new Error('Client is not connected');
994
1038
  const message = generateInteractiveListMessage(options);
995
- return await this.sock.sendMessage(jid, message, { ai: true });
1039
+ return await this.sock.relayMessage(jid, message, { ai: true });
1040
+ }
1041
+
1042
+ /**
1043
+ * Send Buttons Cards Message
1044
+ * @param {string} jid - Target JID
1045
+ * @param {object} options - Cards options (text, title, subtile, footer, cards)
1046
+ */
1047
+ async sendcards(jid, options) {
1048
+ jid = this._normalizeJid(jid);
1049
+ if (!this.isConnected) throw new Error('Client is not connected');
1050
+ return await this.sock.sendMessage(jid, options, { ai: true });
996
1051
  }
997
1052
  /**
998
1053
  * Send an external ad reply with a local image
@@ -1005,6 +1060,7 @@ class WhatsAppClient extends EventEmitter {
1005
1060
  */
1006
1061
 
1007
1062
  async sendAdReply(number, msg, imgpath, title, body, sourceurl) {
1063
+ number = this._normalizeJid(number);
1008
1064
  if (!this.isConnected) {
1009
1065
  throw new Error('Client is not connected');
1010
1066
  }
@@ -1074,7 +1130,8 @@ class WhatsAppClient extends EventEmitter {
1074
1130
  const results = [];
1075
1131
 
1076
1132
  try {
1077
- for (const participantId of participantIds) {
1133
+ for (let participantId of participantIds) {
1134
+ participantId = this._normalizeJid(participantId);
1078
1135
  try {
1079
1136
  let updateResult = await this.sock.groupParticipantsUpdate(
1080
1137
  groupId,
@@ -2520,6 +2577,89 @@ class WhatsAppClient extends EventEmitter {
2520
2577
  throw error;
2521
2578
  }
2522
2579
  }
2580
+
2581
+ /**
2582
+ * Post a status update (story) with various media types and styles
2583
+ * @param {object} options Options for the status update
2584
+ * @param {string} [options.text] Text content for a text status
2585
+ * @param {string|number[]} [options.backgroundColor] Background color for text status (hex or array of rgb)
2586
+ * @param {number} [options.font] Font type for text status (1-5)
2587
+ * @param {string} [options.textColor] Text color (hex)
2588
+ * @param {string} [options.imagePath] Path to image file for image status
2589
+ * @param {string} [options.videoPath] Path to video file for video status
2590
+ * @param {string} [options.audioPath] Path to audio file for voice note status
2591
+ * @param {Buffer} [options.imageBuffer] Buffer containing image data
2592
+ * @param {Buffer} [options.videoBuffer] Buffer containing video data
2593
+ * @param {Buffer} [options.audioBuffer] Buffer containing audio data
2594
+ * @param {string} [options.caption] Caption for image or video status
2595
+ * @param {boolean} [options.isGif=false] Whether the video should be played as a GIF
2596
+ * @param {Array<string>} [contacts=[]] List of JIDs who should receive the status (important for Multi-Device)
2597
+ * @returns {Promise<object>} The sent message info
2598
+ * @throws {Error} If client is not connected or options are invalid
2599
+ */
2600
+ async sendStatus(options = {}, contacts = []) {
2601
+ if (!this.isConnected) {
2602
+ throw new Error('Client is not connected');
2603
+ }
2604
+
2605
+ try {
2606
+ let statusMessage;
2607
+
2608
+ // Voice Note Status
2609
+ if (options.audioPath || options.audioBuffer) {
2610
+ const buffer = options.audioBuffer || fs.readFileSync(options.audioPath);
2611
+ statusMessage = StatusHelper.voiceNote(buffer);
2612
+ }
2613
+ // Image Status
2614
+ else if (options.imagePath || options.imageBuffer) {
2615
+ const buffer = options.imageBuffer || fs.readFileSync(options.imagePath);
2616
+ statusMessage = StatusHelper.image(buffer, options.caption || '');
2617
+ }
2618
+ // Video / GIF Status
2619
+ else if (options.videoPath || options.videoBuffer) {
2620
+ const buffer = options.videoBuffer || fs.readFileSync(options.videoPath);
2621
+ if (options.isGif) {
2622
+ statusMessage = StatusHelper.gif(buffer, options.caption || '');
2623
+ } else {
2624
+ statusMessage = StatusHelper.video(buffer, options.caption || '');
2625
+ }
2626
+ }
2627
+ // Text Status
2628
+ else if (options.text) {
2629
+ statusMessage = StatusHelper.text(
2630
+ options.text,
2631
+ options.backgroundColor || STATUS_BACKGROUNDS.solid.purple,
2632
+ options.font || STATUS_FONTS.SANS_SERIF,
2633
+ options.textColor
2634
+ );
2635
+ } else {
2636
+ throw new Error('Invalid status options: Provide text, image, video, or audio.');
2637
+ }
2638
+
2639
+ // Send using the new StatusHelper
2640
+ return await StatusHelper.send(this.sock, statusMessage, contacts);
2641
+
2642
+ } catch (error) {
2643
+ console.error('Error sending status:', error);
2644
+ throw error;
2645
+ }
2646
+ }
2647
+
2648
+ async sendGroupStatus(jid, content = {}, options = {}) {
2649
+ if (!this.isConnected) {
2650
+ throw new Error('Client is not connected');
2651
+ }
2652
+
2653
+ if (!jid || typeof jid !== 'string' || !jid.endsWith('@g.us')) {
2654
+ throw new Error('Invalid group JID. Expected a JID ending with @g.us');
2655
+ }
2656
+
2657
+ if (!content || typeof content !== 'object') {
2658
+ throw new Error('Invalid content. Expected an object');
2659
+ }
2660
+
2661
+ return await this.sock.sendMessage(jid, { ...content, groupStatus: true }, options);
2662
+ }
2523
2663
  }
2524
2664
 
2525
2665
  function formatCode(code) {
@@ -2532,4 +2672,6 @@ function formatCode(code) {
2532
2672
  module.exports = {
2533
2673
  WhatsAppClient: WhatsAppClient,
2534
2674
  Group: Group,
2675
+ STATUS_BACKGROUNDS,
2676
+ STATUS_FONTS
2535
2677
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "innovators-bot2",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "description": "WhatsApp API",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -30,7 +30,7 @@
30
30
  },
31
31
  "homepage": "https://github.com/innovatorssoft/WhatsAppAPI?tab=readme-ov-file#whatsapp-api",
32
32
  "dependencies": {
33
- "@innovatorssoft/baileys": "latest",
33
+ "@innovatorssoft/baileys": "^7.4.3",
34
34
  "figlet": "^1.8.0",
35
35
  "mime": "^3.0.0",
36
36
  "mime-types": "^2.1.35",
@@ -39,4 +39,4 @@
39
39
  "qrcode-terminal": "^0.12.0",
40
40
  "wa-sticker-formatter": "^4.4.4"
41
41
  }
42
- }
42
+ }