@nuiisweety/baileys 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,6 +19,22 @@ const buildLatexUrl = (expression) => {
19
19
  return `https://latex.codecogs.com/png.image?\dpi{150}\bg{white}${encoded}`;
20
20
  };
21
21
 
22
+ /* ─────────────────────────────────────────────────────────────
23
+ IMAGE URL HELPER
24
+ Konversi objek AIRichResponseImageURL ke snake_case JSON
25
+ agar WA client bisa baca dengan benar~
26
+ ───────────────────────────────────────────────────────────── */
27
+ const toImageUrlJson = (imgUrl) => {
28
+ if (!imgUrl) return null;
29
+ // support both plain string and object
30
+ if (typeof imgUrl === 'string') return { image_preview_url: imgUrl, image_high_res_url: imgUrl, source_url: null };
31
+ return {
32
+ image_preview_url: imgUrl.imagePreviewUrl || imgUrl.image_preview_url || null,
33
+ image_high_res_url: imgUrl.imageHighResUrl || imgUrl.image_high_res_url || null,
34
+ source_url: imgUrl.sourceUrl || imgUrl.source_url || null
35
+ };
36
+ };
37
+
22
38
  /* ─────────────────────────────────────────────────────────────
23
39
  TOKENIZER
24
40
  ───────────────────────────────────────────────────────────── */
@@ -259,8 +275,8 @@ const buildUnifiedSection = (submessage) => {
259
275
  return {
260
276
  view_model: {
261
277
  primitive: {
262
- grid_image_url: gm.gridImageUrl,
263
- image_urls: gm.imageUrls,
278
+ grid_image_url: toImageUrlJson(gm.gridImageUrl),
279
+ image_urls: (gm.imageUrls || []).map(toImageUrlJson),
264
280
  __typename: 'GenAIGridImageUXPrimitive'
265
281
  },
266
282
  __typename: 'GenAISingleLayoutViewModel'
@@ -273,7 +289,7 @@ const buildUnifiedSection = (submessage) => {
273
289
  return {
274
290
  view_model: {
275
291
  primitive: {
276
- image_url: im.imageUrl,
292
+ image_url: toImageUrlJson(im.imageUrl),
277
293
  image_text: im.imageText,
278
294
  alignment: im.alignment ?? 0,
279
295
  tap_link_url: im.tapLinkUrl || null,
@@ -416,16 +432,35 @@ const makeTableSub = (rows, title, noHeading) => ({
416
432
  }
417
433
  });
418
434
 
435
+ /** Normalize input ke format AIRichResponseImageURL */
436
+ const normalizeImageUrl = (u) => {
437
+ if (!u) return null;
438
+ if (typeof u === 'string') return { imagePreviewUrl: u, imageHighResUrl: u, sourceUrl: null };
439
+ return {
440
+ imagePreviewUrl: u.imagePreviewUrl || u.image_preview_url || null,
441
+ imageHighResUrl: u.imageHighResUrl || u.image_high_res_url || null,
442
+ sourceUrl: u.sourceUrl || u.source_url || null
443
+ };
444
+ };
445
+
419
446
  /** Buat submessage GRID_IMAGE */
420
447
  const makeGridImageSub = (gridImageUrl, imageUrls = []) => ({
421
448
  messageType: RichSubMessageType.GRID_IMAGE,
422
- gridImageMetadata: { gridImageUrl, imageUrls }
449
+ gridImageMetadata: {
450
+ gridImageUrl: normalizeImageUrl(gridImageUrl),
451
+ imageUrls: (imageUrls || []).map(normalizeImageUrl)
452
+ }
423
453
  });
424
454
 
425
455
  /** Buat submessage INLINE_IMAGE */
426
456
  const makeInlineImageSub = (imageUrl, imageText = '', alignment = 0, tapLinkUrl = null) => ({
427
457
  messageType: RichSubMessageType.INLINE_IMAGE,
428
- imageMetadata: { imageUrl, imageText, alignment, tapLinkUrl }
458
+ imageMetadata: {
459
+ imageUrl: normalizeImageUrl(imageUrl),
460
+ imageText,
461
+ alignment,
462
+ tapLinkUrl
463
+ }
429
464
  });
430
465
 
431
466
  /** Buat submessage DYNAMIC (animated image/GIF) */
@@ -499,6 +534,231 @@ const makeContentItemsSub = (items, contentType = 0) => ({
499
534
  }
500
535
  });
501
536
 
537
+ /** Buat section SOURCE (search result links) — hanya unified, tidak ada submessage proto */
538
+ const makeSourceSection = (sources = []) => {
539
+ const list = Array.isArray(sources) ? sources : [sources];
540
+ return {
541
+ view_model: {
542
+ primitive: {
543
+ sources: list.map(s => ({
544
+ source_url: s.url ?? s.source_url ?? '',
545
+ source_title: s.title ?? s.source_title ?? '',
546
+ source_display_name: s.display_name ?? s.displayName ?? s.title ?? '',
547
+ source_subtitle: s.subtitle ?? s.source_subtitle ?? '',
548
+ source_type: s.source_type ?? 'THIRD_PARTY',
549
+ favicon: {
550
+ url: s.favicon ?? s.faviconCDNURL ?? '',
551
+ width: 16,
552
+ height: 16
553
+ }
554
+ })),
555
+ __typename: 'GenAISearchResultPrimitive'
556
+ },
557
+ __typename: 'GenAISingleLayoutViewModel'
558
+ }
559
+ };
560
+ };
561
+
562
+ /** Buat submessage + unified section untuk IMAGE (grid image style) */
563
+ const makeImageSub = (imageUrl) => {
564
+ const urls = Array.isArray(imageUrl) ? imageUrl : [imageUrl];
565
+ const imageUrls = urls.map(u => ({
566
+ imagePreviewUrl: u,
567
+ imageHighResUrl: u,
568
+ sourceUrl: null
569
+ }));
570
+ return {
571
+ sub: {
572
+ messageType: RichSubMessageType.GRID_IMAGE,
573
+ gridImageMetadata: {
574
+ gridImageUrl: normalizeImageUrl(urls[0]),
575
+ imageUrls: imageUrls.map(normalizeImageUrl)
576
+ }
577
+ },
578
+ sections: imageUrls.map(({ imagePreviewUrl }) => ({
579
+ view_model: {
580
+ primitive: {
581
+ media: { url: imagePreviewUrl, mime_type: 'image/png' },
582
+ imagine_type: 'IMAGE',
583
+ status: { status: 'READY' },
584
+ __typename: 'GenAIImaginePrimitive'
585
+ },
586
+ __typename: 'GenAISingleLayoutViewModel'
587
+ }
588
+ }))
589
+ };
590
+ };
591
+
592
+ /** Buat submessage + unified section untuk VIDEO */
593
+ const makeVideoSub = (videoUrl) => {
594
+ const urls = Array.isArray(videoUrl) ? videoUrl : [videoUrl];
595
+ const parsed = urls.map(item => {
596
+ const [url, duration = '0'] = item.split('|');
597
+ return { url, duration: Number(duration) || 0 };
598
+ });
599
+ return {
600
+ sub: {
601
+ messageType: RichSubMessageType.TEXT,
602
+ messageText: '[ CANNOT_LOAD_VIDEO ]'
603
+ },
604
+ sections: parsed.map(({ url, duration }) => ({
605
+ view_model: {
606
+ primitive: {
607
+ media: { url, mime_type: 'video/mp4', duration },
608
+ imagine_type: 'ANIMATE',
609
+ status: { status: 'READY' },
610
+ __typename: 'GenAIImaginePrimitive'
611
+ },
612
+ __typename: 'GenAISingleLayoutViewModel'
613
+ }
614
+ }))
615
+ };
616
+ };
617
+
618
+ /** Buat submessage + unified section untuk REELS (HScroll) */
619
+ const makeReelsSub = (reelsItems = []) => {
620
+ const list = Array.isArray(reelsItems) ? reelsItems : [reelsItems];
621
+ return {
622
+ sub: {
623
+ messageType: RichSubMessageType.CONTENT_ITEMS,
624
+ contentItemsMetadata: {
625
+ contentType: 1,
626
+ itemsMetadata: list.map(item => ({
627
+ reelItem: {
628
+ title: item.username ?? item.title ?? '',
629
+ profileIconUrl: item.profileIconUrl ?? item.profile_url ?? null,
630
+ thumbnailUrl: item.thumbnailUrl ?? item.thumbnail ?? null,
631
+ videoUrl: item.videoUrl ?? item.url ?? null
632
+ }
633
+ }))
634
+ }
635
+ },
636
+ section: {
637
+ view_model: {
638
+ primitives: list.map(item => ({
639
+ reels_url: item.videoUrl ?? item.url ?? '',
640
+ thumbnail_url: item.thumbnailUrl ?? item.thumbnail ?? '',
641
+ creator: item.username ?? item.title ?? '',
642
+ avatar_url: item.profileIconUrl ?? item.profile_url ?? '',
643
+ reels_title: item.reels_title ?? item.title ?? '',
644
+ likes_count: item.likes_count ?? item.like ?? 0,
645
+ shares_count: item.shares_count ?? item.share ?? 0,
646
+ view_count: item.view_count ?? item.view ?? 0,
647
+ reel_source: item.reel_source ?? item.source ?? 'IG',
648
+ is_verified: !!(item.is_verified || item.verified),
649
+ __typename: 'GenAIReelPrimitive'
650
+ })),
651
+ __typename: 'GenAIHScrollLayoutViewModel'
652
+ }
653
+ }
654
+ };
655
+ };
656
+
657
+ /** Buat unified section untuk PRODUCT (single: Single layout, array: HScroll) */
658
+ const makeProductSection = (data) => {
659
+ const items = Array.isArray(data) ? data : [data];
660
+ const primitives = items.map(item => ({
661
+ title: item.title ?? '',
662
+ brand: item.brand ?? '',
663
+ price: item.price ?? '',
664
+ sale_price: item.sale_price ?? item.salePrice ?? '',
665
+ product_url: item.product_url ?? item.url ?? '',
666
+ image: { url: item.image_url ?? item.image ?? '' },
667
+ additional_images: [{ url: item.icon_url ?? item.icon ?? '' }],
668
+ __typename: 'GenAIProductItemCardPrimitive'
669
+ }));
670
+ const isMultiple = Array.isArray(data);
671
+ return {
672
+ sub: {
673
+ messageType: RichSubMessageType.TEXT,
674
+ messageText: '[ CANNOT_LOAD_PRODUCT ]'
675
+ },
676
+ section: isMultiple
677
+ ? {
678
+ view_model: {
679
+ primitives,
680
+ __typename: 'GenAIHScrollLayoutViewModel'
681
+ }
682
+ }
683
+ : {
684
+ view_model: {
685
+ primitive: primitives[0],
686
+ __typename: 'GenAISingleLayoutViewModel'
687
+ }
688
+ }
689
+ };
690
+ };
691
+
692
+ /** Buat unified section untuk POST (HScroll) */
693
+ const makePostSection = (data) => {
694
+ const posts = Array.isArray(data) ? data : [data];
695
+ const primitives = posts.map(p => ({
696
+ title: p.title ?? '',
697
+ subtitle: p.subtitle ?? '',
698
+ username: p.username ?? '',
699
+ profile_picture_url: p.profile_picture_url ?? p.profile_url ?? '',
700
+ is_verified: !!(p.is_verified || p.verified),
701
+ thumbnail_url: p.thumbnail_url ?? p.thumbnail ?? '',
702
+ post_caption: p.post_caption ?? p.caption ?? '',
703
+ likes_count: p.likes_count ?? p.like ?? 0,
704
+ comments_count: p.comments_count ?? p.comment ?? 0,
705
+ shares_count: p.shares_count ?? p.share ?? 0,
706
+ post_url: p.post_url ?? p.url ?? '',
707
+ post_deeplink: p.post_deeplink ?? p.deeplink ?? '',
708
+ source_app: p.source_app ?? p.source ?? 'INSTAGRAM',
709
+ footer_label: p.footer_label ?? p.footer ?? '',
710
+ footer_icon: p.footer_icon ?? p.icon ?? '',
711
+ is_carousel: posts.length > 1,
712
+ orientation: p.orientation ?? 'LANDSCAPE',
713
+ post_type: p.post_type ?? 'VIDEO',
714
+ __typename: 'GenAIPostPrimitive'
715
+ }));
716
+ return {
717
+ sub: {
718
+ messageType: RichSubMessageType.TEXT,
719
+ messageText: '[ CANNOT_LOAD_POST ]'
720
+ },
721
+ section: {
722
+ view_model: {
723
+ primitives,
724
+ __typename: 'GenAIHScrollLayoutViewModel'
725
+ }
726
+ }
727
+ };
728
+ };
729
+
730
+ /** Buat submessage + unified section untuk TIP (metadata text) */
731
+ const makeTipSub = (text) => ({
732
+ sub: {
733
+ messageType: RichSubMessageType.TEXT,
734
+ messageText: text
735
+ },
736
+ section: {
737
+ view_model: {
738
+ primitive: {
739
+ text,
740
+ __typename: 'GenAIMetadataTextPrimitive'
741
+ },
742
+ __typename: 'GenAISingleLayoutViewModel'
743
+ }
744
+ }
745
+ });
746
+
747
+ /** Buat unified section untuk SUGGEST (ActionRow pill buttons) — tidak ada submessage proto */
748
+ const makeSuggestSection = (suggestion) => {
749
+ const suggestions = Array.isArray(suggestion) ? suggestion : [suggestion];
750
+ return {
751
+ view_model: {
752
+ primitives: suggestions.map(text => ({
753
+ prompt_text: text,
754
+ prompt_type: 'SUGGESTED_PROMPT',
755
+ __typename: 'GenAIFollowUpSuggestionPillPrimitive'
756
+ })),
757
+ __typename: 'GenAIActionRowLayoutViewModel'
758
+ }
759
+ };
760
+ };
761
+
502
762
  /* ─────────────────────────────────────────────────────────────
503
763
  MAIN BUILDER — prepareRichResponseMessage
504
764
  ───────────────────────────────────────────────────────────── */
@@ -507,29 +767,54 @@ export const prepareRichResponseMessage = (content) => {
507
767
  const {
508
768
  code, contentText, disclaimerText, footerText, headerText,
509
769
  language, links, noHeading, richResponse, table, title,
510
- // sub-types baru
770
+ // sub-types lama
511
771
  gridImage, inlineImage, dynamic: dynamicContent,
512
- map: mapContent, latex, contentItems
772
+ map: mapContent, latex, contentItems,
773
+ // sub-types baru
774
+ image, video, reels, source, product, post, tip, suggest
513
775
  } = content;
514
776
 
515
777
  let submessages = [];
778
+ // extraSections: section-section unified yang tidak punya proto submessage 1:1
779
+ // (source, product, post, suggest) atau punya struktur multi-section (image, video, reels)
780
+ let extraSections = null;
781
+
782
+ /**
783
+ * Helper: push ke submessages dan optionally ke extraSections.
784
+ * Untuk tipe yang punya make*Sub yang mengembalikan { sub, sections[] } atau { sub, section }
785
+ */
786
+ const pushRich = (built) => {
787
+ if (!built) return;
788
+ if (built.sub) submessages.push(built.sub);
789
+ if (!extraSections) extraSections = [];
790
+ if (built.sections) extraSections.push(...built.sections);
791
+ else if (built.section) extraSections.push(built.section);
792
+ };
516
793
 
517
794
  /* ── mode array (richResponse) — multi-section campuran ── */
518
795
  if (Array.isArray(richResponse)) {
519
- // headerText dan footerText tetap dihormati meskipun pakai mode array
520
796
  if (headerText) submessages.push(makeTextSub(headerText));
521
- submessages.push(...richResponse.map(sub => {
522
- if (sub.text != null) return makeTextSub(sub.text, sub.inlineEntities);
523
- if (sub.code != null) return makeCodeSub(sub.code, sub.language || 'javascript');
524
- if (sub.table != null) return makeTableSub(sub.table, sub.title, sub.noHeading);
525
- if (sub.gridImage != null) return makeGridImageSub(sub.gridImage.gridImageUrl, sub.gridImage.imageUrls);
526
- if (sub.inlineImage != null) return makeInlineImageSub(sub.inlineImage.imageUrl, sub.inlineImage.imageText, sub.inlineImage.alignment, sub.inlineImage.tapLinkUrl);
527
- if (sub.dynamic != null) return makeDynamicSub(sub.dynamic.url, sub.dynamic.type, sub.dynamic.version, sub.dynamic.loopCount);
528
- if (sub.map != null) return makeMapSub(sub.map.centerLatitude, sub.map.centerLongitude, sub.map);
529
- if (sub.latex != null) return makeLatexSub(sub.latex.text, sub.latex.expressions);
530
- if (sub.contentItems != null) return makeContentItemsSub(sub.contentItems.items, sub.contentItems.contentType);
531
- return sub; // passthrough kalau sudah bentuk proto
532
- }).filter(Boolean));
797
+ richResponse.forEach(sub => {
798
+ if (sub.text != null) { submessages.push(makeTextSub(sub.text, sub.inlineEntities)); return; }
799
+ if (sub.code != null) { submessages.push(makeCodeSub(sub.code, sub.language || 'javascript')); return; }
800
+ if (sub.table != null) { submessages.push(makeTableSub(sub.table, sub.title, sub.noHeading)); return; }
801
+ if (sub.gridImage != null) { submessages.push(makeGridImageSub(sub.gridImage.gridImageUrl, sub.gridImage.imageUrls)); return; }
802
+ if (sub.inlineImage != null) { submessages.push(makeInlineImageSub(sub.inlineImage.imageUrl, sub.inlineImage.imageText, sub.inlineImage.alignment, sub.inlineImage.tapLinkUrl)); return; }
803
+ if (sub.dynamic != null) { submessages.push(makeDynamicSub(sub.dynamic.url, sub.dynamic.type, sub.dynamic.version, sub.dynamic.loopCount)); return; }
804
+ if (sub.map != null) { submessages.push(makeMapSub(sub.map.centerLatitude, sub.map.centerLongitude, sub.map)); return; }
805
+ if (sub.latex != null) { submessages.push(makeLatexSub(sub.latex.text, sub.latex.expressions)); return; }
806
+ if (sub.contentItems != null) { submessages.push(makeContentItemsSub(sub.contentItems.items, sub.contentItems.contentType)); return; }
807
+ // tipe baru
808
+ if (sub.image != null) { pushRich(makeImageSub(sub.image)); return; }
809
+ if (sub.video != null) { pushRich(makeVideoSub(sub.video)); return; }
810
+ if (sub.reels != null) { pushRich(makeReelsSub(sub.reels)); return; }
811
+ if (sub.source != null) { if (!extraSections) extraSections = []; extraSections.push(makeSourceSection(sub.source)); return; }
812
+ if (sub.product != null) { pushRich(makeProductSection(sub.product)); return; }
813
+ if (sub.post != null) { pushRich(makePostSection(sub.post)); return; }
814
+ if (sub.tip != null) { pushRich(makeTipSub(sub.tip)); return; }
815
+ if (sub.suggest != null) { if (!extraSections) extraSections = []; extraSections.push(makeSuggestSection(sub.suggest)); return; }
816
+ submessages.push(sub); // passthrough kalau sudah bentuk proto
817
+ });
533
818
  if (footerText) submessages.push(makeTextSub(footerText));
534
819
 
535
820
  /* ── mode flat (convenience fields) ── */
@@ -537,37 +822,24 @@ export const prepareRichResponseMessage = (content) => {
537
822
  if (headerText) submessages.push(makeTextSub(headerText));
538
823
  if (contentText) submessages.push(makeTextSub(contentText));
539
824
 
540
- if (code) {
541
- submessages.push(makeCodeSub(code, language || 'javascript'));
542
- }
543
-
544
- if (table) {
545
- submessages.push(makeTableSub(table, title, noHeading));
546
- }
547
-
548
- if (gridImage) {
549
- submessages.push(makeGridImageSub(gridImage.gridImageUrl, gridImage.imageUrls));
550
- }
551
-
552
- if (inlineImage) {
553
- submessages.push(makeInlineImageSub(inlineImage.imageUrl, inlineImage.imageText, inlineImage.alignment, inlineImage.tapLinkUrl));
554
- }
555
-
556
- if (dynamicContent) {
557
- submessages.push(makeDynamicSub(dynamicContent.url, dynamicContent.type, dynamicContent.version, dynamicContent.loopCount));
558
- }
559
-
560
- if (mapContent) {
561
- submessages.push(makeMapSub(mapContent.centerLatitude, mapContent.centerLongitude, mapContent));
562
- }
563
-
564
- if (latex) {
565
- submessages.push(makeLatexSub(latex.text, latex.expressions));
566
- }
567
-
568
- if (contentItems) {
569
- submessages.push(makeContentItemsSub(contentItems.items, contentItems.contentType));
570
- }
825
+ if (code) submessages.push(makeCodeSub(code, language || 'javascript'));
826
+ if (table) submessages.push(makeTableSub(table, title, noHeading));
827
+ if (gridImage) submessages.push(makeGridImageSub(gridImage.gridImageUrl, gridImage.imageUrls));
828
+ if (inlineImage) submessages.push(makeInlineImageSub(inlineImage.imageUrl, inlineImage.imageText, inlineImage.alignment, inlineImage.tapLinkUrl));
829
+ if (dynamicContent) submessages.push(makeDynamicSub(dynamicContent.url, dynamicContent.type, dynamicContent.version, dynamicContent.loopCount));
830
+ if (mapContent) submessages.push(makeMapSub(mapContent.centerLatitude, mapContent.centerLongitude, mapContent));
831
+ if (latex) submessages.push(makeLatexSub(latex.text, latex.expressions));
832
+ if (contentItems) submessages.push(makeContentItemsSub(contentItems.items, contentItems.contentType));
833
+
834
+ // ── tipe baru ──
835
+ if (image) pushRich(makeImageSub(image));
836
+ if (video) pushRich(makeVideoSub(video));
837
+ if (reels) pushRich(makeReelsSub(reels));
838
+ if (source) { if (!extraSections) extraSections = []; extraSections.push(makeSourceSection(source)); }
839
+ if (product) pushRich(makeProductSection(product));
840
+ if (post) pushRich(makePostSection(post));
841
+ if (tip) pushRich(makeTipSub(tip));
842
+ if (suggest) { if (!extraSections) extraSections = []; extraSections.push(makeSuggestSection(suggest)); }
571
843
 
572
844
  /* links — bisa dikombinasi dengan tipe lain di atas */
573
845
  if (links && Array.isArray(links)) {
@@ -597,11 +869,14 @@ export const prepareRichResponseMessage = (content) => {
597
869
  });
598
870
  }
599
871
 
600
- if (footerText) submessages.push(makeTextSub(footerText));
872
+ if (footerText) submessages.push(makeTextSub(footerText));
601
873
  }
602
874
 
603
- /* build unifiedResponse JSON */
604
- const unified = toUnified(submessages);
875
+ /* build unifiedResponse JSON — gabungkan sections dari submessages + extraSections */
876
+ const baseUnified = toUnified(submessages);
877
+ const unified = extraSections && extraSections.length > 0
878
+ ? { ...baseUnified, sections: [...baseUnified.sections, ...extraSections] }
879
+ : baseUnified;
605
880
 
606
881
  const richResponseMessage = proto.AIRichResponseMessage.create({
607
882
  submessages,