ishumdz-bail 1.0.26 → 1.0.29
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 +109 -1
- package/lib/Pro/sheet-buttons.js +179 -0
- package/lib/Utils/messages.js +50 -2
- package/lib/index.js +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -651,7 +651,7 @@ function resolveButtonResponse(msg) {
|
|
|
651
651
|
const nf = msg.message?.interactiveResponseMessage?.nativeFlowResponseMessage
|
|
652
652
|
if (nf?.paramsJson) {
|
|
653
653
|
try {
|
|
654
|
-
const p = JSON.parse(
|
|
654
|
+
const p = JSON.parse(nf.paramsJson)
|
|
655
655
|
return p.id || p.selectedId || p.selected_row_id || null
|
|
656
656
|
} catch { /* ignore */ }
|
|
657
657
|
}
|
|
@@ -695,6 +695,114 @@ Action buttons (`url` / `copy` / `call`) never send a reply — nothing to handl
|
|
|
695
695
|
> (`.menu` → custom image/GIF + buttons + highlighted menu sheet), plus a visual
|
|
696
696
|
> preview in [`banner-preview.html`](banner-preview.html).
|
|
697
697
|
|
|
698
|
+
### Base Compatibility — cantarella / Case X Style Code (v1.0.27+)
|
|
699
|
+
|
|
700
|
+
Code copied from other Baileys bases (cantarella-baileys, Case X Plugin YOUHU MD, etc.)
|
|
701
|
+
runs without changes — and renders as a **horizontal one-line row** just like those
|
|
702
|
+
bases. Three shapes are accepted:
|
|
703
|
+
|
|
704
|
+
**1) Raw `buttonsMessage` classic menu card — mixed extras are flattened.** A raw
|
|
705
|
+
classic message that mixes `nativeFlowInfo` (single_select sheet) or `cta_*` buttons
|
|
706
|
+
with plain buttons **stays classic horizontal**: the header (location/image/video)
|
|
707
|
+
is preserved, every extra becomes a plain button with its original `buttonId`, and
|
|
708
|
+
its click arrives as a normal `buttonsResponseMessage` — so your bot can send the
|
|
709
|
+
list sheet / URL action itself (e.g. a separate `nativeFlow: true` message):
|
|
710
|
+
|
|
711
|
+
```javascript
|
|
712
|
+
// Case X / cantarella style — works as-is:
|
|
713
|
+
await sock.sendMessage(jid, {
|
|
714
|
+
buttonsMessage: {
|
|
715
|
+
locationMessage: { degreesLatitude: 0, degreesLongitude: 0, name: 'Youhu base', address: '📍Today' },
|
|
716
|
+
contentText: menuText, footerText: footer, headerType: 6,
|
|
717
|
+
buttons: [
|
|
718
|
+
{ buttonId: 'menu', buttonText: { displayText: '☰ menu' }, type: 1,
|
|
719
|
+
nativeFlowInfo: { name: 'single_select', paramsJson: JSON.stringify({
|
|
720
|
+
title: 'Pilih Menu',
|
|
721
|
+
sections: [{ title: 'base', highlight_label: '🔥', rows: [{ title: 'ping', description: 'live', id: '/ping' }] }]
|
|
722
|
+
}) } },
|
|
723
|
+
{ buttonId: 'sc', buttonText: { displayText: '⌕ script' }, type: 1 }
|
|
724
|
+
]
|
|
725
|
+
}
|
|
726
|
+
})
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
**2) Raw `interactiveMessage` native-flow card — straight through `sendMessage`.**
|
|
730
|
+
No `generateWAMessageFromContent` + `relayMessage` dance needed (though that still
|
|
731
|
+
works too). `messageVersion` defaults to 1:
|
|
732
|
+
|
|
733
|
+
```javascript
|
|
734
|
+
await sock.sendMessage(jid, {
|
|
735
|
+
interactiveMessage: {
|
|
736
|
+
body: { text: 'Pairing code: 1234-5678' },
|
|
737
|
+
footer: { text: 'Tap to copy' },
|
|
738
|
+
header: { hasMediaAttachment: false },
|
|
739
|
+
nativeFlowMessage: {
|
|
740
|
+
buttons: [{ name: 'cta_copy', buttonParamsJson: JSON.stringify({ display_text: 'Copy', copy_code: '12345678' }) }]
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
})
|
|
744
|
+
|
|
745
|
+
// short form also accepted:
|
|
746
|
+
await sock.sendMessage(jid, { interactiveMessage: { buttons: [{ name: 'quick_reply', buttonParamsJson: '{"display_text":"hi","id":"hi"}' }] } })
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
**3) Plain raw `buttonsMessage`** (no native-flow extras) stays classic and gets the
|
|
750
|
+
automatic invisible-PNG header when you omit one. Flow params are accepted as
|
|
751
|
+
`paramsJson` or `buttonParamsJson`.
|
|
752
|
+
|
|
753
|
+
> 💡 **Want the tap-to-open sheet too?** Send it as a second message when the button
|
|
754
|
+
> is clicked (see `examples/menu-buttons.js` — the `allmenus` case). Mixing a sheet
|
|
755
|
+
> into the same classic row is what produced the "doesn't support it" bubble; the
|
|
756
|
+
> library keeps the row safe by flattening extras, and the two-message pattern gives
|
|
757
|
+
> you both layouts.
|
|
758
|
+
|
|
759
|
+
### One-Tap Horizontal Button → Automatic List Sheet — v1.0.28+
|
|
760
|
+
|
|
761
|
+
`attachSheetAutoReply` does the two-message pattern **for you**: register it once,
|
|
762
|
+
and when the user taps a horizontal button, the list sheet is sent automatically —
|
|
763
|
+
no extra code in your `messages.upsert` handler:
|
|
764
|
+
|
|
765
|
+
```javascript
|
|
766
|
+
const { makeWASocket, attachSheetAutoReply } = require('ishumdz-bail')
|
|
767
|
+
|
|
768
|
+
const sock = makeWASocket({ auth: state, ... })
|
|
769
|
+
|
|
770
|
+
// register ONCE, right after creating the socket:
|
|
771
|
+
attachSheetAutoReply(sock, {
|
|
772
|
+
// click id → full sheet (auto-sent, click never reaches your parser)
|
|
773
|
+
allmenus: {
|
|
774
|
+
text: '📂 *ALL MENUS* — tap a section 👇',
|
|
775
|
+
footer: 'ISHAN-X MD PRO',
|
|
776
|
+
buttonText: '📂 open menu',
|
|
777
|
+
sectionTitle: 'All Menus',
|
|
778
|
+
highlightLabel: '⭐ MAIN',
|
|
779
|
+
rows: [
|
|
780
|
+
{ title: '📥 Download Menu', description: 'Downloader commands', rowId: '.downloadmenu' },
|
|
781
|
+
{ title: '✨ AI Menu', description: 'AI commands', rowId: '.aimenu' },
|
|
782
|
+
{ title: '🎮 Game Menu', description: 'Fun & games', rowId: '.gamemenu' }
|
|
783
|
+
]
|
|
784
|
+
},
|
|
785
|
+
// shorthand: click id → rewrite into a normal command for your parser
|
|
786
|
+
support: '.owner'
|
|
787
|
+
})
|
|
788
|
+
|
|
789
|
+
// then your horizontal row stays 100% plain → guaranteed one-line render:
|
|
790
|
+
await sock.sendMessage(jid, {
|
|
791
|
+
location: { degreesLatitude: 0, degreesLongitude: 0,
|
|
792
|
+
name: 'ISHAN-X MD PRO', address: '📂 Select Menu 👇' },
|
|
793
|
+
text: menuText, footer,
|
|
794
|
+
buttons: [
|
|
795
|
+
{ buttonText: { displayText: '📂 allmenus' }, buttonId: 'allmenus', type: 1 },
|
|
796
|
+
{ buttonText: { displayText: '👤 owner' }, buttonId: 'owner', type: 1 },
|
|
797
|
+
{ buttonText: { displayText: '⚡ ping' }, buttonId: 'ping', type: 1 }
|
|
798
|
+
]
|
|
799
|
+
}, { quoted: msg })
|
|
800
|
+
// user taps "allmenus" → sheet opens instantly; taps "owner" → your parser gets '.owner'
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
Also exported: `sendSheet(sock, jid, entry, quoted)` (send a sheet manually) and
|
|
804
|
+
`decodeButtonClick(msg)` (the click bridge, shipped with the library).
|
|
805
|
+
|
|
698
806
|
---
|
|
699
807
|
|
|
700
808
|
## 🚫 Ban Checker
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sheet-buttons.js — one-tap horizontal button → automatic list sheet (v1.0.28+)
|
|
3
|
+
*
|
|
4
|
+
* Classic horizontal rows cannot carry a native-flow sheet inside the SAME
|
|
5
|
+
* message on current clients (that mix renders as "version doesn't support
|
|
6
|
+
* it"). The working pattern is TWO messages: the horizontal row, and — when
|
|
7
|
+
* the user clicks the menu button — a native-flow list sheet sent
|
|
8
|
+
* automatically. This module does the second half for you:
|
|
9
|
+
*
|
|
10
|
+
* const { attachSheetAutoReply } = require('ishumdz-bail')
|
|
11
|
+
*
|
|
12
|
+
* attachSheetAutoReply(sock, {
|
|
13
|
+
* // click id → full sheet definition
|
|
14
|
+
* allmenus: {
|
|
15
|
+
* text: '📂 *ALL MENUS* — tap a section 👇',
|
|
16
|
+
* footer: 'ISHAN-X MD PRO',
|
|
17
|
+
* buttonText: '📂 open menu',
|
|
18
|
+
* highlightLabel: '⭐ MAIN',
|
|
19
|
+
* sectionTitle: 'All Menus',
|
|
20
|
+
* rows: [
|
|
21
|
+
* { title: '📥 Download Menu', description: 'Downloaders', rowId: '.downloadmenu' },
|
|
22
|
+
* { title: '✨ AI Menu', description: 'AI commands', rowId: '.aimenu' }
|
|
23
|
+
* ]
|
|
24
|
+
* },
|
|
25
|
+
* // or a shorthand: rewrite the click into another command
|
|
26
|
+
* support: '.owner'
|
|
27
|
+
* })
|
|
28
|
+
*
|
|
29
|
+
* Now a horizontal row can stay 100% plain (guaranteed one-line render):
|
|
30
|
+
*
|
|
31
|
+
* await sock.sendMessage(jid, {
|
|
32
|
+
* location: { degreesLatitude: 0, degreesLongitude: 0,
|
|
33
|
+
* name: 'ISHAN-X MD PRO', address: '📂 Select Menu 👇' },
|
|
34
|
+
* text: menuText, footer,
|
|
35
|
+
* buttons: [
|
|
36
|
+
* { buttonText: { displayText: '📂 allmenus' }, buttonId: 'allmenus', type: 1 },
|
|
37
|
+
* { buttonText: { displayText: '👤 owner' }, buttonId: 'owner', type: 1 }
|
|
38
|
+
* ]
|
|
39
|
+
* })
|
|
40
|
+
*
|
|
41
|
+
* User taps "allmenus" → the sheet opens instantly, and your own
|
|
42
|
+
* messages.upsert handler is NOT called for that click (consumed).
|
|
43
|
+
* A shorthand entry rewrites the click into the given command text and
|
|
44
|
+
* lets your normal command parser handle it.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
// Decode any button / sheet-row / list-row click into its id (same bridge
|
|
48
|
+
// the examples use, now shipped with the library).
|
|
49
|
+
export function decodeButtonClick(msg) {
|
|
50
|
+
// classic horizontal quick-reply buttons
|
|
51
|
+
const classic = msg?.message?.buttonsResponseMessage?.selectedButtonId
|
|
52
|
+
if (classic) return classic
|
|
53
|
+
|
|
54
|
+
// native flow (sheet rows / card quick replies)
|
|
55
|
+
const nf = msg?.message?.interactiveResponseMessage?.nativeFlowResponseMessage
|
|
56
|
+
if (nf?.paramsJson) {
|
|
57
|
+
try {
|
|
58
|
+
const p = JSON.parse(nf.paramsJson)
|
|
59
|
+
return p.id || p.selectedId || p.selected_row_id || null
|
|
60
|
+
} catch { /* ignore */ }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// classic listMessage rows
|
|
64
|
+
const list = msg?.message?.listResponseMessage?.singleSelectReply?.selectedRowId
|
|
65
|
+
if (list) return list
|
|
66
|
+
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const normalizeRows = (rows) => (rows || []).map(r => ({
|
|
71
|
+
title: r.title,
|
|
72
|
+
...(r.description ? { description: r.description } : {}),
|
|
73
|
+
id: r.rowId ?? r.id ?? r.title
|
|
74
|
+
}))
|
|
75
|
+
|
|
76
|
+
const buildSections = (entry) => {
|
|
77
|
+
if (Array.isArray(entry.sections) && entry.sections.length) {
|
|
78
|
+
return entry.sections.map(s => ({
|
|
79
|
+
...(s.title ? { title: s.title } : {}),
|
|
80
|
+
...(s.highlight_label || s.highlightLabel ? { highlight_label: s.highlight_label || s.highlightLabel } : {}),
|
|
81
|
+
rows: normalizeRows(s.rows)
|
|
82
|
+
}))
|
|
83
|
+
}
|
|
84
|
+
return [{
|
|
85
|
+
title: entry.sectionTitle || entry.buttonText || 'Menu',
|
|
86
|
+
...(entry.highlightLabel ? { highlight_label: entry.highlightLabel } : {}),
|
|
87
|
+
rows: normalizeRows(entry.rows)
|
|
88
|
+
}]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const normalizeHandlers = (handlers) => {
|
|
92
|
+
const sheets = {}
|
|
93
|
+
const commands = {}
|
|
94
|
+
for (const [id, val] of Object.entries(handlers || {})) {
|
|
95
|
+
if (typeof val === 'string') {
|
|
96
|
+
commands[id] = val
|
|
97
|
+
} else if (val && (Array.isArray(val.rows) || Array.isArray(val.sections))) {
|
|
98
|
+
sheets[id] = val
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return { sheets, commands }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Manually send a native-flow list sheet (the tap-to-open menu).
|
|
106
|
+
* attachSheetAutoReply calls this for you on a matching click.
|
|
107
|
+
*/
|
|
108
|
+
export async function sendSheet(sock, jid, entry, quoted) {
|
|
109
|
+
const sections = buildSections(entry)
|
|
110
|
+
return sock.sendMessage(jid, {
|
|
111
|
+
text: entry.text || '📋 Select an option 👇',
|
|
112
|
+
...(entry.footer ? { footer: entry.footer } : {}),
|
|
113
|
+
nativeFlow: true,
|
|
114
|
+
buttons: [{
|
|
115
|
+
buttonText: { displayText: entry.buttonText || '☰ menu' },
|
|
116
|
+
buttonId: entry.buttonId || 'sheet',
|
|
117
|
+
type: 1,
|
|
118
|
+
sections
|
|
119
|
+
}]
|
|
120
|
+
}, quoted ? { quoted } : {})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Register automatic sheet replies on a socket.
|
|
125
|
+
*
|
|
126
|
+
* @param {object} sock the makeWASocket() instance
|
|
127
|
+
* @param {object} handlers map of clickId → sheet definition { text?, footer?,
|
|
128
|
+
* buttonText?, sectionTitle?, highlightLabel?, rows|sections }
|
|
129
|
+
* OR clickId → '.command' string shorthand
|
|
130
|
+
* @returns {Function} uninstall — restores the original sock.ev.on
|
|
131
|
+
*/
|
|
132
|
+
export function attachSheetAutoReply(sock, handlers) {
|
|
133
|
+
const { sheets, commands } = normalizeHandlers(handlers)
|
|
134
|
+
|
|
135
|
+
async function handleUpsert(payload) {
|
|
136
|
+
const { messages, type } = payload || {}
|
|
137
|
+
if (type !== 'notify' || !Array.isArray(messages)) return false
|
|
138
|
+
for (const msg of messages) {
|
|
139
|
+
if (!msg?.message || msg.key?.fromMe) continue
|
|
140
|
+
const clicked = decodeButtonClick(msg)
|
|
141
|
+
if (!clicked) continue
|
|
142
|
+
|
|
143
|
+
// 1) full sheet definition → send the sheet, consume the click
|
|
144
|
+
const entry = sheets[clicked]
|
|
145
|
+
if (entry) {
|
|
146
|
+
try {
|
|
147
|
+
await sendSheet(sock, msg.key.remoteJid, { ...entry, buttonId: clicked }, msg)
|
|
148
|
+
} catch (e) {
|
|
149
|
+
try { sock.logger?.error?.({ err: e }, 'sheet auto-reply failed') } catch { /* ignore */ }
|
|
150
|
+
}
|
|
151
|
+
return true
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 2) command shorthand → rewrite into normal command text for the parser
|
|
155
|
+
const cmd = commands[clicked]
|
|
156
|
+
if (cmd) {
|
|
157
|
+
msg.message = { conversation: cmd }
|
|
158
|
+
return false
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return false
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Wrap the user's messages.upsert registration so the sheet fires first
|
|
165
|
+
// and consumed clicks never reach the bot's command parser.
|
|
166
|
+
const origOn = sock.ev.on.bind(sock.ev)
|
|
167
|
+
sock.ev.on = function (ev, handler) {
|
|
168
|
+
if (ev === 'messages.upsert') {
|
|
169
|
+
return origOn(ev, async (...args) => {
|
|
170
|
+
const consumed = await handleUpsert(args[0]).catch(() => false)
|
|
171
|
+
if (consumed) return true
|
|
172
|
+
return handler(...args)
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
return origOn(ev, handler)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return () => { sock.ev.on = origOn }
|
|
179
|
+
}
|
package/lib/Utils/messages.js
CHANGED
|
@@ -654,20 +654,68 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
654
654
|
applyContextInfoAndMentions(interactiveMessage, message);
|
|
655
655
|
m = { interactiveMessage };
|
|
656
656
|
}
|
|
657
|
+
else if ('interactiveMessage' in message && !!message.interactiveMessage) {
|
|
658
|
+
// PATCH (1.0.27): cantarella / Case X-style RAW interactiveMessage
|
|
659
|
+
// pass-through — send the card exactly like those bases do, but via a
|
|
660
|
+
// normal sendMessage call. Two accepted shapes:
|
|
661
|
+
// { interactiveMessage: { body, footer, header, nativeFlowMessage: { buttons } } }
|
|
662
|
+
// { interactiveMessage: { buttons } } (short form)
|
|
663
|
+
// messageVersion defaults to 1 (0 renders greyed-out placeholders).
|
|
664
|
+
let card = message.interactiveMessage;
|
|
665
|
+
if (card && !card.nativeFlowMessage && Array.isArray(card.buttons)) {
|
|
666
|
+
const { buttons, messageParamsJson, ...rest } = card;
|
|
667
|
+
card = { ...rest, nativeFlowMessage: { buttons, messageParamsJson: messageParamsJson || "" } };
|
|
668
|
+
}
|
|
669
|
+
if (card?.nativeFlowMessage && (card.nativeFlowMessage.messageVersion == null || card.nativeFlowMessage.messageVersion === 0)) {
|
|
670
|
+
card.nativeFlowMessage.messageVersion = 1;
|
|
671
|
+
}
|
|
672
|
+
if (card && !card.body && 'text' in message && !!message.text) {
|
|
673
|
+
card.body = { text: message.text };
|
|
674
|
+
}
|
|
675
|
+
m = { interactiveMessage: card };
|
|
676
|
+
}
|
|
657
677
|
else if ('buttonsMessage' in message && !!message.buttonsMessage) {
|
|
658
678
|
// PATCH: raw buttonsMessage — classic pass-through. Modern clients render
|
|
659
679
|
// the horizontal row only when a header exists (image/video/document/
|
|
660
680
|
// location). A text-only raw message WITHOUT any header is exactly the
|
|
661
681
|
// "version doesn't support it" case — so when the caller passed none, we
|
|
662
682
|
// attach the invisible 1x1 PNG image header automatically (same trick the
|
|
663
|
-
// `buttons` API uses) and the row always renders.
|
|
664
|
-
// header-less raw messages can never produce the "not supported" bubble.
|
|
683
|
+
// `buttons` API uses) and the row always renders.
|
|
665
684
|
const raw = proto.Message.ButtonsMessage.fromObject(message.buttonsMessage)
|
|
666
685
|
// NOTE: fromObject turns missing fields into null (protobuf defaults), so
|
|
667
686
|
// a nullish headerType (= caller never set it) counts as "no header" too.
|
|
668
687
|
const hasHeader = !!(raw.imageMessage || raw.videoMessage || raw.documentMessage ||
|
|
669
688
|
raw.locationMessage ||
|
|
670
689
|
(raw.headerType != null && raw.headerType !== ButtonType.EMPTY && raw.headerType !== ButtonType.UNKNOWN))
|
|
690
|
+
// PATCH (1.0.27): a raw classic message that MIXES native-flow extras
|
|
691
|
+
// (single_select nativeFlowInfo, cta_* buttons) into a ButtonsMessage is
|
|
692
|
+
// the Case X / cantarella menu-card pattern — on current clients it
|
|
693
|
+
// renders as "version doesn't support it" (real-device evidence). Convert
|
|
694
|
+
// the whole message to a native-flow interactive card that renders fully.
|
|
695
|
+
// Read the caller's ORIGINAL button objects — proto fromObject drops
|
|
696
|
+
// unknown fields (e.g. nativeFlowInfo.buttonParamsJson), and some bases
|
|
697
|
+
// (cantarella) put params there.
|
|
698
|
+
const inputButtons = Array.isArray(message.buttonsMessage.buttons) ? message.buttonsMessage.buttons : raw.buttons
|
|
699
|
+
const rawExtras = (inputButtons || []).filter(b =>
|
|
700
|
+
b?.nativeFlowInfo?.name || Number(b?.type) === proto.Message.ButtonsMessage.Button.Type.NATIVE_FLOW)
|
|
701
|
+
if (rawExtras.length) {
|
|
702
|
+
// PATCH (1.0.28): a raw classic message that MIXES native-flow extras
|
|
703
|
+
// (single_select nativeFlowInfo, cta_* buttons) into a ButtonsMessage is
|
|
704
|
+
// the Case X / cantarella menu-card pattern — on current clients it
|
|
705
|
+
// renders as "version doesn't support it" (real-device evidence).
|
|
706
|
+
// Instead of upgrading to the vertical native-flow card, keep the
|
|
707
|
+
// HORIZONTAL classic layout: every extra becomes a plain RESPONSE
|
|
708
|
+
// button with its original buttonId, clicks arrive as
|
|
709
|
+
// buttonsResponseMessage, and the bot sends the list sheet / URL /
|
|
710
|
+
// copy action itself (e.g. a separate nativeFlow message). The header
|
|
711
|
+
// (location/image/video/document) is preserved untouched — that is the
|
|
712
|
+
// proven horizontal Case X / cantarella render.
|
|
713
|
+
raw.buttons = inputButtons.map(b => proto.Message.ButtonsMessage.Button.fromObject({
|
|
714
|
+
buttonId: b?.buttonId || b?.buttonText?.displayText || 'button',
|
|
715
|
+
buttonText: { displayText: b?.buttonText?.displayText || b?.displayText || 'Button' },
|
|
716
|
+
type: proto.Message.ButtonsMessage.Button.Type.RESPONSE
|
|
717
|
+
}))
|
|
718
|
+
}
|
|
671
719
|
if (!hasHeader) {
|
|
672
720
|
try {
|
|
673
721
|
const media = await prepareWAMessageMedia({ image: BUTTONS_INVISIBLE_PNG() }, options)
|
package/lib/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import makeWASocket from './Socket/index.js';
|
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { enableCallAutoAnswer, getActiveVoipClient, CallState } from './Caller/auto-answer.js';
|
|
4
4
|
import { attachProMethods } from './Pro/index.js';
|
|
5
|
+
import { attachSheetAutoReply, sendSheet, decodeButtonClick } from './Pro/sheet-buttons.js';
|
|
5
6
|
import * as PollsPro from './Pro/polls.js';
|
|
6
7
|
import * as NewsletterPro from './Pro/newsletter.js';
|
|
7
8
|
import * as StatusPro from './Pro/status.js';
|
|
@@ -91,5 +92,8 @@ export const removeProfilePicture = ProfilePro.removeProfilePicture;
|
|
|
91
92
|
export const rejectCall = ProfilePro.rejectCall;
|
|
92
93
|
|
|
93
94
|
export { enableCallAutoAnswer, getActiveVoipClient, CallState, attachProMethods, makeWASocket };
|
|
95
|
+
|
|
96
|
+
// One-tap horizontal button → automatic list sheet (v1.0.28+)
|
|
97
|
+
export { attachSheetAutoReply, sendSheet, decodeButtonClick };
|
|
94
98
|
export default makeWASocket;
|
|
95
99
|
//# sourceMappingURL=index.js.map
|