@ryuu-reinzz/haruka-lib 4.0.0-beta.1 → 4.0.0-beta.3

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 (2) hide show
  1. package/main/socket.js +1274 -1272
  2. package/package.json +1 -1
package/main/socket.js CHANGED
@@ -51,1493 +51,1497 @@ import Sticker from './sticker-engine/index.js';
51
51
  const __filename = fileURLToPath(import.meta.url);
52
52
  const __dirname = dirname(__filename);
53
53
 
54
- function extractIE(text, {
55
- extract = true,
56
- hyperlink = true,
57
- citation = true,
58
- latex = true
59
- } = {}) {
60
- if (!extract) {
61
- return {
62
- text,
63
- ie: [],
64
- };
65
- }
66
- let ie = [],
67
- result = '',
68
- last = 0,
69
- citation_index = 1,
70
- hyperlink_index = 0,
71
- latex_index = 0,
72
- stack = [];
73
- for (let i = 0; i < text.length; i++) {
74
- if (text[i] == '[' && text[i - 1] != '\\') {
75
- stack.push(i);
76
- } else if (text[i] == ']' && (text[i + 1] == '(' || text[i + 1] == '<')) {
77
- let start = stack.pop();
78
- if (start == null) continue;
79
- let open = text[i + 1],
80
- close = open == '(' ? ')' : '>',
81
- type = open == '(' ? 'link' : 'latex',
82
- end = i + 2,
83
- depth = 1;
84
- while (end < text.length && depth) {
85
- if (text[end] == open && text[end - 1] != '\\') depth++;
86
- else if (text[end] == close && text[end - 1] != '\\') depth--;
87
- end++;
88
- }
89
- if (depth) continue;
90
- let raw = text.slice(start + 1, i).trim(),
91
- url = text.slice(i + 2, end - 1).trim(),
92
- key,
93
- tag,
94
- data;
95
- if (type == 'latex') {
96
- if (!latex) continue;
97
- let [txt = '', width = null, height = null, font_height = null, padding = null] = raw.split('|');
98
- key = `\u004E\u0049\u0058\u0045\u004C_LATEX_${latex_index++}`;
99
- tag = `{{${key}}}${txt || 'image'}{{/${key}}}`;
100
- data = {
101
- type: 'latex',
102
- ie: {
103
- key,
104
- text: txt,
105
- url,
106
- width,
107
- height,
108
- font_height,
109
- padding,
110
- },
111
- };
112
- } else if (raw) {
113
- if (!hyperlink) continue;
114
- key = `\u004E\u0049\u0058\u0045\u004C_HYPERLINK_${hyperlink_index++}`;
115
- tag = `{{${key}}}${url}{{/${key}}}`;
116
- data = {
117
- type: 'hyperlink',
118
- ie: {
119
- key,
120
- text: raw,
121
- url,
122
- },
123
- };
124
- } else {
125
- if (!citation) continue;
126
- key = `\u004E\u0049\u0058\u0045\u004C_CITATION_${citation_index - 1}`;
127
- tag = `{{${key}}}${url}{{/${key}}}`;
128
- data = {
129
- type: 'citation',
130
- ie: {
131
- reference_id: citation_index++,
132
- key,
133
- text: '',
134
- url,
135
- },
136
- };
54
+ /**
55
+ * @param {import('baileys').WASocket} socket
56
+ */
57
+
58
+ function addProperty(socket, baileys) {
59
+ const {
60
+ proto,
61
+ generateWAMessageFromContent,
62
+ jidDecode,
63
+ downloadContentFromMessage,
64
+ prepareWAMessageMedia,
65
+ generateMessageID,
66
+ generateWAMessage
67
+ } = baileys;
68
+ let sendMessage = socket.sendMessage;
69
+
70
+ function extractIE(text, {
71
+ extract = true,
72
+ hyperlink = true,
73
+ citation = true,
74
+ latex = true
75
+ } = {}) {
76
+ if (!extract) {
77
+ return {
78
+ text,
79
+ ie: [],
80
+ };
81
+ }
82
+ let ie = [],
83
+ result = '',
84
+ last = 0,
85
+ citation_index = 1,
86
+ hyperlink_index = 0,
87
+ latex_index = 0,
88
+ stack = [];
89
+ for (let i = 0; i < text.length; i++) {
90
+ if (text[i] == '[' && text[i - 1] != '\\') {
91
+ stack.push(i);
92
+ } else if (text[i] == ']' && (text[i + 1] == '(' || text[i + 1] == '<')) {
93
+ let start = stack.pop();
94
+ if (start == null) continue;
95
+ let open = text[i + 1],
96
+ close = open == '(' ? ')' : '>',
97
+ type = open == '(' ? 'link' : 'latex',
98
+ end = i + 2,
99
+ depth = 1;
100
+ while (end < text.length && depth) {
101
+ if (text[end] == open && text[end - 1] != '\\') depth++;
102
+ else if (text[end] == close && text[end - 1] != '\\') depth--;
103
+ end++;
104
+ }
105
+ if (depth) continue;
106
+ let raw = text.slice(start + 1, i).trim(),
107
+ url = text.slice(i + 2, end - 1).trim(),
108
+ key,
109
+ tag,
110
+ data;
111
+ if (type == 'latex') {
112
+ if (!latex) continue;
113
+ let [txt = '', width = null, height = null, font_height = null, padding = null] = raw.split('|');
114
+ key = `\u004E\u0049\u0058\u0045\u004C_LATEX_${latex_index++}`;
115
+ tag = `{{${key}}}${txt || 'image'}{{/${key}}}`;
116
+ data = {
117
+ type: 'latex',
118
+ ie: {
119
+ key,
120
+ text: txt,
121
+ url,
122
+ width,
123
+ height,
124
+ font_height,
125
+ padding,
126
+ },
127
+ };
128
+ } else if (raw) {
129
+ if (!hyperlink) continue;
130
+ key = `\u004E\u0049\u0058\u0045\u004C_HYPERLINK_${hyperlink_index++}`;
131
+ tag = `{{${key}}}${url}{{/${key}}}`;
132
+ data = {
133
+ type: 'hyperlink',
134
+ ie: {
135
+ key,
136
+ text: raw,
137
+ url,
138
+ },
139
+ };
140
+ } else {
141
+ if (!citation) continue;
142
+ key = `\u004E\u0049\u0058\u0045\u004C_CITATION_${citation_index - 1}`;
143
+ tag = `{{${key}}}${url}{{/${key}}}`;
144
+ data = {
145
+ type: 'citation',
146
+ ie: {
147
+ reference_id: citation_index++,
148
+ key,
149
+ text: '',
150
+ url,
151
+ },
152
+ };
153
+ }
154
+ result += text.slice(last, start) + tag;
155
+ last = end;
156
+ ie.push(data);
157
+ i = end - 1;
137
158
  }
138
- result += text.slice(last, start) + tag;
139
- last = end;
140
- ie.push(data);
141
- i = end - 1;
142
159
  }
143
- }
144
- result += text.slice(last);
145
- return {
146
- text: result,
147
- ie,
148
- };
149
- }
150
-
151
- class BaseBuilder {
152
- constructor() {
153
- this._title = '';
154
- this._subtitle = '';
155
- this._body = '';
156
- this._footer = '';
157
- this._contextInfo = {};
158
- this._extraPayload = {};
160
+ result += text.slice(last);
161
+ return {
162
+ text: result,
163
+ ie,
164
+ };
159
165
  }
160
166
 
161
- setTitle(title) {
162
- if (typeof title !== 'string') {
163
- throw new TypeError('Title must be a string');
167
+ class BaseBuilder {
168
+ constructor() {
169
+ this._title = '';
170
+ this._subtitle = '';
171
+ this._body = '';
172
+ this._footer = '';
173
+ this._contextInfo = {};
174
+ this._extraPayload = {};
164
175
  }
165
- this._title = title;
166
- return this;
167
- }
168
176
 
169
- setSubtitle(subtitle) {
170
- if (typeof subtitle !== 'string') {
171
- throw new TypeError('Subtitle must be a string');
177
+ setTitle(title) {
178
+ if (typeof title !== 'string') {
179
+ throw new TypeError('Title must be a string');
180
+ }
181
+ this._title = title;
182
+ return this;
172
183
  }
173
- this._subtitle = subtitle;
174
- return this;
175
- }
176
184
 
177
- setBody(body) {
178
- if (typeof body !== 'string') {
179
- throw new TypeError('Body must be a string');
185
+ setSubtitle(subtitle) {
186
+ if (typeof subtitle !== 'string') {
187
+ throw new TypeError('Subtitle must be a string');
188
+ }
189
+ this._subtitle = subtitle;
190
+ return this;
180
191
  }
181
- this._body = body;
182
- return this;
183
- }
184
192
 
185
- setFooter(footer) {
186
- if (typeof footer !== 'string') {
187
- throw new TypeError('Footer must be a string');
193
+ setBody(body) {
194
+ if (typeof body !== 'string') {
195
+ throw new TypeError('Body must be a string');
196
+ }
197
+ this._body = body;
198
+ return this;
188
199
  }
189
- this._footer = footer;
190
- return this;
191
- }
192
200
 
193
- setContextInfo(obj) {
194
- if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
195
- throw new TypeError('ContextInfo must be a plain object');
201
+ setFooter(footer) {
202
+ if (typeof footer !== 'string') {
203
+ throw new TypeError('Footer must be a string');
204
+ }
205
+ this._footer = footer;
206
+ return this;
196
207
  }
197
208
 
198
- this._contextInfo = obj;
199
- return this;
200
- }
209
+ setContextInfo(obj) {
210
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
211
+ throw new TypeError('ContextInfo must be a plain object');
212
+ }
201
213
 
202
- addPayload(obj) {
203
- if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
204
- throw new TypeError('Payload must be a plain object');
214
+ this._contextInfo = obj;
215
+ return this;
205
216
  }
206
217
 
207
- Object.assign(this._extraPayload, obj);
208
-
209
- return this;
210
- }
218
+ addPayload(obj) {
219
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
220
+ throw new TypeError('Payload must be a plain object');
221
+ }
211
222
 
212
- static async resize(buffer, x, y, fit = 'cover') {
213
- return await sharp(buffer)
214
- .resize(x, y, {
215
- fit,
216
- position: 'center',
217
- background: {
218
- r: 0,
219
- g: 0,
220
- b: 0,
221
- alpha: 0
222
- },
223
- })
224
- .png()
225
- .toBuffer();
226
- }
223
+ Object.assign(this._extraPayload, obj);
227
224
 
228
- static async fetchBuffer(url, options = {}, config = {}) {
229
- try {
230
- let response = await fetch(url, options);
231
- if (!response.ok) throw Error(`HTTP ${response.status}`);
232
- return Buffer.from(await response.arrayBuffer());
233
- } catch (error) {
234
- if (config.silent) return Buffer.alloc(0);
235
- throw error;
225
+ return this;
236
226
  }
237
- }
238
- }
239
-
240
- class Button extends BaseBuilder {
241
- #client;
242
227
 
243
- constructor(client) {
244
- super();
245
- if (!client) {
246
- throw new Error('Socket is required');
228
+ static async resize(buffer, x, y, fit = 'cover') {
229
+ return await sharp(buffer)
230
+ .resize(x, y, {
231
+ fit,
232
+ position: 'center',
233
+ background: {
234
+ r: 0,
235
+ g: 0,
236
+ b: 0,
237
+ alpha: 0
238
+ },
239
+ })
240
+ .png()
241
+ .toBuffer();
247
242
  }
248
- this.#client = client;
249
243
 
250
- this._buttons = [];
251
- this._data;
252
- this._currentSelectionIndex = -1;
253
- this._currentSectionIndex = -1;
254
- this._params = {};
244
+ static async fetchBuffer(url, options = {}, config = {}) {
245
+ try {
246
+ let response = await fetch(url, options);
247
+ if (!response.ok) throw Error(`HTTP ${response.status}`);
248
+ return Buffer.from(await response.arrayBuffer());
249
+ } catch (error) {
250
+ if (config.silent) return Buffer.alloc(0);
251
+ throw error;
252
+ }
253
+ }
255
254
  }
256
255
 
257
- setVideo(path, options = {}) {
258
- if (!path) throw new Error('Url or buffer needed');
259
- Buffer.isBuffer(path) ? (this._data = {
260
- video: path,
261
- ...options
262
- }) : (this._data = {
263
- video: {
264
- url: path
265
- },
266
- ...options
267
- });
268
- return this;
269
- }
256
+ class Button extends BaseBuilder {
257
+ #client;
270
258
 
271
- setImage(path, options = {}) {
272
- if (!path) throw new Error('Url or buffer needed');
273
- Buffer.isBuffer(path) ? (this._data = {
274
- image: path,
275
- ...options
276
- }) : (this._data = {
277
- image: {
278
- url: path
279
- },
280
- ...options
281
- });
282
- return this;
283
- }
259
+ constructor(client) {
260
+ super();
261
+ if (!client) {
262
+ throw new Error('Socket is required');
263
+ }
264
+ this.#client = client;
284
265
 
285
- setDocument(path, options = {}) {
286
- if (!path) throw new Error('Url or buffer needed');
287
- Buffer.isBuffer(path) ? (this._data = {
288
- document: path,
289
- ...options
290
- }) : (this._data = {
291
- document: {
292
- url: path
293
- },
294
- ...options
295
- });
296
- return this;
297
- }
266
+ this._buttons = [];
267
+ this._data;
268
+ this._currentSelectionIndex = -1;
269
+ this._currentSectionIndex = -1;
270
+ this._params = {};
271
+ }
298
272
 
299
- setMedia(obj) {
300
- if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
301
- throw new TypeError('Media must be a plain object');
273
+ setVideo(path, options = {}) {
274
+ if (!path) throw new Error('Url or buffer needed');
275
+ Buffer.isBuffer(path) ? (this._data = {
276
+ video: path,
277
+ ...options
278
+ }) : (this._data = {
279
+ video: {
280
+ url: path
281
+ },
282
+ ...options
283
+ });
284
+ return this;
302
285
  }
303
286
 
304
- this._data = obj;
305
- return this;
306
- }
287
+ setImage(path, options = {}) {
288
+ if (!path) throw new Error('Url or buffer needed');
289
+ Buffer.isBuffer(path) ? (this._data = {
290
+ image: path,
291
+ ...options
292
+ }) : (this._data = {
293
+ image: {
294
+ url: path
295
+ },
296
+ ...options
297
+ });
298
+ return this;
299
+ }
307
300
 
308
- clearButtons() {
309
- this._buttons = [];
310
- return this;
311
- }
301
+ setDocument(path, options = {}) {
302
+ if (!path) throw new Error('Url or buffer needed');
303
+ Buffer.isBuffer(path) ? (this._data = {
304
+ document: path,
305
+ ...options
306
+ }) : (this._data = {
307
+ document: {
308
+ url: path
309
+ },
310
+ ...options
311
+ });
312
+ return this;
313
+ }
312
314
 
313
- setParams(obj) {
314
- this._params = obj;
315
- return this;
316
- }
315
+ setMedia(obj) {
316
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
317
+ throw new TypeError('Media must be a plain object');
318
+ }
317
319
 
318
- addButton(name, params) {
319
- this._buttons.push({
320
- name,
321
- buttonParamsJson: typeof params === 'string' ? params : JSON.stringify(params),
322
- });
320
+ this._data = obj;
321
+ return this;
322
+ }
323
323
 
324
- return this;
325
- }
324
+ clearButtons() {
325
+ this._buttons = [];
326
+ return this;
327
+ }
326
328
 
327
- makeRow(header = '', title = '', description = '', id = '') {
328
- if (this._currentSelectionIndex === -1 || this._currentSectionIndex === -1) {
329
- throw new Error('You need to create a selection and a section first');
329
+ setParams(obj) {
330
+ this._params = obj;
331
+ return this;
330
332
  }
331
- const buttonParams = JSON.parse(this._buttons[this._currentSelectionIndex].buttonParamsJson);
332
- buttonParams.sections[this._currentSectionIndex].rows.push({
333
- header,
334
- title,
335
- description,
336
- id
337
- });
338
- this._buttons[this._currentSelectionIndex].buttonParamsJson = JSON.stringify(buttonParams);
339
- return this;
340
- }
341
333
 
342
- makeSection(title = '', highlight_label = '') {
343
- if (this._currentSelectionIndex === -1) {
344
- throw new Error('You need to create a selection first');
334
+ addButton(name, params) {
335
+ this._buttons.push({
336
+ name,
337
+ buttonParamsJson: typeof params === 'string' ? params : JSON.stringify(params),
338
+ });
339
+
340
+ return this;
345
341
  }
346
- const buttonParams = JSON.parse(this._buttons[this._currentSelectionIndex].buttonParamsJson);
347
- buttonParams.sections.push({
348
- title,
349
- highlight_label,
350
- rows: []
351
- });
352
- this._currentSectionIndex = buttonParams.sections.length - 1;
353
- this._buttons[this._currentSelectionIndex].buttonParamsJson = JSON.stringify(buttonParams);
354
- return this;
355
- }
356
342
 
357
- addSelection(title, options = {}) {
358
- this._buttons.push({
359
- ...options,
360
- name: 'single_select',
361
- buttonParamsJson: JSON.stringify({
343
+ makeRow(header = '', title = '', description = '', id = '') {
344
+ if (this._currentSelectionIndex === -1 || this._currentSectionIndex === -1) {
345
+ throw new Error('You need to create a selection and a section first');
346
+ }
347
+ const buttonParams = JSON.parse(this._buttons[this._currentSelectionIndex].buttonParamsJson);
348
+ buttonParams.sections[this._currentSectionIndex].rows.push({
349
+ header,
362
350
  title,
363
- sections: []
364
- })
365
- });
366
- this._currentSelectionIndex = this._buttons.length - 1;
367
- this._currentSectionIndex = -1;
368
- return this;
369
- }
351
+ description,
352
+ id
353
+ });
354
+ this._buttons[this._currentSelectionIndex].buttonParamsJson = JSON.stringify(buttonParams);
355
+ return this;
356
+ }
370
357
 
371
- addReply(display_text = '', id = '', options = {}) {
372
- this._buttons.push({
373
- name: 'quick_reply',
374
- buttonParamsJson: JSON.stringify({
375
- display_text,
376
- id,
377
- ...options,
378
- }),
379
- });
380
- return this;
381
- }
358
+ makeSection(title = '', highlight_label = '') {
359
+ if (this._currentSelectionIndex === -1) {
360
+ throw new Error('You need to create a selection first');
361
+ }
362
+ const buttonParams = JSON.parse(this._buttons[this._currentSelectionIndex].buttonParamsJson);
363
+ buttonParams.sections.push({
364
+ title,
365
+ highlight_label,
366
+ rows: []
367
+ });
368
+ this._currentSectionIndex = buttonParams.sections.length - 1;
369
+ this._buttons[this._currentSelectionIndex].buttonParamsJson = JSON.stringify(buttonParams);
370
+ return this;
371
+ }
382
372
 
383
- addCall(display_text = '', id = '', options = {}) {
384
- this._buttons.push({
385
- name: 'cta_call',
386
- buttonParamsJson: JSON.stringify({
387
- display_text,
388
- id,
373
+ addSelection(title, options = {}) {
374
+ this._buttons.push({
389
375
  ...options,
390
- }),
391
- });
392
- return this;
393
- }
376
+ name: 'single_select',
377
+ buttonParamsJson: JSON.stringify({
378
+ title,
379
+ sections: []
380
+ })
381
+ });
382
+ this._currentSelectionIndex = this._buttons.length - 1;
383
+ this._currentSectionIndex = -1;
384
+ return this;
385
+ }
394
386
 
395
- addReminder(display_text = '', id = '', options = {}) {
396
- this._buttons.push({
397
- name: 'cta_reminder',
398
- buttonParamsJson: JSON.stringify({
399
- display_text,
400
- id,
401
- ...options,
402
- }),
403
- });
404
- return this;
405
- }
387
+ addReply(display_text = '', id = '', options = {}) {
388
+ this._buttons.push({
389
+ name: 'quick_reply',
390
+ buttonParamsJson: JSON.stringify({
391
+ display_text,
392
+ id,
393
+ ...options,
394
+ }),
395
+ });
396
+ return this;
397
+ }
406
398
 
407
- addCancelReminder(display_text = '', id = '', options = {}) {
408
- this._buttons.push({
409
- name: 'cta_cancel_reminder',
410
- buttonParamsJson: JSON.stringify({
411
- display_text,
412
- id,
413
- ...options,
414
- }),
415
- });
416
- return this;
417
- }
399
+ addCall(display_text = '', id = '', options = {}) {
400
+ this._buttons.push({
401
+ name: 'cta_call',
402
+ buttonParamsJson: JSON.stringify({
403
+ display_text,
404
+ id,
405
+ ...options,
406
+ }),
407
+ });
408
+ return this;
409
+ }
418
410
 
419
- addAddress(display_text = '', id = '', options = {}) {
420
- this._buttons.push({
421
- name: 'address_message',
422
- buttonParamsJson: JSON.stringify({
423
- display_text,
424
- id,
425
- ...options,
426
- }),
427
- });
428
- return this;
429
- }
411
+ addReminder(display_text = '', id = '', options = {}) {
412
+ this._buttons.push({
413
+ name: 'cta_reminder',
414
+ buttonParamsJson: JSON.stringify({
415
+ display_text,
416
+ id,
417
+ ...options,
418
+ }),
419
+ });
420
+ return this;
421
+ }
430
422
 
431
- addLocation(options = {}) {
432
- this._buttons.push({
433
- name: 'send_location',
434
- buttonParamsJson: JSON.stringify(options),
435
- });
436
- return this;
437
- }
423
+ addCancelReminder(display_text = '', id = '', options = {}) {
424
+ this._buttons.push({
425
+ name: 'cta_cancel_reminder',
426
+ buttonParamsJson: JSON.stringify({
427
+ display_text,
428
+ id,
429
+ ...options,
430
+ }),
431
+ });
432
+ return this;
433
+ }
438
434
 
439
- addUrl(display_text = '', url = '', webview_interaction = false, options = {}) {
440
- this._buttons.push({
441
- ...options,
442
- name: 'cta_url',
443
- buttonParamsJson: JSON.stringify({
444
- display_text,
445
- url,
446
- webview_interaction,
447
- ...options,
448
- }),
449
- });
450
- return this;
451
- }
435
+ addAddress(display_text = '', id = '', options = {}) {
436
+ this._buttons.push({
437
+ name: 'address_message',
438
+ buttonParamsJson: JSON.stringify({
439
+ display_text,
440
+ id,
441
+ ...options,
442
+ }),
443
+ });
444
+ return this;
445
+ }
446
+
447
+ addLocation(options = {}) {
448
+ this._buttons.push({
449
+ name: 'send_location',
450
+ buttonParamsJson: JSON.stringify(options),
451
+ });
452
+ return this;
453
+ }
452
454
 
453
- addCopy(display_text = '', copy_code = '', options = {}) {
454
- this._buttons.push({
455
- name: 'cta_copy',
456
- buttonParamsJson: JSON.stringify({
457
- display_text,
458
- copy_code,
455
+ addUrl(display_text = '', url = '', webview_interaction = false, options = {}) {
456
+ this._buttons.push({
459
457
  ...options,
460
- }),
461
- });
462
- return this;
463
- }
458
+ name: 'cta_url',
459
+ buttonParamsJson: JSON.stringify({
460
+ display_text,
461
+ url,
462
+ webview_interaction,
463
+ ...options,
464
+ }),
465
+ });
466
+ return this;
467
+ }
464
468
 
465
- static paramsList = {
466
- limited_time_offer: {
467
- text: 'string',
468
- url: 'string',
469
- copy_code: 'string',
470
- expiration_time: 'number',
471
- },
472
- bottom_sheet: {
473
- in_thread_buttons_limit: 'number',
474
- divider_indices: ['number'],
475
- list_title: 'string',
476
- button_title: 'string',
477
- },
478
- tap_target_configuration: {
479
- title: 'string',
480
- description: 'string',
481
- canonical_url: 'string',
482
- domain: 'string',
483
- buttonIndex: 'number',
484
- },
485
- };
469
+ addCopy(display_text = '', copy_code = '', options = {}) {
470
+ this._buttons.push({
471
+ name: 'cta_copy',
472
+ buttonParamsJson: JSON.stringify({
473
+ display_text,
474
+ copy_code,
475
+ ...options,
476
+ }),
477
+ });
478
+ return this;
479
+ }
486
480
 
487
- async toCard() {
488
- return {
489
- body: {
490
- text: this._body,
491
- },
492
- footer: {
493
- text: this._footer,
481
+ static paramsList = {
482
+ limited_time_offer: {
483
+ text: 'string',
484
+ url: 'string',
485
+ copy_code: 'string',
486
+ expiration_time: 'number',
494
487
  },
495
- header: {
496
- title: this._title,
497
- subtitle: this._subtitle,
498
- hasMediaAttachment: !!this._data,
499
- ...(this._data ?
500
- await prepareWAMessageMedia(this._data, {
501
- upload: this.#client.waUploadToServer
502
- }).catch((e) => {
503
- if (String(e).includes('Invalid media type')) return this._data;
504
- throw e;
505
- }) : {}),
488
+ bottom_sheet: {
489
+ in_thread_buttons_limit: 'number',
490
+ divider_indices: ['number'],
491
+ list_title: 'string',
492
+ button_title: 'string',
506
493
  },
507
- nativeFlowMessage: {
508
- messageParamsJson: JSON.stringify(this._params),
509
- buttons: this._buttons,
494
+ tap_target_configuration: {
495
+ title: 'string',
496
+ description: 'string',
497
+ canonical_url: 'string',
498
+ domain: 'string',
499
+ buttonIndex: 'number',
510
500
  },
511
501
  };
512
- }
513
502
 
514
- async build(jid, {
515
- ...options
516
- } = {}) {
517
- const message = await this.toCard();
518
-
519
- return generateWAMessageFromContent(
520
- jid, {
521
- ...this._extraPayload,
522
- interactiveMessage: {
523
- ...message,
524
- contextInfo: this._contextInfo,
503
+ async toCard() {
504
+ return {
505
+ body: {
506
+ text: this._body,
525
507
  },
526
- }, {
527
- ...options
528
- }
529
- );
530
- }
508
+ footer: {
509
+ text: this._footer,
510
+ },
511
+ header: {
512
+ title: this._title,
513
+ subtitle: this._subtitle,
514
+ hasMediaAttachment: !!this._data,
515
+ ...(this._data ?
516
+ await prepareWAMessageMedia(this._data, {
517
+ upload: this.#client.waUploadToServer
518
+ }).catch((e) => {
519
+ if (String(e).includes('Invalid media type')) return this._data;
520
+ throw e;
521
+ }) : {}),
522
+ },
523
+ nativeFlowMessage: {
524
+ messageParamsJson: JSON.stringify(this._params),
525
+ buttons: this._buttons,
526
+ },
527
+ };
528
+ }
531
529
 
532
- async send(jid, {
533
- ...options
534
- } = {}) {
535
- const msg = await this.build(jid, options);
530
+ async build(jid, {
531
+ ...options
532
+ } = {}) {
533
+ const message = await this.toCard();
536
534
 
537
- await this.#client.relayMessage(msg.key.remoteJid, msg.message, {
538
- messageId: msg.key.id,
539
- additionalNodes: [{
540
- tag: 'biz',
541
- attrs: {},
542
- content: [{
543
- tag: 'interactive',
544
- attrs: {
545
- type: 'native_flow',
546
- v: '1'
535
+ return generateWAMessageFromContent(
536
+ jid, {
537
+ ...this._extraPayload,
538
+ interactiveMessage: {
539
+ ...message,
540
+ contextInfo: this._contextInfo,
547
541
  },
542
+ }, {
543
+ ...options
544
+ }
545
+ );
546
+ }
547
+
548
+ async send(jid, {
549
+ ...options
550
+ } = {}) {
551
+ const msg = await this.build(jid, options);
552
+
553
+ await this.#client.relayMessage(msg.key.remoteJid, msg.message, {
554
+ messageId: msg.key.id,
555
+ additionalNodes: [{
556
+ tag: 'biz',
557
+ attrs: {},
548
558
  content: [{
549
- tag: 'native_flow',
559
+ tag: 'interactive',
550
560
  attrs: {
551
- v: '9',
552
- name: 'mixed'
553
- }
554
- }],
561
+ type: 'native_flow',
562
+ v: '1'
563
+ },
564
+ content: [{
565
+ tag: 'native_flow',
566
+ attrs: {
567
+ v: '9',
568
+ name: 'mixed'
569
+ }
570
+ }],
571
+ }, ],
555
572
  }, ],
556
- }, ],
557
- ...options,
558
- });
559
- return msg;
560
- }
561
- }
562
-
563
- class ButtonV2 extends BaseBuilder {
564
- #client;
565
-
566
- constructor(client) {
567
- super();
568
- if (!client) {
569
- throw new Error('Socket is required');
573
+ ...options,
574
+ });
575
+ return msg;
570
576
  }
571
-
572
- this.#client = client;
573
- this._image;
574
- this._data;
575
- this._buttons = [];
576
577
  }
577
578
 
578
- addButton(displayText = '', buttonId = crypto.randomUUID()) {
579
- this._buttons.push({
580
- buttonId,
581
- buttonText: {
582
- displayText
583
- },
584
- type: 1,
585
- });
586
- return this;
587
- }
579
+ class ButtonV2 extends BaseBuilder {
580
+ #client;
581
+
582
+ constructor(client) {
583
+ super();
584
+ if (!client) {
585
+ throw new Error('Socket is required');
586
+ }
588
587
 
589
- addRawButton(obj) {
590
- if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
591
- throw new TypeError('Buttons must be a plain object');
588
+ this.#client = client;
589
+ this._image;
590
+ this._data;
591
+ this._buttons = [];
592
592
  }
593
593
 
594
- this._buttons.push(obj);
595
- return this;
596
- }
594
+ addButton(displayText = '', buttonId = crypto.randomUUID()) {
595
+ this._buttons.push({
596
+ buttonId,
597
+ buttonText: {
598
+ displayText
599
+ },
600
+ type: 1,
601
+ });
602
+ return this;
603
+ }
597
604
 
598
- setThumbnail(path) {
599
- if (!path) throw new Error('Url or buffer needed');
600
- this._image = path;
601
- return this;
602
- }
605
+ addRawButton(obj) {
606
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
607
+ throw new TypeError('Buttons must be a plain object');
608
+ }
603
609
 
604
- setMedia(obj) {
605
- if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
606
- throw new TypeError('Media must be a plain object');
610
+ this._buttons.push(obj);
611
+ return this;
607
612
  }
608
613
 
609
- this._data = obj;
610
- return this;
611
- }
614
+ setThumbnail(path) {
615
+ if (!path) throw new Error('Url or buffer needed');
616
+ this._image = path;
617
+ return this;
618
+ }
612
619
 
613
- async build(jid, {
614
- ...options
615
- } = {}) {
616
- let _thumbnail = this._image ? await BaseBuilder.resize(Buffer.isBuffer(this._image) ? this._image : await BaseBuilder.fetchBuffer(this._image, {}, {
617
- silent: true
618
- }), 300, 300) : null;
619
- const msg = generateWAMessageFromContent(
620
- jid, {
621
- ...this._extraPayload,
622
- buttonsMessage: {
623
- contentText: this._body,
624
- footerText: this._footer,
625
- ...(this._data ?
626
- this._data : {
627
- headerType: 6,
628
- locationMessage: {
629
- degreesLatitude: 0,
630
- degreesLongitude: 0,
631
- name: this._title,
632
- address: this._subtitle,
633
- jpegThumbnail: _thumbnail,
634
- },
635
- }),
636
- viewOnce: true,
637
- contextInfo: this._contextInfo,
638
- buttons: [...this._buttons],
639
- },
640
- }, {
641
- ...options
620
+ setMedia(obj) {
621
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
622
+ throw new TypeError('Media must be a plain object');
642
623
  }
643
- );
644
- return msg;
645
- }
646
624
 
647
- async send(jid, {
648
- ...options
649
- } = {}) {
650
- if (this._buttons.length < 1) throw new Error('ButtonV2 requires at least one button');
651
- const msg = await this.build(jid, options);
625
+ this._data = obj;
626
+ return this;
627
+ }
652
628
 
653
- await this.#client.relayMessage(msg.key.remoteJid, msg.message, {
654
- messageId: msg.key.id,
655
- additionalNodes: [{
656
- tag: 'biz',
657
- attrs: {},
658
- content: [{
659
- tag: 'interactive',
660
- attrs: {
661
- type: 'native_flow',
662
- v: '1'
629
+ async build(jid, {
630
+ ...options
631
+ } = {}) {
632
+ let _thumbnail = this._image ? await BaseBuilder.resize(Buffer.isBuffer(this._image) ? this._image : await BaseBuilder.fetchBuffer(this._image, {}, {
633
+ silent: true
634
+ }), 300, 300) : null;
635
+ const msg = generateWAMessageFromContent(
636
+ jid, {
637
+ ...this._extraPayload,
638
+ buttonsMessage: {
639
+ contentText: this._body,
640
+ footerText: this._footer,
641
+ ...(this._data ?
642
+ this._data : {
643
+ headerType: 6,
644
+ locationMessage: {
645
+ degreesLatitude: 0,
646
+ degreesLongitude: 0,
647
+ name: this._title,
648
+ address: this._subtitle,
649
+ jpegThumbnail: _thumbnail,
650
+ },
651
+ }),
652
+ viewOnce: true,
653
+ contextInfo: this._contextInfo,
654
+ buttons: [...this._buttons],
663
655
  },
656
+ }, {
657
+ ...options
658
+ }
659
+ );
660
+ return msg;
661
+ }
662
+
663
+ async send(jid, {
664
+ ...options
665
+ } = {}) {
666
+ if (this._buttons.length < 1) throw new Error('ButtonV2 requires at least one button');
667
+ const msg = await this.build(jid, options);
668
+
669
+ await this.#client.relayMessage(msg.key.remoteJid, msg.message, {
670
+ messageId: msg.key.id,
671
+ additionalNodes: [{
672
+ tag: 'biz',
673
+ attrs: {},
664
674
  content: [{
665
- tag: 'native_flow',
675
+ tag: 'interactive',
666
676
  attrs: {
667
- v: '9',
668
- name: 'mixed'
669
- }
670
- }],
677
+ type: 'native_flow',
678
+ v: '1'
679
+ },
680
+ content: [{
681
+ tag: 'native_flow',
682
+ attrs: {
683
+ v: '9',
684
+ name: 'mixed'
685
+ }
686
+ }],
687
+ }, ],
671
688
  }, ],
672
- }, ],
673
- ...options,
674
- });
675
- return msg;
676
- }
677
- }
678
-
679
- class Carousel extends BaseBuilder {
680
- #client;
681
-
682
- constructor(client) {
683
- super();
684
- if (!client) {
685
- throw new Error('Socket is required');
689
+ ...options,
690
+ });
691
+ return msg;
686
692
  }
687
-
688
- this.#client = client;
689
- this._cards = [];
690
693
  }
691
694
 
692
- addCard(card) {
693
- const cards = Array.isArray(card) ? card : [card];
694
- const baseIndex = this._cards.length;
695
+ class Carousel extends BaseBuilder {
696
+ #client;
695
697
 
696
- for (const [index, c] of cards.entries()) {
697
- if (!c?.header?.hasMediaAttachment) {
698
- throw new Error(`Card [${baseIndex + index}] must include an image or video in header`);
698
+ constructor(client) {
699
+ super();
700
+ if (!client) {
701
+ throw new Error('Socket is required');
699
702
  }
703
+
704
+ this.#client = client;
705
+ this._cards = [];
700
706
  }
701
707
 
702
- this._cards.push(...cards);
703
- return this;
704
- }
708
+ addCard(card) {
709
+ const cards = Array.isArray(card) ? card : [card];
710
+ const baseIndex = this._cards.length;
705
711
 
706
- build(jid, {
707
- ...options
708
- } = {}) {
709
- return generateWAMessageFromContent(
710
- jid, {
711
- ...this._extraPayload,
712
- interactiveMessage: {
713
- header: {
714
- hasMediaAttachment: false,
715
- },
716
- body: {
717
- text: this._body
718
- },
719
- footer: {
720
- text: this._footer
721
- },
722
- contextInfo: this._contextInfo,
723
- carouselMessage: {
724
- cards: this._cards,
725
- },
726
- },
727
- }, {
728
- ...options
712
+ for (const [index, c] of cards.entries()) {
713
+ if (!c?.header?.hasMediaAttachment) {
714
+ throw new Error(`Card [${baseIndex + index}] must include an image or video in header`);
715
+ }
729
716
  }
730
- );
731
- }
732
717
 
733
- async send(jid, {
734
- ...options
735
- } = {}) {
736
- const msg = this.build(jid, options);
718
+ this._cards.push(...cards);
719
+ return this;
720
+ }
737
721
 
738
- await this.#client.relayMessage(msg.key.remoteJid, msg.message, {
739
- messageId: msg.key.id,
740
- additionalNodes: [{
741
- tag: 'biz',
742
- attrs: {},
743
- content: [{
744
- tag: 'interactive',
745
- attrs: {
746
- type: 'native_flow',
747
- v: '1'
722
+ build(jid, {
723
+ ...options
724
+ } = {}) {
725
+ return generateWAMessageFromContent(
726
+ jid, {
727
+ ...this._extraPayload,
728
+ interactiveMessage: {
729
+ header: {
730
+ hasMediaAttachment: false,
731
+ },
732
+ body: {
733
+ text: this._body
734
+ },
735
+ footer: {
736
+ text: this._footer
737
+ },
738
+ contextInfo: this._contextInfo,
739
+ carouselMessage: {
740
+ cards: this._cards,
741
+ },
748
742
  },
743
+ }, {
744
+ ...options
745
+ }
746
+ );
747
+ }
748
+
749
+ async send(jid, {
750
+ ...options
751
+ } = {}) {
752
+ const msg = this.build(jid, options);
753
+
754
+ await this.#client.relayMessage(msg.key.remoteJid, msg.message, {
755
+ messageId: msg.key.id,
756
+ additionalNodes: [{
757
+ tag: 'biz',
758
+ attrs: {},
749
759
  content: [{
750
- tag: 'native_flow',
760
+ tag: 'interactive',
751
761
  attrs: {
752
- v: '9',
753
- name: 'mixed'
754
- }
755
- }],
762
+ type: 'native_flow',
763
+ v: '1'
764
+ },
765
+ content: [{
766
+ tag: 'native_flow',
767
+ attrs: {
768
+ v: '9',
769
+ name: 'mixed'
770
+ }
771
+ }],
772
+ }, ],
756
773
  }, ],
757
- }, ],
758
- ...options,
759
- });
760
- return msg;
774
+ ...options,
775
+ });
776
+ return msg;
777
+ }
761
778
  }
762
- }
763
779
 
764
- class AIRich extends BaseBuilder {
765
- #client;
780
+ class AIRich extends BaseBuilder {
781
+ #client;
766
782
 
767
- constructor(client) {
768
- if (!client) {
769
- throw new Error('Socket is required');
770
- }
783
+ constructor(client) {
784
+ if (!client) {
785
+ throw new Error('Socket is required');
786
+ }
771
787
 
772
- super();
773
- this.#client = client;
774
- this._contextInfo = {};
775
- this._submessages = [];
776
- this._sections = [];
777
- this._richResponseSources = [];
778
- }
788
+ super();
789
+ this.#client = client;
790
+ this._contextInfo = {};
791
+ this._submessages = [];
792
+ this._sections = [];
793
+ this._richResponseSources = [];
794
+ }
779
795
 
780
- static newLayout(name, data) {
781
- return {
782
- view_model: {
783
- [Array.isArray(data) ? 'primitives' : 'primitive']: data,
784
- __typename: `GenAI${name}LayoutViewModel`,
785
- },
786
- };
787
- }
796
+ static newLayout(name, data) {
797
+ return {
798
+ view_model: {
799
+ [Array.isArray(data) ? 'primitives' : 'primitive']: data,
800
+ __typename: `GenAI${name}LayoutViewModel`,
801
+ },
802
+ };
803
+ }
788
804
 
789
- addSubmessage(submessage) {
790
- const items = Array.isArray(submessage) ? submessage : [submessage];
805
+ addSubmessage(submessage) {
806
+ const items = Array.isArray(submessage) ? submessage : [submessage];
807
+
808
+ for (const item of items) {
809
+ if (typeof item !== 'object' || item === null || Array.isArray(item)) {
810
+ throw new TypeError('Submessage must be a plain object or array of plain objects');
811
+ }
791
812
 
792
- for (const item of items) {
793
- if (typeof item !== 'object' || item === null || Array.isArray(item)) {
794
- throw new TypeError('Submessage must be a plain object or array of plain objects');
813
+ this._submessages.push(item);
795
814
  }
796
815
 
797
- this._submessages.push(item);
816
+ return this;
798
817
  }
799
818
 
800
- return this;
801
- }
819
+ addSection(section) {
820
+ const items = Array.isArray(section) ? section : [section];
802
821
 
803
- addSection(section) {
804
- const items = Array.isArray(section) ? section : [section];
822
+ for (const item of items) {
823
+ if (typeof item !== 'object' || item === null || Array.isArray(item)) {
824
+ throw new TypeError('Section must be a plain object or array of plain objects');
825
+ }
805
826
 
806
- for (const item of items) {
807
- if (typeof item !== 'object' || item === null || Array.isArray(item)) {
808
- throw new TypeError('Section must be a plain object or array of plain objects');
827
+ this._sections.push(item);
809
828
  }
810
829
 
811
- this._sections.push(item);
830
+ return this;
812
831
  }
813
832
 
814
- return this;
815
- }
833
+ addText(text, {
834
+ hyperlink = true,
835
+ citation = true,
836
+ latex = true
837
+ } = {}) {
838
+ if (typeof text != 'string') {
839
+ throw new TypeError('Text must be a string');
840
+ }
816
841
 
817
- addText(text, {
818
- hyperlink = true,
819
- citation = true,
820
- latex = true
821
- } = {}) {
822
- if (typeof text != 'string') {
823
- throw new TypeError('Text must be a string');
824
- }
842
+ const extractedIE = extractIE(text, {
843
+ hyperlink,
844
+ citation,
845
+ latex,
846
+ });
847
+
848
+ const inline_entities = extractedIE.ie.map(({
849
+ type,
850
+ ie
851
+ }) => {
852
+ if (type == 'hyperlink') {
853
+ return {
854
+ key: ie.key,
855
+ metadata: {
856
+ display_name: ie.text,
857
+ is_trusted: true,
858
+ url: ie.url,
859
+ __typename: 'GenAIInlineLinkItem',
860
+ },
861
+ };
862
+ }
863
+ if (type == 'citation') {
864
+ return {
865
+ key: ie.key,
866
+ metadata: {
867
+ reference_id: ie.reference_id,
868
+ reference_url: ie.url,
869
+ reference_title: ie.url,
870
+ reference_display_name: ie.url,
871
+ sources: [],
872
+ __typename: 'GenAISearchCitationItem',
873
+ },
874
+ };
875
+ }
876
+ if (type == 'latex') {
877
+ return {
878
+ key: ie.key,
879
+ metadata: {
880
+ latex_expression: ie.text,
881
+ latex_image: {
882
+ url: ie.url,
883
+ width: Number(ie.width) || 100,
884
+ height: Number(ie.height) || 100,
885
+ },
886
+ font_height: Number(ie.font_height) || 83.333333333333,
887
+ padding: Number(ie.padding) || 15,
888
+ __typename: 'GenAILatexItem',
889
+ },
890
+ };
891
+ }
825
892
 
826
- const extractedIE = extractIE(text, {
827
- hyperlink,
828
- citation,
829
- latex,
830
- });
831
-
832
- const inline_entities = extractedIE.ie.map(({
833
- type,
834
- ie
835
- }) => {
836
- if (type == 'hyperlink') {
837
- return {
838
- key: ie.key,
839
- metadata: {
840
- display_name: ie.text,
841
- is_trusted: true,
842
- url: ie.url,
843
- __typename: 'GenAIInlineLinkItem',
844
- },
845
- };
846
- }
847
- if (type == 'citation') {
848
- return {
849
- key: ie.key,
850
- metadata: {
851
- reference_id: ie.reference_id,
852
- reference_url: ie.url,
853
- reference_title: ie.url,
854
- reference_display_name: ie.url,
855
- sources: [],
856
- __typename: 'GenAISearchCitationItem',
857
- },
858
- };
859
- }
860
- if (type == 'latex') {
861
893
  return {
862
894
  key: ie.key,
863
895
  metadata: {
864
896
  latex_expression: ie.text,
865
897
  latex_image: {
866
898
  url: ie.url,
867
- width: Number(ie.width) || 100,
868
- height: Number(ie.height) || 100,
899
+ width,
900
+ height,
869
901
  },
870
902
  font_height: Number(ie.font_height) || 83.333333333333,
871
903
  padding: Number(ie.padding) || 15,
872
904
  __typename: 'GenAILatexItem',
873
905
  },
874
906
  };
907
+ });
908
+
909
+ this._submessages.push({
910
+ messageType: 2,
911
+ messageText: extractedIE.text,
912
+ });
913
+
914
+ this._sections.push(
915
+ AIRich.newLayout('Single', {
916
+ text: extractedIE.text,
917
+ ...(inline_entities.length && {
918
+ inline_entities,
919
+ }),
920
+ __typename: 'GenAIMarkdownTextUXPrimitive',
921
+ })
922
+ );
923
+
924
+ return this;
925
+ }
926
+
927
+ addCode(language, code) {
928
+ if (typeof language !== 'string' || typeof code !== 'string') {
929
+ throw new TypeError('Language and code must be a string');
875
930
  }
876
931
 
877
- return {
878
- key: ie.key,
879
- metadata: {
880
- latex_expression: ie.text,
881
- latex_image: {
882
- url: ie.url,
883
- width,
884
- height,
885
- },
886
- font_height: Number(ie.font_height) || 83.333333333333,
887
- padding: Number(ie.padding) || 15,
888
- __typename: 'GenAILatexItem',
932
+ const meta = AIRich.tokenizer(code, language);
933
+
934
+ this._submessages.push({
935
+ messageType: 5,
936
+ codeMetadata: {
937
+ codeLanguage: language,
938
+ codeBlocks: meta.codeBlock,
889
939
  },
890
- };
891
- });
892
-
893
- this._submessages.push({
894
- messageType: 2,
895
- messageText: extractedIE.text,
896
- });
897
-
898
- this._sections.push(
899
- AIRich.newLayout('Single', {
900
- text: extractedIE.text,
901
- ...(inline_entities.length && {
902
- inline_entities,
903
- }),
904
- __typename: 'GenAIMarkdownTextUXPrimitive',
905
- })
906
- );
940
+ });
907
941
 
908
- return this;
909
- }
942
+ this._sections.push(
943
+ AIRich.newLayout('Single', {
944
+ language,
945
+ code_blocks: meta.unified_codeBlock,
946
+ __typename: 'GenAICodeUXPrimitive',
947
+ })
948
+ );
910
949
 
911
- addCode(language, code) {
912
- if (typeof language !== 'string' || typeof code !== 'string') {
913
- throw new TypeError('Language and code must be a string');
950
+ return this;
914
951
  }
915
952
 
916
- const meta = AIRich.tokenizer(code, language);
953
+ addTable(table) {
954
+ if (!Array.isArray(table)) {
955
+ throw new TypeError('Table must be an array');
956
+ }
917
957
 
918
- this._submessages.push({
919
- messageType: 5,
920
- codeMetadata: {
921
- codeLanguage: language,
922
- codeBlocks: meta.codeBlock,
923
- },
924
- });
958
+ const meta = AIRich.toTableMetadata(table);
925
959
 
926
- this._sections.push(
927
- AIRich.newLayout('Single', {
928
- language,
929
- code_blocks: meta.unified_codeBlock,
930
- __typename: 'GenAICodeUXPrimitive',
931
- })
932
- );
960
+ this._submessages.push({
961
+ messageType: 4,
962
+ tableMetadata: {
963
+ title: meta.title,
964
+ rows: meta.rows,
965
+ },
966
+ });
933
967
 
934
- return this;
935
- }
968
+ this._sections.push(
969
+ AIRich.newLayout('Single', {
970
+ rows: meta.unified_rows,
971
+ __typename: 'GenATableUXPrimitive',
972
+ })
973
+ );
936
974
 
937
- addTable(table) {
938
- if (!Array.isArray(table)) {
939
- throw new TypeError('Table must be an array');
975
+ return this;
940
976
  }
941
977
 
942
- const meta = AIRich.toTableMetadata(table);
943
978
 
944
- this._submessages.push({
945
- messageType: 4,
946
- tableMetadata: {
947
- title: meta.title,
948
- rows: meta.rows,
949
- },
950
- });
979
+ addSource(sources = []) {
980
+ if (!(Array.isArray(sources) && (sources.every((item) => typeof item === 'string') || sources.every((item) => Array.isArray(item) && item.every((v) => typeof v === 'string'))))) {
981
+ throw new TypeError('Sources must be a string array or an array of string arrays');
982
+ }
951
983
 
952
- this._sections.push(
953
- AIRich.newLayout('Single', {
954
- rows: meta.unified_rows,
955
- __typename: 'GenATableUXPrimitive',
956
- })
957
- );
984
+ if (sources.every((item) => typeof item === 'string')) {
985
+ sources = [sources];
986
+ }
958
987
 
959
- return this;
960
- }
988
+ const source = sources.map(([profile_url, url, text]) => ({
989
+ source_type: 'THIRD_PARTY',
990
+ source_display_name: text ?? '',
991
+ source_subtitle: 'AI',
992
+ source_url: url ?? '',
993
+ favicon: {
994
+ url: profile_url ?? '',
995
+ mime_type: 'image/jpeg',
996
+ width: 16,
997
+ height: 16,
998
+ },
999
+ }));
961
1000
 
1001
+ this._sections.push(
1002
+ AIRich.newLayout('Single', {
1003
+ sources: source,
1004
+ __typename: 'GenAISearchResultPrimitive',
1005
+ })
1006
+ );
962
1007
 
963
- addSource(sources = []) {
964
- if (!(Array.isArray(sources) && (sources.every((item) => typeof item === 'string') || sources.every((item) => Array.isArray(item) && item.every((v) => typeof v === 'string'))))) {
965
- throw new TypeError('Sources must be a string array or an array of string arrays');
1008
+ return this;
966
1009
  }
967
1010
 
968
- if (sources.every((item) => typeof item === 'string')) {
969
- sources = [sources];
970
- }
1011
+ addReels(reelsItems = []) {
1012
+ if (
1013
+ !(
1014
+ (reelsItems && typeof reelsItems === 'object' && !Array.isArray(reelsItems)) ||
1015
+ (Array.isArray(reelsItems) && reelsItems.every((item) => item && typeof item === 'object' && !Array.isArray(item)))
1016
+ )
1017
+ ) {
1018
+ throw new TypeError('Reels items must be an object or an array of objects');
1019
+ }
971
1020
 
972
- const source = sources.map(([profile_url, url, text]) => ({
973
- source_type: 'THIRD_PARTY',
974
- source_display_name: text ?? '',
975
- source_subtitle: 'AI',
976
- source_url: url ?? '',
977
- favicon: {
978
- url: profile_url ?? '',
979
- mime_type: 'image/jpeg',
980
- width: 16,
981
- height: 16,
982
- },
983
- }));
1021
+ if (!Array.isArray(reelsItems)) {
1022
+ reelsItems = [reelsItems];
1023
+ }
984
1024
 
985
- this._sections.push(
986
- AIRich.newLayout('Single', {
987
- sources: source,
988
- __typename: 'GenAISearchResultPrimitive',
989
- })
990
- );
1025
+ this._submessages.push({
1026
+ messageType: 9,
1027
+ contentItemsMetadata: {
1028
+ contentType: 1,
1029
+ itemsMetadata: reelsItems.map((item) => ({
1030
+ reelItem: {
1031
+ title: item.username ?? '',
1032
+ profileIconUrl: item.profileIconUrl ?? item.profile_url ?? '',
1033
+ thumbnailUrl: item.thumbnailUrl ?? item.thumbnail ?? '',
1034
+ videoUrl: item.videoUrl ?? item.url ?? '',
1035
+ },
1036
+ })),
1037
+ },
1038
+ });
991
1039
 
992
- return this;
993
- }
1040
+ reelsItems.forEach((item, idx) => {
1041
+ this._richResponseSources.push({
1042
+ provider: '\u004E\u0049\u0058\u0045\u004C',
1043
+ thumbnailCDNURL: item.thumbnailUrl ?? item.thumbnail ?? '',
1044
+ sourceProviderURL: item.videoUrl ?? item.url ?? '',
1045
+ sourceQuery: '',
1046
+ faviconCDNURL: item.profileIconUrl ?? item.profile_url ?? '',
1047
+ citationNumber: idx + 1,
1048
+ sourceTitle: item.username ?? '',
1049
+ });
1050
+ });
994
1051
 
995
- addReels(reelsItems = []) {
996
- if (
997
- !(
998
- (reelsItems && typeof reelsItems === 'object' && !Array.isArray(reelsItems)) ||
999
- (Array.isArray(reelsItems) && reelsItems.every((item) => item && typeof item === 'object' && !Array.isArray(item)))
1000
- )
1001
- ) {
1002
- throw new TypeError('Reels items must be an object or an array of objects');
1003
- }
1052
+ this._sections.push(
1053
+ AIRich.newLayout(
1054
+ 'HScroll',
1055
+ reelsItems.map((item) => ({
1056
+ reels_url: item.videoUrl ?? item.url ?? '',
1057
+ thumbnail_url: item.thumbnailUrl ?? item.thumbnail ?? '',
1058
+ creator: item.username ?? item.title ?? '',
1059
+ avatar_url: item.profileIconUrl ?? item.profile_url ?? '',
1060
+ reels_title: item.reels_title ?? item.title ?? '',
1061
+ likes_count: item.likes_count ?? item.like ?? 0,
1062
+ shares_count: item.shares_count ?? item.share ?? 0,
1063
+ view_count: item.view_count ?? item.view ?? 0,
1064
+ reel_source: item.reel_source ?? item.source ?? 'IG',
1065
+ is_verified: !!(item.is_verified || item.verified),
1066
+ __typename: 'GenAIReelPrimitive',
1067
+ }))
1068
+ )
1069
+ );
1004
1070
 
1005
- if (!Array.isArray(reelsItems)) {
1006
- reelsItems = [reelsItems];
1071
+ return this;
1007
1072
  }
1008
1073
 
1009
- this._submessages.push({
1010
- messageType: 9,
1011
- contentItemsMetadata: {
1012
- contentType: 1,
1013
- itemsMetadata: reelsItems.map((item) => ({
1014
- reelItem: {
1015
- title: item.username ?? '',
1016
- profileIconUrl: item.profileIconUrl ?? item.profile_url ?? '',
1017
- thumbnailUrl: item.thumbnailUrl ?? item.thumbnail ?? '',
1018
- videoUrl: item.videoUrl ?? item.url ?? '',
1074
+ addImage(imageUrl) {
1075
+ if (!(typeof imageUrl === 'string' || (Array.isArray(imageUrl) && imageUrl.every((v) => typeof v === 'string')))) {
1076
+ throw new TypeError('imageUrl must be a string or array of strings');
1077
+ }
1078
+ const imageUrls = Array.isArray(imageUrl) ?
1079
+ imageUrl.map((url) => ({
1080
+ imagePreviewUrl: url,
1081
+ imageHighResUrl: url,
1082
+ sourceUrl: String.fromCharCode(104, 116, 116, 112, 115, 58, 47, 47, 102, 105, 111, 114, 97, 46, 110, 105, 120, 101, 108, 46, 109, 121, 46, 105, 100, 47),
1083
+ })) : [{
1084
+ imagePreviewUrl: imageUrl,
1085
+ imageHighResUrl: imageUrl,
1086
+ sourceUrl: String.fromCharCode(104, 116, 116, 112, 115, 58, 47, 47, 102, 105, 111, 114, 97, 46, 110, 105, 120, 101, 108, 46, 109, 121, 46, 105, 100, 47),
1087
+ }, ];
1088
+
1089
+ this._submessages.push({
1090
+ messageType: 1,
1091
+ gridImageMetadata: {
1092
+ gridImageUrl: {
1093
+ imagePreviewUrl: Array.isArray(imageUrl) ? imageUrl[0] : imageUrl,
1019
1094
  },
1020
- })),
1021
- },
1022
- });
1023
-
1024
- reelsItems.forEach((item, idx) => {
1025
- this._richResponseSources.push({
1026
- provider: '\u004E\u0049\u0058\u0045\u004C',
1027
- thumbnailCDNURL: item.thumbnailUrl ?? item.thumbnail ?? '',
1028
- sourceProviderURL: item.videoUrl ?? item.url ?? '',
1029
- sourceQuery: '',
1030
- faviconCDNURL: item.profileIconUrl ?? item.profile_url ?? '',
1031
- citationNumber: idx + 1,
1032
- sourceTitle: item.username ?? '',
1095
+ imageUrls,
1096
+ },
1033
1097
  });
1034
- });
1035
-
1036
- this._sections.push(
1037
- AIRich.newLayout(
1038
- 'HScroll',
1039
- reelsItems.map((item) => ({
1040
- reels_url: item.videoUrl ?? item.url ?? '',
1041
- thumbnail_url: item.thumbnailUrl ?? item.thumbnail ?? '',
1042
- creator: item.username ?? item.title ?? '',
1043
- avatar_url: item.profileIconUrl ?? item.profile_url ?? '',
1044
- reels_title: item.reels_title ?? item.title ?? '',
1045
- likes_count: item.likes_count ?? item.like ?? 0,
1046
- shares_count: item.shares_count ?? item.share ?? 0,
1047
- view_count: item.view_count ?? item.view ?? 0,
1048
- reel_source: item.reel_source ?? item.source ?? 'IG',
1049
- is_verified: !!(item.is_verified || item.verified),
1050
- __typename: 'GenAIReelPrimitive',
1051
- }))
1052
- )
1053
- );
1054
1098
 
1055
- return this;
1056
- }
1099
+ imageUrls.forEach(({
1100
+ imagePreviewUrl
1101
+ }) => {
1102
+ this._sections.push(
1103
+ AIRich.newLayout('Single', {
1104
+ media: {
1105
+ url: imagePreviewUrl,
1106
+ mime_type: 'image/png',
1107
+ },
1108
+ imagine_type: 'IMAGE',
1109
+ status: {
1110
+ status: 'READY',
1111
+ },
1112
+ __typename: 'GenAIImaginePrimitive',
1113
+ })
1114
+ );
1115
+ });
1057
1116
 
1058
- addImage(imageUrl) {
1059
- if (!(typeof imageUrl === 'string' || (Array.isArray(imageUrl) && imageUrl.every((v) => typeof v === 'string')))) {
1060
- throw new TypeError('imageUrl must be a string or array of strings');
1117
+ return this;
1061
1118
  }
1062
- const imageUrls = Array.isArray(imageUrl) ?
1063
- imageUrl.map((url) => ({
1064
- imagePreviewUrl: url,
1065
- imageHighResUrl: url,
1066
- sourceUrl: String.fromCharCode(104, 116, 116, 112, 115, 58, 47, 47, 102, 105, 111, 114, 97, 46, 110, 105, 120, 101, 108, 46, 109, 121, 46, 105, 100, 47),
1067
- })) : [{
1068
- imagePreviewUrl: imageUrl,
1069
- imageHighResUrl: imageUrl,
1070
- sourceUrl: String.fromCharCode(104, 116, 116, 112, 115, 58, 47, 47, 102, 105, 111, 114, 97, 46, 110, 105, 120, 101, 108, 46, 109, 121, 46, 105, 100, 47),
1071
- }, ];
1072
1119
 
1073
- this._submessages.push({
1074
- messageType: 1,
1075
- gridImageMetadata: {
1076
- gridImageUrl: {
1077
- imagePreviewUrl: Array.isArray(imageUrl) ? imageUrl[0] : imageUrl,
1078
- },
1079
- imageUrls,
1080
- },
1081
- });
1120
+ addVideo(videoUrl) {
1121
+ if (!(typeof videoUrl === 'string' || (Array.isArray(videoUrl) && videoUrl.every((v) => typeof v === 'string')))) {
1122
+ throw new TypeError('videoUrl must be a string or array of strings');
1123
+ }
1082
1124
 
1083
- imageUrls.forEach(({
1084
- imagePreviewUrl
1085
- }) => {
1086
- this._sections.push(
1087
- AIRich.newLayout('Single', {
1088
- media: {
1089
- url: imagePreviewUrl,
1090
- mime_type: 'image/png',
1091
- },
1092
- imagine_type: 'IMAGE',
1093
- status: {
1094
- status: 'READY',
1095
- },
1096
- __typename: 'GenAIImaginePrimitive',
1097
- })
1098
- );
1099
- });
1125
+ const videoUrls = (Array.isArray(videoUrl) ? videoUrl : [videoUrl]).map((item) => {
1126
+ const [url, duration = 0] = item.split('|');
1100
1127
 
1101
- return this;
1102
- }
1128
+ return {
1129
+ videoPreviewUrl: url,
1130
+ videoHighResUrl: url,
1131
+ duration: Number(duration) || 0,
1132
+ sourceUrl: String.fromCharCode(104, 116, 116, 112, 115, 58, 47, 47, 102, 105, 111, 114, 97, 46, 110, 105, 120, 101, 108, 46, 109, 121, 46, 105, 100, 47),
1133
+ };
1134
+ });
1135
+
1136
+ this._submessages.push({
1137
+ messageType: 2,
1138
+ messageText: '[ CANNOT_LOAD_VIDEO - \u0052\u0059\u0055\u0055 ]',
1139
+ });
1140
+
1141
+ videoUrls.forEach(({
1142
+ videoPreviewUrl,
1143
+ duration = 0
1144
+ }) => {
1145
+ this._sections.push(
1146
+ AIRich.newLayout('Single', {
1147
+ media: {
1148
+ url: videoPreviewUrl,
1149
+ mime_type: 'video/mp4',
1150
+ duration,
1151
+ },
1152
+ imagine_type: 'ANIMATE',
1153
+ status: {
1154
+ status: 'READY',
1155
+ },
1156
+ __typename: 'GenAIImaginePrimitive',
1157
+ })
1158
+ );
1159
+ });
1103
1160
 
1104
- addVideo(videoUrl) {
1105
- if (!(typeof videoUrl === 'string' || (Array.isArray(videoUrl) && videoUrl.every((v) => typeof v === 'string')))) {
1106
- throw new TypeError('videoUrl must be a string or array of strings');
1161
+ return this;
1107
1162
  }
1108
1163
 
1109
- const videoUrls = (Array.isArray(videoUrl) ? videoUrl : [videoUrl]).map((item) => {
1110
- const [url, duration = 0] = item.split('|');
1164
+ addProduct(data = {}) {
1165
+ if (!((data && typeof data === 'object' && !Array.isArray(data)) || (Array.isArray(data) && data.every((item) => item && typeof item === 'object' && !Array.isArray(item))))) {
1166
+ throw new TypeError('Product items must be an object or an array of objects');
1167
+ }
1111
1168
 
1112
- return {
1113
- videoPreviewUrl: url,
1114
- videoHighResUrl: url,
1115
- duration: Number(duration) || 0,
1116
- sourceUrl: String.fromCharCode(104, 116, 116, 112, 115, 58, 47, 47, 102, 105, 111, 114, 97, 46, 110, 105, 120, 101, 108, 46, 109, 121, 46, 105, 100, 47),
1117
- };
1118
- });
1169
+ this._submessages.push({
1170
+ messageType: 2,
1171
+ messageText: '[ CANNOT_LOAD_PRODUCT - \u0052\u0059\u0055\u0055 ]',
1172
+ });
1119
1173
 
1120
- this._submessages.push({
1121
- messageType: 2,
1122
- messageText: '[ CANNOT_LOAD_VIDEO - \u0052\u0059\u0055\u0055 ]',
1123
- });
1174
+ const items = Array.isArray(data) ? data : [data];
1124
1175
 
1125
- videoUrls.forEach(({
1126
- videoPreviewUrl,
1127
- duration = 0
1128
- }) => {
1129
- this._sections.push(
1130
- AIRich.newLayout('Single', {
1131
- media: {
1132
- url: videoPreviewUrl,
1133
- mime_type: 'video/mp4',
1134
- duration,
1135
- },
1136
- imagine_type: 'ANIMATE',
1137
- status: {
1138
- status: 'READY',
1139
- },
1140
- __typename: 'GenAIImaginePrimitive',
1141
- })
1142
- );
1143
- });
1176
+ const product = items.map((item) => ({
1177
+ title: item.title,
1178
+ brand: item.brand,
1179
+ price: item.price,
1180
+ sale_price: item.sale_price,
1181
+ product_url: item.product_url ?? item.url,
1182
+ image: {
1183
+ url: item.image_url ?? item.image,
1184
+ },
1185
+ additional_images: [{
1186
+ url: item.icon_url ?? item.icon,
1187
+ }, ],
1188
+ __typename: 'GenAIProductItemCardPrimitive',
1189
+ }));
1144
1190
 
1145
- return this;
1146
- }
1191
+ this._sections.push(AIRich.newLayout(Array.isArray(data) ? 'HScroll' : 'Single', Array.isArray(data) ? product : product[0]));
1147
1192
 
1148
- addProduct(data = {}) {
1149
- if (!((data && typeof data === 'object' && !Array.isArray(data)) || (Array.isArray(data) && data.every((item) => item && typeof item === 'object' && !Array.isArray(item))))) {
1150
- throw new TypeError('Product items must be an object or an array of objects');
1193
+ return this;
1151
1194
  }
1152
1195
 
1153
- this._submessages.push({
1154
- messageType: 2,
1155
- messageText: '[ CANNOT_LOAD_PRODUCT - \u0052\u0059\u0055\u0055 ]',
1156
- });
1157
-
1158
- const items = Array.isArray(data) ? data : [data];
1159
-
1160
- const product = items.map((item) => ({
1161
- title: item.title,
1162
- brand: item.brand,
1163
- price: item.price,
1164
- sale_price: item.sale_price,
1165
- product_url: item.product_url ?? item.url,
1166
- image: {
1167
- url: item.image_url ?? item.image,
1168
- },
1169
- additional_images: [{
1170
- url: item.icon_url ?? item.icon,
1171
- }, ],
1172
- __typename: 'GenAIProductItemCardPrimitive',
1173
- }));
1196
+ addPost(data = {}) {
1197
+ if (!((data && typeof data === 'object' && !Array.isArray(data)) || (Array.isArray(data) && data.every((item) => item && typeof item === 'object' && !Array.isArray(item))))) {
1198
+ throw new TypeError('Post items must be an object or an array of objects');
1199
+ }
1174
1200
 
1175
- this._sections.push(AIRich.newLayout(Array.isArray(data) ? 'HScroll' : 'Single', Array.isArray(data) ? product : product[0]));
1201
+ const posts = Array.isArray(data) ? data : [data];
1176
1202
 
1177
- return this;
1178
- }
1203
+ this._submessages.push({
1204
+ messageType: 2,
1205
+ messageText: '[ CANNOT_LOAD_POST - \u0052\u0059\u0055\u0055 ]',
1206
+ });
1179
1207
 
1180
- addPost(data = {}) {
1181
- if (!((data && typeof data === 'object' && !Array.isArray(data)) || (Array.isArray(data) && data.every((item) => item && typeof item === 'object' && !Array.isArray(item))))) {
1182
- throw new TypeError('Post items must be an object or an array of objects');
1208
+ const primitives = posts.map((p) => ({
1209
+ title: p.title ?? '',
1210
+ subtitle: p.subtitle ?? '',
1211
+ username: p.username ?? '',
1212
+ profile_picture_url: p.profile_picture_url ?? p.profile_url ?? '',
1213
+ is_verified: !!(p.is_verified || p.verified),
1214
+ thumbnail_url: p.thumbnail_url ?? p.thumbnail ?? '',
1215
+ post_caption: p.post_caption ?? p.caption ?? '',
1216
+ likes_count: p.likes_count ?? p.like ?? 0,
1217
+ comments_count: p.comments_count ?? p.comment ?? 0,
1218
+ shares_count: p.shares_count ?? p.share ?? 0,
1219
+ post_url: p.post_url ?? p.url ?? '',
1220
+ post_deeplink: p.post_deeplink ?? p.deeplink ?? '',
1221
+ source_app: p.source_app || p.source || 'INSTAGRAM',
1222
+ footer_label: p.footer_label ?? p.footer ?? '',
1223
+ footer_icon: p.footer_icon ?? p.icon ?? '',
1224
+ is_carousel: posts.length > 1,
1225
+ orientation: p.orientation ?? 'LANDSCAPE',
1226
+ post_type: p.post_type ?? 'VIDEO',
1227
+ __typename: 'GenAIPostPrimitive',
1228
+ }));
1229
+
1230
+ this._sections.push(AIRich.newLayout('HScroll', primitives));
1231
+
1232
+ return this;
1183
1233
  }
1184
1234
 
1185
- const posts = Array.isArray(data) ? data : [data];
1186
-
1187
- this._submessages.push({
1188
- messageType: 2,
1189
- messageText: '[ CANNOT_LOAD_POST - \u0052\u0059\u0055\u0055 ]',
1190
- });
1191
-
1192
- const primitives = posts.map((p) => ({
1193
- title: p.title ?? '',
1194
- subtitle: p.subtitle ?? '',
1195
- username: p.username ?? '',
1196
- profile_picture_url: p.profile_picture_url ?? p.profile_url ?? '',
1197
- is_verified: !!(p.is_verified || p.verified),
1198
- thumbnail_url: p.thumbnail_url ?? p.thumbnail ?? '',
1199
- post_caption: p.post_caption ?? p.caption ?? '',
1200
- likes_count: p.likes_count ?? p.like ?? 0,
1201
- comments_count: p.comments_count ?? p.comment ?? 0,
1202
- shares_count: p.shares_count ?? p.share ?? 0,
1203
- post_url: p.post_url ?? p.url ?? '',
1204
- post_deeplink: p.post_deeplink ?? p.deeplink ?? '',
1205
- source_app: p.source_app || p.source || 'INSTAGRAM',
1206
- footer_label: p.footer_label ?? p.footer ?? '',
1207
- footer_icon: p.footer_icon ?? p.icon ?? '',
1208
- is_carousel: posts.length > 1,
1209
- orientation: p.orientation ?? 'LANDSCAPE',
1210
- post_type: p.post_type ?? 'VIDEO',
1211
- __typename: 'GenAIPostPrimitive',
1212
- }));
1213
-
1214
- this._sections.push(AIRich.newLayout('HScroll', primitives));
1215
-
1216
- return this;
1217
- }
1218
-
1219
- addTip(text) {
1220
- this._submessages.push({
1221
- messageType: 2,
1222
- messageText: text,
1223
- });
1224
-
1225
- this._sections.push(
1226
- AIRich.newLayout('Single', {
1227
- text,
1228
- __typename: 'GenAIMetadataTextPrimitive',
1229
- })
1230
- );
1235
+ addTip(text) {
1236
+ this._submessages.push({
1237
+ messageType: 2,
1238
+ messageText: text,
1239
+ });
1231
1240
 
1232
- return this;
1233
- }
1241
+ this._sections.push(
1242
+ AIRich.newLayout('Single', {
1243
+ text,
1244
+ __typename: 'GenAIMetadataTextPrimitive',
1245
+ })
1246
+ );
1234
1247
 
1235
- addSuggest(suggestion) {
1236
- if (!(typeof suggestion === 'string' || (Array.isArray(suggestion) && suggestion.every((v) => typeof v === 'string')))) {
1237
- throw new TypeError('Suggestion must be a string or array of strings');
1248
+ return this;
1238
1249
  }
1239
1250
 
1240
- const suggest = Array.isArray(suggestion) ?
1241
- suggestion.map((text) => ({
1242
- prompt_text: text,
1243
- prompt_type: 'SUGGESTED_PROMPT',
1244
- __typename: 'GenAIFollowUpSuggestionPillPrimitive',
1245
- })) : [{
1246
- prompt_text: suggestion,
1247
- prompt_type: 'SUGGESTED_PROMPT',
1248
- __typename: 'GenAIFollowUpSuggestionPillPrimitive',
1249
- }, ];
1251
+ addSuggest(suggestion) {
1252
+ if (!(typeof suggestion === 'string' || (Array.isArray(suggestion) && suggestion.every((v) => typeof v === 'string')))) {
1253
+ throw new TypeError('Suggestion must be a string or array of strings');
1254
+ }
1250
1255
 
1251
- this._sections.push(AIRich.newLayout('ActionRow', suggest));
1256
+ const suggest = Array.isArray(suggestion) ?
1257
+ suggestion.map((text) => ({
1258
+ prompt_text: text,
1259
+ prompt_type: 'SUGGESTED_PROMPT',
1260
+ __typename: 'GenAIFollowUpSuggestionPillPrimitive',
1261
+ })) : [{
1262
+ prompt_text: suggestion,
1263
+ prompt_type: 'SUGGESTED_PROMPT',
1264
+ __typename: 'GenAIFollowUpSuggestionPillPrimitive',
1265
+ }, ];
1252
1266
 
1253
- return this;
1254
- }
1267
+ this._sections.push(AIRich.newLayout('ActionRow', suggest));
1255
1268
 
1256
- build({
1257
- forwarded = true,
1258
- includesUnifiedResponse = true,
1259
- includesSubmessages = true,
1260
- quoted,
1261
- quotedParticipant,
1262
- ...options
1263
- } = {}) {
1264
- const forward = forwarded ? {
1265
- forwardingScore: 1,
1266
- isForwarded: true,
1267
- forwardedAiBotMessageInfo: {
1268
- botJid: '0@bot'
1269
- },
1270
- forwardOrigin: 4,
1271
- } : {};
1272
-
1273
- const qObj = quoted ? {
1274
- stanzaId: quoted?.key?.id || quoted?.id,
1275
- participant: quotedParticipant || quoted?.key?.participant || quoted?.key?.remoteJid,
1276
- quotedType: 0,
1277
- quotedMessage: typeof quoted === 'object' && quoted !== null ? (quoted.message ?? quoted) : undefined,
1278
- } : {};
1279
-
1280
- const sections = this._footer ? [
1281
- ...this._sections,
1282
- AIRich.newLayout('Single', {
1283
- text: this._footer,
1284
- __typename: 'GenAIMetadataTextPrimitive',
1285
- }),
1286
- ] : [...this._sections];
1269
+ return this;
1270
+ }
1287
1271
 
1288
- return {
1289
- messageContextInfo: {
1290
- deviceListMetadata: {},
1291
- deviceListMetadataVersion: 2,
1292
- botMetadata: {
1293
- messageDisclaimerText: this._title,
1294
- richResponseSourcesMetadata: {
1295
- sources: this._richResponseSources
1296
- },
1272
+ build({
1273
+ forwarded = true,
1274
+ includesUnifiedResponse = true,
1275
+ includesSubmessages = true,
1276
+ quoted,
1277
+ quotedParticipant,
1278
+ ...options
1279
+ } = {}) {
1280
+ const forward = forwarded ? {
1281
+ forwardingScore: 1,
1282
+ isForwarded: true,
1283
+ forwardedAiBotMessageInfo: {
1284
+ botJid: '0@bot'
1297
1285
  },
1298
- },
1299
- ...this._extraPayload,
1300
- botForwardedMessage: {
1301
- message: {
1302
- richResponseMessage: {
1303
- messageType: 1,
1304
- submessages: includesSubmessages ? this._submessages : [],
1305
- unifiedResponse: {
1306
- data: includesUnifiedResponse ? Buffer.from(JSON.stringify({
1307
- response_id: crypto.randomUUID(),
1308
- sections
1309
- })).toString("base64") : ''
1286
+ forwardOrigin: 4,
1287
+ } : {};
1288
+
1289
+ const qObj = quoted ? {
1290
+ stanzaId: quoted?.key?.id || quoted?.id,
1291
+ participant: quotedParticipant || quoted?.key?.participant || quoted?.key?.remoteJid,
1292
+ quotedType: 0,
1293
+ quotedMessage: typeof quoted === 'object' && quoted !== null ? (quoted.message ?? quoted) : undefined,
1294
+ } : {};
1295
+
1296
+ const sections = this._footer ? [
1297
+ ...this._sections,
1298
+ AIRich.newLayout('Single', {
1299
+ text: this._footer,
1300
+ __typename: 'GenAIMetadataTextPrimitive',
1301
+ }),
1302
+ ] : [...this._sections];
1303
+
1304
+ return {
1305
+ messageContextInfo: {
1306
+ deviceListMetadata: {},
1307
+ deviceListMetadataVersion: 2,
1308
+ botMetadata: {
1309
+ messageDisclaimerText: this._title,
1310
+ richResponseSourcesMetadata: {
1311
+ sources: this._richResponseSources
1310
1312
  },
1311
- contextInfo: {
1312
- ...forward,
1313
- ...qObj,
1314
- ...this._contextInfo,
1313
+ },
1314
+ },
1315
+ ...this._extraPayload,
1316
+ botForwardedMessage: {
1317
+ message: {
1318
+ richResponseMessage: {
1319
+ messageType: 1,
1320
+ submessages: includesSubmessages ? this._submessages : [],
1321
+ unifiedResponse: {
1322
+ data: includesUnifiedResponse ? Buffer.from(JSON.stringify({
1323
+ response_id: crypto.randomUUID(),
1324
+ sections
1325
+ })).toString("base64") : ''
1326
+ },
1327
+ contextInfo: {
1328
+ ...forward,
1329
+ ...qObj,
1330
+ ...this._contextInfo,
1331
+ },
1315
1332
  },
1316
1333
  },
1317
1334
  },
1318
- },
1319
- };
1320
- }
1335
+ };
1336
+ }
1321
1337
 
1322
- async send(jid, {
1323
- forwarded,
1324
- includesUnifiedResponse,
1325
- includesSubmessages,
1326
- ...options
1327
- } = {}) {
1328
- const msg = this.build({
1338
+ async send(jid, {
1329
1339
  forwarded,
1330
1340
  includesUnifiedResponse,
1341
+ includesSubmessages,
1331
1342
  ...options
1332
- });
1343
+ } = {}) {
1344
+ const msg = this.build({
1345
+ forwarded,
1346
+ includesUnifiedResponse,
1347
+ ...options
1348
+ });
1333
1349
 
1334
- await this.#client.relayMessage(jid, msg, {
1335
- ...options
1336
- });
1337
- return msg
1338
- }
1350
+ await this.#client.relayMessage(jid, msg, {
1351
+ ...options
1352
+ });
1353
+ return msg
1354
+ }
1339
1355
 
1340
- static tokenizer(code, lang = 'javascript') {
1341
- const keywordsMap = {
1342
- javascript: new Set([
1343
- 'break',
1344
- 'case',
1345
- 'catch',
1346
- 'continue',
1347
- 'debugger',
1348
- 'delete',
1349
- 'do',
1350
- 'else',
1351
- 'finally',
1352
- 'for',
1353
- 'function',
1354
- 'if',
1355
- 'in',
1356
- 'instanceof',
1357
- 'new',
1358
- 'return',
1359
- 'switch',
1360
- 'this',
1361
- 'throw',
1362
- 'try',
1363
- 'typeof',
1364
- 'var',
1365
- 'void',
1366
- 'while',
1367
- 'with',
1368
- 'true',
1369
- 'false',
1370
- 'null',
1371
- 'undefined',
1372
- 'class',
1373
- 'const',
1374
- 'let',
1375
- 'super',
1376
- 'extends',
1377
- 'export',
1378
- 'import',
1379
- 'yield',
1380
- 'static',
1381
- 'constructor',
1382
- 'async',
1383
- 'await',
1384
- 'get',
1385
- 'set',
1386
- ]),
1387
- };
1356
+ static tokenizer(code, lang = 'javascript') {
1357
+ const keywordsMap = {
1358
+ javascript: new Set([
1359
+ 'break',
1360
+ 'case',
1361
+ 'catch',
1362
+ 'continue',
1363
+ 'debugger',
1364
+ 'delete',
1365
+ 'do',
1366
+ 'else',
1367
+ 'finally',
1368
+ 'for',
1369
+ 'function',
1370
+ 'if',
1371
+ 'in',
1372
+ 'instanceof',
1373
+ 'new',
1374
+ 'return',
1375
+ 'switch',
1376
+ 'this',
1377
+ 'throw',
1378
+ 'try',
1379
+ 'typeof',
1380
+ 'var',
1381
+ 'void',
1382
+ 'while',
1383
+ 'with',
1384
+ 'true',
1385
+ 'false',
1386
+ 'null',
1387
+ 'undefined',
1388
+ 'class',
1389
+ 'const',
1390
+ 'let',
1391
+ 'super',
1392
+ 'extends',
1393
+ 'export',
1394
+ 'import',
1395
+ 'yield',
1396
+ 'static',
1397
+ 'constructor',
1398
+ 'async',
1399
+ 'await',
1400
+ 'get',
1401
+ 'set',
1402
+ ]),
1403
+ };
1388
1404
 
1389
- const TYPE_MAP = {
1390
- 0: 'DEFAULT',
1391
- 1: 'KEYWORD',
1392
- 2: 'METHOD',
1393
- 3: 'STR',
1394
- 4: 'NUMBER',
1395
- 5: 'COMMENT',
1396
- };
1405
+ const TYPE_MAP = {
1406
+ 0: 'DEFAULT',
1407
+ 1: 'KEYWORD',
1408
+ 2: 'METHOD',
1409
+ 3: 'STR',
1410
+ 4: 'NUMBER',
1411
+ 5: 'COMMENT',
1412
+ };
1397
1413
 
1398
- const keywords = keywordsMap[lang] || new Set();
1399
- const tokens = [];
1414
+ const keywords = keywordsMap[lang] || new Set();
1415
+ const tokens = [];
1400
1416
 
1401
- let i = 0;
1417
+ let i = 0;
1402
1418
 
1403
- const push = (content, type) => {
1404
- if (!content) return;
1405
- const last = tokens[tokens.length - 1];
1406
- if (last && last.highlightType === type) last.codeContent += content;
1407
- else tokens.push({
1408
- codeContent: content,
1409
- highlightType: type
1410
- });
1411
- };
1419
+ const push = (content, type) => {
1420
+ if (!content) return;
1421
+ const last = tokens[tokens.length - 1];
1422
+ if (last && last.highlightType === type) last.codeContent += content;
1423
+ else tokens.push({
1424
+ codeContent: content,
1425
+ highlightType: type
1426
+ });
1427
+ };
1412
1428
 
1413
- while (i < code.length) {
1414
- const c = code[i];
1429
+ while (i < code.length) {
1430
+ const c = code[i];
1415
1431
 
1416
- if (/\s/.test(c)) {
1417
- let s = i;
1418
- while (i < code.length && /\s/.test(code[i])) i++;
1419
- push(code.slice(s, i), 0);
1420
- continue;
1421
- }
1432
+ if (/\s/.test(c)) {
1433
+ let s = i;
1434
+ while (i < code.length && /\s/.test(code[i])) i++;
1435
+ push(code.slice(s, i), 0);
1436
+ continue;
1437
+ }
1422
1438
 
1423
- if (c === '/' && code[i + 1] === '/') {
1424
- let s = i;
1425
- i += 2;
1426
- while (i < code.length && code[i] !== '\n') i++;
1427
- push(code.slice(s, i), 5);
1428
- continue;
1429
- }
1439
+ if (c === '/' && code[i + 1] === '/') {
1440
+ let s = i;
1441
+ i += 2;
1442
+ while (i < code.length && code[i] !== '\n') i++;
1443
+ push(code.slice(s, i), 5);
1444
+ continue;
1445
+ }
1430
1446
 
1431
- if (c === '"' || c === "'" || c === '`') {
1432
- let s = i;
1433
- const q = c;
1434
- i++;
1435
- while (i < code.length) {
1436
- if (code[i] === '\\' && i + 1 < code.length) i += 2;
1437
- else if (code[i] === q) {
1438
- i++;
1439
- break;
1440
- } else i++;
1447
+ if (c === '"' || c === "'" || c === '`') {
1448
+ let s = i;
1449
+ const q = c;
1450
+ i++;
1451
+ while (i < code.length) {
1452
+ if (code[i] === '\\' && i + 1 < code.length) i += 2;
1453
+ else if (code[i] === q) {
1454
+ i++;
1455
+ break;
1456
+ } else i++;
1457
+ }
1458
+ push(code.slice(s, i), 3);
1459
+ continue;
1441
1460
  }
1442
- push(code.slice(s, i), 3);
1443
- continue;
1444
- }
1445
1461
 
1446
- if (/[0-9]/.test(c)) {
1447
- let s = i;
1448
- while (i < code.length && /[0-9.]/.test(code[i])) i++;
1449
- push(code.slice(s, i), 4);
1450
- continue;
1451
- }
1462
+ if (/[0-9]/.test(c)) {
1463
+ let s = i;
1464
+ while (i < code.length && /[0-9.]/.test(code[i])) i++;
1465
+ push(code.slice(s, i), 4);
1466
+ continue;
1467
+ }
1468
+
1469
+ if (/[a-zA-Z_$]/.test(c)) {
1470
+ let s = i;
1471
+ while (i < code.length && /[a-zA-Z0-9_$]/.test(code[i])) i++;
1472
+ const word = code.slice(s, i);
1473
+
1474
+ let type = 0;
1475
+ if (keywords.has(word)) type = 1;
1476
+ else {
1477
+ let j = i;
1478
+ while (j < code.length && /\s/.test(code[j])) j++;
1479
+ if (code[j] === '(') type = 2;
1480
+ }
1452
1481
 
1453
- if (/[a-zA-Z_$]/.test(c)) {
1454
- let s = i;
1455
- while (i < code.length && /[a-zA-Z0-9_$]/.test(code[i])) i++;
1456
- const word = code.slice(s, i);
1457
-
1458
- let type = 0;
1459
- if (keywords.has(word)) type = 1;
1460
- else {
1461
- let j = i;
1462
- while (j < code.length && /\s/.test(code[j])) j++;
1463
- if (code[j] === '(') type = 2;
1482
+ push(word, type);
1483
+ continue;
1464
1484
  }
1465
1485
 
1466
- push(word, type);
1467
- continue;
1486
+ push(c, 0);
1487
+ i++;
1468
1488
  }
1469
1489
 
1470
- push(c, 0);
1471
- i++;
1490
+ return {
1491
+ codeBlock: tokens,
1492
+ unified_codeBlock: tokens.map((t) => ({
1493
+ content: t.codeContent,
1494
+ type: TYPE_MAP[t.highlightType],
1495
+ })),
1496
+ };
1472
1497
  }
1473
1498
 
1474
- return {
1475
- codeBlock: tokens,
1476
- unified_codeBlock: tokens.map((t) => ({
1477
- content: t.codeContent,
1478
- type: TYPE_MAP[t.highlightType],
1479
- })),
1480
- };
1481
- }
1482
-
1483
- static toTableMetadata(arr) {
1484
- if (!Array.isArray(arr) || !arr.every((row) => Array.isArray(row) && row.every((cell) => typeof cell === 'string'))) {
1485
- throw new TypeError('Table must be a nested array of strings');
1486
- }
1499
+ static toTableMetadata(arr) {
1500
+ if (!Array.isArray(arr) || !arr.every((row) => Array.isArray(row) && row.every((cell) => typeof cell === 'string'))) {
1501
+ throw new TypeError('Table must be a nested array of strings');
1502
+ }
1487
1503
 
1488
- const [header, ...rows] = arr;
1489
- const maxLen = Math.max(header.length, ...rows.map((r) => r.length));
1490
- const normalize = (r) => [...r, ...Array(maxLen - r.length).fill('')];
1504
+ const [header, ...rows] = arr;
1505
+ const maxLen = Math.max(header.length, ...rows.map((r) => r.length));
1506
+ const normalize = (r) => [...r, ...Array(maxLen - r.length).fill('')];
1491
1507
 
1492
- const unified_rows = [{
1493
- is_header: true,
1494
- cells: normalize(header),
1495
- markdown_cells: normalize(header).map(cell => ({
1496
- text: cell
1497
- }))
1498
- },
1499
- ...rows.map((r) => {
1500
- const normalizedRow = normalize(r);
1501
- return {
1502
- is_header: false,
1503
- cells: normalizedRow,
1504
- markdown_cells: normalizedRow.map(cell => ({
1508
+ const unified_rows = [{
1509
+ is_header: true,
1510
+ cells: normalize(header),
1511
+ markdown_cells: normalize(header).map(cell => ({
1505
1512
  text: cell
1506
1513
  }))
1507
- };
1508
- }),
1509
- ];
1514
+ },
1515
+ ...rows.map((r) => {
1516
+ const normalizedRow = normalize(r);
1517
+ return {
1518
+ is_header: false,
1519
+ cells: normalizedRow,
1520
+ markdown_cells: normalizedRow.map(cell => ({
1521
+ text: cell
1522
+ }))
1523
+ };
1524
+ }),
1525
+ ];
1510
1526
 
1511
- const rowsMeta = unified_rows.map((r) => ({
1512
- items: r.cells,
1513
- ...(r.is_header ? {
1514
- isHeading: true
1515
- } : {}),
1516
- }));
1527
+ const rowsMeta = unified_rows.map((r) => ({
1528
+ items: r.cells,
1529
+ ...(r.is_header ? {
1530
+ isHeading: true
1531
+ } : {}),
1532
+ }));
1517
1533
 
1518
- return {
1519
- title: '',
1520
- rows: rowsMeta,
1521
- unified_rows,
1522
- };
1534
+ return {
1535
+ title: '',
1536
+ rows: rowsMeta,
1537
+ unified_rows,
1538
+ };
1539
+ }
1523
1540
  }
1524
- }
1525
-
1526
- /**
1527
- * @param {import('baileys').WASocket} socket
1528
- */
1529
-
1530
- function addProperty(socket, baileys) {
1531
- const {
1532
- proto,
1533
- generateWAMessageFromContent,
1534
- jidDecode,
1535
- downloadContentFromMessage,
1536
- prepareWAMessageMedia,
1537
- generateMessageID,
1538
- generateWAMessage
1539
- } = baileys;
1540
- let sendMessage = socket.sendMessage;
1541
+ global.Button = Button;
1542
+ global.ButtonV2 = ButtonV2;
1543
+ global.Carousel = Carousel;
1544
+ global.AIRich = AIRich;
1541
1545
  Object.assign(socket, {
1542
1546
  sendMessage: async (jid, content, options = {}) => {
1543
1547
  let {
@@ -2440,9 +2444,7 @@ function addProperty(socket, baileys) {
2440
2444
  };
2441
2445
 
2442
2446
  export default addProperty;
2443
- export {
2444
- Button,
2445
- ButtonV2,
2446
- Carousel,
2447
- AIRich
2448
- };
2447
+ export const Button = global.Button;
2448
+ export const ButtonV2 = global.ButtonV2;
2449
+ export const Carousel = global.Carousel;
2450
+ export const AIRich = global.AIRich;