ishumdz-bail 1.0.21 → 1.0.25
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.
- package/README.md +182 -17
- package/lib/Socket/messages-send.js +18 -10
- package/lib/Utils/messages.js +102 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -423,6 +423,19 @@ await sock.sendMessage(jid, {
|
|
|
423
423
|
> card + horizontal row, and a **custom image or GIF** works with one media upload.
|
|
424
424
|
> Set `{ nativeFlow: true }` for vertical native-flow quick_reply buttons instead.
|
|
425
425
|
|
|
426
|
+
### Button Types — Quick Reference
|
|
427
|
+
|
|
428
|
+
| Button property | Tap behavior | Since |
|
|
429
|
+
| ------------------------- | --------------------------------------------- | ------- |
|
|
430
|
+
| `buttonId` + `buttonText` | Quick reply — sends the id back to your bot | v1.0.19 |
|
|
431
|
+
| `rows` / `sections` | Opens a highlighted list sheet on tap | v1.0.22 |
|
|
432
|
+
| `url` | Opens the link / WhatsApp channel immediately | v1.0.23 |
|
|
433
|
+
| `copy` | Copies the code to the clipboard | v1.0.23 |
|
|
434
|
+
| `call` | Opens the dialer with the number | v1.0.23 |
|
|
435
|
+
|
|
436
|
+
All of them mix freely in one message and render as a single horizontal row
|
|
437
|
+
(when the message has a header) — see the full example below.
|
|
438
|
+
|
|
426
439
|
### Text + Horizontal Buttons (location header = zero uploads)
|
|
427
440
|
|
|
428
441
|
```javascript
|
|
@@ -483,6 +496,87 @@ await sock.sendMessage(jid, {
|
|
|
483
496
|
})
|
|
484
497
|
```
|
|
485
498
|
|
|
499
|
+
### Tap-to-Open List Sheet (rows on a button) — v1.0.22+
|
|
500
|
+
|
|
501
|
+
Give any horizontal button a `rows` or `sections` array and **tapping it opens a
|
|
502
|
+
highlighted list sheet** — the same sheet classic `listMessage` shows, with section
|
|
503
|
+
titles, a `highlight_label` badge and row descriptions:
|
|
504
|
+
|
|
505
|
+
```javascript
|
|
506
|
+
await sock.sendMessage(jid, {
|
|
507
|
+
image: { url: './banner.jpg' }, // or gif / location / video header
|
|
508
|
+
caption: 'Pong 9 Ms ⚡',
|
|
509
|
+
footer: 'ISHAN-X MD PRO',
|
|
510
|
+
buttons: [
|
|
511
|
+
{ buttonText: { displayText: '☰ menu' }, buttonId: 'menu', type: 1 },
|
|
512
|
+
{ buttonText: { displayText: '🔍 owner' }, buttonId: 'owner', type: 1 },
|
|
513
|
+
// 📂 this button opens the sheet on tap:
|
|
514
|
+
{
|
|
515
|
+
buttonText: { displayText: '📂 allmenus' },
|
|
516
|
+
buttonId: 'allmenus', type: 1,
|
|
517
|
+
highlightLabel: '⭐ MAIN', // optional — badge on the section
|
|
518
|
+
sectionTitle: 'All Menus', // optional — section heading
|
|
519
|
+
rows: [
|
|
520
|
+
{ title: '📥 Download Menu', description: 'Downloader commands', rowId: '.downloadmenu' },
|
|
521
|
+
{ title: '✨ AI Menu', description: 'AI commands', rowId: '.aimenu' }
|
|
522
|
+
]
|
|
523
|
+
},
|
|
524
|
+
// multiple sections? pass `sections` instead of `rows`:
|
|
525
|
+
{
|
|
526
|
+
buttonText: { displayText: '⚙️ settings' }, buttonId: 'settings', type: 1,
|
|
527
|
+
sections: [
|
|
528
|
+
{ title: 'Main', highlight_label: '⭐ MAIN', rows: [ /* ... */ ] },
|
|
529
|
+
{ title: 'More', rows: [ /* ... */ ] }
|
|
530
|
+
]
|
|
531
|
+
}
|
|
532
|
+
]
|
|
533
|
+
})
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
**How it works:**
|
|
537
|
+
|
|
538
|
+
- `rows` — single-section shortcut (optional `sectionTitle` and `highlightLabel` on the button)
|
|
539
|
+
- `sections` — full control: multiple sections, each with its own `title` and `highlight_label`
|
|
540
|
+
- Each row accepts `{ title, description?, rowId }` (`id` also works)
|
|
541
|
+
- Tapping a row sends back an `interactiveResponseMessage` — parse its `paramsJson`
|
|
542
|
+
for the row id (the click bridge below handles this)
|
|
543
|
+
- Works in both layouts: the classic horizontal row (with header) and `{ nativeFlow: true }` vertical
|
|
544
|
+
|
|
545
|
+
### One-Click Action Buttons (URL / Copy / Call) — v1.0.23+
|
|
546
|
+
|
|
547
|
+
Give a button a `url`, `copy` or `call` value and it becomes a **one-click action
|
|
548
|
+
button** — tapping performs the action directly instead of sending a reply back
|
|
549
|
+
to your bot (opens a link/channel, copies a code, opens the dialer):
|
|
550
|
+
|
|
551
|
+
```javascript
|
|
552
|
+
await sock.sendMessage(jid, {
|
|
553
|
+
image: { url: './banner.jpg' }, // location / gif / video header um ok
|
|
554
|
+
caption: 'Pong 9 Ms ⚡',
|
|
555
|
+
footer: 'ISHAN-X MD PRO',
|
|
556
|
+
buttons: [
|
|
557
|
+
{ buttonText: { displayText: '☰ menu' }, buttonId: 'menu', type: 1 },
|
|
558
|
+
// 📢 one tap → channel/page opens:
|
|
559
|
+
{ buttonText: { displayText: '📢 Channel' }, url: 'https://whatsapp.com/channel/0029V...' },
|
|
560
|
+
// 🎁 one tap → code copies to clipboard:
|
|
561
|
+
{ buttonText: { displayText: '🎁 Voucher' }, copy: 'ISHAN2026' },
|
|
562
|
+
// 📞 one tap → dialer opens:
|
|
563
|
+
{ buttonText: { displayText: '📞 Call Owner' }, call: '919999999999' },
|
|
564
|
+
// a tap-to-open sheet button can share the same message:
|
|
565
|
+
{ buttonText: { displayText: '📂 allmenus' }, buttonId: 'allmenus',
|
|
566
|
+
highlightLabel: '⭐ MAIN', rows: [ /* ... */ ] }
|
|
567
|
+
]
|
|
568
|
+
})
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
**How it works:**
|
|
572
|
+
|
|
573
|
+
- `url` → native-flow `cta_url` (WhatsApp channel link, website, wa.me — anything)
|
|
574
|
+
- `copy` → `cta_copy` (coupon codes, voucher codes, pairing codes)
|
|
575
|
+
- `call` → `cta_call` (phone number including country code)
|
|
576
|
+
- Plain buttons + sheet buttons + action buttons all mix in **one horizontal row**
|
|
577
|
+
- Action buttons never send a reply to your bot — nothing to handle in `messages.upsert`
|
|
578
|
+
- Works in groups too — the group auto-converter preserves the native-flow names
|
|
579
|
+
|
|
486
580
|
### Text-only (TEXT header, best-effort) & native flow escape hatch
|
|
487
581
|
|
|
488
582
|
```javascript
|
|
@@ -500,36 +594,106 @@ await sock.sendMessage(jid, {
|
|
|
500
594
|
})
|
|
501
595
|
```
|
|
502
596
|
|
|
597
|
+
### Full Example — Everything in One Message
|
|
598
|
+
|
|
599
|
+
A complete bot reply: location map-card header, a plain quick-reply, a highlighted
|
|
600
|
+
list-sheet button and a one-click channel button — all in one horizontal row:
|
|
601
|
+
|
|
602
|
+
```javascript
|
|
603
|
+
await sock.sendMessage(jid, {
|
|
604
|
+
location: {
|
|
605
|
+
degreesLatitude: 9.9312,
|
|
606
|
+
degreesLongitude: 76.2673,
|
|
607
|
+
name: 'ISHAN-X MD PRO',
|
|
608
|
+
address: 'Select an option below'
|
|
609
|
+
},
|
|
610
|
+
text: 'Pong 9 Ms ⚡\nDeveloper: ISHAN-X × LOVELY',
|
|
611
|
+
footer: 'ISHAN-X MD PRO',
|
|
612
|
+
buttons: [
|
|
613
|
+
// 1) plain quick-reply → sends 'menu' back to your bot
|
|
614
|
+
{ buttonText: { displayText: '☰ menu' }, buttonId: 'menu', type: 1 },
|
|
615
|
+
// 2) tap-to-open highlighted list sheet
|
|
616
|
+
{
|
|
617
|
+
buttonText: { displayText: '📂 allmenus' },
|
|
618
|
+
buttonId: 'allmenus', type: 1,
|
|
619
|
+
highlightLabel: '⭐ MAIN',
|
|
620
|
+
sectionTitle: 'All Menus',
|
|
621
|
+
rows: [
|
|
622
|
+
{ title: '📥 Download Menu', description: 'Downloader commands', rowId: '.downloadmenu' },
|
|
623
|
+
{ title: '✨ AI Menu', description: 'AI commands', rowId: '.aimenu' }
|
|
624
|
+
]
|
|
625
|
+
},
|
|
626
|
+
// 3) one-click action → opens your channel, nothing is sent back
|
|
627
|
+
{ buttonText: { displayText: '📢 Channel' }, url: 'https://whatsapp.com/channel/0029V...' }
|
|
628
|
+
]
|
|
629
|
+
}, { quoted: msg })
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
> ⚠️ **Limit:** the classic horizontal row renders up to **3 buttons** per message on
|
|
633
|
+
> most clients. Need more? Use `{ nativeFlow: true }` for a vertical layout that
|
|
634
|
+
> supports more buttons, or split across two messages.
|
|
635
|
+
|
|
503
636
|
### Handling Button Clicks
|
|
504
637
|
|
|
505
|
-
Button
|
|
506
|
-
`
|
|
638
|
+
Button and row taps arrive in `messages.upsert`. Three shapes are possible:
|
|
639
|
+
classic quick replies → `buttonsResponseMessage`, native-flow taps (sheet rows and
|
|
640
|
+
vertical quick replies) → `interactiveResponseMessage`, classic list rows →
|
|
641
|
+
`listResponseMessage`. This one bridge converts all three into a plain command id —
|
|
642
|
+
drop it above your command parser so every existing case keeps working:
|
|
507
643
|
|
|
508
644
|
```javascript
|
|
645
|
+
function resolveButtonResponse(msg) {
|
|
646
|
+
// classic horizontal quick-reply buttons
|
|
647
|
+
const classic = msg.message?.buttonsResponseMessage?.selectedButtonId
|
|
648
|
+
if (classic) return classic
|
|
649
|
+
|
|
650
|
+
// native flow: sheet rows and vertical quick replies
|
|
651
|
+
const nf = msg.message?.interactiveResponseMessage?.nativeFlowResponseMessage
|
|
652
|
+
if (nf?.paramsJson) {
|
|
653
|
+
try {
|
|
654
|
+
const p = JSON.parse(native.paramsJson)
|
|
655
|
+
return p.id || p.selectedId || p.selected_row_id || null
|
|
656
|
+
} catch { /* ignore */ }
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// classic listMessage rows
|
|
660
|
+
const list = msg.message?.listResponseMessage?.singleSelectReply?.selectedRowId
|
|
661
|
+
if (list) return list
|
|
662
|
+
|
|
663
|
+
return null
|
|
664
|
+
}
|
|
665
|
+
|
|
509
666
|
sock.ev.on('messages.upsert', async ({ messages, type }) => {
|
|
510
667
|
if (type !== 'notify') return
|
|
511
668
|
const msg = messages[0]
|
|
512
669
|
if (!msg.message || msg.key.fromMe) return
|
|
513
670
|
|
|
514
|
-
|
|
515
|
-
const
|
|
516
|
-
if (
|
|
517
|
-
try { clickedId = JSON.parse(native.paramsJson).id } catch {}
|
|
518
|
-
}
|
|
671
|
+
// turn any button / row tap into normal command text:
|
|
672
|
+
const clicked = resolveButtonResponse(msg)
|
|
673
|
+
if (clicked) msg.message = { conversation: clicked }
|
|
519
674
|
|
|
520
|
-
|
|
521
|
-
|
|
675
|
+
// your existing command parser keeps working untouched:
|
|
676
|
+
// switch (command) { case 'menu': ... case 'owner': ... }
|
|
522
677
|
})
|
|
523
678
|
```
|
|
524
679
|
|
|
680
|
+
Action buttons (`url` / `copy` / `call`) never send a reply — nothing to handle here.
|
|
681
|
+
|
|
525
682
|
> **Notes**
|
|
526
|
-
> - Groups
|
|
527
|
-
> interactive native flow on send — buttons
|
|
528
|
-
>
|
|
529
|
-
>
|
|
530
|
-
> -
|
|
531
|
-
>
|
|
532
|
-
>
|
|
683
|
+
> - **Groups:** `listMessage` / `buttonsMessage` / `templateMessage` are auto-converted
|
|
684
|
+
> to interactive native flow on send — and buttons that carry a native-flow action
|
|
685
|
+
> (list sheet, URL, copy, call) are preserved as-is, so sheets and one-click
|
|
686
|
+
> actions work in groups too (v1.0.23+).
|
|
687
|
+
> - **Client support:** modern Android / iOS / Business clients render everything on
|
|
688
|
+
> this page. WhatsApp Web and very old clients may show only the vertical
|
|
689
|
+
> native-flow layout.
|
|
690
|
+
> - **Media headers:** one media header per message (image, GIF or video). The
|
|
691
|
+
> location map card needs **no media upload at all**.
|
|
692
|
+
> - Full working demos: [`examples/ping-buttons.js`](examples/ping-buttons.js)
|
|
693
|
+
> (`.ping` → image + horizontal buttons + click handling) and
|
|
694
|
+
> [`examples/menu-buttons.js`](examples/menu-buttons.js)
|
|
695
|
+
> (`.menu` → custom image/GIF + buttons + highlighted menu sheet), plus a visual
|
|
696
|
+
> preview in [`banner-preview.html`](banner-preview.html).
|
|
533
697
|
|
|
534
698
|
---
|
|
535
699
|
|
|
@@ -1157,7 +1321,8 @@ Made with ❤️ by **Lovely**
|
|
|
1157
1321
|
|
|
1158
1322
|
## 🚀 Hosting / Troubleshooting (OptikLink, Pterodactyl, etc.)
|
|
1159
1323
|
|
|
1160
|
-
|
|
1324
|
+
If `npm install` fails on bot hosting panels (OptikLink, Pterodactyl, etc.), these are
|
|
1325
|
+
the most common reasons:
|
|
1161
1326
|
|
|
1162
1327
|
### ❌ `npm error code EALLOWGIT`
|
|
1163
1328
|
|
|
@@ -602,16 +602,24 @@ export const makeMessagesSocket = (config) => {
|
|
|
602
602
|
header: list.title? { title: list.title, hasMediaAttachment: false, subtitle: '' } : undefined,
|
|
603
603
|
contextInfo: list.contextInfo
|
|
604
604
|
}
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
605
|
+
} } else if (message.buttonsMessage) {
|
|
606
|
+
const bMsg = message.buttonsMessage
|
|
607
|
+
// PATCH: buttons that carry nativeFlowInfo (single_select sheet /
|
|
608
|
+
// cta_url / cta_copy / cta_call) keep their native flow name so
|
|
609
|
+
// sheets and one-click actions still work in groups — only plain
|
|
610
|
+
// buttons degrade to quick_reply.
|
|
611
|
+
const buttons = (bMsg.buttons || []).map(btn => {
|
|
612
|
+
if (btn.nativeFlowInfo?.name) {
|
|
613
|
+
return { name: btn.nativeFlowInfo.name, buttonParamsJson: btn.nativeFlowInfo.paramsJson || '{}' }
|
|
614
|
+
}
|
|
615
|
+
return {
|
|
616
|
+
name: 'quick_reply',
|
|
617
|
+
buttonParamsJson: JSON.stringify({
|
|
618
|
+
display_text: btn.buttonText?.displayText || btn.buttonText || '',
|
|
619
|
+
id: btn.buttonId || btn.buttonText?.displayText || ''
|
|
620
|
+
})
|
|
621
|
+
}
|
|
622
|
+
})
|
|
615
623
|
message = {
|
|
616
624
|
interactiveMessage: {
|
|
617
625
|
nativeFlowMessage: { buttons, messageParamsJson: '', messageVersion: 1 },
|
package/lib/Utils/messages.js
CHANGED
|
@@ -524,6 +524,62 @@ const BUTTONS_INVISIBLE_PNG = () => Buffer.from(
|
|
|
524
524
|
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=',
|
|
525
525
|
'base64'
|
|
526
526
|
)
|
|
527
|
+
// PATCH: rows/sections on a button → tapping it opens a native-flow list
|
|
528
|
+
// sheet (the same sheet classic listMessage shows). A button may carry
|
|
529
|
+
// inline `rows` (auto-wrapped in one section, optional button-level
|
|
530
|
+
// `highlightLabel` / `sectionTitle`) or a full `sections` array where each
|
|
531
|
+
// section is { title?, highlight_label?, rows: [{ title, description?, rowId|id }] }.
|
|
532
|
+
const buildButtonSections = (b) => {
|
|
533
|
+
let sections = null
|
|
534
|
+
if (Array.isArray(b?.sections) && b.sections.length) {
|
|
535
|
+
sections = b.sections
|
|
536
|
+
} else if (Array.isArray(b?.rows) && b.rows.length) {
|
|
537
|
+
sections = [{
|
|
538
|
+
title: b.sectionTitle || b.buttonText?.displayText || b.displayText || 'Menu',
|
|
539
|
+
...(b.highlightLabel ? { highlight_label: b.highlightLabel } : {}),
|
|
540
|
+
rows: b.rows
|
|
541
|
+
}]
|
|
542
|
+
}
|
|
543
|
+
if (!sections) return null
|
|
544
|
+
return sections.map(s => ({
|
|
545
|
+
...(s.title ? { title: s.title } : {}),
|
|
546
|
+
...(s.highlight_label || s.highlightLabel ? { highlight_label: s.highlight_label || s.highlightLabel } : {}),
|
|
547
|
+
rows: (s.rows || []).map(r => ({
|
|
548
|
+
title: r.title,
|
|
549
|
+
...(r.description ? { description: r.description } : {}),
|
|
550
|
+
id: r.rowId ?? r.id ?? r.title
|
|
551
|
+
}))
|
|
552
|
+
}))
|
|
553
|
+
}
|
|
554
|
+
// PATCH: one-click action buttons — `url` opens a link/channel, `copy`
|
|
555
|
+
// copies a code, `call` dials a number. Sent as native-flow CTA buttons
|
|
556
|
+
// (classic: type NATIVE_FLOW + nativeFlowInfo; nativeFlow: cta_* names).
|
|
557
|
+
const buildActionFlow = (b) => {
|
|
558
|
+
if (b?.url) return { name: 'cta_url', params: { display_text: b.buttonText?.displayText || b.displayText || 'Open', url: b.url, merchant_url: b.url } }
|
|
559
|
+
if (b?.copy) return { name: 'cta_copy', params: { display_text: b.buttonText?.displayText || b.displayText || 'Copy', id: b.buttonId || b.buttonText?.displayText || 'copy', copy_code: b.copy } }
|
|
560
|
+
if (b?.call) return { name: 'cta_call', params: { display_text: b.buttonText?.displayText || b.displayText || 'Call', phone_number: String(b.call) } }
|
|
561
|
+
return null
|
|
562
|
+
}
|
|
563
|
+
const normalizeClassicButton = (b) => {
|
|
564
|
+
const out = { ...b, type: proto.Message.ButtonsMessage.Button.Type.RESPONSE }
|
|
565
|
+
const action = buildActionFlow(b)
|
|
566
|
+
if (action) {
|
|
567
|
+
out.type = proto.Message.ButtonsMessage.Button.Type.NATIVE_FLOW
|
|
568
|
+
out.nativeFlowInfo = { name: action.name, paramsJson: JSON.stringify(action.params) }
|
|
569
|
+
return out
|
|
570
|
+
}
|
|
571
|
+
const sections = buildButtonSections(b)
|
|
572
|
+
if (sections) {
|
|
573
|
+
out.nativeFlowInfo = {
|
|
574
|
+
name: 'single_select',
|
|
575
|
+
paramsJson: JSON.stringify({
|
|
576
|
+
title: b.buttonText?.displayText || b.displayText || 'Menu',
|
|
577
|
+
sections
|
|
578
|
+
})
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return out
|
|
582
|
+
}
|
|
527
583
|
export const generateWAMessageContent = async (message, options) => {
|
|
528
584
|
var _a, _b;
|
|
529
585
|
let m = {};
|
|
@@ -596,12 +652,27 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
596
652
|
m = { interactiveMessage };
|
|
597
653
|
}
|
|
598
654
|
else if ('buttonsMessage' in message && !!message.buttonsMessage) {
|
|
599
|
-
// PATCH: raw buttonsMessage —
|
|
600
|
-
//
|
|
601
|
-
// location)
|
|
602
|
-
//
|
|
603
|
-
//
|
|
604
|
-
|
|
655
|
+
// PATCH: raw buttonsMessage — classic pass-through. Modern clients render
|
|
656
|
+
// the horizontal row only when a header exists (image/video/document/
|
|
657
|
+
// location). A text-only raw message WITHOUT any header is exactly the
|
|
658
|
+
// "version doesn't support it" case — so when the caller passed none, we
|
|
659
|
+
// attach the invisible 1x1 PNG image header automatically (same trick the
|
|
660
|
+
// `buttons` API uses) and the row always renders. This is unconditional:
|
|
661
|
+
// header-less raw messages can never produce the "not supported" bubble.
|
|
662
|
+
const raw = proto.Message.ButtonsMessage.fromObject(message.buttonsMessage)
|
|
663
|
+
// NOTE: fromObject turns missing fields into null (protobuf defaults), so
|
|
664
|
+
// a nullish headerType (= caller never set it) counts as "no header" too.
|
|
665
|
+
const hasHeader = !!(raw.imageMessage || raw.videoMessage || raw.documentMessage ||
|
|
666
|
+
raw.locationMessage ||
|
|
667
|
+
(raw.headerType != null && raw.headerType !== ButtonType.EMPTY && raw.headerType !== ButtonType.UNKNOWN))
|
|
668
|
+
if (!hasHeader) {
|
|
669
|
+
try {
|
|
670
|
+
const media = await prepareWAMessageMedia({ image: BUTTONS_INVISIBLE_PNG() }, options)
|
|
671
|
+
raw.imageMessage = media.imageMessage
|
|
672
|
+
raw.headerType = ButtonType.IMAGE
|
|
673
|
+
} catch { /* upload failed — send as-is */ }
|
|
674
|
+
}
|
|
675
|
+
m = { buttonsMessage: raw };
|
|
605
676
|
}
|
|
606
677
|
else if ('buttons' in message && !!message.buttons) {
|
|
607
678
|
// PATCH: `buttons` API — HORIZONTAL button row via classic ButtonsMessage
|
|
@@ -610,13 +681,29 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
610
681
|
// thumbnail for text-only). Set { nativeFlow: true } to opt out and get
|
|
611
682
|
// vertical native-flow quick_reply buttons instead.
|
|
612
683
|
if (message.nativeFlow === true) {
|
|
613
|
-
const flowButtons = message.buttons.map(b =>
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
684
|
+
const flowButtons = message.buttons.map(b => {
|
|
685
|
+
const action = buildActionFlow(b);
|
|
686
|
+
if (action) {
|
|
687
|
+
return { name: action.name, buttonParamsJson: JSON.stringify(action.params) };
|
|
688
|
+
}
|
|
689
|
+
const sections = buildButtonSections(b);
|
|
690
|
+
if (sections) {
|
|
691
|
+
return {
|
|
692
|
+
name: 'single_select',
|
|
693
|
+
buttonParamsJson: JSON.stringify({
|
|
694
|
+
title: b.buttonText?.displayText || b.displayText || 'Menu',
|
|
695
|
+
sections
|
|
696
|
+
})
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
return {
|
|
700
|
+
name: 'quick_reply',
|
|
701
|
+
buttonParamsJson: JSON.stringify({
|
|
702
|
+
display_text: b.buttonText?.displayText || b.displayText || b.text || '',
|
|
703
|
+
id: b.buttonId || b.id || b.buttonText?.displayText || ''
|
|
704
|
+
})
|
|
705
|
+
};
|
|
706
|
+
});
|
|
620
707
|
const interactiveMessage = {
|
|
621
708
|
nativeFlowMessage: {
|
|
622
709
|
buttons: flowButtons,
|
|
@@ -638,7 +725,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
638
725
|
else if ('location' in message && !!message.location) {
|
|
639
726
|
const loc = message.location;
|
|
640
727
|
const buttonsMessage = {
|
|
641
|
-
buttons: message.buttons.map(b => (
|
|
728
|
+
buttons: message.buttons.map(b => normalizeClassicButton(b)),
|
|
642
729
|
contentText: message.text || message.caption || '',
|
|
643
730
|
headerType: ButtonType.LOCATION,
|
|
644
731
|
locationMessage: {
|
|
@@ -662,7 +749,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
662
749
|
}
|
|
663
750
|
else {
|
|
664
751
|
const buttonsMessage = {
|
|
665
|
-
buttons: message.buttons.map(b => (
|
|
752
|
+
buttons: message.buttons.map(b => normalizeClassicButton(b))
|
|
666
753
|
};
|
|
667
754
|
if ('footer' in message && !!message.footer) {
|
|
668
755
|
buttonsMessage.footerText = message.footer;
|