@nuiisweety/baileys 0.1.1 → 0.1.2

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.
@@ -4,7 +4,13 @@ import { LANGUAGE_KEYWORDS } from '../WABinary/constants.js';
4
4
  import { CodeHighlightType, RichSubMessageType } from '../Types/RichType.js';
5
5
  import { proto } from '../../WAProto/index.js';
6
6
  import { unixTimestampSeconds } from './generics.js';
7
+
7
8
  const NOOP = new Set([]);
9
+
10
+ /* ─────────────────────────────────────────────────────────────
11
+ TOKENIZER
12
+ ───────────────────────────────────────────────────────────── */
13
+
8
14
  export const tokenizeCode = (code, language = 'javascript') => {
9
15
  const keywords = LANGUAGE_KEYWORDS[language] || NOOP;
10
16
  const blocks = [];
@@ -13,181 +19,570 @@ export const tokenizeCode = (code, language = 'javascript') => {
13
19
  while ((match = LEXER_REGEX.exec(code)) !== null) {
14
20
  if (match[1]) {
15
21
  blocks.push({ highlightType: CodeHighlightType.COMMENT, codeContent: match[1] });
16
- }
17
- else if (match[2]) {
22
+ } else if (match[2]) {
18
23
  blocks.push({ highlightType: CodeHighlightType.STRING, codeContent: match[2] });
19
- }
20
- else if (match[3]) {
24
+ } else if (match[3]) {
21
25
  blocks.push({
22
26
  highlightType: keywords.has(match[3]) ? CodeHighlightType.KEYWORD : CodeHighlightType.METHOD,
23
27
  codeContent: match[3],
24
28
  });
25
- }
26
- else if (match[4]) {
29
+ } else if (match[4]) {
27
30
  blocks.push({
28
31
  highlightType: keywords.has(match[4]) ? CodeHighlightType.KEYWORD : CodeHighlightType.DEFAULT,
29
32
  codeContent: match[4],
30
33
  });
31
- }
32
- else if (match[5]) {
34
+ } else if (match[5]) {
33
35
  blocks.push({ highlightType: CodeHighlightType.NUMBER, codeContent: match[5] });
34
- }
35
- else {
36
+ } else {
36
37
  blocks.push({ highlightType: CodeHighlightType.DEFAULT, codeContent: match[6] });
37
38
  }
38
39
  }
39
40
  return blocks;
40
41
  };
42
+
43
+ /* ─────────────────────────────────────────────────────────────
44
+ INCOMING DECODER — parse rich message yang diterima
45
+ ───────────────────────────────────────────────────────────── */
46
+
47
+ /**
48
+ * Parse sebuah AIRichResponseSubMessage proto menjadi object JS yang mudah dipakai.
49
+ * Return null kalau tipe tidak dikenal.
50
+ */
51
+ export const parseRichSubMessage = (submessage) => {
52
+ if (!submessage) return null;
53
+ const type = submessage.messageType;
54
+
55
+ switch (type) {
56
+ case RichSubMessageType.TEXT:
57
+ return {
58
+ type: 'text',
59
+ text: submessage.messageText || '',
60
+ };
61
+
62
+ case RichSubMessageType.CODE:
63
+ return {
64
+ type: 'code',
65
+ language: submessage.codeMetadata?.codeLanguage || 'plain',
66
+ blocks: (submessage.codeMetadata?.codeBlocks || []).map(b => ({
67
+ highlight: CodeHighlightType[b.highlightType] ?? 'DEFAULT',
68
+ content: b.codeContent || '',
69
+ })),
70
+ /** Helper: ambil source code mentah tanpa highlight info */
71
+ get raw() {
72
+ return this.blocks.map(b => b.content).join('');
73
+ },
74
+ };
75
+
76
+ case RichSubMessageType.TABLE:
77
+ return {
78
+ type: 'table',
79
+ title: submessage.tableMetadata?.title || '',
80
+ rows: (submessage.tableMetadata?.rows || []).map(row => ({
81
+ isHeading: row.isHeading ?? false,
82
+ items: row.items || [],
83
+ })),
84
+ };
85
+
86
+ case RichSubMessageType.GRID_IMAGE:
87
+ return {
88
+ type: 'gridImage',
89
+ gridImageUrl: submessage.gridImageMetadata?.gridImageUrl || null,
90
+ imageUrls: submessage.gridImageMetadata?.imageUrls || [],
91
+ };
92
+
93
+ case RichSubMessageType.INLINE_IMAGE:
94
+ return {
95
+ type: 'inlineImage',
96
+ imageUrl: submessage.imageMetadata?.imageUrl || null,
97
+ imageText: submessage.imageMetadata?.imageText || '',
98
+ alignment: submessage.imageMetadata?.alignment ?? 0,
99
+ tapLinkUrl: submessage.imageMetadata?.tapLinkUrl || null,
100
+ };
101
+
102
+ case RichSubMessageType.DYNAMIC:
103
+ return {
104
+ type: 'dynamic',
105
+ dynamicType: submessage.dynamicMetadata?.type ?? 0,
106
+ version: submessage.dynamicMetadata?.version ?? 0,
107
+ url: submessage.dynamicMetadata?.url || null,
108
+ loopCount: submessage.dynamicMetadata?.loopCount ?? 0,
109
+ };
110
+
111
+ case RichSubMessageType.MAP:
112
+ return {
113
+ type: 'map',
114
+ centerLatitude: submessage.mapMetadata?.centerLatitude ?? 0,
115
+ centerLongitude: submessage.mapMetadata?.centerLongitude ?? 0,
116
+ latitudeDelta: submessage.mapMetadata?.latitudeDelta ?? 0,
117
+ longitudeDelta: submessage.mapMetadata?.longitudeDelta ?? 0,
118
+ showInfoList: submessage.mapMetadata?.showInfoList ?? false,
119
+ annotations: (submessage.mapMetadata?.annotations || []).map(a => ({
120
+ number: a.annotationNumber ?? 0,
121
+ latitude: a.latitude ?? 0,
122
+ longitude: a.longitude ?? 0,
123
+ title: a.title || '',
124
+ body: a.body || '',
125
+ })),
126
+ };
127
+
128
+ case RichSubMessageType.LATEX:
129
+ return {
130
+ type: 'latex',
131
+ text: submessage.latexMetadata?.text || '',
132
+ expressions: (submessage.latexMetadata?.expressions || []).map(e => ({
133
+ expression: e.latexExpression || '',
134
+ url: e.url || null,
135
+ width: e.width ?? 0,
136
+ height: e.height ?? 0,
137
+ })),
138
+ };
139
+
140
+ case RichSubMessageType.CONTENT_ITEMS:
141
+ return {
142
+ type: 'contentItems',
143
+ contentType: submessage.contentItemsMetadata?.contentType ?? 0,
144
+ items: (submessage.contentItemsMetadata?.itemsMetadata || []).map(item => {
145
+ if (item.reelItem) {
146
+ return {
147
+ kind: 'reel',
148
+ title: item.reelItem.title || '',
149
+ profileIconUrl: item.reelItem.profileIconUrl || null,
150
+ thumbnailUrl: item.reelItem.thumbnailUrl || null,
151
+ videoUrl: item.reelItem.videoUrl || null,
152
+ };
153
+ }
154
+ return { kind: 'unknown' };
155
+ }),
156
+ };
157
+
158
+ default:
159
+ return { type: 'unknown', raw: submessage };
160
+ }
161
+ };
162
+
163
+ /**
164
+ * Parse seluruh AIRichResponseMessage menjadi array parsed submessages.
165
+ * Bisa dipanggil langsung dari handler messages.upsert:
166
+ *
167
+ * const inner = normalizeMessageContent(msg.message)
168
+ * const parsed = parseRichMessage(inner?.richResponseMessage)
169
+ */
170
+ export const parseRichMessage = (richResponseMessage) => {
171
+ if (!richResponseMessage) return null;
172
+
173
+ const submessages = (richResponseMessage.submessages || [])
174
+ .map(parseRichSubMessage)
175
+ .filter(Boolean);
176
+
177
+ let unifiedData = null;
178
+ if (richResponseMessage.unifiedResponse?.data) {
179
+ try {
180
+ const buf = richResponseMessage.unifiedResponse.data;
181
+ unifiedData = JSON.parse(Buffer.isBuffer(buf) ? buf.toString('utf-8') : Buffer.from(buf).toString('utf-8'));
182
+ } catch (_) { /* ignore parse error */ }
183
+ }
184
+
185
+ return {
186
+ messageType: richResponseMessage.messageType ?? 0,
187
+ submessages,
188
+ unifiedData,
189
+ };
190
+ };
191
+
192
+ /* ─────────────────────────────────────────────────────────────
193
+ OUTGOING BUILDER — unified response JSON per subtype
194
+ ───────────────────────────────────────────────────────────── */
195
+
196
+ const buildUnifiedSection = (submessage) => {
197
+ switch (submessage.messageType) {
198
+ case RichSubMessageType.TEXT:
199
+ return {
200
+ view_model: {
201
+ primitive: {
202
+ text: submessage.messageText,
203
+ inline_entities: submessage.inlineEntities || [],
204
+ __typename: 'GenAIMarkdownTextUXPrimitive'
205
+ },
206
+ __typename: 'GenAISingleLayoutViewModel'
207
+ }
208
+ };
209
+
210
+ case RichSubMessageType.CODE: {
211
+ const cm = submessage.codeMetadata;
212
+ return {
213
+ view_model: {
214
+ primitive: {
215
+ language: cm.codeLanguage,
216
+ code_blocks: cm.codeBlocks.map(b => ({
217
+ content: b.codeContent,
218
+ type: CodeHighlightType[b.highlightType]
219
+ })),
220
+ __typename: 'GenAICodeUXPrimitive'
221
+ },
222
+ __typename: 'GenAISingleLayoutViewModel'
223
+ }
224
+ };
225
+ }
226
+
227
+ case RichSubMessageType.TABLE: {
228
+ const tm = submessage.tableMetadata;
229
+ return {
230
+ view_model: {
231
+ primitive: {
232
+ title: tm.title,
233
+ rows: tm.rows.map(row => ({
234
+ is_header: row.isHeading,
235
+ cells: row.items,
236
+ markdown_cells: row.items.map(item => ({ text: item }))
237
+ })),
238
+ __typename: 'GenATableUXPrimitive'
239
+ },
240
+ __typename: 'GenAISingleLayoutViewModel'
241
+ }
242
+ };
243
+ }
244
+
245
+ case RichSubMessageType.GRID_IMAGE: {
246
+ const gm = submessage.gridImageMetadata;
247
+ return {
248
+ view_model: {
249
+ primitive: {
250
+ grid_image_url: gm.gridImageUrl,
251
+ image_urls: gm.imageUrls,
252
+ __typename: 'GenAIGridImageUXPrimitive'
253
+ },
254
+ __typename: 'GenAISingleLayoutViewModel'
255
+ }
256
+ };
257
+ }
258
+
259
+ case RichSubMessageType.INLINE_IMAGE: {
260
+ const im = submessage.imageMetadata;
261
+ return {
262
+ view_model: {
263
+ primitive: {
264
+ image_url: im.imageUrl,
265
+ image_text: im.imageText,
266
+ alignment: im.alignment ?? 0,
267
+ tap_link_url: im.tapLinkUrl || null,
268
+ __typename: 'GenAIInlineImageUXPrimitive'
269
+ },
270
+ __typename: 'GenAISingleLayoutViewModel'
271
+ }
272
+ };
273
+ }
274
+
275
+ case RichSubMessageType.DYNAMIC: {
276
+ const dm = submessage.dynamicMetadata;
277
+ return {
278
+ view_model: {
279
+ primitive: {
280
+ type: dm.type ?? 0,
281
+ version: dm.version ?? 0,
282
+ url: dm.url,
283
+ loop_count: dm.loopCount ?? 0,
284
+ __typename: 'GenAIDynamicUXPrimitive'
285
+ },
286
+ __typename: 'GenAISingleLayoutViewModel'
287
+ }
288
+ };
289
+ }
290
+
291
+ case RichSubMessageType.MAP: {
292
+ const mm = submessage.mapMetadata;
293
+ return {
294
+ view_model: {
295
+ primitive: {
296
+ center_latitude: mm.centerLatitude,
297
+ center_longitude: mm.centerLongitude,
298
+ latitude_delta: mm.latitudeDelta,
299
+ longitude_delta: mm.longitudeDelta,
300
+ show_info_list: mm.showInfoList ?? false,
301
+ annotations: (mm.annotations || []).map(a => ({
302
+ annotation_number: a.annotationNumber,
303
+ latitude: a.latitude,
304
+ longitude: a.longitude,
305
+ title: a.title,
306
+ body: a.body
307
+ })),
308
+ __typename: 'GenAIMapUXPrimitive'
309
+ },
310
+ __typename: 'GenAISingleLayoutViewModel'
311
+ }
312
+ };
313
+ }
314
+
315
+ case RichSubMessageType.LATEX: {
316
+ const lm = submessage.latexMetadata;
317
+ return {
318
+ view_model: {
319
+ primitive: {
320
+ text: lm.text,
321
+ expressions: (lm.expressions || []).map(e => ({
322
+ latex_expression: e.latexExpression,
323
+ url: e.url,
324
+ width: e.width,
325
+ height: e.height,
326
+ font_height: e.fontHeight,
327
+ image_top_padding: e.imageTopPadding,
328
+ image_leading_padding: e.imageLeadingPadding,
329
+ image_bottom_padding: e.imageBottomPadding,
330
+ image_trailing_padding: e.imageTrailingPadding
331
+ })),
332
+ __typename: 'GenAILatexUXPrimitive'
333
+ },
334
+ __typename: 'GenAISingleLayoutViewModel'
335
+ }
336
+ };
337
+ }
338
+
339
+ case RichSubMessageType.CONTENT_ITEMS: {
340
+ const ci = submessage.contentItemsMetadata;
341
+ return {
342
+ view_model: {
343
+ primitive: {
344
+ content_type: ci.contentType ?? 0,
345
+ items_metadata: (ci.itemsMetadata || []).map(item => {
346
+ if (item.reelItem) {
347
+ return {
348
+ reel_item: {
349
+ title: item.reelItem.title,
350
+ profile_icon_url: item.reelItem.profileIconUrl,
351
+ thumbnail_url: item.reelItem.thumbnailUrl,
352
+ video_url: item.reelItem.videoUrl
353
+ }
354
+ };
355
+ }
356
+ return {};
357
+ }),
358
+ __typename: 'GenAIContentItemsUXPrimitive'
359
+ },
360
+ __typename: 'GenAISingleLayoutViewModel'
361
+ }
362
+ };
363
+ }
364
+
365
+ default:
366
+ return submessage;
367
+ }
368
+ };
369
+
41
370
  export const toUnified = (submessages) => ({
42
371
  response_id: randomUUID(),
43
- sections: submessages.map((submessage, index) => {
44
- switch (submessage.messageType) {
45
- case RichSubMessageType.CODE:
46
- const codeMetadata = submessage.codeMetadata;
47
- return {
48
- view_model: {
49
- primitive: {
50
- language: codeMetadata.codeLanguage,
51
- code_blocks: codeMetadata.codeBlocks.map((block) => ({ content: block.codeContent, type: CodeHighlightType[block.highlightType] })),
52
- __typename: 'GenAICodeUXPrimitive'
53
- },
54
- __typename: 'GenAISingleLayoutViewModel'
55
- }
56
- };
57
- case RichSubMessageType.TABLE:
58
- const tableMetadata = submessage.tableMetadata;
59
- return {
60
- view_model: {
61
- primitive: {
62
- title: tableMetadata.title,
63
- rows: tableMetadata.rows.map((row) => ({
64
- is_header: row.isHeading,
65
- cells: row.items,
66
- markdown_cells: row.items.map((item) => ({ text: item }))
67
- })),
68
- __typename: 'GenATableUXPrimitive'
69
- },
70
- __typename: 'GenAISingleLayoutViewModel'
71
- }
72
- };
73
- case RichSubMessageType.TEXT:
372
+ sections: submessages.map(buildUnifiedSection)
373
+ });
374
+
375
+ /* ─────────────────────────────────────────────────────────────
376
+ PREPARE HELPERS — builder per tipe submessage
377
+ ───────────────────────────────────────────────────────────── */
378
+
379
+ /** Buat submessage TEXT */
380
+ const makeTextSub = (text, inlineEntities) => ({
381
+ messageType: RichSubMessageType.TEXT,
382
+ messageText: text,
383
+ ...(inlineEntities ? { inlineEntities } : {})
384
+ });
385
+
386
+ /** Buat submessage CODE dengan auto-tokenize */
387
+ const makeCodeSub = (code, language = 'javascript') => ({
388
+ messageType: RichSubMessageType.CODE,
389
+ codeMetadata: {
390
+ codeLanguage: language,
391
+ codeBlocks: tokenizeCode(code, language)
392
+ }
393
+ });
394
+
395
+ /** Buat submessage TABLE */
396
+ const makeTableSub = (rows, title, noHeading) => ({
397
+ messageType: RichSubMessageType.TABLE,
398
+ tableMetadata: {
399
+ title: title || '',
400
+ rows: rows.map((items, i) => ({
401
+ isHeading: !noHeading && i === 0,
402
+ items
403
+ }))
404
+ }
405
+ });
406
+
407
+ /** Buat submessage GRID_IMAGE */
408
+ const makeGridImageSub = (gridImageUrl, imageUrls = []) => ({
409
+ messageType: RichSubMessageType.GRID_IMAGE,
410
+ gridImageMetadata: { gridImageUrl, imageUrls }
411
+ });
412
+
413
+ /** Buat submessage INLINE_IMAGE */
414
+ const makeInlineImageSub = (imageUrl, imageText = '', alignment = 0, tapLinkUrl = null) => ({
415
+ messageType: RichSubMessageType.INLINE_IMAGE,
416
+ imageMetadata: { imageUrl, imageText, alignment, tapLinkUrl }
417
+ });
418
+
419
+ /** Buat submessage DYNAMIC (animated image/GIF) */
420
+ const makeDynamicSub = (url, dynamicType = 1, version = 1, loopCount = 0) => ({
421
+ messageType: RichSubMessageType.DYNAMIC,
422
+ dynamicMetadata: { type: dynamicType, version, url, loopCount }
423
+ });
424
+
425
+ /** Buat submessage MAP */
426
+ const makeMapSub = (centerLatitude, centerLongitude, options = {}) => ({
427
+ messageType: RichSubMessageType.MAP,
428
+ mapMetadata: {
429
+ centerLatitude,
430
+ centerLongitude,
431
+ latitudeDelta: options.latitudeDelta ?? 0.05,
432
+ longitudeDelta: options.longitudeDelta ?? 0.05,
433
+ showInfoList: options.showInfoList ?? false,
434
+ annotations: (options.annotations || []).map((a, i) => ({
435
+ annotationNumber: a.number ?? i + 1,
436
+ latitude: a.latitude,
437
+ longitude: a.longitude,
438
+ title: a.title || '',
439
+ body: a.body || ''
440
+ }))
441
+ }
442
+ });
443
+
444
+ /** Buat submessage LATEX */
445
+ const makeLatexSub = (text, expressions = []) => ({
446
+ messageType: RichSubMessageType.LATEX,
447
+ latexMetadata: {
448
+ text,
449
+ expressions: expressions.map(e => ({
450
+ latexExpression: e.expression || e.latexExpression || '',
451
+ url: e.url || null,
452
+ width: e.width ?? 0,
453
+ height: e.height ?? 0,
454
+ fontHeight: e.fontHeight ?? 0,
455
+ imageTopPadding: e.imageTopPadding ?? 0,
456
+ imageLeadingPadding: e.imageLeadingPadding ?? 0,
457
+ imageBottomPadding: e.imageBottomPadding ?? 0,
458
+ imageTrailingPadding: e.imageTrailingPadding ?? 0
459
+ }))
460
+ }
461
+ });
462
+
463
+ /** Buat submessage CONTENT_ITEMS (carousel reel) */
464
+ const makeContentItemsSub = (items, contentType = 0) => ({
465
+ messageType: RichSubMessageType.CONTENT_ITEMS,
466
+ contentItemsMetadata: {
467
+ contentType,
468
+ itemsMetadata: items.map(item => {
469
+ if (item.reelItem || item.kind === 'reel') {
470
+ const r = item.reelItem || item;
74
471
  return {
75
- view_model: {
76
- primitive: {
77
- text: submessage.messageText,
78
- inline_entities: submessage.inlineEntities || [],
79
- __typename: 'GenAIMarkdownTextUXPrimitive'
80
- },
81
- __typename: 'GenAISingleLayoutViewModel'
472
+ reelItem: {
473
+ title: r.title || '',
474
+ profileIconUrl: r.profileIconUrl || null,
475
+ thumbnailUrl: r.thumbnailUrl || null,
476
+ videoUrl: r.videoUrl || null
82
477
  }
83
478
  };
84
- }
85
- return submessage;
86
- })
479
+ }
480
+ return {};
481
+ })
482
+ }
87
483
  });
484
+
485
+ /* ─────────────────────────────────────────────────────────────
486
+ MAIN BUILDER — prepareRichResponseMessage
487
+ ───────────────────────────────────────────────────────────── */
488
+
88
489
  export const prepareRichResponseMessage = (content) => {
89
- const { code, contentText, disclaimerText, footerText, headerText, language, links, noHeading, richResponse, table, title } = content;
490
+ const {
491
+ code, contentText, disclaimerText, footerText, headerText,
492
+ language, links, noHeading, richResponse, table, title,
493
+ // sub-types baru
494
+ gridImage, inlineImage, dynamic: dynamicContent,
495
+ map: mapContent, latex, contentItems
496
+ } = content;
497
+
90
498
  let submessages = [];
499
+
500
+ /* ── mode array (richResponse) — multi-section campuran ── */
91
501
  if (Array.isArray(richResponse)) {
92
- submessages = richResponse.map((submessage) => {
93
- if (submessage.text) {
94
- return {
95
- messageType: RichSubMessageType.TEXT,
96
- messageText: submessage.text,
97
- inlineEntities: submessage.inlineEntities
98
- };
99
- }
100
- else if (submessage.code) {
101
- return {
102
- messageType: RichSubMessageType.CODE,
103
- codeMetadata: {
104
- codeLanguage: submessage.language,
105
- codeBlocks: submessage.code
106
- }
107
- };
108
- }
109
- else if (submessage.table) {
110
- return {
111
- messageType: RichSubMessageType.TABLE,
112
- tableMetadata: {
113
- title: submessage.title,
114
- rows: submessage.table
115
- }
116
- };
117
- }
118
- return submessage;
119
- });
120
- }
121
- else {
122
- if (headerText) {
123
- submessages.push({
124
- messageType: RichSubMessageType.TEXT,
125
- messageText: headerText
126
- });
502
+ submessages = richResponse.map(sub => {
503
+ if (sub.text != null) return makeTextSub(sub.text, sub.inlineEntities);
504
+ if (sub.code != null) return makeCodeSub(sub.code, sub.language || 'javascript');
505
+ if (sub.table != null) return makeTableSub(sub.table, sub.title, sub.noHeading);
506
+ if (sub.gridImage != null) return makeGridImageSub(sub.gridImage.gridImageUrl, sub.gridImage.imageUrls);
507
+ if (sub.inlineImage != null) return makeInlineImageSub(sub.inlineImage.imageUrl, sub.inlineImage.imageText, sub.inlineImage.alignment, sub.inlineImage.tapLinkUrl);
508
+ if (sub.dynamic != null) return makeDynamicSub(sub.dynamic.url, sub.dynamic.type, sub.dynamic.version, sub.dynamic.loopCount);
509
+ if (sub.map != null) return makeMapSub(sub.map.centerLatitude, sub.map.centerLongitude, sub.map);
510
+ if (sub.latex != null) return makeLatexSub(sub.latex.text, sub.latex.expressions);
511
+ if (sub.contentItems != null) return makeContentItemsSub(sub.contentItems.items, sub.contentItems.contentType);
512
+ return sub; // passthrough kalau sudah bentuk proto
513
+ }).filter(Boolean);
514
+
515
+ /* ── mode flat (convenience fields) ── */
516
+ } else {
517
+ if (headerText) submessages.push(makeTextSub(headerText));
518
+ if (contentText) submessages.push(makeTextSub(contentText));
519
+
520
+ if (code) {
521
+ submessages.push(makeCodeSub(code, language || 'javascript'));
127
522
  }
128
- if (contentText) {
129
- submessages.push({
130
- messageType: RichSubMessageType.TEXT,
131
- messageText: contentText
132
- });
523
+
524
+ if (table) {
525
+ submessages.push(makeTableSub(table, title, noHeading));
133
526
  }
134
- if (code) {
135
- language ||= 'javascript';
136
- submessages.push({
137
- messageType: RichSubMessageType.CODE,
138
- codeMetadata: {
139
- codeLanguage: language,
140
- codeBlocks: tokenizeCode(code, language)
141
- }
142
- });
527
+
528
+ if (gridImage) {
529
+ submessages.push(makeGridImageSub(gridImage.gridImageUrl, gridImage.imageUrls));
530
+ }
531
+
532
+ if (inlineImage) {
533
+ submessages.push(makeInlineImageSub(inlineImage.imageUrl, inlineImage.imageText, inlineImage.alignment, inlineImage.tapLinkUrl));
143
534
  }
144
- else if (links) {
535
+
536
+ if (dynamicContent) {
537
+ submessages.push(makeDynamicSub(dynamicContent.url, dynamicContent.type, dynamicContent.version, dynamicContent.loopCount));
538
+ }
539
+
540
+ if (mapContent) {
541
+ submessages.push(makeMapSub(mapContent.centerLatitude, mapContent.centerLongitude, mapContent));
542
+ }
543
+
544
+ if (latex) {
545
+ submessages.push(makeLatexSub(latex.text, latex.expressions));
546
+ }
547
+
548
+ if (contentItems) {
549
+ submessages.push(makeContentItemsSub(contentItems.items, contentItems.contentType));
550
+ }
551
+
552
+ /* links — bisa dikombinasi dengan tipe lain di atas */
553
+ if (links && Array.isArray(links)) {
145
554
  links.forEach((linkField, index) => {
146
555
  const prefix = 'SS_' + index;
147
556
  const url = linkField.url || DONATE_URL;
148
- const sources = linkField.sources?.map((sourceField) => ({
557
+ const sources = (linkField.sources || []).map(s => ({
149
558
  source_type: 'THIRD_PARTY',
150
- source_display_name: sourceField.displayName || 'Donate',
151
- source_subtitle: sourceField.subtitle || 'Saweria',
152
- source_url: sourceField.url || url
559
+ source_display_name: s.displayName || 'Source',
560
+ source_subtitle: s.subtitle || '',
561
+ source_url: s.url || url
153
562
  }));
154
- submessages.push({
155
- messageType: RichSubMessageType.TEXT,
156
- messageText: linkField.text + ` {{${prefix}}}¹{{/${prefix}}} `,
157
- inlineEntities: [{
158
- key: prefix,
159
- metadata: {
160
- reference_id: index + 1,
161
- reference_url: url,
162
- reference_title: linkField.title || 'For Donation via Saweria',
163
- reference_display_name: linkField.displayName || 'Donation',
164
- sources: sources || [],
165
- __typename: 'GenAISearchCitationItem'
166
- }
167
- }]
168
- });
169
- });
170
- }
171
- else if (table) {
172
- submessages.push({
173
- messageType: RichSubMessageType.TABLE,
174
- tableMetadata: {
175
- title,
176
- rows: table.map((items, index) => ({
177
- isHeading: !noHeading && index == 0,
178
- items
179
- }))
180
- }
181
- });
182
- }
183
- if (footerText) {
184
- submessages.push({
185
- messageType: RichSubMessageType.TEXT,
186
- messageText: footerText
563
+ submessages.push(makeTextSub(
564
+ linkField.text + ` {{${prefix}}}¹{{/${prefix}}} `,
565
+ [{
566
+ key: prefix,
567
+ metadata: {
568
+ reference_id: index + 1,
569
+ reference_url: url,
570
+ reference_title: linkField.title || url,
571
+ reference_display_name: linkField.displayName || url,
572
+ sources,
573
+ __typename: 'GenAISearchCitationItem'
574
+ }
575
+ }]
576
+ ));
187
577
  });
188
578
  }
579
+
580
+ if (footerText) submessages.push(makeTextSub(footerText));
189
581
  }
582
+
583
+ /* build unifiedResponse JSON */
190
584
  const unified = toUnified(submessages);
585
+
191
586
  const richResponseMessage = proto.AIRichResponseMessage.create({
192
587
  submessages,
193
588
  messageType: proto.AIRichResponseMessageType.AI_RICH_RESPONSE_TYPE_STANDARD,
@@ -201,19 +596,28 @@ export const prepareRichResponseMessage = (content) => {
201
596
  forwardOrigin: 4
202
597
  }
203
598
  });
599
+
204
600
  const message = wrapToBotForwardedMessage(richResponseMessage);
205
601
  const botMetadata = message.messageContextInfo.botMetadata;
602
+
206
603
  if (disclaimerText) {
207
604
  botMetadata.messageDisclaimerText = disclaimerText;
208
605
  }
209
606
  botMetadata.botResponseId = unified.response_id;
607
+
210
608
  return message;
211
609
  };
610
+
611
+ /* ─────────────────────────────────────────────────────────────
612
+ BOT WRAPPER HELPERS
613
+ ───────────────────────────────────────────────────────────── */
614
+
212
615
  export const botMetadataSignature = () => {
213
616
  const signature = new Uint8Array(64);
214
617
  getRandomValues(signature);
215
618
  return signature;
216
619
  };
620
+
217
621
  export const botMetadataCertificate = (length = 685) => {
218
622
  const certificate = new Uint8Array(length);
219
623
  certificate[0] = 48;
@@ -221,6 +625,7 @@ export const botMetadataCertificate = (length = 685) => {
221
625
  getRandomValues(certificate.subarray(2));
222
626
  return certificate;
223
627
  };
628
+
224
629
  export const wrapToBotForwardedMessage = (richResponseMessage) => ({
225
630
  messageContextInfo: {
226
631
  botMetadata: {
@@ -243,4 +648,4 @@ export const wrapToBotForwardedMessage = (richResponseMessage) => ({
243
648
  message: { richResponseMessage }
244
649
  }
245
650
  });
246
- //# sourceMappingURL=rich-message-utils.js.map
651
+ //# sourceMappingURL=rich-message-utils.js.map