@pontasockets/baileys 0.3.3 → 1.0.1

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.
@@ -24,7 +24,9 @@ const CodeHighlightType = {
24
24
  }
25
25
 
26
26
  const RichSubMessageType = {
27
- UNKNOWN: 0, TEXT: 2, TABLE: 4, CODE: 5
27
+ UNKNOWN: 0, IMAGES: 1, TEXT: 2, TABLE: 4, CODE: 5, VIDEO: 7, SUGGESTIONS: 8,
28
+ REELS: 9, PRODUCT: 10, POST: 11, SOURCES: 12, TIP: 13, FOOTER: 14,
29
+ LATEX: 99
28
30
  }
29
31
 
30
32
  // ─── Keyword Sets ─────────────────────────────────────────────────────────────
@@ -166,7 +168,20 @@ exports.tokenizeCode = tokenizeCode
166
168
 
167
169
  const toUnified = (submessages, uuid) => ({
168
170
  response_id: uuid,
169
- sections: submessages.map((submessage) => {
171
+ sections: submessages.flatMap((submessage) => {
172
+ if (submessage.messageType === RichSubMessageType.IMAGES) {
173
+ return (submessage._imageUrls || []).map(url => ({
174
+ view_model: {
175
+ primitive: {
176
+ media: { url, mime_type: submessage._mimeType || 'image/jpeg' },
177
+ imagine_type: 3,
178
+ status: { status: 'READY' },
179
+ __typename: 'GenAIImaginePrimitive'
180
+ },
181
+ __typename: 'GenAISingleLayoutViewModel'
182
+ }
183
+ }))
184
+ }
170
185
  if (submessage.messageType === RichSubMessageType.TABLE) {
171
186
  const tm = submessage.tableMetadata
172
187
  return {
@@ -212,6 +227,142 @@ const toUnified = (submessages, uuid) => ({
212
227
  }
213
228
  }
214
229
  }
230
+ if (submessage.messageType === RichSubMessageType.VIDEO) {
231
+ const vm = submessage.videoMetadata
232
+ return {
233
+ view_model: {
234
+ primitive: {
235
+ media: { url: vm.url, mime_type: vm.mimeType || 'video/mp4', duration: vm.duration || 10 },
236
+ imagine_type: 'ANIMATE',
237
+ status: { status: 'READY' },
238
+ __typename: 'GenAIImaginePrimitive'
239
+ },
240
+ __typename: 'GenAISingleLayoutViewModel'
241
+ }
242
+ }
243
+ }
244
+ if (submessage.messageType === RichSubMessageType.SUGGESTIONS) {
245
+ return {
246
+ view_model: {
247
+ primitives: submessage.suggestions.map(s => ({
248
+ prompt_text: s,
249
+ prompt_type: 'SUGGESTED_PROMPT',
250
+ __typename: 'GenAIFollowUpSuggestionPillPrimitive'
251
+ })),
252
+ __typename: 'GenAIActionRowLayoutViewModel'
253
+ }
254
+ }
255
+ }
256
+ if (submessage.messageType === RichSubMessageType.REELS) {
257
+ return {
258
+ view_model: {
259
+ primitives: (submessage._reelItems || []).map(i => ({
260
+ reels_url: i.videoUrl,
261
+ thumbnail_url: i.thumbnailUrl,
262
+ creator: i.title,
263
+ avatar_url: i.profileIconUrl,
264
+ reels_title: i.reels_title || '',
265
+ likes_count: i.likes_count || 0,
266
+ shares_count: i.shares_count || 0,
267
+ view_count: i.view_count || 0,
268
+ reel_source: i.reel_source || 'IG',
269
+ is_verified: i.is_verified || false,
270
+ __typename: 'GenAIReelPrimitive'
271
+ })),
272
+ __typename: 'GenAIHScrollLayoutViewModel'
273
+ }
274
+ }
275
+ }
276
+ if (submessage.messageType === RichSubMessageType.PRODUCT) {
277
+ const { isMultiple, products } = submessage.productMetadata
278
+ if (isMultiple) {
279
+ return {
280
+ view_model: {
281
+ primitives: products.map(p => ({ ...p, __typename: 'GenAIProductItemCardPrimitive' })),
282
+ __typename: 'GenAIHScrollLayoutViewModel'
283
+ }
284
+ }
285
+ }
286
+ return {
287
+ view_model: {
288
+ primitive: { ...products[0], __typename: 'GenAIProductItemCardPrimitive' },
289
+ __typename: 'GenAISingleLayoutViewModel'
290
+ }
291
+ }
292
+ }
293
+ if (submessage.messageType === RichSubMessageType.POST) {
294
+ const { isMultiple, posts } = submessage.postMetadata
295
+ if (isMultiple) {
296
+ return {
297
+ view_model: {
298
+ primitives: posts.map(p => ({ ...p, __typename: 'GenAIPostPrimitive' })),
299
+ __typename: 'GenAIHScrollLayoutViewModel'
300
+ }
301
+ }
302
+ }
303
+ return {
304
+ view_model: {
305
+ primitive: { ...posts[0], __typename: 'GenAIPostPrimitive' },
306
+ __typename: 'GenAISingleLayoutViewModel'
307
+ }
308
+ }
309
+ }
310
+ if (submessage.messageType === RichSubMessageType.SOURCES) {
311
+ return {
312
+ view_model: {
313
+ primitive: {
314
+ sources: submessage.sourcesMetadata.sources.map(s => Array.isArray(s) ? {
315
+ source_type: 'THIRD_PARTY',
316
+ source_display_name: s[2] || '',
317
+ source_subtitle: 'AI',
318
+ source_url: s[1] || '',
319
+ favicon: { url: s[0] || '', mime_type: 'image/jpeg', width: 16, height: 16 }
320
+ } : s),
321
+ __typename: 'GenAISearchResultPrimitive'
322
+ },
323
+ __typename: 'GenAISingleLayoutViewModel'
324
+ }
325
+ }
326
+ }
327
+ if (submessage.messageType === RichSubMessageType.TIP) {
328
+ return {
329
+ view_model: {
330
+ primitive: { text: submessage.tipText, __typename: 'GenAIMetadataTextPrimitive' },
331
+ __typename: 'GenAISingleLayoutViewModel'
332
+ }
333
+ }
334
+ }
335
+ if (submessage.messageType === RichSubMessageType.FOOTER) {
336
+ return {
337
+ view_model: {
338
+ primitive: { text: submessage.footerText, __typename: 'GenAIMetadataTextPrimitive' },
339
+ __typename: 'GenAISingleLayoutViewModel'
340
+ }
341
+ }
342
+ }
343
+ if (submessage.messageType === RichSubMessageType.LATEX) {
344
+ const lm = submessage.latexMetadata
345
+ const key = 'PONTA_LATEX_0'
346
+ return {
347
+ view_model: {
348
+ primitive: {
349
+ text: `{{${key}}}${lm.text || 'image'}{{/${key}}}`,
350
+ inline_entities: [{
351
+ key,
352
+ metadata: {
353
+ latex_expression: lm.text || '',
354
+ latex_image: { url: lm.url, width: lm.width || 100, height: lm.height || 100 },
355
+ font_height: lm.font_height || 83.33,
356
+ padding: lm.padding || 15,
357
+ __typename: 'GenAILatexItem'
358
+ }
359
+ }],
360
+ __typename: 'GenAIMarkdownTextUXPrimitive'
361
+ },
362
+ __typename: 'GenAISingleLayoutViewModel'
363
+ }
364
+ }
365
+ }
215
366
  return {}
216
367
  })
217
368
  })
@@ -238,19 +389,31 @@ const prepareRichResponseMessage = (content) => {
238
389
 
239
390
  // Normalize ke array of items
240
391
  // Support:
241
- // { code, language } — single code block
242
- // { codes: [{ code, language }, ...] } — multi code block
243
- // { table: { title?, headers?, rows } } — single table
244
- // { richText: 'string' } — single text
245
- // { items: [{ text } | { code, language } | { table }] } mixed, bebas urutan
246
- // { richResponse: [{ text, inlineEntities? } | { code, language } full array mode
247
- // | { table, title? } | { inlineImage } | ...] }
392
+ // { code, language } — single code block
393
+ // { codes: [{ code, language }, ...] } — multi code block
394
+ // { table: { title?, headers?, rows } } — single table
395
+ // { richText: 'string' } — single text
396
+ // { richImages: 'url' | ['url1', 'url2'] } image grid shorthand
397
+ // { richSuggestions: ['a', 'b'] } suggestion pills shorthand
398
+ // { richLatex: 'url' | { url, text?, ... } } latex shorthand
399
+ // { richProduct: {} | [{}] } — product card(s) shorthand
400
+ // { richPost: {} | [{}] } — post card(s) shorthand
401
+ // { richReels: {} | [{}] } — reels carousel shorthand
402
+ // { richSources: [{...}|[fav,url,name]] } — search sources shorthand
403
+ // { richTip: 'text' } — tip/metadata text shorthand
404
+ // { richFooter: 'text' } — footer text shorthand
405
+ // { items: [{ text }|{ code }|{ table }|{ videoUrl }|{ images }|{ suggestions }
406
+ // |{ latexUrl }|{ product }|{ post }|{ reels }
407
+ // |{ sources }|{ tip }|{ footer }] }
408
+ // { richResponse: [{ text }|{ code }|{ table }|{ video }|{ images }|{ suggestions }
409
+ // |{ latex }|{ product }|{ post }|{ reels }
410
+ // |{ sources }|{ tip }|{ footer }] }
248
411
 
249
412
  let submessages = []
250
413
 
251
414
  if (Array.isArray(content.richResponse)) {
252
- // ── richResponse array mode (dari Lia) ────────────────────────────────
253
- submessages = content.richResponse.map(sub => {
415
+ // ── richResponse array mode ───────────────────────────────────────────
416
+ submessages = content.richResponse.flatMap(sub => {
254
417
  if (sub.text !== undefined) {
255
418
  return {
256
419
  messageType: RichSubMessageType.TEXT,
@@ -277,9 +440,181 @@ const prepareRichResponseMessage = (content) => {
277
440
  }
278
441
  }
279
442
  }
443
+ if (sub.images !== undefined) {
444
+ const raw = sub.images
445
+ const urls = typeof raw === 'string' ? [raw] : (Array.isArray(raw) ? raw : [raw])
446
+ const mimeType = 'image/jpeg'
447
+ return {
448
+ messageType: RichSubMessageType.IMAGES,
449
+ gridImageMetadata: {
450
+ gridImageUrl: { imagePreviewUrl: urls[0] },
451
+ imageUrls: urls.map(url => ({ imagePreviewUrl: url, imageHighResUrl: url, sourceUrl: url }))
452
+ },
453
+ _imageUrls: urls,
454
+ _mimeType: mimeType
455
+ }
456
+ }
457
+ if (sub.video !== undefined) {
458
+ const url = typeof sub.video === 'string' ? sub.video : sub.video.url
459
+ const mimeType = (typeof sub.video === 'object' && sub.video.mimeType) || 'video/mp4'
460
+ const duration = (typeof sub.video === 'object' && sub.video.duration) || 10
461
+ const fallbackText = (typeof sub.video === 'object' && sub.video.fallbackText) || '[ VIDEO - PontaCT ]'
462
+ return [
463
+ { messageType: RichSubMessageType.TEXT, messageText: fallbackText },
464
+ { messageType: RichSubMessageType.VIDEO, videoMetadata: { url, mimeType, duration } }
465
+ ]
466
+ }
467
+ if (sub.suggestions !== undefined) {
468
+ const arr = Array.isArray(sub.suggestions) ? sub.suggestions : [sub.suggestions]
469
+ return { messageType: RichSubMessageType.SUGGESTIONS, suggestions: arr }
470
+ }
471
+ if (sub.latex !== undefined) {
472
+ const raw = sub.latex
473
+ const url = typeof raw === 'string' ? raw : raw.url
474
+ const text = (typeof raw === 'object' && raw.text) || ''
475
+ return [
476
+ { messageType: RichSubMessageType.TEXT, messageText: text || '[latex]' },
477
+ {
478
+ messageType: RichSubMessageType.LATEX,
479
+ latexMetadata: {
480
+ url,
481
+ text,
482
+ width: Number((typeof raw === 'object' && raw.width) || 100),
483
+ height: Number((typeof raw === 'object' && raw.height) || 100),
484
+ font_height: Number((typeof raw === 'object' && raw.font_height) || 83.33),
485
+ padding: Number((typeof raw === 'object' && raw.padding) || 15)
486
+ }
487
+ }
488
+ ]
489
+ }
490
+ if (sub.product !== undefined) {
491
+ const isMultiple = Array.isArray(sub.product)
492
+ const products = isMultiple ? sub.product : [sub.product]
493
+ return [
494
+ { messageType: RichSubMessageType.TEXT, messageText: '[ PRODUCT - PontaCT ]' },
495
+ { messageType: RichSubMessageType.PRODUCT, productMetadata: { isMultiple, products } }
496
+ ]
497
+ }
498
+ if (sub.post !== undefined) {
499
+ const isMultiple = Array.isArray(sub.post)
500
+ const posts = isMultiple ? sub.post : [sub.post]
501
+ return [
502
+ { messageType: RichSubMessageType.TEXT, messageText: '[ POST - PontaCT ]' },
503
+ { messageType: RichSubMessageType.POST, postMetadata: { isMultiple, posts } }
504
+ ]
505
+ }
506
+ if (sub.reels !== undefined) {
507
+ const reelItems = Array.isArray(sub.reels) ? sub.reels : [sub.reels]
508
+ return {
509
+ messageType: RichSubMessageType.REELS,
510
+ contentItemsMetadata: {
511
+ contentType: 1,
512
+ itemsMetadata: reelItems.map(i => ({
513
+ reelItem: { title: i.title, profileIconUrl: i.profileIconUrl, thumbnailUrl: i.thumbnailUrl, videoUrl: i.videoUrl }
514
+ }))
515
+ },
516
+ _reelItems: reelItems
517
+ }
518
+ }
519
+ if (sub.sources !== undefined) {
520
+ const arr = Array.isArray(sub.sources) ? sub.sources : [sub.sources]
521
+ return { messageType: RichSubMessageType.SOURCES, sourcesMetadata: { sources: arr } }
522
+ }
523
+ if (sub.tip !== undefined) {
524
+ return { messageType: RichSubMessageType.TIP, tipText: sub.tip }
525
+ }
526
+ if (sub.footer !== undefined) {
527
+ return { messageType: RichSubMessageType.FOOTER, footerText: sub.footer }
528
+ }
280
529
  // passthrough — kalau ada tipe lain langsung lewat
281
530
  return sub
282
531
  })
532
+ } else if ('richImages' in content) {
533
+ // ── richImages shorthand ──────────────────────────────────────────────
534
+ const raw = content.richImages
535
+ const urls = typeof raw === 'string' ? [raw] : (Array.isArray(raw) ? raw : [raw])
536
+ submessages = [{
537
+ messageType: RichSubMessageType.IMAGES,
538
+ gridImageMetadata: {
539
+ gridImageUrl: { imagePreviewUrl: urls[0] },
540
+ imageUrls: urls.map(url => ({ imagePreviewUrl: url, imageHighResUrl: url, sourceUrl: url }))
541
+ },
542
+ _imageUrls: urls,
543
+ _mimeType: 'image/jpeg'
544
+ }]
545
+ } else if ('richVideo' in content) {
546
+ // ── richVideo shorthand ───────────────────────────────────────────────
547
+ const rawVideo = content.richVideo
548
+ const url = typeof rawVideo === 'string' ? rawVideo : rawVideo.url
549
+ const mimeType = (typeof rawVideo === 'object' && rawVideo.mimeType) || 'video/mp4'
550
+ const duration = (typeof rawVideo === 'object' && rawVideo.duration) || 10
551
+ const fallbackText = (typeof rawVideo === 'object' && rawVideo.fallbackText) || '[ VIDEO - PontaCT ]'
552
+ submessages = [
553
+ { messageType: RichSubMessageType.TEXT, messageText: fallbackText },
554
+ { messageType: RichSubMessageType.VIDEO, videoMetadata: { url, mimeType, duration } }
555
+ ]
556
+ } else if ('richSuggestions' in content) {
557
+ // ── richSuggestions shorthand ─────────────────────────────────────────
558
+ const arr = Array.isArray(content.richSuggestions) ? content.richSuggestions : [content.richSuggestions]
559
+ submessages = [{ messageType: RichSubMessageType.SUGGESTIONS, suggestions: arr }]
560
+ } else if ('richLatex' in content) {
561
+ // ── richLatex shorthand ───────────────────────────────────────────────
562
+ const raw = content.richLatex
563
+ const url = typeof raw === 'string' ? raw : raw.url
564
+ const text = (typeof raw === 'object' && raw.text) || ''
565
+ submessages = [
566
+ { messageType: RichSubMessageType.TEXT, messageText: text || '[latex]' },
567
+ {
568
+ messageType: RichSubMessageType.LATEX,
569
+ latexMetadata: {
570
+ url,
571
+ text,
572
+ width: Number((typeof raw === 'object' && raw.width) || 100),
573
+ height: Number((typeof raw === 'object' && raw.height) || 100),
574
+ font_height: Number((typeof raw === 'object' && raw.font_height) || 83.33),
575
+ padding: Number((typeof raw === 'object' && raw.padding) || 15)
576
+ }
577
+ }
578
+ ]
579
+ } else if ('richProduct' in content) {
580
+ // ── richProduct shorthand ─────────────────────────────────────────────
581
+ const isMultiple = Array.isArray(content.richProduct)
582
+ const products = isMultiple ? content.richProduct : [content.richProduct]
583
+ submessages = [
584
+ { messageType: RichSubMessageType.TEXT, messageText: '[ PRODUCT - PontaCT ]' },
585
+ { messageType: RichSubMessageType.PRODUCT, productMetadata: { isMultiple, products } }
586
+ ]
587
+ } else if ('richPost' in content) {
588
+ // ── richPost shorthand ────────────────────────────────────────────────
589
+ const isMultiple = Array.isArray(content.richPost)
590
+ const posts = isMultiple ? content.richPost : [content.richPost]
591
+ submessages = [
592
+ { messageType: RichSubMessageType.TEXT, messageText: '[ POST - PontaCT ]' },
593
+ { messageType: RichSubMessageType.POST, postMetadata: { isMultiple, posts } }
594
+ ]
595
+ } else if ('richReels' in content) {
596
+ // ── richReels shorthand ───────────────────────────────────────────────
597
+ const reelItems = Array.isArray(content.richReels) ? content.richReels : [content.richReels]
598
+ submessages = [{
599
+ messageType: RichSubMessageType.REELS,
600
+ contentItemsMetadata: {
601
+ contentType: 1,
602
+ itemsMetadata: reelItems.map(i => ({
603
+ reelItem: { title: i.title, profileIconUrl: i.profileIconUrl, thumbnailUrl: i.thumbnailUrl, videoUrl: i.videoUrl }
604
+ }))
605
+ },
606
+ _reelItems: reelItems
607
+ }]
608
+ } else if ('richSources' in content) {
609
+ // ── richSources shorthand ─────────────────────────────────────────────
610
+ const arr = Array.isArray(content.richSources) ? content.richSources : [content.richSources]
611
+ submessages = [{ messageType: RichSubMessageType.SOURCES, sourcesMetadata: { sources: arr } }]
612
+ } else if ('richTip' in content) {
613
+ // ── richTip shorthand ─────────────────────────────────────────────────
614
+ submessages = [{ messageType: RichSubMessageType.TIP, tipText: content.richTip }]
615
+ } else if ('richFooter' in content) {
616
+ // ── richFooter shorthand ──────────────────────────────────────────────
617
+ submessages = [{ messageType: RichSubMessageType.FOOTER, footerText: content.richFooter }]
283
618
  } else {
284
619
  // ── shorthand / items mode ────────────────────────────────────────────
285
620
  let items = []
@@ -308,6 +643,113 @@ const prepareRichResponseMessage = (content) => {
308
643
  }
309
644
  }
310
645
 
646
+ // ── IMAGES ────────────────────────────────────────────────────────
647
+ if ('images' in item) {
648
+ const raw = item.images
649
+ const urls = typeof raw === 'string' ? [raw] : (Array.isArray(raw) ? raw : [raw])
650
+ return {
651
+ messageType: RichSubMessageType.IMAGES,
652
+ gridImageMetadata: {
653
+ gridImageUrl: { imagePreviewUrl: urls[0] },
654
+ imageUrls: urls.map(url => ({ imagePreviewUrl: url, imageHighResUrl: url, sourceUrl: url }))
655
+ },
656
+ _imageUrls: urls,
657
+ _mimeType: 'image/jpeg'
658
+ }
659
+ }
660
+
661
+ // ── VIDEO ─────────────────────────────────────────────────────────
662
+ if ('videoUrl' in item) {
663
+ const fallbackText = item.fallbackText || '[ VIDEO - PontaCT ]'
664
+ return [
665
+ { messageType: RichSubMessageType.TEXT, messageText: fallbackText },
666
+ {
667
+ messageType: RichSubMessageType.VIDEO,
668
+ videoMetadata: {
669
+ url: item.videoUrl,
670
+ mimeType: item.mimeType || 'video/mp4',
671
+ duration: item.duration || 10
672
+ }
673
+ }
674
+ ]
675
+ }
676
+
677
+ // ── SUGGESTIONS ───────────────────────────────────────────────────
678
+ if ('suggestions' in item) {
679
+ const arr = Array.isArray(item.suggestions) ? item.suggestions : [item.suggestions]
680
+ return { messageType: RichSubMessageType.SUGGESTIONS, suggestions: arr }
681
+ }
682
+
683
+ // ── LATEX ─────────────────────────────────────────────────────────
684
+ if ('latexUrl' in item) {
685
+ const text = item.latexText || ''
686
+ return [
687
+ { messageType: RichSubMessageType.TEXT, messageText: text || '[latex]' },
688
+ {
689
+ messageType: RichSubMessageType.LATEX,
690
+ latexMetadata: {
691
+ url: item.latexUrl,
692
+ text,
693
+ width: Number(item.latexWidth || 100),
694
+ height: Number(item.latexHeight || 100),
695
+ font_height: Number(item.latexFontHeight || 83.33),
696
+ padding: Number(item.latexPadding || 15)
697
+ }
698
+ }
699
+ ]
700
+ }
701
+
702
+ // ── PRODUCT ───────────────────────────────────────────────────────
703
+ if ('product' in item) {
704
+ const isMultiple = Array.isArray(item.product)
705
+ const products = isMultiple ? item.product : [item.product]
706
+ return [
707
+ { messageType: RichSubMessageType.TEXT, messageText: '[ PRODUCT - PontaCT ]' },
708
+ { messageType: RichSubMessageType.PRODUCT, productMetadata: { isMultiple, products } }
709
+ ]
710
+ }
711
+
712
+ // ── POST ──────────────────────────────────────────────────────────
713
+ if ('post' in item) {
714
+ const isMultiple = Array.isArray(item.post)
715
+ const posts = isMultiple ? item.post : [item.post]
716
+ return [
717
+ { messageType: RichSubMessageType.TEXT, messageText: '[ POST - PontaCT ]' },
718
+ { messageType: RichSubMessageType.POST, postMetadata: { isMultiple, posts } }
719
+ ]
720
+ }
721
+
722
+ // ── REELS ─────────────────────────────────────────────────────────
723
+ if ('reels' in item) {
724
+ const reelItems = Array.isArray(item.reels) ? item.reels : [item.reels]
725
+ return {
726
+ messageType: RichSubMessageType.REELS,
727
+ contentItemsMetadata: {
728
+ contentType: 1,
729
+ itemsMetadata: reelItems.map(i => ({
730
+ reelItem: { title: i.title, profileIconUrl: i.profileIconUrl, thumbnailUrl: i.thumbnailUrl, videoUrl: i.videoUrl }
731
+ }))
732
+ },
733
+ _reelItems: reelItems
734
+ }
735
+ }
736
+
737
+ // ── SOURCES ───────────────────────────────────────────────────────
738
+ if ('sources' in item) {
739
+ const arr = Array.isArray(item.sources) ? item.sources : [item.sources]
740
+ return { messageType: RichSubMessageType.SOURCES, sourcesMetadata: { sources: arr } }
741
+ }
742
+
743
+ // ── TIP ───────────────────────────────────────────────────────────
744
+ if ('tip' in item) {
745
+ return { messageType: RichSubMessageType.TIP, tipText: item.tip }
746
+ }
747
+
748
+ // ── FOOTER ────────────────────────────────────────────────────────
749
+ if ('footer' in item) {
750
+ return { messageType: RichSubMessageType.FOOTER, footerText: item.footer }
751
+ }
752
+
311
753
  // ── TABLE ─────────────────────────────────────────────────────────
312
754
  if (item.table) {
313
755
  const { title, headers, rows } = item.table
@@ -354,9 +796,22 @@ const prepareRichResponseMessage = (content) => {
354
796
  const unified = toUnified(submessages, uuid)
355
797
  const aiForwarded = content.aiForwarded !== false
356
798
 
799
+ const pontaSources = submessages
800
+ .filter(s => s.messageType === RichSubMessageType.REELS && s._reelItems)
801
+ .flatMap(s => (s._reelItems || []).map((i, idx) => ({
802
+ provider: 'PontaCT',
803
+ thumbnailCDNURL: i.thumbnailUrl,
804
+ sourceProviderURL: i.videoUrl,
805
+ sourceQuery: '',
806
+ faviconCDNURL: i.profileIconUrl,
807
+ citationNumber: idx + 1,
808
+ sourceTitle: i.title
809
+ })))
810
+
357
811
  return {
358
812
  messageContextInfo: {
359
813
  botMetadata: {
814
+ ...(pontaSources.length ? { richResponseSourcesMetadata: { sources: pontaSources } } : {}),
360
815
  verificationMetadata: {
361
816
  proofs: [{
362
817
  certificateChain: [botMetadataCertificate(), botMetadataCertificate(892)],
@@ -8,6 +8,7 @@ Object.defineProperty(exports, "__esModule", { value: true })
8
8
 
9
9
  const async_mutex_1 = __importDefault(require("async-mutex"))
10
10
  const promises_1 = require("fs/promises")
11
+ const { rename: fsRename } = promises_1
11
12
  const path_1 = require("path")
12
13
  const WAProto_1 = require("../../WAProto")
13
14
  const auth_utils_1 = require("./auth-utils")
@@ -37,13 +38,20 @@ const getFileLock = (path) => {
37
38
  * Would recommend writing an auth state for use with a proper SQL or No-SQL DB
38
39
  * */
39
40
  const useMultiFileAuthState = async (folder) => {
41
+ // Debounce timers per file to avoid rapid successive writes hammering disk
42
+ const writeDebounceTimers = new Map()
43
+ const WRITE_DEBOUNCE_MS = 300
44
+
40
45
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
46
  const writeData = async (data, file) => {
42
47
  const filePath = path_1.join(folder, fixFileName(file))
43
48
  const mutex = getFileLock(filePath)
44
49
  return mutex.acquire().then(async (release) => {
45
50
  try {
46
- await promises_1.writeFile(filePath, JSON.stringify(data, generics_1.BufferJSON.replacer))
51
+ // Atomic write: write to temp file then rename to prevent corruption
52
+ const tmpPath = filePath + '.tmp'
53
+ await promises_1.writeFile(tmpPath, JSON.stringify(data, generics_1.BufferJSON.replacer))
54
+ await fsRename(tmpPath, filePath)
47
55
  } finally {
48
56
  release()
49
57
  }
@@ -120,7 +128,24 @@ const useMultiFileAuthState = async (folder) => {
120
128
  }
121
129
  }
122
130
  },
123
- saveCreds: async () => {
131
+ // saveCreds debounced by default — aman dipanggil tiap creds.update
132
+ // tanpa spam disk. Untuk force immediate write, pakai saveCredsNow.
133
+ saveCreds: () => {
134
+ const existing = writeDebounceTimers.get('creds.json')
135
+ if (existing) clearTimeout(existing)
136
+ const timer = setTimeout(() => {
137
+ writeDebounceTimers.delete('creds.json')
138
+ writeData(creds, 'creds.json').catch(err => {
139
+ console.error('[useMultiFileAuthState] Failed to save creds.json:', err)
140
+ })
141
+ }, WRITE_DEBOUNCE_MS)
142
+ writeDebounceTimers.set('creds.json', timer)
143
+ },
144
+ // Force immediate write — pakai saat disconnect/cleanup agar creds tidak hilang
145
+ saveCredsNow: async () => {
146
+ const existing = writeDebounceTimers.get('creds.json')
147
+ if (existing) clearTimeout(existing)
148
+ writeDebounceTimers.delete('creds.json')
124
149
  return writeData(creds, 'creds.json')
125
150
  }
126
151
  }
@@ -128,4 +153,4 @@ const useMultiFileAuthState = async (folder) => {
128
153
 
129
154
  module.exports = {
130
155
  useMultiFileAuthState
131
- }
156
+ }
@@ -58,7 +58,7 @@ const generateLoginNode = (userJid, config) => {
58
58
  const { user, device } = WABinary_1.jidDecode(userJid)
59
59
  const payload = {
60
60
  ...getClientPayload(config),
61
- passive: false,
61
+ passive: true,
62
62
  pull: true,
63
63
  username: +user,
64
64
  device: device,
@@ -185,4 +185,4 @@ module.exports = {
185
185
  generateRegistrationNode,
186
186
  configureSuccessfulPairing,
187
187
  encodeSignedDeviceIdentity
188
- }
188
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pontasockets/baileys",
3
- "version": "0.3.3",
3
+ "version": "1.0.1",
4
4
  "description": "Baileys is a lightweight JavaScript library for interacting with the WhatsApp Web API using WebSocket.",
5
5
  "keywords": [
6
6
  "facebook",