@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.
Files changed (51) hide show
  1. package/NOTICE.md +50 -0
  2. package/lib/Utils/A2UI.js +217 -0
  3. package/lib/Utils/MessageBuilder.js +332 -46
  4. package/lib/Utils/MessageBuilder_d.ts +45 -0
  5. package/lib/Utils/PersistentStore.js +592 -0
  6. package/lib/Utils/PersistentStore_d.ts +60 -0
  7. package/lib/Utils/anti-delete.d.ts +68 -0
  8. package/lib/Utils/anti-delete.js +185 -0
  9. package/lib/Utils/auto-reply.d.ts +47 -0
  10. package/lib/Utils/auto-reply.js +155 -0
  11. package/lib/Utils/button-helper-utils.js +314 -0
  12. package/lib/Utils/button-sender.js +817 -0
  13. package/lib/Utils/chat-history-helpers.d.ts +21 -0
  14. package/lib/Utils/chat-history-helpers.js +71 -0
  15. package/lib/Utils/index.d.ts +11 -0
  16. package/lib/Utils/index.js +16 -0
  17. package/lib/Utils/media-messages.d.ts +18 -0
  18. package/lib/Utils/media-messages.js +71 -0
  19. package/lib/Utils/media-set.d.ts +13 -0
  20. package/lib/Utils/media-set.js +165 -0
  21. package/lib/Utils/message-kind.js +139 -0
  22. package/lib/Utils/message-search.d.ts +44 -0
  23. package/lib/Utils/message-search.js +174 -0
  24. package/lib/Utils/scheduling.d.ts +42 -0
  25. package/lib/Utils/scheduling.js +140 -0
  26. package/lib/Utils/status.d.ts +50 -0
  27. package/lib/Utils/status.js +108 -0
  28. package/lib/Utils/stickerpack.d.ts +51 -0
  29. package/lib/Utils/stickerpack.js +276 -0
  30. package/lib/Utils/templates.d.ts +76 -0
  31. package/lib/Utils/templates.js +151 -0
  32. package/lib/Utils/use-sqlite-auth-state.js +28 -1
  33. package/lib/Utils/vcard.d.ts +58 -0
  34. package/lib/Utils/vcard.js +94 -0
  35. package/lib/VoIP/audio-feeder.d.ts +15 -0
  36. package/lib/VoIP/audio-feeder.js +132 -0
  37. package/lib/VoIP/index.js +277 -0
  38. package/lib/VoIP/relay-transport.d.ts +43 -0
  39. package/lib/VoIP/relay-transport.js +559 -0
  40. package/lib/VoIP/signaling.js +624 -0
  41. package/lib/VoIP/types.d.ts +69 -0
  42. package/lib/VoIP/types.js +17 -0
  43. package/lib/VoIP/wasm-engine.d.ts +103 -0
  44. package/lib/VoIP/wasm-engine.js +1214 -0
  45. package/lib/VoIP/worker-bootstrap.js +1042 -0
  46. package/lib/WABinary/generic-utils.js +8 -0
  47. package/lib/assets/wasm/loader.js +5 -0
  48. package/lib/assets/wasm/whatsapp.wasm +0 -0
  49. package/lib/assets/wasm/worker-modules.js +273 -0
  50. package/lib/index.js +4 -0
  51. 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 };