@vanzxy/baileys 1.6.2 → 1.6.4
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/NOTICE.md +50 -0
- package/lib/Utils/A2UI.js +217 -0
- package/lib/Utils/MessageBuilder.js +332 -46
- package/lib/Utils/MessageBuilder_d.ts +45 -0
- package/lib/Utils/PersistentStore.js +592 -0
- package/lib/Utils/PersistentStore_d.ts +60 -0
- package/lib/Utils/anti-delete.d.ts +68 -0
- package/lib/Utils/anti-delete.js +185 -0
- package/lib/Utils/auto-reply.d.ts +47 -0
- package/lib/Utils/auto-reply.js +155 -0
- package/lib/Utils/button-helper-utils.js +314 -0
- package/lib/Utils/button-sender.js +817 -0
- package/lib/Utils/chat-history-helpers.d.ts +21 -0
- package/lib/Utils/chat-history-helpers.js +71 -0
- package/lib/Utils/index.d.ts +11 -0
- package/lib/Utils/index.js +16 -0
- package/lib/Utils/media-messages.d.ts +18 -0
- package/lib/Utils/media-messages.js +71 -0
- package/lib/Utils/media-set.d.ts +13 -0
- package/lib/Utils/media-set.js +165 -0
- package/lib/Utils/message-kind.js +139 -0
- package/lib/Utils/message-search.d.ts +44 -0
- package/lib/Utils/message-search.js +174 -0
- package/lib/Utils/scheduling.d.ts +42 -0
- package/lib/Utils/scheduling.js +140 -0
- package/lib/Utils/status.d.ts +50 -0
- package/lib/Utils/status.js +108 -0
- package/lib/Utils/stickerpack.d.ts +51 -0
- package/lib/Utils/stickerpack.js +276 -0
- package/lib/Utils/templates.d.ts +76 -0
- package/lib/Utils/templates.js +151 -0
- package/lib/Utils/use-sqlite-auth-state.js +28 -1
- package/lib/Utils/vcard.d.ts +58 -0
- package/lib/Utils/vcard.js +94 -0
- package/lib/VoIP/audio-feeder.d.ts +15 -0
- package/lib/VoIP/audio-feeder.js +132 -0
- package/lib/VoIP/index.js +277 -0
- package/lib/VoIP/relay-transport.d.ts +43 -0
- package/lib/VoIP/relay-transport.js +559 -0
- package/lib/VoIP/signaling.js +624 -0
- package/lib/VoIP/types.d.ts +69 -0
- package/lib/VoIP/types.js +17 -0
- package/lib/VoIP/wasm-engine.d.ts +103 -0
- package/lib/VoIP/wasm-engine.js +1214 -0
- package/lib/VoIP/worker-bootstrap.js +1042 -0
- package/lib/WABinary/generic-utils.js +8 -0
- package/lib/assets/wasm/loader.js +5 -0
- package/lib/assets/wasm/whatsapp.wasm +0 -0
- package/lib/assets/wasm/worker-modules.js +273 -0
- package/lib/index.js +4 -0
- package/package.json +22 -1
package/NOTICE.md
CHANGED
|
@@ -29,11 +29,61 @@ inline `Vanz@` comments for specifics): lazy-loading of optional
|
|
|
29
29
|
and neutral fallback text (previously referenced the original author's
|
|
30
30
|
name in a small number of user-facing fallback strings).
|
|
31
31
|
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## lib/Utils/message-kind.js — button/list "addon kind" resolution
|
|
35
|
+
|
|
36
|
+
`resolveButtonAddonKind()` is adapted from **zapo-js**
|
|
37
|
+
(`resolveButtonAddonKind` / `resolveNativeFlowAddonKind` in
|
|
38
|
+
`src/message/encode/content.ts`), created by **vinikjkkj**
|
|
39
|
+
<contact@vinicius.email>. <https://github.com/vinikjkkj/zapo>
|
|
40
|
+
|
|
41
|
+
- License: MIT, Copyright (c) 2026 vinikjkkj
|
|
42
|
+
- Ported into `@vanzxy/baileys` 1.6.4, adapted from zapo's internal
|
|
43
|
+
`Proto.IMessage` shape to this fork's message-content shape.
|
|
44
|
+
`parseInteractiveReply()` in the same file is original code written
|
|
45
|
+
for this fork (not from zapo), covering `buttonsResponseMessage` /
|
|
46
|
+
`listResponseMessage` / `interactiveResponseMessage` /
|
|
47
|
+
`templateButtonReplyMessage`.
|
|
48
|
+
|
|
32
49
|
Additional performance/authenticity reference drawn from `arslan-baileys`
|
|
33
50
|
(1.1.0), which shares the same underlying builder API.
|
|
34
51
|
|
|
35
52
|
---
|
|
36
53
|
|
|
54
|
+
## lib/Utils/button-sender.js + lib/Utils/button-helper-utils.js — interactive/native-flow button send layer
|
|
55
|
+
|
|
56
|
+
Ported from `@queenanya/baileys` (fork by **QueenAnya** / OLDUSER 06,
|
|
57
|
+
package `@queenanya/baileys`), files `src/addons/button-sender.ts` and
|
|
58
|
+
`src/addons/message-utils.ts`. That fork's own header credits the base
|
|
59
|
+
implementation as "Ported from `@ryuu-reinzz/button-helper` v2.2.5".
|
|
60
|
+
|
|
61
|
+
- License: MIT (per `@queenanya/baileys` `package.json`)
|
|
62
|
+
- Ported into `@vanzxy/baileys` 1.6.5, converted TS → JS ESM. Adjustments:
|
|
63
|
+
`console.log`/`console.warn` calls replaced with `sock.logger` (pino)
|
|
64
|
+
calls to match this fork's logging convention; default dummy-file
|
|
65
|
+
name/branding strings genericized; import paths rewired to this fork's
|
|
66
|
+
`Utils`/`WABinary`/`Types` layout (`generateWAMessage`,
|
|
67
|
+
`generateWAMessageFromContent`, `normalizeMessageContent`,
|
|
68
|
+
`getUrlFromDirectPath`, `unixTimestampSeconds`, `isJidGroup`,
|
|
69
|
+
`isJidNewsletter`, `QueryIds`, `XWAPaths`, etc. — all already present
|
|
70
|
+
in `@vanzxy/baileys` and reused as-is, no duplication).
|
|
71
|
+
- Adds `sendButtons()`, `sendInteractiveMessage()`,
|
|
72
|
+
`sendInteractiveMessageV2()`, plus supporting validators
|
|
73
|
+
(`validateSendButtonsPayload`, `validateSendInteractiveMessagePayload`,
|
|
74
|
+
`validateInteractiveMessageContent`, `validateAuthoringButtons`),
|
|
75
|
+
`buildInteractiveButtons()`, `convertToInteractiveMessage()`, the
|
|
76
|
+
`InteractiveValidationError` class, and message-introspection helpers
|
|
77
|
+
(`getButtonType`, `getButtonArgs`, `getMediaType`, `getMessageType`,
|
|
78
|
+
`prepareAlbumMessageContent`, `makeMessageExtrasAddon`, etc.). These
|
|
79
|
+
send buttons via `relayMessage` directly (bypassing `sendMessage`'s
|
|
80
|
+
validation path, which doesn't recognise `interactiveMessage`
|
|
81
|
+
payloads) with the correct `biz`/`interactive`/`native_flow` binary
|
|
82
|
+
nodes so buttons render on WhatsApp Messenger + Business, Android +
|
|
83
|
+
iOS. Complements the existing `Button`/`ButtonV2`/`ButtonV3` builder
|
|
84
|
+
classes in `MessageBuilder.js`, which build message *content* — this
|
|
85
|
+
addon handles the *send* layer.
|
|
86
|
+
|
|
37
87
|
## rich-message-utils.js — AIRICH inline-image bug fix
|
|
38
88
|
|
|
39
89
|
Original implementation is this project's own; fixed 2026-08-15 (bad
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/Utils/A2UI.js — A2UI (Bloks) widget builder + sender
|
|
3
|
+
*
|
|
4
|
+
* Part of @vanzxy/baileys. Builds the flat `components` array A2UI/Bloks
|
|
5
|
+
* expects (id-referencing tree: Column/Row hold `children`, Card/Button hold
|
|
6
|
+
* `child`, Modal holds `trigger`/`content`) and sends it as an
|
|
7
|
+
* `interactiveMessage.bloksWidget` via the same `getBizBinaryNode()` path
|
|
8
|
+
* Button/ButtonV2 use, so the wire-level <biz>/<native_flow> node always
|
|
9
|
+
* matches the actual button names sent — no more hand-rolled duplicate of
|
|
10
|
+
* that logic living outside the library.
|
|
11
|
+
*
|
|
12
|
+
* See MessageBuilder.js's `Button.setBloksWidget()` for the declarative
|
|
13
|
+
* (nested-tree) alternative to this imperative (id-returning-factory) API;
|
|
14
|
+
* both produce the same wire format and can be mixed freely.
|
|
15
|
+
*/
|
|
16
|
+
"use strict";
|
|
17
|
+
|
|
18
|
+
import crypto from "crypto";
|
|
19
|
+
import { generateWAMessageFromContent } from "./messages.js";
|
|
20
|
+
import { getBizBinaryNode } from "../WABinary/index.js";
|
|
21
|
+
|
|
22
|
+
class A2UI {
|
|
23
|
+
constructor({ catalogId = "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json", version = "v0.9" } = {}) {
|
|
24
|
+
this._version = version;
|
|
25
|
+
this._catalogId = catalogId;
|
|
26
|
+
this._components = new Map();
|
|
27
|
+
this._counter = 0;
|
|
28
|
+
this._rootChildren = [];
|
|
29
|
+
}
|
|
30
|
+
#nextId(prefix) {
|
|
31
|
+
return `${prefix}_${(this._counter++).toString(36)}`;
|
|
32
|
+
}
|
|
33
|
+
#reg(id, component, extra = {}) {
|
|
34
|
+
id ??= this.#nextId(component.toLowerCase());
|
|
35
|
+
if (id === "root") throw new Error(`Component id "root" is reserved for the implicit root wrapper`);
|
|
36
|
+
if (this._components.has(id)) throw new Error(`Component id "${id}" already used`);
|
|
37
|
+
this._components.set(id, { id, component, ...extra });
|
|
38
|
+
return id;
|
|
39
|
+
}
|
|
40
|
+
text(text, { id, variant = "body" } = {}) {
|
|
41
|
+
return this.#reg(id, "Text", { text, variant });
|
|
42
|
+
}
|
|
43
|
+
image(url, { id, variant, fit = "cover" } = {}) {
|
|
44
|
+
return this.#reg(id, "Image", { url, ...(variant ? { variant } : {}), fit });
|
|
45
|
+
}
|
|
46
|
+
video(url, { id } = {}) {
|
|
47
|
+
return this.#reg(id, "Video", { url });
|
|
48
|
+
}
|
|
49
|
+
checkbox(label, { id, value = false } = {}) {
|
|
50
|
+
return this.#reg(id, "CheckBox", { label, value });
|
|
51
|
+
}
|
|
52
|
+
textField(label, { id, variant = "text" } = {}) {
|
|
53
|
+
return this.#reg(id, "TextField", { label, variant });
|
|
54
|
+
}
|
|
55
|
+
button(childId, { id, variant = "primary", action } = {}) {
|
|
56
|
+
if (!childId) throw new TypeError("button(childId) requires the id of a child component (e.g. from .text())");
|
|
57
|
+
return this.#reg(id, "Button", { child: childId, variant, ...(action ? { action } : {}) });
|
|
58
|
+
}
|
|
59
|
+
card(childId, { id } = {}) {
|
|
60
|
+
return this.#reg(id, "Card", { child: childId });
|
|
61
|
+
}
|
|
62
|
+
// trigger: id of the component that opens the modal (e.g. a Button); content: id of the
|
|
63
|
+
// component shown inside it. Both are ids of already-registered SIBLING components, not
|
|
64
|
+
// nested children — that's how the wire format expects Modal to reference them.
|
|
65
|
+
modal(triggerId, contentId, { id } = {}) {
|
|
66
|
+
if (!triggerId) throw new TypeError("modal(triggerId, contentId) requires the id of the trigger component");
|
|
67
|
+
if (!contentId) throw new TypeError("modal(triggerId, contentId) requires the id of the content component");
|
|
68
|
+
return this.#reg(id, "Modal", { trigger: triggerId, content: contentId });
|
|
69
|
+
}
|
|
70
|
+
// Escape hatch for any catalog component without a dedicated method yet (Divider, Slider,
|
|
71
|
+
// Switch, List, etc). props is merged as-is into the registered node.
|
|
72
|
+
raw(component, props = {}, { id } = {}) {
|
|
73
|
+
if (typeof component !== "string" || !component) throw new TypeError("raw(component, props) requires a non-empty component type string");
|
|
74
|
+
return this.#reg(id, component, props);
|
|
75
|
+
}
|
|
76
|
+
column(children = [], { id } = {}) {
|
|
77
|
+
if (!children.length) throw new TypeError("column(children) requires at least one child id");
|
|
78
|
+
return this.#reg(id, "Column", { children });
|
|
79
|
+
}
|
|
80
|
+
row(children = [], { id } = {}) {
|
|
81
|
+
if (!children.length) throw new TypeError("row(children) requires at least one child id");
|
|
82
|
+
return this.#reg(id, "Row", { children });
|
|
83
|
+
}
|
|
84
|
+
divider({ id } = {}) {
|
|
85
|
+
return this.#reg(id, "Divider", {});
|
|
86
|
+
}
|
|
87
|
+
choicePicker(label, options, { id, variant = "mutuallyExclusive", value, displayStyle = "checkbox", filterable = false } = {}) {
|
|
88
|
+
if (!Array.isArray(options) || !options.length) {
|
|
89
|
+
throw new TypeError("choicePicker(label, options) requires a non-empty options array of {label, value}");
|
|
90
|
+
}
|
|
91
|
+
return this.#reg(id, "ChoicePicker", {
|
|
92
|
+
label,
|
|
93
|
+
variant,
|
|
94
|
+
...(value !== undefined ? { value } : {}),
|
|
95
|
+
options,
|
|
96
|
+
displayStyle,
|
|
97
|
+
filterable
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
root(children) {
|
|
101
|
+
if (!Array.isArray(children) || !children.length) {
|
|
102
|
+
throw new TypeError("root(children) requires a non-empty array of top-level component ids");
|
|
103
|
+
}
|
|
104
|
+
this._rootChildren = children;
|
|
105
|
+
return this;
|
|
106
|
+
}
|
|
107
|
+
// Vanz@Add 29-08-26 --- Product/list carousel card. This is a DIFFERENT wire
|
|
108
|
+
// payload shape from the Column/Row component-tree the rest of this class
|
|
109
|
+
// builds (type: 'list_card', flat items array) — not a catalog component, so
|
|
110
|
+
// it doesn't go through #reg()/root(). Call this instead of root()+build();
|
|
111
|
+
// build() returns the list_card payload directly when this was set.
|
|
112
|
+
listCard({ title, items, fallbackText, uuid = crypto.randomUUID() } = {}) {
|
|
113
|
+
if (!title) throw new TypeError("listCard requires a title");
|
|
114
|
+
if (!Array.isArray(items) || !items.length) {
|
|
115
|
+
throw new TypeError("listCard requires a non-empty items array");
|
|
116
|
+
}
|
|
117
|
+
this._listCardPayload = {
|
|
118
|
+
uuid,
|
|
119
|
+
data: JSON.stringify({
|
|
120
|
+
type: "list_card",
|
|
121
|
+
title,
|
|
122
|
+
fallback_text: fallbackText ?? "",
|
|
123
|
+
items: items.map((it) => ({
|
|
124
|
+
asset_id: it.assetId ?? crypto.randomUUID().replace(/-/g, "").slice(0, 17),
|
|
125
|
+
asset_type: it.assetType ?? "PRODUCT_ITEM",
|
|
126
|
+
title: it.title,
|
|
127
|
+
trailing_label: it.price ?? it.trailingLabel ?? "",
|
|
128
|
+
trailing_emphasis: it.emphasis ?? "strong"
|
|
129
|
+
}))
|
|
130
|
+
}),
|
|
131
|
+
type: "im_a2ui",
|
|
132
|
+
fallback: fallbackText ?? ""
|
|
133
|
+
};
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
136
|
+
build({ uuid = crypto.randomUUID(), surfaceId, type = "im_a2ui", wrapped = true } = {}) {
|
|
137
|
+
if (this._listCardPayload) return this._listCardPayload;
|
|
138
|
+
if (!this._rootChildren.length) throw new Error("Call root([...ids]) before build()");
|
|
139
|
+
const root = { id: "root", component: "Column", children: this._rootChildren };
|
|
140
|
+
const components = [root, ...this._components.values()];
|
|
141
|
+
const data = wrapped
|
|
142
|
+
? {
|
|
143
|
+
version: this._version,
|
|
144
|
+
createSurface: {
|
|
145
|
+
surfaceId: surfaceId ?? `starcore-widget=${uuid}`,
|
|
146
|
+
catalogId: this._catalogId,
|
|
147
|
+
components
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
: { components };
|
|
151
|
+
return {
|
|
152
|
+
uuid,
|
|
153
|
+
data: JSON.stringify(data),
|
|
154
|
+
type
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Build + send an A2UI/Bloks widget as an interactiveMessage.
|
|
161
|
+
* @param {import('../../WAProto/index.js').WASocket} client Active Baileys socket.
|
|
162
|
+
* @param {string} jid Destination chat/group jid.
|
|
163
|
+
*/
|
|
164
|
+
async function sendA2UIWidget(client, jid, {
|
|
165
|
+
a2ui,
|
|
166
|
+
bodyText = "",
|
|
167
|
+
footer = "",
|
|
168
|
+
buttons = [],
|
|
169
|
+
contextInfo = {},
|
|
170
|
+
expiration,
|
|
171
|
+
quoted,
|
|
172
|
+
type = "im_a2ui",
|
|
173
|
+
wrapped = true,
|
|
174
|
+
singleScreen = false
|
|
175
|
+
} = {}) {
|
|
176
|
+
if (!client) throw new Error("Socket is required");
|
|
177
|
+
if (!(a2ui instanceof A2UI)) throw new TypeError("a2ui must be an A2UI instance");
|
|
178
|
+
|
|
179
|
+
const nativeFlowMessage = buttons && buttons.length
|
|
180
|
+
? {
|
|
181
|
+
buttons: buttons.map((b) => ({
|
|
182
|
+
name: b.name ?? "cta_url",
|
|
183
|
+
buttonParamsJson: typeof b.params === "string" ? b.params : JSON.stringify(b.params ?? {}),
|
|
184
|
+
})),
|
|
185
|
+
messageParamsJson: "{}",
|
|
186
|
+
messageVersion: 1
|
|
187
|
+
}
|
|
188
|
+
: { messageParamsJson: "" };
|
|
189
|
+
|
|
190
|
+
const interactiveMessage = singleScreen
|
|
191
|
+
? {
|
|
192
|
+
nativeFlowMessage,
|
|
193
|
+
bloksWidget: a2ui.build({ type, wrapped }),
|
|
194
|
+
...(expiration || Object.keys(contextInfo).length ? { contextInfo: { ...(expiration ? { expiration } : {}), ...contextInfo } } : {})
|
|
195
|
+
}
|
|
196
|
+
: {
|
|
197
|
+
header: { hasMediaAttachment: false },
|
|
198
|
+
body: { text: bodyText },
|
|
199
|
+
...(footer ? { footer: { text: footer } } : {}),
|
|
200
|
+
nativeFlowMessage,
|
|
201
|
+
bloksWidget: a2ui.build({ type, wrapped }),
|
|
202
|
+
...(expiration || Object.keys(contextInfo).length ? { contextInfo: { ...(expiration ? { expiration } : {}), ...contextInfo } } : {})
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const msg = generateWAMessageFromContent(jid, {
|
|
206
|
+
messageContextInfo: { messageSecret: crypto.randomBytes(32) },
|
|
207
|
+
interactiveMessage
|
|
208
|
+
}, { quoted });
|
|
209
|
+
|
|
210
|
+
await client.relayMessage(msg.key.remoteJid, msg.message, {
|
|
211
|
+
messageId: msg.key.id,
|
|
212
|
+
additionalNodes: [getBizBinaryNode(msg.message)]
|
|
213
|
+
});
|
|
214
|
+
return msg;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export { A2UI, sendA2UIWidget };
|