ishumdz-bail 1.0.26 → 1.0.27
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 +54 -1
- package/lib/Utils/messages.js +84 -2
- 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,59 @@ 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. Three shapes are accepted:
|
|
702
|
+
|
|
703
|
+
**1) Raw `buttonsMessage` classic menu card — even the risky mix.** A raw classic
|
|
704
|
+
message that mixes `nativeFlowInfo` (single_select sheet) or `cta_*` buttons with
|
|
705
|
+
plain buttons is **auto-upgraded to a native-flow interactive card**, so it can never
|
|
706
|
+
render the "version doesn't support it" bubble:
|
|
707
|
+
|
|
708
|
+
```javascript
|
|
709
|
+
// Case X / cantarella style — works as-is:
|
|
710
|
+
await sock.sendMessage(jid, {
|
|
711
|
+
buttonsMessage: {
|
|
712
|
+
locationMessage: { degreesLatitude: 0, degreesLongitude: 0, name: 'Youhu base', address: '📍Today' },
|
|
713
|
+
contentText: menuText, footerText: footer, headerType: 6,
|
|
714
|
+
buttons: [
|
|
715
|
+
{ buttonId: 'menu', buttonText: { displayText: '☰ menu' }, type: 1,
|
|
716
|
+
nativeFlowInfo: { name: 'single_select', paramsJson: JSON.stringify({
|
|
717
|
+
title: 'Pilih Menu',
|
|
718
|
+
sections: [{ title: 'base', highlight_label: '🔥', rows: [{ title: 'ping', description: 'live', id: '/ping' }] }]
|
|
719
|
+
}) } },
|
|
720
|
+
{ buttonId: 'sc', buttonText: { displayText: '⌕ script' }, type: 1 }
|
|
721
|
+
]
|
|
722
|
+
}
|
|
723
|
+
})
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
**2) Raw `interactiveMessage` native-flow card — straight through `sendMessage`.**
|
|
727
|
+
No `generateWAMessageFromContent` + `relayMessage` dance needed (though that still
|
|
728
|
+
works too). `messageVersion` defaults to 1:
|
|
729
|
+
|
|
730
|
+
```javascript
|
|
731
|
+
await sock.sendMessage(jid, {
|
|
732
|
+
interactiveMessage: {
|
|
733
|
+
body: { text: 'Pairing code: 1234-5678' },
|
|
734
|
+
footer: { text: 'Tap to copy' },
|
|
735
|
+
header: { hasMediaAttachment: false },
|
|
736
|
+
nativeFlowMessage: {
|
|
737
|
+
buttons: [{ name: 'cta_copy', buttonParamsJson: JSON.stringify({ display_text: 'Copy', copy_code: '12345678' }) }]
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
})
|
|
741
|
+
|
|
742
|
+
// short form also accepted:
|
|
743
|
+
await sock.sendMessage(jid, { interactiveMessage: { buttons: [{ name: 'quick_reply', buttonParamsJson: '{"display_text":"hi","id":"hi"}' }] } })
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
**3) Plain raw `buttonsMessage`** (no native-flow extras) stays classic and gets the
|
|
747
|
+
automatic invisible-PNG header when you omit one. Flow params are accepted as
|
|
748
|
+
`paramsJson` or `buttonParamsJson`, and `single_select` / `cta_url` / `cta_copy` /
|
|
749
|
+
`cta_call` / `quick_reply` names are preserved as-is.
|
|
750
|
+
|
|
698
751
|
---
|
|
699
752
|
|
|
700
753
|
## 🚫 Ban Checker
|
package/lib/Utils/messages.js
CHANGED
|
@@ -654,20 +654,101 @@ 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
|
+
const rawLoc = raw.locationMessage
|
|
703
|
+
const flowButtons = inputButtons.map(b => {
|
|
704
|
+
const name = b?.nativeFlowInfo?.name
|
|
705
|
+
if (name === 'single_select') {
|
|
706
|
+
let params = b.nativeFlowInfo.paramsJson
|
|
707
|
+
try { params = JSON.stringify(JSON.parse(params)) } catch { params = typeof params === 'string' ? params : '{}' }
|
|
708
|
+
return { name: 'single_select', buttonParamsJson: params }
|
|
709
|
+
}
|
|
710
|
+
if (name) {
|
|
711
|
+
return { name, buttonParamsJson: b.nativeFlowInfo.buttonParamsJson || b.nativeFlowInfo.paramsJson || '{}' }
|
|
712
|
+
}
|
|
713
|
+
return {
|
|
714
|
+
name: 'quick_reply',
|
|
715
|
+
buttonParamsJson: JSON.stringify({
|
|
716
|
+
display_text: b.buttonText?.displayText || '',
|
|
717
|
+
id: b.buttonId || b.buttonText?.displayText || ''
|
|
718
|
+
})
|
|
719
|
+
}
|
|
720
|
+
})
|
|
721
|
+
const interactiveMessage = {
|
|
722
|
+
nativeFlowMessage: { buttons: flowButtons, messageParamsJson: '', messageVersion: 1 }
|
|
723
|
+
}; const bodyText = raw.contentText || (raw.imageMessage?.caption ?? raw.videoMessage?.caption ?? '') || ''
|
|
724
|
+
if (bodyText) interactiveMessage.body = { text: bodyText };
|
|
725
|
+
if (raw.footerText) interactiveMessage.footer = { text: raw.footerText };
|
|
726
|
+
const header = { title: raw.text || (interactiveMessage.body.text ? String(interactiveMessage.body.text).split('\n')[0].slice(0, 42) : '') || 'Menu', subtitle: '', hasMediaAttachment: false };
|
|
727
|
+
if (rawLoc) {
|
|
728
|
+
header.locationMessage = {
|
|
729
|
+
degreesLatitude: rawLoc.degreesLatitude ?? 0,
|
|
730
|
+
degreesLongitude: rawLoc.degreesLongitude ?? 0,
|
|
731
|
+
name: rawLoc.name ?? null,
|
|
732
|
+
address: rawLoc.address ?? null,
|
|
733
|
+
...(rawLoc.jpegThumbnail ? { jpegThumbnail: rawLoc.jpegThumbnail } : {})
|
|
734
|
+
};
|
|
735
|
+
header.hasMediaAttachment = true;
|
|
736
|
+
} else if (raw.imageMessage) {
|
|
737
|
+
header.imageMessage = raw.imageMessage;
|
|
738
|
+
header.hasMediaAttachment = true;
|
|
739
|
+
} else if (raw.videoMessage) {
|
|
740
|
+
header.videoMessage = raw.videoMessage;
|
|
741
|
+
header.hasMediaAttachment = true;
|
|
742
|
+
} else if (raw.documentMessage) {
|
|
743
|
+
header.documentMessage = raw.documentMessage;
|
|
744
|
+
header.hasMediaAttachment = true;
|
|
745
|
+
}
|
|
746
|
+
if (header.title || header.hasMediaAttachment) interactiveMessage.header = header;
|
|
747
|
+
if (raw.contextInfo?.mentionedJid?.length) {
|
|
748
|
+
interactiveMessage.contextInfo = { mentionedJid: raw.contextInfo.mentionedJid };
|
|
749
|
+
}
|
|
750
|
+
m = { interactiveMessage };
|
|
751
|
+
} else {
|
|
671
752
|
if (!hasHeader) {
|
|
672
753
|
try {
|
|
673
754
|
const media = await prepareWAMessageMedia({ image: BUTTONS_INVISIBLE_PNG() }, options)
|
|
@@ -676,6 +757,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
676
757
|
} catch { /* upload failed — send as-is */ }
|
|
677
758
|
}
|
|
678
759
|
m = { buttonsMessage: raw };
|
|
760
|
+
}
|
|
679
761
|
}
|
|
680
762
|
else if ('buttons' in message && !!message.buttons) {
|
|
681
763
|
// PATCH: `buttons` API — HORIZONTAL button row via classic ButtonsMessage
|