@itsliaaa/baileys 0.1.18 โ†’ 0.1.19

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 CHANGED
@@ -1,6 +1,27 @@
1
1
  # ๐ŸŒฑ @itsliaaa/baileys
2
2
 
3
- ![Logo](https://files.catbox.moe/c5s9g0.jpg)
3
+ [![Logo](https://files.catbox.moe/c5s9g0.jpg)](https://www.npmjs.com/package/@itsliaaa/baileys)
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/@itsliaaa/baileys">
7
+ <img src="https://img.shields.io/npm/v/@itsliaaa/baileys?color=FFFFFF&labelColor=red&logo=npm&logoColor=white&style=for-the-badge"/>
8
+ </a>
9
+ <a href="https://www.npmjs.com/package/@itsliaaa/baileys">
10
+ <img src="https://img.shields.io/npm/dm/@itsliaaa/baileys?color=FFFFFF&labelColor=red&logo=npm&logoColor=white&style=for-the-badge"/>
11
+ </a>
12
+ <a href="https://github.com/itsliaaa/baileys">
13
+ <img src="https://img.shields.io/github/stars/itsliaaa/baileys?color=FFFFFF&labelColor=black&logo=github&logoColor=white&style=for-the-badge"/>
14
+ </a>
15
+ <a href="LICENSE">
16
+ <img src="https://img.shields.io/badge/license-MIT-blue?labelColor=black&style=for-the-badge"/>
17
+ </a>
18
+ <a href="https://nodejs.org">
19
+ <img src="https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js&labelColor=green&logoColor=white&style=for-the-badge"/>
20
+ </a>
21
+ <a href="#">
22
+ <img src="https://img.shields.io/badge/ESM-only?logo=javascript&labelColor=yellow&logoColor=black&style=for-the-badge"/>
23
+ </a>
24
+ </p>
4
25
 
5
26
  A lightweight fork of Baileys with practical fixes and small but meaningful improvements.
6
27
 
@@ -20,9 +41,16 @@ This fork focuses on clarity and safety:
20
41
  - ๐Ÿ—ƒ๏ธ Added [`@napi-rs/image`](https://www.npmjs.com/package/@napi-rs/image) as a supported image processing backend in [`getImageProcessingLibrary()`](#%EF%B8%8F-image-processing), offering a balance between performance and compatibility.
21
42
 
22
43
  #### ๐Ÿ“จ Message Handling & Compatibility
23
- - ๐Ÿ‘‰๐Ÿป Added support for sending [interactive message](#-sending-interactive-messages) types (button, list, interactive, template, carousel).
24
- - ๐Ÿ“ฉ Added support for [album messages](#%EF%B8%8F-album-image--video), [group status messages](#4%EF%B8%8Fโƒฃ-group-status), [status mention messages](#%EF%B8%8F-status-mention), [sticker pack messages](#-sticker-pack), and several [payment-related messages](#-sending-payment-messages) (request payment, payment invite, order, invoice).
25
- - ๐Ÿ“ฐ Simplified sending messages with ad thumbnails via [`externalAdReply`](#3%EF%B8%8Fโƒฃ-external-ad-reply) without requiring manual `contextInfo`.
44
+ - ๐Ÿ‘‰๐Ÿป Added support for sending [interactive messages](#-sending-interactive-messages) (buttons, lists, interactive, templates, carousel).
45
+ - ๐Ÿ“ฉ Expanded message support for:
46
+ - [album messages](#%EF%B8%8F-album-image--video)
47
+ - [group status messages](#4%EF%B8%8Fโƒฃ-group-status)
48
+ - [status mention messages](#%EF%B8%8F-status-mention)
49
+ - [sticker pack messages](#-sticker-pack)
50
+ - [messages with code blocks](#-message-with-code-block)
51
+ - [messages with tables](#-message-with-table)
52
+ - [payment-related messages](#-sending-payment-messages) (payment requests, invites, orders, invoices).
53
+ - ๐Ÿ“ฐ Simplified sending messages with ad thumbnails using [`externalAdReply`](#3%EF%B8%8Fโƒฃ-external-ad-reply), without requiring manual `contextInfo`.
26
54
 
27
55
  #### ๐Ÿงฉ Additional Message Options
28
56
  - ๐Ÿ‘๏ธ Added optional boolean flags for message handling:
@@ -377,6 +405,32 @@ sock.sendMessage([jidA, jidB, jidC], {
377
405
  })
378
406
  ```
379
407
 
408
+ ##### ๐Ÿงพ Message with Code Block
409
+
410
+ ```javascript
411
+ sock.sendMessage(jid, {
412
+ header: 'Example Usage',
413
+ code: 'console.log("Hello, World!")',
414
+ footer: 'Pretty simple, right?',
415
+ language: 'javascript'
416
+ })
417
+ ```
418
+
419
+ ##### ๐Ÿ“‹ Message with Table
420
+
421
+ ```javascript
422
+ sock.sendMessage(jid, {
423
+ header: 'Comparison between Node.js, Bun, and Deno',
424
+ title: 'Runtime Comparison',
425
+ table: [
426
+ ['', 'Node.js', 'Bun', 'Deno'],
427
+ ['Engine', 'V8 (C++)', 'JavaScriptCore (C++)', 'V8 (C++)'],
428
+ ['Performance', '4/5', '5/5', '4/5']
429
+ ],
430
+ footer: 'Does this help clarify the differences?'
431
+ })
432
+ ```
433
+
380
434
  #### ๐Ÿ“ Sending Media Messages
381
435
 
382
436
  > [!NOTE]
@@ -669,7 +723,7 @@ sock.sendMessage(jid, {
669
723
  caption: '๐Ÿ–ผ๏ธ Image 3',
670
724
  footer: '๐Ÿท๏ธ Pinterest',
671
725
  optionText: '๐Ÿ‘‰๐Ÿป Select Options',
672
- optionTitle: '๐Ÿ“„ Select Options',
726
+ optionTitle: '๐Ÿ‘‰๐Ÿป Select Options',
673
727
  offerText: '๐Ÿท๏ธ New Coupon!',
674
728
  offerCode: '@itsliaaa/baileys',
675
729
  offerUrl: 'https://www.npmjs.com/package/@itsliaaa/baileys',
@@ -26,6 +26,7 @@ export const NOISE_MODE = 'Noise_XX_25519_AESGCM_SHA256\0\0\0\0';
26
26
  export const DICT_VERSION = 3;
27
27
  export const KEY_BUNDLE_TYPE = Buffer.from([5]);
28
28
  export const NOISE_WA_HEADER = Buffer.from([87, 65, 6, DICT_VERSION]); // last is "DICT_VERSION"
29
+ export const LEXER_REGEX = /(\/\/.*|\/\*[\s\S]*?\*\/|#.*)|("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`[\s\S]*?`)|(\b[a-zA-Z_]\w*\b)(?=\s*\()|(\b[a-zA-Z_]\w*\b)|(\b\d+(?:\.\d+)?\b)|(\s+|[^\w\s]+)/g;
29
30
  /** from: https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url */
30
31
  export const URL_REGEX = /https:\/\/(?![^:@\/\s]+:[^:@\/\s]+@)[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(:\d+)?(\/[^\s]*)?/g;
31
32
  export const WA_CERT_DETAILS = {
@@ -140,4 +141,10 @@ export const TimeMs = {
140
141
  Hour: 60 * 60 * 1000,
141
142
  Day: 24 * 60 * 60 * 1000,
142
143
  Week: 7 * 24 * 60 * 60 * 1000
144
+ };
145
+ export const FORWARDED_AI_BOT_INFO = {
146
+ isForwarded: true,
147
+ forwardingScore: 1,
148
+ forwardedAiBotMessageInfo: { botJid: '867051314767696@bot' },
149
+ forwardOrigin: 4
143
150
  };
@@ -1,6 +1,5 @@
1
1
  /**
2
- * Lia@Note 03-02-26
3
- * --- [WIP]
2
+ * Lia@Note 03-02-26 [WIP]
4
3
  * Manually converted to ESM and modified by me
5
4
  * Originally based on @whiskeysockets/baileys v6.7.16
6
5
  * Minor adjustments for compatibility with baileys v7 (โ ใคโ โ‰งโ โ–ฝโ โ‰ฆโ )โ ใค
@@ -0,0 +1,22 @@
1
+ export var CodeHighlightType;
2
+ (function (CodeHighlightType) {
3
+ CodeHighlightType[CodeHighlightType["DEFAULT"] = 0] = "DEFAULT";
4
+ CodeHighlightType[CodeHighlightType["KEYWORD"] = 1] = "KEYWORD";
5
+ CodeHighlightType[CodeHighlightType["METHOD"] = 2] = "METHOD";
6
+ CodeHighlightType[CodeHighlightType["STRING"] = 3] = "STRING";
7
+ CodeHighlightType[CodeHighlightType["NUMBER"] = 4] = "NUMBER";
8
+ CodeHighlightType[CodeHighlightType["COMMENT"] = 5] = "COMMENT";
9
+ })(CodeHighlightType || (CodeHighlightType = {}));
10
+ export var RichSubMessageType;
11
+ (function (RichSubMessageType) {
12
+ RichSubMessageType[RichSubMessageType["UNKNOWN"] = 0] = "UNKNOWN";
13
+ RichSubMessageType[RichSubMessageType["GRID_IMAGE"] = 1] = "GRID_IMAGE";
14
+ RichSubMessageType[RichSubMessageType["TEXT"] = 2] = "TEXT";
15
+ RichSubMessageType[RichSubMessageType["INLINE_IMAGE"] = 3] = "INLINE_IMAGE";
16
+ RichSubMessageType[RichSubMessageType["TABLE"] = 4] = "TABLE";
17
+ RichSubMessageType[RichSubMessageType["CODE"] = 5] = "CODE";
18
+ RichSubMessageType[RichSubMessageType["DYNAMIC"] = 6] = "DYNAMIC";
19
+ RichSubMessageType[RichSubMessageType["MAP"] = 7] = "MAP";
20
+ RichSubMessageType[RichSubMessageType["LATEX"] = 8] = "LATEX";
21
+ RichSubMessageType[RichSubMessageType["CONTENT_ITEMS"] = 9] = "CONTENT_ITEMS";
22
+ })(RichSubMessageType || (RichSubMessageType = {}));
@@ -2,6 +2,7 @@ export * from './generics.js';
2
2
  export * from './decode-wa-message.js';
3
3
  export * from './messages.js';
4
4
  export * from './messages-media.js';
5
+ export * from './rich-message-utils.js';
5
6
  export * from './validate-connection.js';
6
7
  export * from './crypto.js';
7
8
  export * from './signal.js';
@@ -10,6 +10,7 @@ import { isPnUser, isLidUser, isJidGroup, isJidNewsletter, isJidStatusBroadcast,
10
10
  import { sha256 } from './crypto.js';
11
11
  import { generateMessageIDV2, getKeyAuthor, unixTimestampSeconds } from './generics.js';
12
12
  import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, getAudioWaveform, getImageProcessingLibrary, getRawMediaUploadData, getStream, toBuffer } from './messages-media.js';
13
+ import { generateRichCodeBlock, generateRichTable, wrapToBotForwardedMessage } from './rich-message-utils.js';
13
14
  import { shouldIncludeReportingToken } from './reporting-utils.js';
14
15
  const MIMETYPE_MAP = {
15
16
  image: 'image/jpeg',
@@ -692,7 +693,7 @@ export const generateWAMessageContent = async (message, options) => {
692
693
  // Lia@Changes 30-01-26 --- Add "raw" boolean to send raw messages directly via generateWAMessage()
693
694
  if (hasNonNullishProperty(message, 'raw')) {
694
695
  delete message.raw;
695
- return proto.Message.create(message);
696
+ return message;
696
697
  }
697
698
  else if (hasNonNullishProperty(message, 'text')) {
698
699
  const extContent = { text: message.text };
@@ -726,27 +727,25 @@ export const generateWAMessageContent = async (message, options) => {
726
727
  m.extendedTextMessage = extContent;
727
728
  }
728
729
  else if (hasNonNullishProperty(message, 'contacts')) {
729
- const { contacts } = message; // Lia@Changes 04-02-26 --- Destructured for readability & cleaner access (โ โœทโ โ€ฟโ โœทโ )
730
- const contactLen = contacts.contacts.length;
730
+ const contactLen = message.contacts.contacts.length;
731
731
  if (!contactLen) {
732
732
  throw new Boom('require atleast 1 contact', { statusCode: 400 });
733
733
  }
734
734
  if (contactLen === 1) {
735
- m.contactMessage = contacts.contacts[0];
735
+ m.contactMessage = message.contacts.contacts[0];
736
736
  }
737
737
  else {
738
- m.contactsArrayMessage = contacts;
738
+ m.contactsArrayMessage = message.contacts;
739
739
  }
740
740
  }
741
741
  else if (hasNonNullishProperty(message, 'location')) {
742
742
  m.locationMessage = message.location;
743
743
  }
744
744
  else if (hasNonNullishProperty(message, 'react')) {
745
- const { react } = message; // Lia@Changes 04-02-26 --- Destructured for readability & cleaner access (โ โœทโ โ€ฟโ โœทโ )
746
- if (!react.senderTimestampMs) {
747
- react.senderTimestampMs = Date.now();
745
+ if (!message.react.senderTimestampMs) {
746
+ message.react.senderTimestampMs = Date.now();
748
747
  }
749
- m.reactionMessage = react;
748
+ m.reactionMessage = message.react;
750
749
  }
751
750
  else if (hasNonNullishProperty(message, 'delete')) {
752
751
  m.protocolMessage = {
@@ -758,26 +757,24 @@ export const generateWAMessageContent = async (message, options) => {
758
757
  m = generateForwardMessageContent(message.forward, message.force);
759
758
  }
760
759
  else if (hasNonNullishProperty(message, 'disappearingMessagesInChat')) {
761
- const { disappearingMessagesInChat } = message; // Lia@Changes 04-02-26 --- Destructured for readability & cleaner access (โ โœทโ โ€ฟโ โœทโ )
762
- const exp = typeof disappearingMessagesInChat === 'boolean'
763
- ? disappearingMessagesInChat
760
+ const exp = typeof message.disappearingMessagesInChat === 'boolean'
761
+ ? message.disappearingMessagesInChat
764
762
  ? WA_DEFAULT_EPHEMERAL
765
763
  : 0
766
- : disappearingMessagesInChat;
764
+ : message.disappearingMessagesInChat;
767
765
  m = prepareDisappearingMessageSettingContent(exp);
768
766
  }
769
767
  else if (hasNonNullishProperty(message, 'groupInvite')) {
770
- const { groupInvite } = message; // Lia@Changes 04-02-26 --- Destructured for readability & cleaner access (โ โœทโ โ€ฟโ โœทโ )
771
768
  m.groupInviteMessage = {};
772
- m.groupInviteMessage.inviteCode = groupInvite.inviteCode;
773
- m.groupInviteMessage.inviteExpiration = groupInvite.inviteExpiration;
774
- m.groupInviteMessage.caption = groupInvite.text;
775
- m.groupInviteMessage.groupJid = groupInvite.jid;
776
- m.groupInviteMessage.groupName = groupInvite.subject;
769
+ m.groupInviteMessage.inviteCode = message.groupInvite.inviteCode;
770
+ m.groupInviteMessage.inviteExpiration = message.groupInvite.inviteExpiration;
771
+ m.groupInviteMessage.caption = message.groupInvite.text;
772
+ m.groupInviteMessage.groupJid = message.groupInvite.jid;
773
+ m.groupInviteMessage.groupName = message.groupInvite.subject;
777
774
  //TODO: use built-in interface and get disappearing mode info etc.
778
775
  //TODO: cache / use store!?
779
776
  if (options.getProfilePicUrl) {
780
- const pfpUrl = await options.getProfilePicUrl(groupInvite.jid, 'preview');
777
+ const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
781
778
  if (pfpUrl) {
782
779
  const resp = await fetch(pfpUrl, { method: 'GET', dispatcher: options?.options?.dispatcher });
783
780
  if (resp.ok) {
@@ -805,47 +802,44 @@ export const generateWAMessageContent = async (message, options) => {
805
802
  m.keepInChatMessage.timestampMs = Date.now();
806
803
  }
807
804
  else if (hasNonNullishProperty(message, 'flowReply')) {
808
- const { flowReply } = message; // Lia@Changes 04-02-26 --- Destructured for readability & cleaner access (โ โœทโ โ€ฟโ โœทโ )
809
805
  m.interactiveResponseMessage = {
810
806
  body: {
811
- format: flowReply.format || proto.Message.InteractiveResponseMessage.Body.Format.DEFAULT,
812
- text: flowReply.text
807
+ format: message.flowReply.format || proto.Message.InteractiveResponseMessage.Body.Format.DEFAULT,
808
+ text: message.flowReply.text
813
809
  },
814
810
  nativeFlowResponseMessage: {
815
- name: flowReply.name,
816
- paramsJson: flowReply.paramsJson || '{}',
817
- version: flowReply.version || 1
811
+ name: message.flowReply.name,
812
+ paramsJson: message.flowReply.paramsJson || '{}',
813
+ version: message.flowReply.version || 1
818
814
  }
819
815
  };
820
816
  }
821
817
  else if (hasNonNullishProperty(message, 'buttonReply')) {
822
- const { buttonReply } = message; // Lia@Changes 04-02-26 --- Destructured for readability & cleaner access (โ โœทโ โ€ฟโ โœทโ )
823
818
  switch (message.type) {
824
819
  case 'template':
825
820
  m.templateButtonReplyMessage = {
826
- selectedDisplayText: buttonReply.displayText,
827
- selectedId: buttonReply.id,
828
- selectedIndex: buttonReply.index
821
+ selectedDisplayText: message.buttonReply.displayText,
822
+ selectedId: message.buttonReply.id,
823
+ selectedIndex: message.buttonReply.index
829
824
  };
830
825
  break;
831
826
  case 'plain':
832
827
  m.buttonsResponseMessage = {
833
- selectedButtonId: buttonReply.id,
834
- selectedDisplayText: buttonReply.displayText,
828
+ selectedButtonId: message.buttonReply.id,
829
+ selectedDisplayText: message.buttonReply.displayText,
835
830
  type: proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
836
831
  };
837
832
  break;
838
833
  }
839
834
  }
840
835
  else if (hasNonNullishProperty(message, 'listReply')) {
841
- const { listReply } = message; // Lia@Changes 04-02-26 --- Destructured for readability & cleaner access (โ โœทโ โ€ฟโ โœทโ )
842
836
  m.listResponseMessage = {
843
- description: listReply.description,
837
+ description: message.listReply.description,
844
838
  listType: proto.Message.ListResponseMessage.ListType.SINGLE_SELECT,
845
839
  singleSelectReply: {
846
- selectedRowId: listReply.id
840
+ selectedRowId: message.listReply.id
847
841
  },
848
- title: listReply.title
842
+ title: message.listReply.title
849
843
  };
850
844
  }
851
845
  else if (hasOptionalProperty(message, 'ptv') && message.ptv) {
@@ -856,68 +850,66 @@ export const generateWAMessageContent = async (message, options) => {
856
850
  m.productMessage = await prepareProductMessage(message, options);
857
851
  }
858
852
  else if (hasNonNullishProperty(message, 'event')) {
859
- const { event } = message; // Lia@Changes 04-02-26 --- Destructured for readability & cleaner access (โ โœทโ โ€ฟโ โœทโ )
860
853
  m.eventMessage = {};
861
- const startTime = Math.floor(event.startDate.getTime() / 1000);
862
- if (event.call && options.getCallLink) {
863
- const token = await options.getCallLink(event.call, { startTime });
864
- m.eventMessage.joinLink = (event.call === 'audio' ? CALL_AUDIO_PREFIX : CALL_VIDEO_PREFIX) + token;
854
+ const startTime = Math.floor(message.event.startDate.getTime() / 1000);
855
+ if (message.event.call && options.getCallLink) {
856
+ const token = await options.getCallLink(message.event.call, { startTime });
857
+ m.eventMessage.joinLink = (message.event.call === 'audio' ? CALL_AUDIO_PREFIX : CALL_VIDEO_PREFIX) + token;
865
858
  }
866
859
  m.messageContextInfo = {
867
860
  // encKey
868
- messageSecret: event.messageSecret || randomBytes(32)
861
+ messageSecret: message.event.messageSecret || randomBytes(32)
869
862
  };
870
- m.eventMessage.name = event.name;
871
- m.eventMessage.description = event.description;
863
+ m.eventMessage.name = message.event.name;
864
+ m.eventMessage.description = message.event.description;
872
865
  m.eventMessage.startTime = startTime;
873
- m.eventMessage.endTime = event.endDate ? event.endDate.getTime() / 1000 : undefined;
874
- m.eventMessage.isCanceled = event.isCancelled ?? false;
875
- m.eventMessage.extraGuestsAllowed = event.extraGuestsAllowed;
876
- m.eventMessage.isScheduleCall = event.isScheduleCall ?? false;
877
- m.eventMessage.location = event.location;
866
+ m.eventMessage.endTime = message.event.endDate ? message.event.endDate.getTime() / 1000 : undefined;
867
+ m.eventMessage.isCanceled = message.event.isCancelled ?? false;
868
+ m.eventMessage.extraGuestsAllowed = message.event.extraGuestsAllowed;
869
+ m.eventMessage.isScheduleCall = message.event.isScheduleCall ?? false;
870
+ m.eventMessage.location = message.event.location;
878
871
  }
879
872
  else if (hasNonNullishProperty(message, 'poll')) {
880
- const { poll } = message; // Lia@Changes 04-02-26 --- Destructured for readability & cleaner access (โ โœทโ โ€ฟโ โœทโ )
881
- (_a = poll).selectableCount || (_a.selectableCount = 0);
882
- (_b = poll).toAnnouncementGroup || (_b.toAnnouncementGroup = false);
883
- if (!Array.isArray(poll.values)) {
873
+ (_a = message.poll).selectableCount || (_a.selectableCount = 0);
874
+ (_b = message.poll).toAnnouncementGroup || (_b.toAnnouncementGroup = false);
875
+ if (!Array.isArray(message.poll.values)) {
884
876
  throw new Boom('Invalid poll values', { statusCode: 400 });
885
877
  }
886
- if (poll.selectableCount < 0 || poll.selectableCount > poll.values.length) {
887
- throw new Boom(`poll.selectableCount in poll should be >= 0 and <= ${poll.values.length}`, {
878
+ if (message.poll.selectableCount < 0 || message.poll.selectableCount > message.poll.values.length) {
879
+ throw new Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, {
888
880
  statusCode: 400
889
881
  });
890
882
  }
891
883
  m.messageContextInfo = {
892
884
  // encKey
893
- messageSecret: poll.messageSecret || randomBytes(32)
885
+ messageSecret: message.poll.messageSecret || randomBytes(32)
894
886
  };
895
887
  const pollCreationMessage = {
896
- name: poll.name,
897
- selectableOptionsCount: poll.selectableCount,
898
- options: poll.values.map(optionName => ({ optionName }))
888
+ name: message.poll.name,
889
+ selectableOptionsCount: message.poll.selectableCount,
890
+ options: message.poll.values.map(optionName => ({ optionName }))
899
891
  };
900
- if (poll.toAnnouncementGroup) {
892
+ if (message.poll.toAnnouncementGroup) {
901
893
  // poll v2 is for community announcement groups (single select and multiple)
902
894
  m.pollCreationMessageV2 = pollCreationMessage;
903
895
  }
904
896
  else {
905
897
  // Lia@Changes 08-02-26 --- Add quiz message support
906
- if (poll.pollType === 1) {
907
- if (!poll.correctAnswer) {
898
+ if (message.poll.pollType == 1) {
899
+ if (!message.poll.correctAnswer) {
908
900
  throw new Boom('No "correctAnswer" provided for quiz', { statusCode: 400 });
909
901
  }
910
902
  m.pollCreationMessageV5 = {
911
903
  // Lia@Note 08-02-26 --- quiz for newsletter only
912
904
  ...pollCreationMessage,
913
905
  correctAnswer: {
914
- optionName: poll.correctAnswer.toString()
906
+ optionName: message.poll.correctAnswer.toString()
915
907
  },
916
- pollType: poll.pollType,
908
+ pollType: message.poll.pollType,
917
909
  selectableOptionsCount: 1
918
910
  };
919
911
  }
920
- else if (poll.selectableCount === 1) {
912
+ else if (message.poll.selectableCount === 1) {
921
913
  //poll v3 is for single select polls
922
914
  m.pollCreationMessageV3 = pollCreationMessage;
923
915
  }
@@ -929,15 +921,14 @@ export const generateWAMessageContent = async (message, options) => {
929
921
  }
930
922
  // Lia@Changes 08-02-26 --- Add poll result snapshot message
931
923
  else if (hasNonNullishProperty(message, 'pollResult')) {
932
- const { pollResult } = message;
933
924
  const pollResultSnapshotMessage = {
934
- name: pollResult.name,
935
- pollVotes: pollResult.votes.map(vote => ({
925
+ name: message.pollResult.name,
926
+ pollVotes: message.pollResult.votes.map(vote => ({
936
927
  optionName: vote.name,
937
928
  optionVoteCount: parseInt(vote.voteCount)
938
929
  }))
939
930
  };
940
- if (pollResult.pollType === 1) {
931
+ if (message.pollResult.pollType == 1) {
941
932
  pollResultSnapshotMessage.pollType = proto.Message.PollType.QUIZ;
942
933
  m.pollResultSnapshotMessageV3 = pollResultSnapshotMessage;
943
934
  }
@@ -948,18 +939,17 @@ export const generateWAMessageContent = async (message, options) => {
948
939
  }
949
940
  // Lia@Changes 08-02-26 --- Add poll update message
950
941
  else if (hasNonNullishProperty(message, 'pollUpdate')) {
951
- const { pollUpdate } = message;
952
- if (!pollUpdate.key) {
942
+ if (!message.pollUpdate.key) {
953
943
  throw new Boom('Message key is required', { statusCode: 400 });
954
944
  }
955
- if (!pollUpdate.vote) {
945
+ if (!message.pollUpdate.vote) {
956
946
  throw new Boom('Encrypted vote payload is required', { statusCode: 400 });
957
947
  }
958
948
  m.pollUpdateMessage = {
959
- metadata: pollUpdate.metadata,
960
- pollCreationMessageKey: pollUpdate.key,
949
+ metadata: message.pollUpdate.metadata,
950
+ pollCreationMessageKey: message.pollUpdate.key,
961
951
  senderTimestampMs: Date.now(),
962
- vote: pollUpdate.vote
952
+ vote: message.pollUpdate.vote
963
953
  };
964
954
  }
965
955
  else if (hasNonNullishProperty(message, 'sharePhoneNumber')) {
@@ -1009,17 +999,16 @@ export const generateWAMessageContent = async (message, options) => {
1009
999
  }
1010
1000
  // Lia@Changes 31-01-26 --- Add support for album messages
1011
1001
  else if (hasNonNullishProperty(message, 'album')) {
1012
- const { album } = message;
1013
- if (!Array.isArray(album)) {
1002
+ if (!Array.isArray(message.album)) {
1014
1003
  throw new Boom('Invalid album type. Expected an array.', { statusCode: 400 });
1015
1004
  }
1016
1005
  let videoCount = 0;
1017
- for (let i = 0; i < album.length; i++) {
1018
- if (album[i].video) videoCount++;
1006
+ for (let i = 0; i < message.album.length; i++) {
1007
+ if (message.album[i].video) videoCount++;
1019
1008
  };
1020
1009
  let imageCount = 0;
1021
- for (let i = 0; i < album.length; i++) {
1022
- if (album[i].image) imageCount++;
1010
+ for (let i = 0; i < message.album.length; i++) {
1011
+ if (message.album[i].image) imageCount++;
1023
1012
  };
1024
1013
  if ((videoCount + imageCount) < 2) {
1025
1014
  throw new Boom('Minimum provide 2 media to upload album message', { statusCode: 400 });
@@ -1029,6 +1018,13 @@ export const generateWAMessageContent = async (message, options) => {
1029
1018
  expectedVideoCount: videoCount
1030
1019
  };
1031
1020
  }
1021
+ // Lia@Changes 09-04-26 --- Add support for code block and table
1022
+ else if (hasNonNullishProperty(message, 'code')) {
1023
+ m.richResponseMessage = generateRichCodeBlock(message);
1024
+ }
1025
+ else if (hasNonNullishProperty(message, 'table')) {
1026
+ m.richResponseMessage = generateRichTable(message);
1027
+ }
1032
1028
  else {
1033
1029
  m = await prepareWAMessageMedia(message, options);
1034
1030
  }
@@ -1420,6 +1416,10 @@ export const generateWAMessageContent = async (message, options) => {
1420
1416
  m = { viewOnceMessageV2Extension: { message: m } };
1421
1417
  delete message.viewOnceV2Extension;
1422
1418
  }
1419
+ // Lia@Note 09-04-26 --- Wrap richResponseMessage into botForwardedMessage
1420
+ if (!!m.richResponseMessage) {
1421
+ m = wrapToBotForwardedMessage(m)
1422
+ }
1423
1423
  if (hasOptionalProperty(message, 'edit')) {
1424
1424
  m = {
1425
1425
  protocolMessage: {
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Lia@Changes 09-04-26 [WIP]
3
+ * Add support for tables and code blocks in richResponseMessage (wrapped in botForwardedMessage)
4
+ */
5
+ import { FORWARDED_AI_BOT_INFO, LEXER_REGEX } from '../Defaults/index.js';
6
+ import { CodeHighlightType } from '../Types/RichType.js';
7
+ const CPP_KEYWORDS = new Set([
8
+ 'alignas', 'alignof', 'and', 'and_eq', 'asm', 'auto', 'bitand', 'bitor', 'bool', 'break', 'case',
9
+ 'catch', 'char', 'class', 'compl', 'concept', 'const', 'consteval', 'constexpr', 'constinit',
10
+ 'const_cast', 'continue', 'co_await', 'co_return', 'co_yield', 'decltype', 'default', 'delete',
11
+ 'do', 'double', 'dynamic_cast', 'else', 'enum', 'explicit', 'export', 'extern', 'false', 'float',
12
+ 'for', 'friend', 'goto', 'if', 'inline', 'int', 'long', 'mutable', 'namespace', 'new', 'noexcept',
13
+ 'not', 'not_eq', 'nullptr', 'operator', 'or', 'or_eq', 'private', 'protected', 'public', 'register',
14
+ 'reinterpret_cast', 'requires', 'return', 'short', 'signed', 'sizeof', 'static', 'static_assert',
15
+ 'static_cast', 'struct', 'switch', 'template', 'this', 'thread_local', 'throw', 'true', 'try',
16
+ 'typedef', 'typeid', 'typename', 'union', 'unsigned', 'using', 'virtual', 'void', 'volatile',
17
+ 'wchar_t', 'while', 'xor', 'xor_eq'
18
+ ]);
19
+ const CSS_KEYWORDS = new Set([
20
+ 'import', 'media', 'font-face', 'keyframes', 'supports', 'charset',
21
+ 'important', 'root', 'hover', 'active', 'focus', 'visited', 'before', 'after',
22
+ 'not', 'nth-child', 'first-child', 'last-child', 'only-child',
23
+ 'none', 'inherit', 'initial', 'unset', 'auto', 'transparent', 'currentcolor'
24
+ ]);
25
+ const GO_KEYWORDS = new Set([
26
+ 'break', 'default', 'func', 'interface', 'select', 'case', 'defer', 'go', 'map', 'struct',
27
+ 'chan', 'else', 'goto', 'package', 'switch', 'const', 'fallthrough', 'if', 'range', 'type',
28
+ 'continue', 'for', 'import', 'return', 'var', 'true', 'false', 'nil'
29
+ ]);
30
+ const HTML_KEYWORDS = new Set([
31
+ 'html', 'head', 'body', 'title', 'meta', 'link', 'script', 'style',
32
+ 'header', 'footer', 'main', 'section', 'article', 'aside', 'nav',
33
+ 'div', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'a', 'img',
34
+ 'ul', 'ol', 'li', 'table', 'tr', 'td', 'th', 'thead', 'tbody',
35
+ 'form', 'input', 'button', 'select', 'textarea', 'label', 'option',
36
+ 'canvas', 'svg', 'iframe', 'video', 'audio', 'source'
37
+ ]);
38
+ const JS_KEYWORDS = new Set([
39
+ 'import', 'export', 'from', 'default', 'as',
40
+ 'const', 'let', 'var', 'function', 'class', 'extends', 'new',
41
+ 'return', 'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'break', 'continue',
42
+ 'try', 'catch', 'finally', 'throw',
43
+ 'async', 'await', 'yield',
44
+ 'typeof', 'instanceof', 'in', 'of', 'delete', 'void',
45
+ 'true', 'false', 'null', 'undefined', 'NaN', 'Infinity',
46
+ 'this', 'super', 'static', 'get', 'set',
47
+ 'debugger', 'with'
48
+ ]);
49
+ const PYTHON_KEYWORDS = new Set([
50
+ 'import', 'from', 'as', 'def', 'class', 'return', 'if', 'elif', 'else',
51
+ 'for', 'while', 'break', 'continue', 'try', 'except', 'finally', 'raise',
52
+ 'with', 'yield', 'lambda', 'pass', 'del', 'global', 'nonlocal', 'assert',
53
+ 'True', 'False', 'None', 'and', 'or', 'not', 'in', 'is', 'async', 'await',
54
+ 'self', 'print'
55
+ ]);
56
+ const RUST_KEYWORDS = new Set([
57
+ 'as', 'break', 'const', 'continue', 'crate', 'else', 'enum', 'extern', 'false', 'fn', 'for',
58
+ 'if', 'impl', 'in', 'let', 'loop', 'match', 'mod', 'move', 'mut', 'pub', 'ref', 'return',
59
+ 'self', 'Self', 'static', 'struct', 'super', 'trait', 'true', 'type', 'unsafe', 'use',
60
+ 'where', 'while', 'async', 'await', 'dyn', 'abstract', 'become', 'box', 'do', 'final',
61
+ 'macro', 'override', 'priv', 'typeof', 'unsized', 'virtual', 'yield'
62
+ ]);
63
+ const NOOP = new Set([])
64
+ export const LANGUAGE_KEYWORDS = {
65
+ css: CSS_KEYWORDS,
66
+ html: HTML_KEYWORDS,
67
+ javascript: JS_KEYWORDS,
68
+ typescript: JS_KEYWORDS,
69
+ js: JS_KEYWORDS,
70
+ ts: JS_KEYWORDS,
71
+ python: PYTHON_KEYWORDS,
72
+ py: PYTHON_KEYWORDS,
73
+ go: GO_KEYWORDS,
74
+ golang: GO_KEYWORDS,
75
+ cpp: CPP_KEYWORDS,
76
+ 'c++': CPP_KEYWORDS,
77
+ rust: RUST_KEYWORDS,
78
+ rs: RUST_KEYWORDS,
79
+ };
80
+ export const tokenizeCode = (code, language = 'javascript') => {
81
+ const keywords = LANGUAGE_KEYWORDS[language] || NOOP;
82
+ const blocks = [];
83
+ LEXER_REGEX.lastIndex = 0;
84
+ let match;
85
+ while ((match = LEXER_REGEX.exec(code)) !== null) {
86
+ if (match[1]) {
87
+ blocks.push({ highlightType: CodeHighlightType.COMMENT, codeContent: match[1] });
88
+ }
89
+ else if (match[2]) {
90
+ blocks.push({ highlightType: CodeHighlightType.STRING, codeContent: match[2] });
91
+ }
92
+ else if (match[3]) {
93
+ blocks.push({
94
+ highlightType: keywords.has(match[3]) ? CodeHighlightType.KEYWORD : CodeHighlightType.METHOD,
95
+ codeContent: match[3],
96
+ });
97
+ }
98
+ else if (match[4]) {
99
+ blocks.push({
100
+ highlightType: keywords.has(match[4]) ? CodeHighlightType.KEYWORD : CodeHighlightType.DEFAULT,
101
+ codeContent: match[4],
102
+ });
103
+ }
104
+ else if (match[5]) {
105
+ blocks.push({ highlightType: CodeHighlightType.NUMBER, codeContent: match[5] });
106
+ }
107
+ else {
108
+ blocks.push({ highlightType: CodeHighlightType.DEFAULT, codeContent: match[6] });
109
+ }
110
+ }
111
+ return blocks;
112
+ };
113
+ export const wrapToBotForwardedMessage = (message) =>
114
+ ({
115
+ messageContextInfo: {
116
+ botMetadata: {
117
+ // Lia@Note 09-04-26 --- TODO: Fill verificationMetadata field
118
+ verificationMetadata: {},
119
+ botRenderingConfigMetadata: {}
120
+ }
121
+ },
122
+ botForwardedMessage: { message }
123
+ });
124
+ export const generateRichCodeBlock = ({ header, code, footer, language } = {}) => {
125
+ language ??= 'javascript'
126
+ const submessages = [];
127
+ if (header) {
128
+ submessages.push({
129
+ messageType: 2,
130
+ messageText: header
131
+ });
132
+ }
133
+ submessages.push({
134
+ messageType: 5,
135
+ codeMetadata: {
136
+ codeLanguage: language,
137
+ codeBlocks: tokenizeCode(code, language)
138
+ }
139
+ });
140
+ if (footer) {
141
+ submessages.push({
142
+ messageType: 2,
143
+ messageText: footer
144
+ });
145
+ }
146
+ return ({
147
+ submessages,
148
+ messageType: 1,
149
+ contextInfo: FORWARDED_AI_BOT_INFO
150
+ });
151
+ };
152
+ export const generateRichTable = ({ header, title, table, footer } = {}) => {
153
+ const tableRows = table.map((items, index) => ({
154
+ isHeading: index == 0,
155
+ items
156
+ }));
157
+ const submessages = [];
158
+ if (header) {
159
+ submessages.push({
160
+ messageType: 2,
161
+ messageText: header
162
+ });
163
+ }
164
+ submessages.push({
165
+ messageType: 4,
166
+ tableMetadata: {
167
+ title,
168
+ rows: tableRows
169
+ }
170
+ });
171
+ if (footer) {
172
+ submessages.push({
173
+ messageType: 2,
174
+ messageText: footer
175
+ });
176
+ }
177
+ return ({
178
+ submessages,
179
+ messageType: 1,
180
+ contextInfo: FORWARDED_AI_BOT_INFO
181
+ });
182
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itsliaaa/baileys",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "A lightweight fork of Baileys with practical fixes and small but meaningful improvements.",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",