@alannxd/baileys 6.0.5 → 6.0.9

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 (123) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +341 -286
  3. package/WAProto/WAProto.proto +1782 -359
  4. package/WAProto/index.d.ts +75133 -9893
  5. package/WAProto/index.js +205861 -60606
  6. package/lib/Socket/luxu.js +6 -117
  7. package/lib/Socket/messages-send.js +637 -493
  8. package/lib/Socket/newsletter.js +229 -156
  9. package/lib/Utils/browser-utils.js +26 -6
  10. package/lib/Utils/decode-wa-message.js +33 -0
  11. package/lib/Utils/generics.js +10 -0
  12. package/lib/Utils/index.js +1 -0
  13. package/lib/Utils/message-composer.js +273 -0
  14. package/lib/Utils/messages.js +361 -24
  15. package/lib/WABinary/generic-utils.js +8 -1
  16. package/lib/WABinary/jid-utils.js +2 -0
  17. package/lib/index.js +1 -2
  18. package/package.json +5 -4
  19. package/lib/Defaults/index.d.ts +0 -75
  20. package/lib/Signal/Group/ciphertext-message.d.ts +0 -10
  21. package/lib/Signal/Group/group-session-builder.d.ts +0 -15
  22. package/lib/Signal/Group/group_cipher.d.ts +0 -17
  23. package/lib/Signal/Group/index.d.ts +0 -12
  24. package/lib/Signal/Group/keyhelper.d.ts +0 -11
  25. package/lib/Signal/Group/sender-chain-key.d.ts +0 -14
  26. package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -17
  27. package/lib/Signal/Group/sender-key-message.d.ts +0 -19
  28. package/lib/Signal/Group/sender-key-name.d.ts +0 -18
  29. package/lib/Signal/Group/sender-key-record.d.ts +0 -31
  30. package/lib/Signal/Group/sender-key-state.d.ts +0 -39
  31. package/lib/Signal/Group/sender-message-key.d.ts +0 -12
  32. package/lib/Signal/libsignal.d.ts +0 -5
  33. package/lib/Signal/lid-mapping.d.ts +0 -23
  34. package/lib/Socket/Client/index.d.ts +0 -3
  35. package/lib/Socket/Client/types.d.ts +0 -16
  36. package/lib/Socket/Client/websocket.d.ts +0 -13
  37. package/lib/Socket/business.d.ts +0 -217
  38. package/lib/Socket/chats.d.ts +0 -124
  39. package/lib/Socket/communities.d.ts +0 -273
  40. package/lib/Socket/groups.d.ts +0 -162
  41. package/lib/Socket/index.d.ts +0 -260
  42. package/lib/Socket/luxu.d.ts +0 -22
  43. package/lib/Socket/messages-recv.d.ts +0 -213
  44. package/lib/Socket/messages-send.d.ts +0 -199
  45. package/lib/Socket/mex.d.ts +0 -3
  46. package/lib/Socket/newsletter.d.ts +0 -170
  47. package/lib/Socket/socket.d.ts +0 -59
  48. package/lib/Store/index.d.ts +0 -10
  49. package/lib/Store/keyed-db.d.ts +0 -22
  50. package/lib/Store/make-cache-manager-store.d.ts +0 -19
  51. package/lib/Store/make-in-memory-store.d.ts +0 -39
  52. package/lib/Store/make-ordered-dictionary.d.ts +0 -14
  53. package/lib/Store/object-repository.d.ts +0 -11
  54. package/lib/Types/Auth.d.ts +0 -117
  55. package/lib/Types/Bussines.d.ts +0 -25
  56. package/lib/Types/Call.d.ts +0 -15
  57. package/lib/Types/Chat.d.ts +0 -124
  58. package/lib/Types/Contact.d.ts +0 -26
  59. package/lib/Types/Events.d.ts +0 -256
  60. package/lib/Types/GroupMetadata.d.ts +0 -71
  61. package/lib/Types/Label.d.ts +0 -47
  62. package/lib/Types/LabelAssociation.d.ts +0 -30
  63. package/lib/Types/Message.d.ts +0 -320
  64. package/lib/Types/Mex.d.ts +0 -141
  65. package/lib/Types/Product.d.ts +0 -79
  66. package/lib/Types/Signal.d.ts +0 -87
  67. package/lib/Types/Socket.d.ts +0 -136
  68. package/lib/Types/State.d.ts +0 -97
  69. package/lib/Types/USync.d.ts +0 -26
  70. package/lib/Types/index.d.ts +0 -65
  71. package/lib/Utils/auth-utils.d.ts +0 -24
  72. package/lib/Utils/browser-utils.d.ts +0 -4
  73. package/lib/Utils/business.d.ts +0 -23
  74. package/lib/Utils/chat-utils.d.ts +0 -100
  75. package/lib/Utils/companion-reg-client-utils.d.ts +0 -17
  76. package/lib/Utils/crypto.d.ts +0 -37
  77. package/lib/Utils/decode-wa-message.d.ts +0 -66
  78. package/lib/Utils/event-buffer.d.ts +0 -36
  79. package/lib/Utils/generics.d.ts +0 -91
  80. package/lib/Utils/history.d.ts +0 -24
  81. package/lib/Utils/identity-change-handler.d.ts +0 -44
  82. package/lib/Utils/index.d.ts +0 -22
  83. package/lib/Utils/link-preview.d.ts +0 -21
  84. package/lib/Utils/logger.d.ts +0 -12
  85. package/lib/Utils/lt-hash.d.ts +0 -8
  86. package/lib/Utils/make-mutex.d.ts +0 -9
  87. package/lib/Utils/message-retry-manager.d.ts +0 -115
  88. package/lib/Utils/messages-media.d.ts +0 -133
  89. package/lib/Utils/messages.d.ts +0 -91
  90. package/lib/Utils/noise-handler.d.ts +0 -20
  91. package/lib/Utils/offline-node-processor.d.ts +0 -17
  92. package/lib/Utils/pre-key-manager.d.ts +0 -28
  93. package/lib/Utils/process-message.d.ts +0 -60
  94. package/lib/Utils/reporting-utils.d.ts +0 -11
  95. package/lib/Utils/signal.d.ts +0 -47
  96. package/lib/Utils/stanza-ack.d.ts +0 -11
  97. package/lib/Utils/sync-action-utils.d.ts +0 -19
  98. package/lib/Utils/tc-token-utils.d.ts +0 -37
  99. package/lib/Utils/use-multi-file-auth-state.d.ts +0 -13
  100. package/lib/Utils/validate-connection.d.ts +0 -11
  101. package/lib/WABinary/constants.d.ts +0 -28
  102. package/lib/WABinary/decode.d.ts +0 -7
  103. package/lib/WABinary/encode.d.ts +0 -3
  104. package/lib/WABinary/generic-utils.d.ts +0 -18
  105. package/lib/WABinary/index.d.ts +0 -6
  106. package/lib/WABinary/jid-utils.d.ts +0 -48
  107. package/lib/WABinary/types.d.ts +0 -19
  108. package/lib/WAM/BinaryInfo.d.ts +0 -9
  109. package/lib/WAM/constants.d.ts +0 -40
  110. package/lib/WAM/encode.d.ts +0 -3
  111. package/lib/WAM/index.d.ts +0 -4
  112. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +0 -10
  113. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +0 -23
  114. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +0 -13
  115. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +0 -13
  116. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +0 -10
  117. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +0 -26
  118. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +0 -10
  119. package/lib/WAUSync/Protocols/index.d.ts +0 -6
  120. package/lib/WAUSync/USyncQuery.d.ts +0 -30
  121. package/lib/WAUSync/USyncUser.d.ts +0 -17
  122. package/lib/WAUSync/index.d.ts +0 -4
  123. package/lib/index.d.ts +0 -13
@@ -0,0 +1,273 @@
1
+ import { proto } from '../../WAProto/index.js'
2
+ import { generateMessageIDV2 } from './generics.js'
3
+
4
+ const JS_KEYWORDS = new Set([
5
+ 'import', 'export', 'from', 'default', 'as', 'const', 'let', 'var',
6
+ 'function', 'class', 'extends', 'new', 'return', 'if', 'else', 'for',
7
+ 'while', 'do', 'switch', 'case', 'break', 'continue', 'try', 'catch',
8
+ 'finally', 'throw', 'async', 'await', 'yield', 'typeof', 'instanceof',
9
+ 'in', 'of', 'delete', 'void', 'true', 'false', 'null', 'undefined',
10
+ 'NaN', 'Infinity', 'this', 'super', 'static', 'get', 'set', 'debugger', 'with'
11
+ ])
12
+
13
+ const PYTHON_KEYWORDS = new Set([
14
+ 'import', 'from', 'as', 'def', 'class', 'return', 'if', 'elif', 'else',
15
+ 'for', 'while', 'break', 'continue', 'try', 'except', 'finally', 'raise',
16
+ 'with', 'yield', 'lambda', 'pass', 'del', 'global', 'nonlocal', 'assert',
17
+ 'True', 'False', 'None', 'and', 'or', 'not', 'in', 'is', 'async', 'await',
18
+ 'self', 'print'
19
+ ])
20
+
21
+ const LANGUAGE_KEYWORDS = {
22
+ javascript: JS_KEYWORDS,
23
+ typescript: JS_KEYWORDS,
24
+ js: JS_KEYWORDS,
25
+ ts: JS_KEYWORDS,
26
+ python: PYTHON_KEYWORDS,
27
+ py: PYTHON_KEYWORDS
28
+ }
29
+
30
+ export var CodeHighlightType
31
+ ;(function (CodeHighlightType) {
32
+ CodeHighlightType[(CodeHighlightType['DEFAULT'] = 0)] = 'DEFAULT'
33
+ CodeHighlightType[(CodeHighlightType['KEYWORD'] = 1)] = 'KEYWORD'
34
+ CodeHighlightType[(CodeHighlightType['METHOD'] = 2)] = 'METHOD'
35
+ CodeHighlightType[(CodeHighlightType['STRING'] = 3)] = 'STRING'
36
+ CodeHighlightType[(CodeHighlightType['NUMBER'] = 4)] = 'NUMBER'
37
+ CodeHighlightType[(CodeHighlightType['COMMENT'] = 5)] = 'COMMENT'
38
+ })(CodeHighlightType || (CodeHighlightType = {}))
39
+
40
+ export var RichSubMessageType
41
+ ;(function (RichSubMessageType) {
42
+ RichSubMessageType[(RichSubMessageType['UNKNOWN'] = 0)] = 'UNKNOWN'
43
+ RichSubMessageType[(RichSubMessageType['GRID_IMAGE'] = 1)] = 'GRID_IMAGE'
44
+ RichSubMessageType[(RichSubMessageType['TEXT'] = 2)] = 'TEXT'
45
+ RichSubMessageType[(RichSubMessageType['INLINE_IMAGE'] = 3)] = 'INLINE_IMAGE'
46
+ RichSubMessageType[(RichSubMessageType['TABLE'] = 4)] = 'TABLE'
47
+ RichSubMessageType[(RichSubMessageType['CODE'] = 5)] = 'CODE'
48
+ RichSubMessageType[(RichSubMessageType['DYNAMIC'] = 6)] = 'DYNAMIC'
49
+ RichSubMessageType[(RichSubMessageType['MAP'] = 7)] = 'MAP'
50
+ RichSubMessageType[(RichSubMessageType['LATEX'] = 8)] = 'LATEX'
51
+ RichSubMessageType[(RichSubMessageType['CONTENT_ITEMS'] = 9)] = 'CONTENT_ITEMS'
52
+ })(RichSubMessageType || (RichSubMessageType = {}))
53
+
54
+ export const tokenizeCode = (codeStr, language = 'javascript') => {
55
+ const keywords = LANGUAGE_KEYWORDS[language] || JS_KEYWORDS
56
+ const blocks = []
57
+ const lines = codeStr.split('\n')
58
+ for (let li = 0; li < lines.length; li++) {
59
+ const line = lines[li]
60
+ const isLast = li === lines.length - 1
61
+ const nl = isLast? '' : '\n'
62
+ if (!line.trim()) {
63
+ blocks.push({ highlightType: CodeHighlightType.DEFAULT, codeContent: line + nl })
64
+ continue
65
+ }
66
+ if (line.trim().startsWith('//') || line.trim().startsWith('#')) {
67
+ blocks.push({ highlightType: CodeHighlightType.COMMENT, codeContent: line + nl })
68
+ continue
69
+ }
70
+ const regex = /(\/\/.*$|#.*$)|(["'`](?:[^"'`\\]|\\.)*["'`])|(\b\d+(?:\.\d+)?\b)|(\b[a-zA-Z_$][\w$]*\b)|([^\s\w$"'`]+)|(\s+)/g
71
+ let match
72
+ const tokens = []
73
+ while ((match = regex.exec(line))!== null) {
74
+ const val = match[0]
75
+ if (match[1]) {
76
+ tokens.push({ highlightType: CodeHighlightType.COMMENT, codeContent: val })
77
+ } else if (match[2]) {
78
+ tokens.push({ highlightType: CodeHighlightType.STRING, codeContent: val })
79
+ } else if (match[3]) {
80
+ tokens.push({ highlightType: CodeHighlightType.NUMBER, codeContent: val })
81
+ } else if (match[4]) {
82
+ if (keywords.has(val)) {
83
+ tokens.push({ highlightType: CodeHighlightType.KEYWORD, codeContent: val })
84
+ } else {
85
+ const after = line.slice(regex.lastIndex).trimStart()
86
+ if (after.startsWith('(')) {
87
+ tokens.push({ highlightType: CodeHighlightType.METHOD, codeContent: val })
88
+ } else {
89
+ tokens.push({ highlightType: CodeHighlightType.DEFAULT, codeContent: val })
90
+ }
91
+ }
92
+ } else {
93
+ tokens.push({ highlightType: CodeHighlightType.DEFAULT, codeContent: val })
94
+ }
95
+ }
96
+ if (tokens.length === 0) {
97
+ blocks.push({ highlightType: CodeHighlightType.DEFAULT, codeContent: line + nl })
98
+ continue
99
+ }
100
+ const merged = []
101
+ for (const t of tokens) {
102
+ const prev = merged.length > 0? merged[merged.length - 1] : undefined
103
+ if (prev && prev.highlightType === t.highlightType) {
104
+ prev.codeContent += t.codeContent
105
+ } else {
106
+ merged.push({...t })
107
+ }
108
+ }
109
+ if (merged.length > 0) {
110
+ merged[merged.length - 1].codeContent += nl
111
+ }
112
+ blocks.push(...merged)
113
+ }
114
+ return blocks
115
+ }
116
+
117
+ export const buildRichContextInfo = (quoted, options) => {
118
+ const ctxInfo = {
119
+ forwardingScore: 1,
120
+ isForwarded: true,
121
+ forwardedAiBotMessageInfo: { botJid: options?.botJid? options.botJid : '867051314767696@bot' },
122
+ forwardOrigin: 4,
123
+ ...(options?.mentions? { mentionedJid: options.mentions } : {})
124
+ }
125
+ if (quoted?.key) {
126
+ ctxInfo.stanzaId = quoted.key.id
127
+ ctxInfo.participant = quoted.key.participant || quoted.sender || quoted.key.remoteJid
128
+ ctxInfo.quotedMessage = quoted.message
129
+ }
130
+ return ctxInfo
131
+ }
132
+
133
+ export const buildBotForwardedMessage = (submessages, contextInfo, unifiedResponse) => {
134
+ const richResponse = { messageType: 1, submessages, contextInfo }
135
+ if (unifiedResponse) {
136
+ richResponse.unifiedResponse = unifiedResponse
137
+ }
138
+ return {
139
+ botForwardedMessage: {
140
+ message: { richResponseMessage: richResponse }
141
+ }
142
+ }
143
+ }
144
+
145
+ export const generateTableContent = (title, headers, rows, quoted, options = {}) => {
146
+ const { footer, headerText } = options
147
+ const tableRows = [{ items: headers, isHeading: true },...rows.map(row => ({ items: row.map(String) }))]
148
+ const submessages = []
149
+ if (headerText) submessages.push({ messageType: 2, messageText: headerText })
150
+ submessages.push({ messageType: 4, tableMetadata: { title, rows: tableRows } })
151
+ if (footer) submessages.push({ messageType: 2, messageText: footer })
152
+ const ctxInfo = buildRichContextInfo(quoted)
153
+ return { message: buildBotForwardedMessage(submessages, ctxInfo), messageId: generateMessageIDV2() }
154
+ }
155
+
156
+ export const generateListContent = (title, items, quoted, options = {}) => {
157
+ const { footer, headerText } = options
158
+ const tableRows = items.map(item => ({
159
+ items: Array.isArray(item)? item.map(String) : [String(item)]
160
+ }))
161
+ const submessages = []
162
+ if (headerText) submessages.push({ messageType: 2, messageText: headerText })
163
+ submessages.push({ messageType: 4, tableMetadata: { title, rows: tableRows } })
164
+ if (footer) submessages.push({ messageType: 2, messageText: footer })
165
+ const ctxInfo = buildRichContextInfo(quoted)
166
+ return { message: buildBotForwardedMessage(submessages, ctxInfo), messageId: generateMessageIDV2() }
167
+ }
168
+
169
+ export const generateCodeBlockContent = (code, quoted, options = {}) => {
170
+ const { title, footer, language = 'javascript' } = options
171
+ const submessages = []
172
+ if (title) submessages.push({ messageType: 2, messageText: title })
173
+ submessages.push({
174
+ messageType: 5,
175
+ codeMetadata: { codeLanguage: language, codeBlocks: tokenizeCode(code, language) }
176
+ })
177
+ if (footer) submessages.push({ messageType: 2, messageText: footer })
178
+ const ctxInfo = buildRichContextInfo(quoted)
179
+ return { message: buildBotForwardedMessage(submessages, ctxInfo), messageId: generateMessageIDV2() }
180
+ }
181
+
182
+ export const generateLatexContent = (quoted, options) => {
183
+ const { text, expressions, headerText, footer } = options
184
+ const submessages = []
185
+ if (headerText) submessages.push({ messageType: 2, messageText: headerText })
186
+ const latexExpressions = expressions.map(expr => {
187
+ const entry = {
188
+ latexExpression: expr.latexExpression,
189
+ url: expr.url,
190
+ width: expr.width,
191
+ height: expr.height
192
+ }
193
+ if (expr.fontHeight!== undefined) entry.fontHeight = expr.fontHeight
194
+ if (expr.imageTopPadding!== undefined) entry.imageTopPadding = expr.imageTopPadding
195
+ if (expr.imageLeadingPadding!== undefined) entry.imageLeadingPadding = expr.imageLeadingPadding
196
+ if (expr.imageBottomPadding!== undefined) entry.imageBottomPadding = expr.imageBottomPadding
197
+ if (expr.imageTrailingPadding!== undefined) entry.imageTrailingPadding = expr.imageTrailingPadding
198
+ return entry
199
+ })
200
+ submessages.push({ messageType: 8, latexMetadata: { text: text || '', expressions: latexExpressions } })
201
+ if (footer) submessages.push({ messageType: 2, messageText: footer })
202
+ const ctxInfo = buildRichContextInfo(quoted)
203
+ return { message: buildBotForwardedMessage(submessages, ctxInfo), messageId: generateMessageIDV2() }
204
+ }
205
+
206
+ export const generateLatexImageContent = async (quoted, options, uploadFn, renderLatexToPng) => {
207
+ const { text, expressions, headerText, footer } = options
208
+ const submessages = []
209
+ if (headerText) submessages.push({ messageType: 2, messageText: headerText })
210
+ const latexExpressions = await Promise.all(
211
+ expressions.map(async expr => {
212
+ const { buffer, width, height } = await renderLatexToPng(expr.latexExpression)
213
+ const uploadResult = await uploadFn(buffer, 'image')
214
+ const imageUrl = uploadResult.url || uploadResult.directPath
215
+ return { latexExpression: expr.latexExpression, url: imageUrl, width, height }
216
+ })
217
+ )
218
+ submessages.push({ messageType: 8, latexMetadata: { text: text || '', expressions: latexExpressions } })
219
+ if (footer) submessages.push({ messageType: 2, messageText: footer })
220
+ const ctxInfo = buildRichContextInfo(quoted)
221
+ return { message: buildBotForwardedMessage(submessages, ctxInfo), messageId: generateMessageIDV2() }
222
+ }
223
+
224
+ export const generateLatexInlineImageContent = async (quoted, options, uploadFn, renderLatexToPng) => {
225
+ const { text, expressions, headerText, footer } = options
226
+ const submessages = []
227
+ if (headerText) submessages.push({ messageType: 2, messageText: headerText })
228
+ if (text) submessages.push({ messageType: 2, messageText: text })
229
+ for (const expr of expressions) {
230
+ const { buffer, width, height } = await renderLatexToPng(expr.latexExpression)
231
+ const uploadResult = await uploadFn(buffer, 'image')
232
+ const imageUrl = uploadResult.url || uploadResult.directPath
233
+ submessages.push({
234
+ messageType: 3,
235
+ imageMetadata: {
236
+ imageUrl: { imagePreviewUrl: imageUrl, imageHighResUrl: imageUrl },
237
+ imageText: expr.latexExpression,
238
+ alignment: 2
239
+ }
240
+ })
241
+ }
242
+ if (footer) submessages.push({ messageType: 2, messageText: footer })
243
+ const ctxInfo = buildRichContextInfo(quoted)
244
+ return { message: buildBotForwardedMessage(submessages, ctxInfo), messageId: generateMessageIDV2() }
245
+ }
246
+
247
+ export const captureUnifiedResponse = msg => {
248
+ const botFwd = msg?.botForwardedMessage?.message
249
+ if (!botFwd) return null
250
+ const rich = botFwd.richResponseMessage
251
+ if (!rich?.unifiedResponse?.data) return null
252
+ return {
253
+ unifiedResponse: { data: rich.unifiedResponse.data },
254
+ submessages: rich.submessages || [],
255
+ contextInfo: rich.contextInfo || {}
256
+ }
257
+ }
258
+
259
+ export const generateUnifiedResponseContent = (quoted, captured) => {
260
+ const ctxInfo = buildRichContextInfo(quoted)
261
+ return { message: buildBotForwardedMessage(captured.submessages, ctxInfo, captured.unifiedResponse), messageId: generateMessageIDV2() }
262
+ }
263
+
264
+ export const generateRichMessageContent = (submessages, quoted, options) => {
265
+ const ctxInfo = buildRichContextInfo(quoted, options)
266
+ return { message: buildBotForwardedMessage(submessages, ctxInfo), messageId: generateMessageIDV2() }
267
+ }
268
+
269
+ export {
270
+ JS_KEYWORDS,
271
+ PYTHON_KEYWORDS,
272
+ LANGUAGE_KEYWORDS
273
+ }
@@ -1,5 +1,5 @@
1
1
  import { Boom } from '@hapi/boom';
2
- import { randomBytes } from 'crypto';
2
+ import { randomUUID, randomBytes } from 'crypto';
3
3
  import { promises as fs } from 'fs';
4
4
  import {} from 'stream';
5
5
  import { proto } from '../../WAProto/index.js';
@@ -26,6 +26,133 @@ const MessageTypeProto = {
26
26
  document: WAProto.Message.DocumentMessage
27
27
  };
28
28
  const ButtonType = proto.Message.ButtonsMessage.HeaderType;
29
+ const RICH_RESPONSE_CODE_KEYWORDS = new Set([
30
+ 'break',
31
+ 'case',
32
+ 'catch',
33
+ 'continue',
34
+ 'debugger',
35
+ 'default',
36
+ 'delete',
37
+ 'do',
38
+ 'else',
39
+ 'finally',
40
+ 'for',
41
+ 'function',
42
+ 'if',
43
+ 'in',
44
+ 'instanceof',
45
+ 'new',
46
+ 'return',
47
+ 'switch',
48
+ 'this',
49
+ 'throw',
50
+ 'try',
51
+ 'typeof',
52
+ 'var',
53
+ 'void',
54
+ 'while',
55
+ 'with',
56
+ 'true',
57
+ 'false',
58
+ 'null',
59
+ 'undefined',
60
+ 'NaN',
61
+ 'Infinity',
62
+ 'class',
63
+ 'const',
64
+ 'let',
65
+ 'super',
66
+ 'extends',
67
+ 'export',
68
+ 'import',
69
+ 'yield',
70
+ 'static',
71
+ 'constructor',
72
+ 'of',
73
+ 'async',
74
+ 'await',
75
+ 'get',
76
+ 'set',
77
+ 'implements',
78
+ 'interface',
79
+ 'package',
80
+ 'private',
81
+ 'protected',
82
+ 'public',
83
+ 'enum',
84
+ 'throws',
85
+ 'transient'
86
+ ])
87
+ const tokenizeCode = code => {
88
+ const tokens = []
89
+ let i = 0
90
+ const len = code.length
91
+ while (i < len) {
92
+ if (/\s/.test(code[i])) {
93
+ const start = i
94
+ while (i < len && /\s/.test(code[i])) i++
95
+ tokens.push({ content: code.slice(start, i), type: 'DEFAULT' })
96
+ continue
97
+ }
98
+ if (code[i] === '"' || code[i] === "'" || code[i] === '`') {
99
+ const start = i
100
+ const quote = code[i]
101
+ i++
102
+ while (i < len && code[i] !== quote) {
103
+ if (code[i] === '\\') i++
104
+ i++
105
+ }
106
+ i++
107
+ tokens.push({ content: code.slice(start, i), type: 'STR' })
108
+ continue
109
+ }
110
+ if (code[i] === '/' && i + 1 < len && code[i + 1] === '/') {
111
+ const start = i
112
+ while (i < len && code[i] !== '\n') i++
113
+ tokens.push({ content: code.slice(start, i), type: 'COMMENT' })
114
+ continue
115
+ }
116
+ if (code[i] === '/' && i + 1 < len && code[i + 1] === '*') {
117
+ const start = i
118
+ i += 2
119
+ while (i + 1 < len && !(code[i] === '*' && code[i + 1] === '/')) i++
120
+ i += 2
121
+ tokens.push({ content: code.slice(start, i), type: 'COMMENT' })
122
+ continue
123
+ }
124
+ if (/[0-9]/.test(code[i])) {
125
+ const start = i
126
+ while (i < len && /[0-9.]/.test(code[i])) i++
127
+ tokens.push({ content: code.slice(start, i), type: 'NUMBER' })
128
+ continue
129
+ }
130
+ if (/[a-zA-Z_$]/.test(code[i])) {
131
+ const start = i
132
+ while (i < len && /[a-zA-Z0-9_$]/.test(code[i])) i++
133
+ const word = code.slice(start, i)
134
+ if (RICH_RESPONSE_CODE_KEYWORDS.has(word)) {
135
+ tokens.push({ content: word, type: 'KEYWORD' })
136
+ } else {
137
+ let j = i
138
+ while (j < len && /\s/.test(code[j])) j++
139
+ tokens.push({ content: word, type: j < len && code[j] === '(' ? 'METHOD' : 'DEFAULT' })
140
+ }
141
+ continue
142
+ }
143
+ tokens.push({ content: code[i], type: 'DEFAULT' })
144
+ i++
145
+ }
146
+ const merged = []
147
+ for (const t of tokens) {
148
+ if (merged.length && merged[merged.length - 1].type === 'DEFAULT' && t.type === 'DEFAULT') {
149
+ merged[merged.length - 1].content += t.content
150
+ } else {
151
+ merged.push(t)
152
+ }
153
+ }
154
+ return merged
155
+ }
29
156
  /**
30
157
  * Uses a regex to test whether the string contains a URL, and returns the URL if it does.
31
158
  * @param text eg. hello https://google.com
@@ -271,10 +398,242 @@ export const hasNonNullishProperty = (message, key) => {
271
398
  function hasOptionalProperty(obj, key) {
272
399
  return typeof obj === 'object' && obj !== null && key in obj && obj[key] !== null;
273
400
  }
401
+ const applyContextInfoAndMentions = (interactiveMessage, message) => {
402
+ if ('contextInfo' in message && !!message.contextInfo) {
403
+ interactiveMessage.contextInfo = message.contextInfo
404
+ }
405
+ if ('mentions' in message && !!message.mentions) {
406
+ interactiveMessage.contextInfo = {
407
+ ...(interactiveMessage.contextInfo || {}),
408
+ mentionedJid: message.mentions
409
+ }
410
+ }
411
+ }
274
412
  export const generateWAMessageContent = async (message, options) => {
275
413
  var _a, _b;
276
414
  let m = {};
277
- if (hasNonNullishProperty(message, 'text')) {
415
+ if ('interactiveButtons' in message && !!message.interactiveButtons) {
416
+ const nativeFlow = proto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
417
+ buttons: message.interactiveButtons,
418
+ messageParamsJson: message.messageParams ?? "{}"
419
+ });
420
+ let interactiveMessage = { nativeFlowMessage: nativeFlow };
421
+ if ('text' in message) {
422
+ interactiveMessage.body = { text: message.text };
423
+ } else if ('caption' in message) {
424
+ interactiveMessage.body = { text: message.caption };
425
+ }
426
+ if ('title' in message && !!message.title) {
427
+ interactiveMessage.header = {
428
+ title: message.title,
429
+ subtitle: message.subtitle || "",
430
+ hasMediaAttachment: false
431
+ };
432
+ let media = null;
433
+ if ('image' in message && !!message.image) {
434
+ media = await prepareWAMessageMedia({ image: message.image }, options);
435
+ interactiveMessage.header.imageMessage = media.imageMessage;
436
+ if (message.image.caption) {
437
+ interactiveMessage.header.imageMessage.caption = message.image.caption;
438
+ }
439
+ } else if ('video' in message && !!message.video) {
440
+ media = await prepareWAMessageMedia({ video: message.video }, options);
441
+ interactiveMessage.header.videoMessage = media.videoMessage;
442
+ if (message.video.caption) {
443
+ interactiveMessage.header.videoMessage.caption = message.video.caption;
444
+ }
445
+ } else if ('gif' in message && !!message.gif) {
446
+ media = await prepareWAMessageMedia({ video: message.gif }, options);
447
+ interactiveMessage.header.videoMessage = media.videoMessage;
448
+ interactiveMessage.header.videoMessage.gifPlayback = true;
449
+ if (message.gif.caption) {
450
+ interactiveMessage.header.videoMessage.caption = message.gif.caption;
451
+ }
452
+ } else if ('document' in message && !!message.document) {
453
+ media = await prepareWAMessageMedia({ document: message.document }, options);
454
+ interactiveMessage.header.documentMessage = media.documentMessage;
455
+ let docuR = interactiveMessage.header.documentMessage;
456
+ docuR.fileName = message.document.fileName || "Document";
457
+ docuR.mimetype = message.document.mimetype || docuR.mimetype;
458
+ if (message.document.caption) docuR.caption = message.document.caption;
459
+ if (message.document.jpegThumbnail) docuR.jpegThumbnail = message.document.jpegThumbnail;
460
+ } else if ('location' in message && !!message.location) {
461
+ let mLoc = message.location;
462
+ interactiveMessage.header.locationMessage = {
463
+ degreesLongitude: mLoc.longitude || 0,
464
+ degreesLatitude: mLoc.latitude || 0,
465
+ name: mLoc.name || null,
466
+ address: mLoc.address || null,
467
+ url: mLoc.url || null
468
+ };
469
+ media = true;
470
+ } else if ('thumbnail' in message && !!message.thumbnail) {
471
+ interactiveMessage.header.jpegThumbnail = message.thumbnail;
472
+ }
473
+ if (media || ('thumbnail' in message && !!message.thumbnail)) {
474
+ interactiveMessage.header.hasMediaAttachment = true;
475
+ }
476
+ }
477
+ if ('footer' in message && !!message.footer) {
478
+ interactiveMessage.footer = { text: message.footer };
479
+ }
480
+ applyContextInfoAndMentions(interactiveMessage, message);
481
+ m = { interactiveMessage };
482
+ }
483
+ else if ('buttons' in message && !!message.buttons) {
484
+ const buttonsMessage = {
485
+ buttons: message.buttons.map(b => ({ ...b, type: proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
486
+ };
487
+ if ('text' in message) {
488
+ buttonsMessage.contentText = message.text;
489
+ buttonsMessage.headerType = ButtonType.EMPTY;
490
+ }
491
+ else {
492
+ if ('caption' in message) {
493
+ buttonsMessage.contentText = message.caption;
494
+ }
495
+ const contentType = getContentType(m);
496
+ const type = contentType.replace('Message', '').toUpperCase();
497
+ buttonsMessage.headerType = ButtonType[type];
498
+ Object.assign(buttonsMessage, m);
499
+ }
500
+ if ('footer' in message && !!message.footer) {
501
+ buttonsMessage.footerText = message.footer;
502
+ }
503
+ m = { buttonsMessage };
504
+ }
505
+ else if ('richResponse' in message) {
506
+ const {
507
+ text,
508
+ code,
509
+ language = 'javascript',
510
+ botJid = '867051314767696@bot',
511
+ table,
512
+ latex,
513
+ map,
514
+ imageUrl,
515
+ imageUrls,
516
+ responseId,
517
+ messageSecret: richSecret
518
+ } = message.richResponse
519
+ const sections = []
520
+ if (text) {
521
+ sections.push({
522
+ view_model: {
523
+ primitive: { text, __typename: 'GenAIMarkdownTextUXPrimitive' },
524
+ __typename: 'GenAISingleLayoutViewModel'
525
+ }
526
+ })
527
+ }
528
+ if (code) {
529
+ sections.push({
530
+ view_model: {
531
+ primitive: {
532
+ language,
533
+ code_blocks: tokenizeCode(String(code)),
534
+ __typename: 'GenAICodeUXPrimitive'
535
+ },
536
+ __typename: 'GenAISingleLayoutViewModel'
537
+ }
538
+ })
539
+ }
540
+ if (table && Array.isArray(table.rows)) {
541
+ sections.push({
542
+ view_model: {
543
+ primitive: {
544
+ rows: table.rows.map(row => ({
545
+ cells: Array.isArray(row) ? row.map(c => ({ text: String(c) })) : row.cells
546
+ })),
547
+ __typename: 'GenAITableUXPrimitive'
548
+ },
549
+ __typename: 'GenAISingleLayoutViewModel'
550
+ }
551
+ })
552
+ }
553
+ if (latex) {
554
+ const expressions = Array.isArray(latex)
555
+ ? latex.map(e => (typeof e === 'string' ? { expression: e } : e))
556
+ : [{ expression: String(latex) }]
557
+ sections.push({
558
+ view_model: {
559
+ primitive: { expressions, __typename: 'GenAILatexUXPrimitive' },
560
+ __typename: 'GenAISingleLayoutViewModel'
561
+ }
562
+ })
563
+ }
564
+ if (map) {
565
+ sections.push({
566
+ view_model: {
567
+ primitive: {
568
+ latitude: map.latitude,
569
+ longitude: map.longitude,
570
+ zoom: map.zoom,
571
+ title: map.title,
572
+ annotations: map.annotations || [],
573
+ __typename: 'GenAIMapUXPrimitive'
574
+ },
575
+ __typename: 'GenAISingleLayoutViewModel'
576
+ }
577
+ })
578
+ }
579
+ if (imageUrl) {
580
+ sections.push({
581
+ view_model: {
582
+ primitive: { url: imageUrl, __typename: 'GenAIInlineImageUXPrimitive' },
583
+ __typename: 'GenAISingleLayoutViewModel'
584
+ }
585
+ })
586
+ }
587
+ if (imageUrls && Array.isArray(imageUrls) && imageUrls.length > 0) {
588
+ sections.push({
589
+ view_model: {
590
+ primitive: {
591
+ urls: imageUrls.map(u => (typeof u === 'string' ? { url: u } : u)),
592
+ __typename: 'GenAIGridImageUXPrimitive'
593
+ },
594
+ __typename: 'GenAISingleLayoutViewModel'
595
+ }
596
+ })
597
+ }
598
+ if (!sections.length && !text) {
599
+ sections.push({
600
+ view_model: {
601
+ primitive: { text: '', __typename: 'GenAIMarkdownTextUXPrimitive' },
602
+ __typename: 'GenAISingleLayoutViewModel'
603
+ }
604
+ })
605
+ }
606
+ const unifiedData = {
607
+ response_id: responseId || randomUUID(),
608
+ sections
609
+ }
610
+ return proto.Message.fromObject({
611
+ messageContextInfo: {
612
+ deviceListMetadata: {},
613
+ deviceListMetadataVersion: 2,
614
+ messageSecret: richSecret || randomBytes(32)
615
+ },
616
+ botForwardedMessage: {
617
+ message: {
618
+ richResponseMessage: {
619
+ submessages: [],
620
+ messageType: 1,
621
+ unifiedResponse: { data: Buffer.from(JSON.stringify(unifiedData)) },
622
+ contextInfo: {
623
+ forwardingScore: 2,
624
+ isForwarded: true,
625
+ forwardedAiBotMessageInfo: { botJid },
626
+ botMessageSharingInfo: {
627
+ botEntryPointOrigin: 1,
628
+ forwardScore: 2
629
+ }
630
+ }
631
+ }
632
+ }
633
+ }
634
+ })
635
+ }
636
+ else if (hasNonNullishProperty(message, 'text')) {
278
637
  const extContent = { text: message.text };
279
638
  let urlInfo = message.linkPreview;
280
639
  if (typeof urlInfo === 'undefined') {
@@ -317,28 +676,6 @@ export const generateWAMessageContent = async (message, options) => {
317
676
  m.contactsArrayMessage = WAProto.Message.ContactsArrayMessage.create(message.contacts);
318
677
  }
319
678
  }
320
- else if (hasNonNullishProperty(message, 'buttons')) {
321
- const buttonsMessage = {
322
- buttons: message.buttons.map(b => ({ ...b, type: proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
323
- };
324
- if ('text' in message) {
325
- buttonsMessage.contentText = message.text;
326
- buttonsMessage.headerType = ButtonType.EMPTY;
327
- }
328
- else {
329
- if ('caption' in message) {
330
- buttonsMessage.contentText = message.caption;
331
- }
332
- const contentType = getContentType(m);
333
- const type = contentType.replace('Message', '').toUpperCase();
334
- buttonsMessage.headerType = ButtonType[type];
335
- Object.assign(buttonsMessage, m);
336
- }
337
- if ('footer' in message && !!message.footer) {
338
- buttonsMessage.footerText = message.footer;
339
- }
340
- m = { buttonsMessage };
341
- }
342
679
  else if (hasNonNullishProperty(message, 'location')) {
343
680
  m.locationMessage = WAProto.Message.LocationMessage.create(message.location);
344
681
  }