@itsliaaa/baileys 0.1.3 → 0.1.5

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.
@@ -2,9 +2,9 @@ import { proto } from '../../WAProto/index.js';
2
2
  import { makeLibSignalRepository } from '../Signal/libsignal.js';
3
3
  import { Browsers } from '../Utils/browser-utils.js';
4
4
  import logger from '../Utils/logger.js';
5
- const version = [2, 3000, 1034621774];
5
+ const version = [2, 3000, 1033846690];
6
6
  export const UNAUTHORIZED_CODES = [401, 403, 419];
7
- export const BIZ_BOT_SUPPORT_PAYLOAD = '{"version":1,"is_ai_message":true,"should_show_system_message":true,"ticket_id":"7004947587700716","citation_items":[],"ticket_locale":"us"}';
7
+ export const BIZ_BOT_SUPPORT_PAYLOAD = '{"version":1,"is_ai_message":true,"should_show_system_message":false,"ticket_id":"7004947587700716","citation_items":[],"ticket_locale":"us"}';
8
8
  export const DEFAULT_ORIGIN = 'https://web.whatsapp.com';
9
9
  export const CALL_VIDEO_PREFIX = 'https://call.whatsapp.com/video/';
10
10
  export const CALL_AUDIO_PREFIX = 'https://call.whatsapp.com/voice/';
@@ -1,6 +1,6 @@
1
1
  import NodeCache from '@cacheable/node-cache';
2
- import PQueue from 'p-queue';
3
2
  import { Boom } from '@hapi/boom';
3
+ import { randomBytes } from 'crypto';
4
4
  import { proto } from '../../WAProto/index.js';
5
5
  import { BIZ_BOT_SUPPORT_PAYLOAD, DEFAULT_CACHE_TTLS, OLD_GROUP_ID_REGEX, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
6
6
  import { aggregateMessageKeysNotFromMe, assertMediaContent, bindWaitForEvent, decryptMediaRetryData, delay, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateParticipantHashV2, generateWAMessageFromContent, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, hasValidAlbumMedia, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, shouldIncludeBizBinaryNode, unixTimestampSeconds } from '../Utils/index.js';
@@ -11,10 +11,6 @@ import { getMessageReportingToken, shouldIncludeReportingToken } from '../Utils/
11
11
  import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, getBizBinaryNode, isHostedLidUser, isHostedPnUser, isJidGroup, isJidNewsletter, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
12
12
  import { USyncQuery, USyncUser } from '../WAUSync/index.js';
13
13
  import { makeNewsletterSocket } from './newsletter.js';
14
- // Lia@Changes 03-02-26 --- Replace process.nextTick with PQueue for upsertMessage to avoid RSS spike... (i guess (⁠ ⁠◜⁠‿⁠◝⁠ ⁠)⁠♡)
15
- const EMIT_MESSAGE_QUEUE = new PQueue({
16
- concurrency: 1
17
- });
18
14
  export const makeMessagesSocket = (config) => {
19
15
  const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config;
20
16
  const sock = makeNewsletterSocket(config);
@@ -835,7 +831,9 @@ export const makeMessagesSocket = (config) => {
835
831
  }
836
832
  if (normalizedMessage.pollCreationMessage ||
837
833
  normalizedMessage.pollCreationMessageV2 ||
838
- normalizedMessage.pollCreationMessageV3 || normalizedMessage.pollCreationMessageV5 ||
834
+ normalizedMessage.pollCreationMessageV3 ||
835
+ normalizedMessage.pollCreationMessageV5 ||
836
+ normalizedMessage.pollCreationMessageV6 ||
839
837
  normalizedMessage.pollUpdateMessage) {
840
838
  return 'poll';
841
839
  }
@@ -997,7 +995,102 @@ export const makeMessagesSocket = (config) => {
997
995
  // Lia@Changes 30-01-26 --- Add support for modifying additionalNodes and additionalAttributes using "options" in sendMessage()
998
996
  sendMessage: async (jid, content, options = {}) => {
999
997
  const userJid = authState.creds.me.id;
1000
- if ('disappearingMessagesInChat' in content && isJidGroup(jid)) {
998
+ // Lia@Changes 13-03-26 --- Add status mentions!
999
+ if (Array.isArray(jid)) {
1000
+ const { delayMs = 1500 } = options;
1001
+ const allUsers = new Set();
1002
+ const fullMsg = await generateWAMessage('status@broadcast', content, {
1003
+ logger,
1004
+ userJid,
1005
+ upload: waUploadToServer,
1006
+ mediaCache: config.mediaCache,
1007
+ options: config.options,
1008
+ ...options,
1009
+ messageId: generateMessageIDV2(userJid)
1010
+ });
1011
+ for (const id of jid) {
1012
+ if (isJidGroup(id)) {
1013
+ try {
1014
+ const groupData = (cachedGroupMetadata ? await cachedGroupMetadata(id) : null) || await groupMetadata(id);
1015
+ for (const participant of groupData.participants) {
1016
+ if (allUsers.has(participant.id))
1017
+ continue;
1018
+ allUsers.add(participant.id);
1019
+ }
1020
+ }
1021
+ catch (error) {
1022
+ logger.error(`Error getting metadata group from ${id}: ${error}`);
1023
+ }
1024
+ }
1025
+ else if (!allUsers.has(id)) {
1026
+ allUsers.add(id);
1027
+ }
1028
+ }
1029
+ await relayMessage('status@broadcast', fullMsg.message, {
1030
+ messageId: fullMsg.key.id,
1031
+ statusJidList: Array.from(allUsers),
1032
+ additionalNodes: [
1033
+ {
1034
+ tag: 'meta',
1035
+ attrs: {},
1036
+ content: [
1037
+ {
1038
+ tag: 'mentioned_users',
1039
+ attrs: {},
1040
+ content: jid.map(id => ({
1041
+ tag: 'to',
1042
+ attrs: { jid: id },
1043
+ content: undefined
1044
+ }))
1045
+ }
1046
+ ]
1047
+ }
1048
+ ]
1049
+ });
1050
+ if (config.emitOwnEvents) {
1051
+ process.nextTick(async () => {
1052
+ await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
1053
+ });
1054
+ }
1055
+ for (const id of jid) {
1056
+ const isGroup = isJidGroup(id)
1057
+ const sendType = isGroup ? 'groupStatusMentionMessage' : 'statusMentionMessage';
1058
+ const mentionMsg = generateWAMessageFromContent(id, {
1059
+ messageContextInfo: {
1060
+ messageSecret: randomBytes(32)
1061
+ },
1062
+ [sendType]: {
1063
+ message: {
1064
+ protocolMessage: {
1065
+ key: fullMsg.key,
1066
+ type: 25
1067
+ }
1068
+ }
1069
+ }
1070
+ }, {
1071
+ userJid
1072
+ });
1073
+ await relayMessage(id, mentionMsg.message, {
1074
+ additionalNodes: [
1075
+ {
1076
+ tag: 'meta',
1077
+ attrs: isGroup ?
1078
+ { is_group_status_mention: 'true' } :
1079
+ { is_status_mention: 'true' },
1080
+ content: undefined
1081
+ }
1082
+ ]
1083
+ });
1084
+ if (config.emitOwnEvents) {
1085
+ process.nextTick(async () => {
1086
+ await messageMutex.mutex(() => upsertMessage(mentionMsg, 'append'));
1087
+ });
1088
+ }
1089
+ await delay(delayMs);
1090
+ }
1091
+ return fullMsg;
1092
+ }
1093
+ else if ('disappearingMessagesInChat' in content && isJidGroup(jid)) {
1001
1094
  const { disappearingMessagesInChat } = content;
1002
1095
  const value = typeof disappearingMessagesInChat === 'boolean'
1003
1096
  ? disappearingMessagesInChat
@@ -1105,9 +1198,9 @@ export const makeMessagesSocket = (config) => {
1105
1198
  additionalNodes
1106
1199
  });
1107
1200
  if (config.emitOwnEvents) {
1108
- EMIT_MESSAGE_QUEUE.add(() =>
1109
- upsertMessage(fullMsg, 'append')
1110
- );
1201
+ process.nextTick(async () => {
1202
+ await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
1203
+ });
1111
1204
  }
1112
1205
  // Lia@Changes 31-01-26 --- Add support for album messages
1113
1206
  // Lia@Note 06-02-26 --- Refactored to reduce high RSS usage (⁠╥⁠﹏⁠╥⁠)
@@ -1139,9 +1232,9 @@ export const makeMessagesSocket = (config) => {
1139
1232
  additionalNodes
1140
1233
  });
1141
1234
  if (config.emitOwnEvents) {
1142
- EMIT_MESSAGE_QUEUE.add(() =>
1143
- upsertMessage(albumMsg, 'append')
1144
- );
1235
+ process.nextTick(async () => {
1236
+ await messageMutex.mutex(() => upsertMessage(albumMsg, 'append'));
1237
+ });
1145
1238
  }
1146
1239
  await delay(delayMs);
1147
1240
  }
@@ -761,8 +761,7 @@ export const makeSocket = (config) => {
761
761
  void sendUnifiedSession();
762
762
  if (node.attrs.lid && authState.creds.me?.id) {
763
763
  const myLID = node.attrs.lid;
764
- // Lia@Changes 03-02-26 --- Replaced process.nextTick setImmediate to avoid event-loop starvation
765
- setImmediate(async () => {
764
+ process.nextTick(async () => {
766
765
  try {
767
766
  const myPN = authState.creds.me.id;
768
767
  // Store our own LID-PN mapping
@@ -1,7 +1,7 @@
1
1
  import { Boom } from '@hapi/boom';
2
2
  import { createHash, randomBytes } from 'crypto';
3
3
  import { proto } from '../../WAProto/index.js';
4
- const baileysVersion = [2, 3000, 1034621774];
4
+ const baileysVersion = [2, 3000, 1033846690];
5
5
  import { DisconnectReason } from '../Types/index.js';
6
6
  import { getAllBinaryNodeChildren, jidDecode } from '../WABinary/index.js';
7
7
  import { sha256 } from './crypto.js';
@@ -26,33 +26,28 @@ const MessageTypeProto = {
26
26
  sticker: WAProto.Message.StickerMessage,
27
27
  document: WAProto.Message.DocumentMessage
28
28
  };
29
- const mediaAnnotation = [{
30
- polygonVertices: [{
31
- x: 60.71664810180664,
32
- y: -36.39784622192383
33
- }, {
34
- x: -16.710189819335938,
35
- y: 49.263675689697266
36
- }, {
37
- x: -56.585853576660156,
38
- y: 37.85963439941406
39
- }, {
40
- x: 20.840980529785156,
41
- y: -47.80188751220703
42
- }],
43
- newsletter: {
44
- // Lia@Note 03-02-26 --- You can change jid, message id, and name via .env (⁠≧⁠▽⁠≦⁠)
45
- newsletterJid: process.env.NEWSLETTER_ID ||
46
- Buffer.from('313230333633343034303036363434313339406e6577736c6574746572', 'hex').toString(),
47
- serverMessageId: process.env.NEWSLETTER_MESSAGE_ID ||
48
- Buffer.from('313033', 'hex').toString(),
49
- newsletterName: process.env.NEWSLETTER_NAME ||
50
- Buffer.from('f09d96b2f09d978df09d96baf09d978bf09d96bff09d96baf09d9785f09d9785', 'hex').toString(),
51
- contentType: proto.ContextInfo.ForwardedNewsletterMessageInfo.ContentType.UPDATE,
52
- accessibilityText: process.env.NEWSLETTER_ACCESSIBILITY_TEXT ||
53
- ''
54
- }
55
- }];
29
+ const mediaAnnotation = [
30
+ {
31
+ polygonVertices: [
32
+ { x: 60.71664810180664, y: -36.39784622192383 },
33
+ { x: -16.710189819335938, y: 49.263675689697266 },
34
+ { x: -56.585853576660156, y: 37.85963439941406 },
35
+ { x: 20.840980529785156, y: -47.80188751220703 }
36
+ ],
37
+ newsletter: {
38
+ // Lia@Note 03-02-26 --- You can change jid, message id, and name via .env (⁠≧⁠▽⁠≦⁠)
39
+ newsletterJid: process.env.NEWSLETTER_ID ||
40
+ Buffer.from('313230333633343034303036363434313339406e6577736c6574746572', 'hex').toString(),
41
+ serverMessageId: process.env.NEWSLETTER_MESSAGE_ID ||
42
+ Buffer.from('313033', 'hex').toString(),
43
+ newsletterName: process.env.NEWSLETTER_NAME ||
44
+ Buffer.from('f09d96b2f09d978df09d96baf09d978bf09d96bff09d96baf09d9785f09d9785', 'hex').toString(),
45
+ contentType: proto.ContextInfo.ForwardedNewsletterMessageInfo.ContentType.UPDATE,
46
+ accessibilityText: process.env.NEWSLETTER_ACCESSIBILITY_TEXT ||
47
+ '@itsliaaa/baileys'
48
+ }
49
+ }
50
+ ];
56
51
  /**
57
52
  * Uses a regex to test whether the string contains a URL, and returns the URL if it does.
58
53
  * @param text eg. hello https://google.com
@@ -552,7 +547,10 @@ const prepareNativeFlowButtons = (message) => {
552
547
  Object.assign(messageParamsJson, {
553
548
  bottom_sheet: {
554
549
  in_thread_buttons_limit: 1,
555
- divide_indices: [],
550
+ divider_indices: Array.from(
551
+ { length: correctedField.length },
552
+ (_, index) => index
553
+ ),
556
554
  list_title: message.optionTitle || '📄 Select Options',
557
555
  button_title: message.optionText
558
556
  }
@@ -560,11 +558,12 @@ const prepareNativeFlowButtons = (message) => {
560
558
  }
561
559
  return {
562
560
  buttons: correctedField.map(button => {
561
+ const buttonText = button.text || button.buttonText;
563
562
  if (hasOptionalProperty(button, 'id') && !!button.id) {
564
563
  return {
565
564
  name: 'quick_reply',
566
565
  buttonParamsJson: JSON.stringify({
567
- display_text: button.text || button.buttonText || '👉🏻 Click',
566
+ display_text: buttonText || '👉🏻 Click',
568
567
  id: button.id
569
568
  })
570
569
  };
@@ -573,7 +572,7 @@ const prepareNativeFlowButtons = (message) => {
573
572
  return {
574
573
  name: 'cta_copy',
575
574
  buttonParamsJson: JSON.stringify({
576
- display_text: button.text || button.buttonText || '📋 Copy',
575
+ display_text: buttonText || '📋 Copy',
577
576
  copy_code: button.copy
578
577
  })
579
578
  };
@@ -582,7 +581,7 @@ const prepareNativeFlowButtons = (message) => {
582
581
  return {
583
582
  name: 'cta_url',
584
583
  buttonParamsJson: JSON.stringify({
585
- display_text: button.text || button.buttonText || '🌐 Visit',
584
+ display_text: buttonText || '🌐 Visit',
586
585
  url: button.url,
587
586
  merchant_url: button.url
588
587
  })
@@ -592,11 +591,21 @@ const prepareNativeFlowButtons = (message) => {
592
591
  return {
593
592
  name: 'cta_call',
594
593
  buttonParamsJson: JSON.stringify({
595
- display_text: button.text || button.buttonText || '📞 Call',
594
+ display_text: buttonText || '📞 Call',
596
595
  phone_number: button.call
597
596
  })
598
597
  };
599
598
  }
599
+ // Lia@Changes 12-03-26 --- Add "single_select" shortcut \⁠(⁠°⁠o⁠°⁠)⁠/
600
+ else if (hasOptionalProperty(button, 'sections') && !!button.sections) {
601
+ return {
602
+ name: 'single_select',
603
+ buttonParamsJson: JSON.stringify({
604
+ title: buttonText || '📋 Select',
605
+ sections: button.sections
606
+ })
607
+ };
608
+ }
600
609
  return button;
601
610
  }),
602
611
  messageParamsJson: JSON.stringify(messageParamsJson),
@@ -679,7 +688,12 @@ export const hasValidCarouselHeader = (message) => {
679
688
  export const generateWAMessageContent = async (message, options) => {
680
689
  var _a, _b;
681
690
  let m = {};
682
- if (hasNonNullishProperty(message, 'text')) {
691
+ // Lia@Changes 30-01-26 --- Add "raw" boolean to send raw messages directly via generateWAMessage()
692
+ if (hasNonNullishProperty(message, 'raw')) {
693
+ delete message.raw;
694
+ return proto.Message.create(message);
695
+ }
696
+ else if (hasNonNullishProperty(message, 'text')) {
683
697
  const extContent = { text: message.text };
684
698
  let urlInfo = message.linkPreview;
685
699
  if (typeof urlInfo === 'undefined') {
@@ -1014,11 +1028,6 @@ export const generateWAMessageContent = async (message, options) => {
1014
1028
  expectedVideoCount: videoCount
1015
1029
  };
1016
1030
  }
1017
- // Lia@Changes 30-01-26 --- Add "raw" boolean to send raw messages directly via generateWAMessage()
1018
- else if (hasNonNullishProperty(message, 'raw')) {
1019
- delete message.raw;
1020
- return proto.Message.create(message);
1021
- }
1022
1031
  else {
1023
1032
  m = await prepareWAMessageMedia(message, options);
1024
1033
  }
@@ -1026,7 +1035,21 @@ export const generateWAMessageContent = async (message, options) => {
1026
1035
  if (hasNonNullishProperty(message, 'buttons')) {
1027
1036
  const buttonsMessage = {
1028
1037
  buttons: message.buttons.map(button => {
1029
- if (hasOptionalProperty(button, 'name')) {
1038
+ // Lia@Changes 12-03-26 --- Add "single_select" shortcut!
1039
+ const buttonText = button.text || button.buttonText
1040
+ if (hasOptionalProperty(button, 'sections')) {
1041
+ return {
1042
+ nativeFlowInfo: {
1043
+ name: 'single_select',
1044
+ paramsJson: JSON.stringify({
1045
+ title: buttonText,
1046
+ sections: button.sections
1047
+ })
1048
+ },
1049
+ type: ButtonType.NATIVE_FLOW
1050
+ };
1051
+ }
1052
+ else if (hasOptionalProperty(button, 'name')) {
1030
1053
  return {
1031
1054
  nativeFlowInfo: {
1032
1055
  name: button.name,
@@ -1035,7 +1058,6 @@ export const generateWAMessageContent = async (message, options) => {
1035
1058
  type: ButtonType.NATIVE_FLOW
1036
1059
  };
1037
1060
  }
1038
- const buttonText = button.text || button.buttonText
1039
1061
  return {
1040
1062
  buttonId: button.id || button.buttonId,
1041
1063
  buttonText: typeof buttonText === 'string' ? { displayText: buttonText } : buttonText,
@@ -123,7 +123,7 @@ export function binaryNodeToString(node, i = 0) {
123
123
  * @param {object} message Normalized message content (after Baileys normalization).
124
124
  * @returns {object} A node with shape { tag, attrs, [content] } to inject into additionalNodes.
125
125
  */
126
- const bizFlowMap = {
126
+ const FLOWS_MAP = {
127
127
  mpm: 1,
128
128
  cta_catalog: 1,
129
129
  send_location: 1,
@@ -131,67 +131,80 @@ const bizFlowMap = {
131
131
  wa_payment_transaction_details: 1,
132
132
  automated_greeting_message_view_catalog: 1
133
133
  };
134
- const bizBinaryQualityAttribute = {
134
+ const qualityAttribute = {
135
135
  tag: 'quality_control',
136
- attrs: { source_type: 'third_party' },
137
- content: undefined
136
+ attrs: { source_type: 'third_party' }
138
137
  };
139
- const baseBizAttrs = {};
140
- const defaultContent = [bizBinaryQualityAttribute];
141
- const listContent = [{
142
- tag: 'list',
143
- attrs: { v: '2', type: 'product_list' },
144
- content: undefined
145
- }, bizBinaryQualityAttribute];
146
- const makeInteractive = (v, name) => {
147
- return [{
148
- tag: 'interactive',
149
- attrs: { type: 'native_flow', v: '1' },
150
- content: [{
151
- tag: 'native_flow',
152
- attrs: { v, name },
153
- content: undefined
154
- }]
155
- }, bizBinaryQualityAttribute];
156
- }
138
+ const defaultContent = [qualityAttribute]
139
+ const listContent = [
140
+ {
141
+ tag: 'list',
142
+ attrs: { v: '2', type: 'product_list' }
143
+ },
144
+ qualityAttribute
145
+ ];
157
146
  export const getBizBinaryNode = (message) => {
158
- const nativeFlowMessage = message.interactiveMessage?.nativeFlowMessage;
159
- const buttonName = nativeFlowMessage?.buttons?.[0]?.name;
147
+ const flowMsg = message.interactiveMessage?.nativeFlowMessage;
148
+ const buttonName = flowMsg?.buttons?.[0]?.name;
160
149
  if (buttonName === 'review_and_pay' || buttonName === 'payment_info') {
161
150
  return {
162
151
  tag: 'biz',
163
152
  attrs: {
164
- native_flow_name: buttonName === 'review_and_pay'
165
- ? 'order_details'
166
- : buttonName
153
+ native_flow_name: buttonName === 'review_and_pay' ?
154
+ 'order_details' :
155
+ buttonName
167
156
  },
168
157
  content: defaultContent
169
158
  };
170
159
  }
171
- if (buttonName && bizFlowMap[buttonName]) {
160
+ else if (buttonName && FLOWS_MAP[buttonName]) {
172
161
  return {
173
162
  tag: 'biz',
174
- attrs: baseBizAttrs,
175
- content: makeInteractive('2', buttonName)
163
+ attrs: {},
164
+ content: [
165
+ {
166
+ tag: 'interactive',
167
+ attrs: { type: 'native_flow', v: '1' },
168
+ content: [
169
+ {
170
+ tag: 'native_flow',
171
+ attrs: { v: '2', name: buttonName }
172
+ }
173
+ ]
174
+ },
175
+ qualityAttribute
176
+ ]
176
177
  };
177
178
  }
178
- if (nativeFlowMessage || message.buttonsMessage || message.templateMessage) {
179
+ if (flowMsg || message.buttonsMessage || message.templateMessage) {
179
180
  return {
180
181
  tag: 'biz',
181
- attrs: baseBizAttrs,
182
- content: makeInteractive('9', 'mixed')
182
+ attrs: {},
183
+ content: [
184
+ {
185
+ tag: 'interactive',
186
+ attrs: { type: 'native_flow', v: '1' },
187
+ content: [
188
+ {
189
+ tag: 'native_flow',
190
+ attrs: { v: '9', name: 'mixed' }
191
+ }
192
+ ]
193
+ },
194
+ qualityAttribute
195
+ ]
183
196
  };
184
197
  }
185
- if (message.listMessage) {
198
+ else if (message.listMessage) {
186
199
  return {
187
200
  tag: 'biz',
188
- attrs: baseBizAttrs,
201
+ attrs: {},
189
202
  content: listContent
190
203
  };
191
204
  }
192
205
  return {
193
206
  tag: 'biz',
194
- attrs: baseBizAttrs,
207
+ attrs: {},
195
208
  content: defaultContent
196
209
  };
197
210
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itsliaaa/baileys",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "A simple fork of Baileys for WhatsApp automation",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",