@itsliaaa/baileys 0.1.19 → 0.1.21

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
@@ -3,17 +3,19 @@
3
3
  [![Logo](https://files.catbox.moe/c5s9g0.jpg)](https://www.npmjs.com/package/@itsliaaa/baileys)
4
4
 
5
5
  <p align="center">
6
+ Enhanced Baileys v7 with fixed newsletter media upload, plus support for interactive messages, albums, and more message types.
7
+ <br><br>
6
8
  <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"/>
9
+ <img src="https://img.shields.io/npm/v/@itsliaaa/baileys?style=for-the-badge&logo=npm"/>
8
10
  </a>
9
11
  <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"/>
12
+ <img src="https://img.shields.io/npm/dm/@itsliaaa/baileys?style=for-the-badge&logo=npm"/>
11
13
  </a>
12
14
  <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"/>
15
+ <img src="https://img.shields.io/github/stars/itsliaaa/baileys?style=for-the-badge&logo=github"/>
14
16
  </a>
15
17
  <a href="LICENSE">
16
- <img src="https://img.shields.io/badge/license-MIT-blue?labelColor=black&style=for-the-badge"/>
18
+ <img src="https://img.shields.io/badge/license-MIT-blue?style=for-the-badge"/>
17
19
  </a>
18
20
  <a href="https://nodejs.org">
19
21
  <img src="https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js&labelColor=green&logoColor=white&style=for-the-badge"/>
@@ -23,11 +25,11 @@
23
25
  </a>
24
26
  </p>
25
27
 
26
- A lightweight fork of Baileys with practical fixes and small but meaningful improvements.
28
+ For donation: [Saweria](https://saweria.co/itsliaaa)
27
29
 
28
30
  ### ✨ Highlights
29
31
 
30
- This fork focuses on clarity and safety:
32
+ This fork designed for production use with a focus on clarity and safety:
31
33
 
32
34
  - 🚫 No obfuscation. Easy to read and audit.
33
35
  - 🚫 No auto-follow channel (newsletter) behavior.
@@ -41,24 +43,25 @@ This fork focuses on clarity and safety:
41
43
  - 🗃️ 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.
42
44
 
43
45
  #### 📨 Message Handling & Compatibility
44
- - 👉🏻 Added support for sending [interactive messages](#-sending-interactive-messages) (buttons, lists, interactive, templates, carousel).
46
+ - 👉🏻 Added support for sending [interactive messages](#-sending-interactive-messages) (buttons, lists, interactive, template, carousel).
45
47
  - 📩 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`.
48
+ - 🖼️ [Album Message](#%EF%B8%8F-album-image--video)
49
+ - 👤 [Group Status Message](#4%EF%B8%8F⃣-group-status)
50
+ - 🎞️ [Status Mention Message](#%EF%B8%8F-status-mention)
51
+ - 📦 [Sticker Pack Message](#-sticker-pack)
52
+ - [Rich Response Message](#-rich-response) **[NEW]**
53
+ - 🧾 [Message with Code Blocks](#-message-with-code-block) **[NEW]**
54
+ - 📋 [Message with Table](#-message-with-table) **[NEW]**
55
+ - 💳 [Payment-related Message](#-sending-payment-messages) (payment requests, invites, orders, invoices).
56
+ - 📰 Simplified sending messages with ad thumbnail using [`externalAdReply`](#3%EF%B8%8F⃣-external-ad-reply), without requiring manual `contextInfo`.
54
57
 
55
58
  #### 🧩 Additional Message Options
56
59
  - 👁️ Added optional boolean flags for message handling:
57
- - [`ai`](#1%EF%B8%8F⃣-ai-label) - AI label on message
58
- - [`mentionAll`](#-mention) - Mentions all group participants without requiring their JIDs in `mentions` or `mentionedJid`
59
- - [`ephemeral`](#2%EF%B8%8F⃣-ephemeral), [`groupStatus`](#4%EF%B8%8F⃣-group-status), [`viewOnceV2`](#8%EF%B8%8F⃣-view-once-v2), [`viewOnceV2Extension`](#9%EF%B8%8F⃣-view-once-v2-extension), [`interactiveAsTemplate`](#3%EF%B8%8F⃣-interactive) - Message wrappers
60
- - [`secureMetaServiceLabel`](#6%EF%B8%8F⃣-secure-meta-service-label) - Secure meta service label on message
61
- - [`raw`](#5%EF%B8%8F⃣-raw) - Build your message manually **(DO NOT USE FOR EXPLOITATION)**
60
+ - 🤖 [`ai`](#1%EF%B8%8F⃣-ai-icon) - AI icon on message
61
+ - 📣 [`mentionAll`](#-mention) - Mention all group participants without requiring their JIDs in `mentions` or `mentionedJid` **[NEW]**
62
+ - 🔧 [`ephemeral`](#2%EF%B8%8F⃣-ephemeral), [`groupStatus`](#4%EF%B8%8F⃣-group-status), [`viewOnceV2`](#8%EF%B8%8F⃣-view-once-v2), [`viewOnceV2Extension`](#9%EF%B8%8F⃣-view-once-v2-extension), [`interactiveAsTemplate`](#3%EF%B8%8F⃣-interactive) - Message wrappers
63
+ - 🔒 [`secureMetaServiceLabel`](#6%EF%B8%8F⃣-secure-meta-service-label) - Secure meta service label on message **[NEW]**
64
+ - 📄 [`raw`](#5%EF%B8%8F⃣-raw) - Build your message manually **(DO NOT USE FOR EXPLOITATION)**
62
65
 
63
66
  > [!NOTE]
64
67
  📄 This project is maintained with limited scope and is not intended to replace upstream Baileys.
@@ -314,7 +317,7 @@ const vcard = 'BEGIN:VCARD\n'
314
317
 
315
318
  sock.sendMessage(jid, {
316
319
  contacts: {
317
- displayName: 'Lia',
320
+ displayName: 'Lia Wynn',
318
321
  contacts: [
319
322
  { vcard }
320
323
  ]
@@ -405,6 +408,47 @@ sock.sendMessage([jidA, jidB, jidC], {
405
408
  })
406
409
  ```
407
410
 
411
+ ##### ✨ Rich Response
412
+
413
+ > [!NOTE]
414
+ `richResponse[]` is a representation of [`submessages[]`](https://baileys.wiki/docs/api/namespaces/proto/interfaces/IAIRichResponseSubMessage) inside `richResponseMessage`.
415
+
416
+ > [!TIP]
417
+ You can still use the original [`submessages[]`](https://baileys.wiki/docs/api/namespaces/proto/interfaces/IAIRichResponseSubMessage) field directly.
418
+ > The code example below is just an implementation using a helper, not a required structure.
419
+
420
+ ```javascript
421
+ sock.sendMessage(jid, {
422
+ richResponse: [{
423
+ text: 'Example Usage',
424
+ }, {
425
+ language: 'javascript',
426
+ code: [{
427
+ highlightType: 0,
428
+ codeContent: 'console.log("Hello, World!")'
429
+ }]
430
+ }, {
431
+ text: 'Pretty simple, right?\n'
432
+ }, {
433
+ text: 'Comparison between Node.js, Bun, and Deno',
434
+ }, {
435
+ title: 'Runtime Comparison',
436
+ table: [{
437
+ isHeading: true,
438
+ items: ['', 'Node.js', 'Bun', 'Deno']
439
+ }, {
440
+ isHeading: false,
441
+ items: ['Engine', 'V8 (C++)', 'JavaScriptCore (C++)', 'V8 (C++)']
442
+ }, {
443
+ isHeading: false,
444
+ items: ['Performance', '4/5', '5/5', '4/5']
445
+ }]
446
+ }, {
447
+ text: 'Does this help clarify the differences?'
448
+ }]
449
+ })
450
+ ```
451
+
408
452
  ##### 🧾 Message with Code Block
409
453
 
410
454
  ```javascript
@@ -828,7 +872,7 @@ sock.sendMessage(jid, {
828
872
 
829
873
  #### 👁️ Other Message Options
830
874
 
831
- ##### 1️⃣ AI Label
875
+ ##### 1️⃣ AI Icon
832
876
 
833
877
  > [!NOTE]
834
878
  It only works in private chat (`@s.whatsapp.net`).
@@ -838,7 +882,7 @@ sock.sendMessage(jid, {
838
882
  image: {
839
883
  url: './path/to/image.jpg'
840
884
  },
841
- caption: '🤖 AI Labeled!',
885
+ caption: '🤖 With AI icon!',
842
886
  ai: true
843
887
  }, {
844
888
  quoted: message
@@ -28,36 +28,40 @@ export const makeMessagesSocket = (config) => {
28
28
  const messageRetryManager = enableRecentMessageCache ? new MessageRetryManager(logger, maxMsgRetryCount) : null;
29
29
  // Prevent race conditions in Signal session encryption by user
30
30
  const encryptionMutex = makeKeyedMutex();
31
+ // Prevent race conditions in media connection refresh
32
+ const mediaConnMutex = makeKeyedMutex();
31
33
  let mediaConn;
32
34
  const refreshMediaConn = async (forceGet = false) => {
33
- const media = await mediaConn;
34
- if (!media || forceGet || new Date().getTime() - media.fetchDate.getTime() > media.ttl * 1000) {
35
- mediaConn = (async () => {
36
- const result = await query({
37
- tag: 'iq',
38
- attrs: {
39
- type: 'set',
40
- xmlns: 'w:m',
41
- to: S_WHATSAPP_NET
42
- },
43
- content: [{ tag: 'media_conn', attrs: {} }]
44
- });
45
- const mediaConnNode = getBinaryNodeChild(result, 'media_conn');
46
- // TODO: explore full length of data that whatsapp provides
47
- const node = {
48
- hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
49
- hostname: attrs.hostname,
50
- maxContentLengthBytes: +attrs.maxContentLengthBytes
51
- })),
52
- auth: mediaConnNode.attrs.auth,
53
- ttl: +mediaConnNode.attrs.ttl,
54
- fetchDate: new Date()
55
- };
56
- logger.debug('fetched media conn');
57
- return node;
58
- })();
59
- }
60
- return mediaConn;
35
+ return mediaConnMutex.mutex('media-conn', async () => {
36
+ const media = await mediaConn;
37
+ if (!media || forceGet || new Date().getTime() - media.fetchDate.getTime() > media.ttl * 1000) {
38
+ mediaConn = (async () => {
39
+ const result = await query({
40
+ tag: 'iq',
41
+ attrs: {
42
+ type: 'set',
43
+ xmlns: 'w:m',
44
+ to: S_WHATSAPP_NET
45
+ },
46
+ content: [{ tag: 'media_conn', attrs: {} }]
47
+ });
48
+ const mediaConnNode = getBinaryNodeChild(result, 'media_conn');
49
+ // TODO: explore full length of data that whatsapp provides
50
+ const node = {
51
+ hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
52
+ hostname: attrs.hostname,
53
+ maxContentLengthBytes: +attrs.maxContentLengthBytes
54
+ })),
55
+ auth: mediaConnNode.attrs.auth,
56
+ ttl: +mediaConnNode.attrs.ttl,
57
+ fetchDate: new Date()
58
+ };
59
+ logger.debug('fetched media conn');
60
+ return node;
61
+ })();
62
+ }
63
+ return mediaConn;
64
+ });
61
65
  };
62
66
  /**
63
67
  * generic send receipt function
@@ -10,7 +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
+ import { prepareRichCodeBlock, prepareRichResponseMessage, prepareRichTable, wrapToBotForwardedMessage } from './rich-message-utils.js';
14
14
  import { shouldIncludeReportingToken } from './reporting-utils.js';
15
15
  const MIMETYPE_MAP = {
16
16
  image: 'image/jpeg',
@@ -1020,10 +1020,13 @@ export const generateWAMessageContent = async (message, options) => {
1020
1020
  }
1021
1021
  // Lia@Changes 09-04-26 --- Add support for code block and table
1022
1022
  else if (hasNonNullishProperty(message, 'code')) {
1023
- m.richResponseMessage = generateRichCodeBlock(message);
1023
+ m.richResponseMessage = prepareRichCodeBlock(message);
1024
1024
  }
1025
1025
  else if (hasNonNullishProperty(message, 'table')) {
1026
- m.richResponseMessage = generateRichTable(message);
1026
+ m.richResponseMessage = prepareRichTable(message);
1027
+ }
1028
+ else if (hasNonNullishProperty(message, 'richResponse')) {
1029
+ m.richResponseMessage = prepareRichResponseMessage(message.richResponse);
1027
1030
  }
1028
1031
  else {
1029
1032
  m = await prepareWAMessageMedia(message, options);
@@ -1,9 +1,13 @@
1
1
  /**
2
2
  * Lia@Changes 09-04-26 [WIP]
3
- * Add support for tables and code blocks in richResponseMessage (wrapped in botForwardedMessage)
3
+ * Adds support for tables and code blocks with richResponseMessage (wrapped inside botForwardedMessage).
4
+ *
5
+ * If you use or copy this code, please credit my name or project.
4
6
  */
7
+ import { randomUUID } from 'crypto';
5
8
  import { FORWARDED_AI_BOT_INFO, LEXER_REGEX } from '../Defaults/index.js';
6
- import { CodeHighlightType } from '../Types/RichType.js';
9
+ import { CodeHighlightType, RichSubMessageType } from '../Types/RichType.js';
10
+ const textEncoder = new TextEncoder();
7
11
  const CPP_KEYWORDS = new Set([
8
12
  'alignas', 'alignof', 'and', 'and_eq', 'asm', 'auto', 'bitand', 'bitor', 'bool', 'break', 'case',
9
13
  'catch', 'char', 'class', 'compl', 'concept', 'const', 'consteval', 'constexpr', 'constinit',
@@ -60,7 +64,7 @@ const RUST_KEYWORDS = new Set([
60
64
  'where', 'while', 'async', 'await', 'dyn', 'abstract', 'become', 'box', 'do', 'final',
61
65
  'macro', 'override', 'priv', 'typeof', 'unsized', 'virtual', 'yield'
62
66
  ]);
63
- const NOOP = new Set([])
67
+ const NOOP = new Set([]);
64
68
  export const LANGUAGE_KEYWORDS = {
65
69
  css: CSS_KEYWORDS,
66
70
  html: HTML_KEYWORDS,
@@ -110,19 +114,47 @@ export const tokenizeCode = (code, language = 'javascript') => {
110
114
  }
111
115
  return blocks;
112
116
  };
113
- export const wrapToBotForwardedMessage = (message) =>
117
+ // Lia@Changes 09-04-26 --- Inject buffer into unifiedResponse.data to support proper rendering of rich messages (ex: tables and code blocks)
118
+ const toUnified = (submessages) =>
114
119
  ({
115
- messageContextInfo: {
116
- botMetadata: {
117
- // Lia@Note 09-04-26 --- TODO: Fill verificationMetadata field
118
- verificationMetadata: {},
119
- botRenderingConfigMetadata: {}
120
+ response_id: randomUUID(),
121
+ sections: submessages.map((submessage) => {
122
+ switch (submessage.messageType) {
123
+ case RichSubMessageType.TEXT:
124
+ return {
125
+ view_model: {
126
+ primitive: { text: submessage.messageText, inline_entities: [], __typename: 'GenAIMarkdownTextUXPrimitive' },
127
+ __typename: 'GenAISingleLayoutViewModel'
128
+ }
129
+ };
130
+ case RichSubMessageType.TABLE:
131
+ return {
132
+ view_model: {
133
+ primitive: {
134
+ title: submessage.tableMetadata.title,
135
+ rows: submessage.tableMetadata.rows.map((row) => ({ is_header: row.isHeading, cells: row.items })),
136
+ __typename: 'GenATableUXPrimitive'
137
+ },
138
+ __typename: 'GenAISingleLayoutViewModel'
139
+ }
140
+ };
141
+ case RichSubMessageType.CODE:
142
+ return {
143
+ view_model: {
144
+ primitive: {
145
+ language: submessage.codeMetadata.codeLanguage,
146
+ code_blocks: submessage.codeMetadata.codeBlocks.map((block) => ({ content: block.codeContent, type: CodeHighlightType[block.highlightType] })),
147
+ __typename: 'GenAICodeUXPrimitive'
148
+ },
149
+ __typename: 'GenAISingleLayoutViewModel'
150
+ }
151
+ };
120
152
  }
121
- },
122
- botForwardedMessage: { message }
153
+ return submessage;
154
+ })
123
155
  });
124
- export const generateRichCodeBlock = ({ header, code, footer, language } = {}) => {
125
- language ??= 'javascript'
156
+ export const prepareRichCodeBlock = ({ header, code, footer, language } = {}) => {
157
+ language ??= 'javascript';
126
158
  const submessages = [];
127
159
  if (header) {
128
160
  submessages.push({
@@ -143,13 +175,17 @@ export const generateRichCodeBlock = ({ header, code, footer, language } = {}) =
143
175
  messageText: footer
144
176
  });
145
177
  }
146
- return ({
178
+ const unified = toUnified(submessages);
179
+ return {
147
180
  submessages,
148
181
  messageType: 1,
182
+ unifiedResponse: {
183
+ data: textEncoder.encode(JSON.stringify(unified))
184
+ },
149
185
  contextInfo: FORWARDED_AI_BOT_INFO
150
- });
186
+ };
151
187
  };
152
- export const generateRichTable = ({ header, title, table, footer } = {}) => {
188
+ export const prepareRichTable = ({ header, title, table, footer } = {}) => {
153
189
  const tableRows = table.map((items, index) => ({
154
190
  isHeading: index == 0,
155
191
  items
@@ -174,9 +210,65 @@ export const generateRichTable = ({ header, title, table, footer } = {}) => {
174
210
  messageText: footer
175
211
  });
176
212
  }
177
- return ({
213
+ const unified = toUnified(submessages);
214
+ return {
178
215
  submessages,
179
216
  messageType: 1,
217
+ unifiedResponse: {
218
+ data: textEncoder.encode(JSON.stringify(unified))
219
+ },
180
220
  contextInfo: FORWARDED_AI_BOT_INFO
221
+ };
222
+ };
223
+ export const prepareRichResponseMessage = (content) => {
224
+ const submessages = content.map((submessage) => {
225
+ if (submessage.text) {
226
+ return {
227
+ messageType: 2,
228
+ messageText: submessage.text
229
+ };
230
+ }
231
+ else if (submessage.code) {
232
+ return {
233
+ messageType: 5,
234
+ codeMetadata: {
235
+ codeLanguage: submessage.language,
236
+ codeBlocks: submessage.code
237
+ }
238
+ };
239
+ }
240
+ else if (submessage.table) {
241
+ return {
242
+ messageType: 4,
243
+ tableMetadata: {
244
+ title: submessage.title,
245
+ rows: submessage.table
246
+ }
247
+ };
248
+ }
249
+ return submessage;
181
250
  });
182
- };
251
+ const unified = toUnified(submessages);
252
+ return {
253
+ submessages,
254
+ messageType: 1,
255
+ unifiedResponse: {
256
+ data: textEncoder.encode(JSON.stringify(unified))
257
+ },
258
+ contextInfo: FORWARDED_AI_BOT_INFO
259
+ };
260
+ }
261
+ export const wrapToBotForwardedMessage = (message) =>
262
+ ({
263
+ messageContextInfo: {
264
+ botMetadata: {
265
+ // Lia@Note 09-04-26 --- TODO: Fill verificationMetadata field
266
+ verificationMetadata: {},
267
+ botRenderingConfigMetadata: {
268
+ bloksVersioningId: '0903aa5f7f47de66789d5f4c86d3bd6e05e4bc3ff85e454a9f907d5ed7fef97c',
269
+ pixelDensity: 2.75
270
+ }
271
+ }
272
+ },
273
+ botForwardedMessage: { message }
274
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@itsliaaa/baileys",
3
- "version": "0.1.19",
4
- "description": "A lightweight fork of Baileys with practical fixes and small but meaningful improvements.",
3
+ "version": "0.1.21",
4
+ "description": "Enhanced Baileys v7 with fixed newsletter media upload, plus support for interactive messages, albums, and more message types.",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",
7
7
  "scripts": {
@@ -48,7 +48,7 @@
48
48
  "p-queue": "^9.1.0",
49
49
  "pino": "^9.6.0",
50
50
  "protobufjs": "^7.5.4",
51
- "whatsapp-rust-bridge": "^0.5.3",
51
+ "whatsapp-rust-bridge": "0.5.3",
52
52
  "ws": "^8.19.0"
53
53
  },
54
54
  "peerDependencies": {