@vanzxy/baileys 1.6.6 → 1.6.8
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 +385 -38
- package/WAProto/index.js +1 -1
- package/lib/Utils/MessageBuilder.js +17 -2
- package/lib/Utils/anti-delete.js +9 -1
- package/lib/Utils/generics.js +19 -1
- package/lib/Utils/media-set.js +5 -1
- package/lib/WABinary/generic-utils.js +3 -1
- package/package.json +34 -11
- package/WAProto/CHANGELOG-proto-upgrade.md +0 -111
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<div align="center" id="top">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:1d6a23,100:2ecc71&height=180§ion=header&text=%40vanzxy%2Fbaileys&fontSize=42&fontColor=ffffff&animation=fadeIn&fontAlignY=38&desc=Next-generation%20Baileys%20fork%20—%20built%20different,%20built%20by%20Vanzxy&descAlignY=58&descSize=16" width="100%"/>
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<img src="https://files.catbox.moe/l72xji.svg" width="100%" alt="Sakura night banner"/>
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<p>
|
|
8
|
+
<img src="https://readme-typing-svg.demolab.com?font=Fira+Code&size=18&pause=1200&color=2ECC71¢er=true&vCenter=true&width=650&lines=Extended+interactive+messages+%26+native+flow;Status+tools+%2B+quality-of-life+fixes;Built+on+top+of+WhiskeySockets%2FBaileys" alt="Typing SVG" />
|
|
9
|
+
</p>
|
|
8
10
|
|
|
9
11
|
<p>
|
|
10
12
|
<a href="https://www.npmjs.com/package/@vanzxy/baileys" target="_blank"><img src="https://img.shields.io/npm/v/@vanzxy/baileys?color=2ecc71&label=npm&style=for-the-badge" alt="npm version"/></a>
|
|
@@ -18,26 +20,63 @@ Extended interactive messages • native flow enhancements • status tools •
|
|
|
18
20
|
<img src="https://img.shields.io/github/languages/code-size/vanzxysenpai/vanzxybaileys?color=e67e22&style=flat-square" alt="Code size"/>
|
|
19
21
|
<img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen?style=flat-square" alt="Node >=20"/>
|
|
20
22
|
<img src="https://img.shields.io/badge/module-ESM-blue?style=flat-square" alt="ESM"/>
|
|
23
|
+
<img src="https://img.shields.io/badge/types-included-blue?style=flat-square" alt="TypeScript types included"/>
|
|
21
24
|
<img src="https://img.shields.io/badge/license-see%20NOTICE-lightgrey?style=flat-square" alt="License"/>
|
|
22
25
|
</p>
|
|
23
26
|
|
|
24
27
|
<p>
|
|
25
28
|
<a href="#-why-vanzxybaileys">About</a>  | 
|
|
26
|
-
<a href="#-
|
|
29
|
+
<a href="#-comparison">Comparison</a>  | 
|
|
27
30
|
<a href="#-features">Features</a>  | 
|
|
28
|
-
<a href="#-exclusive-vanzxy-enhancements">Enhancements</a>  | 
|
|
29
31
|
<a href="#-installation">Installation</a>  | 
|
|
32
|
+
<a href="#-quick-start">Quick Start</a>  | 
|
|
30
33
|
<a href="#-usage-examples">Examples</a>  | 
|
|
31
|
-
<a href="#-
|
|
34
|
+
<a href="#-faq--troubleshooting">FAQ</a>  | 
|
|
35
|
+
<a href="#-contributing">Contributing</a>  | 
|
|
32
36
|
<a href="#-credits">Credits</a>  | 
|
|
33
37
|
<a href="#-maintainer">Maintainer</a>
|
|
34
38
|
</p>
|
|
35
39
|
|
|
40
|
+
<details>
|
|
41
|
+
<summary>📖 Full table of contents</summary>
|
|
42
|
+
<br/>
|
|
43
|
+
|
|
44
|
+
- [🍃 Why @vanzxy/baileys](#-why-vanzxybaileys)
|
|
45
|
+
- [🆚 Comparison](#-comparison)
|
|
46
|
+
- [🧰 Built With](#-built-with)
|
|
47
|
+
- [🔥 Features](#-features)
|
|
48
|
+
- [✨ Exclusive Vanzxy Enhancements](#-exclusive-vanzxy-enhancements)
|
|
49
|
+
- [📦 Installation](#-installation)
|
|
50
|
+
- [🚀 Quick Start](#-quick-start)
|
|
51
|
+
- [🔐 Authentication](#-authentication)
|
|
52
|
+
- [🗄️ Store Backends](#-store-backends)
|
|
53
|
+
- [💡 Usage Examples](#-usage-examples)
|
|
54
|
+
- [Buttons & Native Flow](#buttons--native-flow)
|
|
55
|
+
- [Poll](#poll)
|
|
56
|
+
- [Carousel](#carousel)
|
|
57
|
+
- [AIRich — rich response cards](#airich--rich-response-cards)
|
|
58
|
+
- [📞 Voice & Video Calls](#-voice--video-calls)
|
|
59
|
+
- [🔎 User Sync Queries](#-user-sync-queries)
|
|
60
|
+
- [🧩 Utility Modules](#-utility-modules)
|
|
61
|
+
- [🛎️ System Notification Filter](#-system-notification-filter)
|
|
62
|
+
- [🛠 Recommended Environment](#-recommended-environment)
|
|
63
|
+
- [📘 TypeScript Support](#-typescript-support)
|
|
64
|
+
- [📚 Fork Lineage](#-fork-lineage)
|
|
65
|
+
- [❓ FAQ & Troubleshooting](#-faq--troubleshooting)
|
|
66
|
+
- [🤝 Contributing](#-contributing)
|
|
67
|
+
- [🙏 Credits](#-credits)
|
|
68
|
+
- [💖 Support](#-support)
|
|
69
|
+
- [👑 Maintainer](#-maintainer)
|
|
70
|
+
- [⚠️ Disclaimer](#-disclaimer)
|
|
71
|
+
- [📝 Patch Notes](#-v4-patch-notes)
|
|
72
|
+
|
|
73
|
+
</details>
|
|
74
|
+
|
|
36
75
|
</div>
|
|
37
76
|
|
|
38
77
|
---
|
|
39
78
|
|
|
40
|
-
##
|
|
79
|
+
## 🍃 Why @vanzxy/baileys?
|
|
41
80
|
|
|
42
81
|
This fork focuses on:
|
|
43
82
|
|
|
@@ -49,6 +88,27 @@ This fork focuses on:
|
|
|
49
88
|
| 🧩 | More interactive message types |
|
|
50
89
|
| ⚡ | Cleaner implementation for bot developers |
|
|
51
90
|
| 🔧 | Extra utilities not available in standard Baileys forks |
|
|
91
|
+
| 🗄️ | Multiple auth & store backends out of the box (file, SQLite, MongoDB, MySQL, PostgreSQL, Redis) |
|
|
92
|
+
| 📞 | Experimental voice-call (VoIP) support |
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 🆚 Comparison
|
|
97
|
+
|
|
98
|
+
How `@vanzxy/baileys` stacks up against its own lineage and the wider Baileys fork ecosystem:
|
|
99
|
+
|
|
100
|
+
| Capability | `@vanzxy/baileys` | `@itsliaaa/baileys` | `WhiskeySockets/Baileys` |
|
|
101
|
+
|---|:---:|:---:|:---:|
|
|
102
|
+
| Native Flow buttons (V1/V2/V3) | ✅ | ✅ | ⚠️ basic only |
|
|
103
|
+
| Carousel messages | ✅ | ❌ | ❌ |
|
|
104
|
+
| Rich response cards (AIRich) | ✅ | ❌ | ❌ |
|
|
105
|
+
| Commerce flow (catalog/order/payment) | ✅ | ⚠️ partial | ❌ |
|
|
106
|
+
| Voice calling (VoIP) | ✅ experimental | ❌ | ❌ |
|
|
107
|
+
| Multi-backend store (SQL/Mongo/Redis) | ✅ | ⚠️ file/SQLite only | ⚠️ in-memory only |
|
|
108
|
+
| Full `.d.ts` TypeScript definitions | ✅ | ⚠️ partial | ⚠️ partial |
|
|
109
|
+
| User sync queries (WAUSync) | ✅ | ✅ | ✅ |
|
|
110
|
+
|
|
111
|
+
> Tabel ini menggambarkan fitur di level package, bukan benchmark performa. PR untuk memperbarui/mengoreksi tabel ini dipersilakan lewat [Contributing](#-contributing).
|
|
52
112
|
|
|
53
113
|
---
|
|
54
114
|
|
|
@@ -78,10 +138,11 @@ This fork focuses on:
|
|
|
78
138
|
<td valign="top">
|
|
79
139
|
|
|
80
140
|
- Native Flow
|
|
81
|
-
- Buttons
|
|
141
|
+
- Buttons (V1 / V2 / V3)
|
|
82
142
|
- Lists
|
|
83
143
|
- Carousel Messages
|
|
84
|
-
-
|
|
144
|
+
- Poll & Quiz Messages
|
|
145
|
+
- Rich Response Messages (AIRich)
|
|
85
146
|
- CTA / Reply / URL Buttons
|
|
86
147
|
- Call Buttons
|
|
87
148
|
- OTP Buttons
|
|
@@ -116,13 +177,55 @@ This fork focuses on:
|
|
|
116
177
|
</tr>
|
|
117
178
|
</table>
|
|
118
179
|
|
|
180
|
+
<table>
|
|
181
|
+
<tr>
|
|
182
|
+
<th align="center">🔐 Auth & Storage</th>
|
|
183
|
+
<th align="center">📞 Realtime</th>
|
|
184
|
+
<th align="center">🛠 Developer Tooling</th>
|
|
185
|
+
</tr>
|
|
186
|
+
<tr>
|
|
187
|
+
<td valign="top">
|
|
188
|
+
|
|
189
|
+
- Multi-file auth state
|
|
190
|
+
- Single-file auth state
|
|
191
|
+
- SQLite auth state
|
|
192
|
+
- Cache-manager auth state
|
|
193
|
+
- In-memory store
|
|
194
|
+
- SQLite / MongoDB / MySQL /
|
|
195
|
+
PostgreSQL / Redis store adapters
|
|
196
|
+
|
|
197
|
+
</td>
|
|
198
|
+
<td valign="top">
|
|
199
|
+
|
|
200
|
+
- Voice calling (VoIP, WASM engine)
|
|
201
|
+
- User sync queries (WAUSync)
|
|
202
|
+
- Presence / status / device lookup
|
|
203
|
+
- Event buffer for high-volume bots
|
|
204
|
+
|
|
205
|
+
</td>
|
|
206
|
+
<td valign="top">
|
|
207
|
+
|
|
208
|
+
- Full TypeScript definitions (`.d.ts`)
|
|
209
|
+
- Anti-delete detection
|
|
210
|
+
- Message search helpers
|
|
211
|
+
- Auto-reply engine
|
|
212
|
+
- Scheduling helpers
|
|
213
|
+
- Message retry manager
|
|
214
|
+
|
|
215
|
+
</td>
|
|
216
|
+
</tr>
|
|
217
|
+
</table>
|
|
218
|
+
|
|
119
219
|
---
|
|
120
220
|
|
|
121
|
-
##
|
|
221
|
+
## ✨ Exclusive Vanzxy Enhancements
|
|
122
222
|
|
|
123
223
|
### Audio Group Status Fix
|
|
124
224
|
Audio status uses a more compatible implementation to avoid unsupported-version errors on older WhatsApp clients.
|
|
125
225
|
|
|
226
|
+
### AIRich — the rich-response message builder
|
|
227
|
+
A chainable builder (`AIRich`, also exported as `AIVanzxy` / `LeafRich` / `VanzxyAI` / `VanzxyRich`) with 40+ `add*()`/`set*()` methods covering headings, formatted text (hyperlinks/citations/LaTeX), code blocks, tables, image/video/product/post cards, task & progress cards, tip banners, and quick-reply suggestions — the kind of rich card layout you'd normally only see from an official AI/assistant-style bot. See [Usage Examples](#airich--rich-response-cards) below.
|
|
228
|
+
|
|
126
229
|
### Native Flow Expansion
|
|
127
230
|
|
|
128
231
|
<table>
|
|
@@ -198,28 +301,125 @@ Directly from GitHub:
|
|
|
198
301
|
npm install github:vanzxysenpai/vanzxybaileys
|
|
199
302
|
```
|
|
200
303
|
|
|
304
|
+
> Requires **Node.js 20+** — install will refuse to run below that (checked by `engine-requirements.js` on `preinstall`).
|
|
305
|
+
|
|
306
|
+
### Optional peer dependencies
|
|
307
|
+
|
|
308
|
+
Everything below is **optional** — the socket works without any of them. Install only what the features you use need; missing ones fail with a clear install hint instead of a silent crash.
|
|
309
|
+
|
|
310
|
+
| Package | Unlocks |
|
|
311
|
+
|---|---|
|
|
312
|
+
| `sharp` | Fast image resizing/processing (used by the message builders' `Toolkit.resize`) |
|
|
313
|
+
| `@napi-rs/image` | Lighter native alternative to `sharp` for image ops |
|
|
314
|
+
| `jimp` | Pure-JS image fallback when neither of the above is installed |
|
|
315
|
+
| `fluent-ffmpeg` | Audio/video conversion for media messages |
|
|
316
|
+
| `audio-decode` | Audio waveform/duration extraction (voice notes, VoIP capture) |
|
|
317
|
+
| `link-preview-js` | Rich link previews for URLs in outgoing text messages |
|
|
318
|
+
| `better-sqlite3` | SQLite auth state **and** SQLite store adapter |
|
|
319
|
+
| `mongodb` | MongoDB store adapter |
|
|
320
|
+
| `mysql2` | MySQL store adapter |
|
|
321
|
+
| `pg` | PostgreSQL store adapter |
|
|
322
|
+
| `ioredis` | Redis store adapter |
|
|
323
|
+
| `@roamhq/wrtc` | Native WebRTC bindings for [voice calling](#-voice--video-calls) |
|
|
324
|
+
|
|
201
325
|
---
|
|
202
326
|
|
|
203
327
|
## 🚀 Quick Start
|
|
204
328
|
|
|
205
329
|
```js
|
|
206
|
-
import { makeWASocket } from '@vanzxy/baileys'
|
|
330
|
+
import { makeWASocket, useMultiFileAuthState } from '@vanzxy/baileys'
|
|
331
|
+
|
|
332
|
+
const { state, saveCreds } = await useMultiFileAuthState('auth_info')
|
|
207
333
|
|
|
208
334
|
const sock = makeWASocket({
|
|
209
|
-
|
|
335
|
+
auth: state
|
|
210
336
|
})
|
|
211
337
|
|
|
338
|
+
// persist credentials whenever Baileys updates them
|
|
339
|
+
sock.ev.on('creds.update', saveCreds)
|
|
340
|
+
|
|
212
341
|
sock.ev.on('connection.update', (update) => {
|
|
213
|
-
const { connection } = update
|
|
342
|
+
const { connection, qr } = update
|
|
343
|
+
|
|
344
|
+
// `printQRInTerminal` is deprecated upstream — render the QR yourself,
|
|
345
|
+
// e.g. with the `qrcode-terminal` package:
|
|
346
|
+
// import qrcode from 'qrcode-terminal'
|
|
347
|
+
// if (qr) qrcode.generate(qr, { small: true })
|
|
348
|
+
if (qr) console.log('Scan this QR:', qr)
|
|
349
|
+
|
|
214
350
|
if (connection === 'open') console.log('🍃 Connected!')
|
|
215
351
|
})
|
|
352
|
+
|
|
353
|
+
sock.ev.on('messages.upsert', ({ messages }) => {
|
|
354
|
+
const msg = messages[0]
|
|
355
|
+
if (!msg.message || msg.key.fromMe) return
|
|
356
|
+
console.log('New message from', msg.key.remoteJid)
|
|
357
|
+
})
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## 🔐 Authentication
|
|
363
|
+
|
|
364
|
+
Four auth-state backends ship out of the box. All return the same `{ state, saveCreds }` shape expected by `makeWASocket({ auth })`, so they're drop-in interchangeable.
|
|
365
|
+
|
|
366
|
+
| Function | Storage | Best for |
|
|
367
|
+
|---|---|---|
|
|
368
|
+
| `useMultiFileAuthState(folder)` | One JSON file per key, on disk | Default choice — simple, debuggable, works everywhere |
|
|
369
|
+
| `useSingleFileAuthState(fileName)` | One JSON file, on disk | Small bots where a single file is easier to manage/back up |
|
|
370
|
+
| `useSqliteAuthState(opts)` | SQLite (`better-sqlite3`) | Bots that already use SQLite, or want auth in one embedded DB file |
|
|
371
|
+
| `useCacheManagerAuthState(store, sessionKey)` | Any [`cacheable`](https://www.npmjs.com/package/@cacheable/node-cache)-compatible store | Multi-session hosting panels, Redis-backed setups |
|
|
372
|
+
|
|
373
|
+
```js
|
|
374
|
+
import { makeWASocket, useMultiFileAuthState } from '@vanzxy/baileys'
|
|
375
|
+
|
|
376
|
+
const { state, saveCreds } = await useMultiFileAuthState('auth_info')
|
|
377
|
+
const sock = makeWASocket({ auth: state })
|
|
378
|
+
sock.ev.on('creds.update', saveCreds)
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
```js
|
|
382
|
+
// SQLite variant
|
|
383
|
+
import { makeWASocket, useSqliteAuthState } from '@vanzxy/baileys'
|
|
384
|
+
|
|
385
|
+
const { state, saveCreds } = await useSqliteAuthState({ database: './auth.db' })
|
|
386
|
+
const sock = makeWASocket({ auth: state })
|
|
387
|
+
sock.ev.on('creds.update', saveCreds)
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
`useMultiFileAuthState` also exports `pruneStaleAuthFiles(folder, options)` to clean up old sender-key files on a schedule — useful for long-running bots that accumulate thousands of stale key files.
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## 🗄️ Store Backends
|
|
395
|
+
|
|
396
|
+
`makeInMemoryStore()` from `lib/Store` gives you the classic in-memory chat/contact/message cache. For anything that needs to survive a restart, `makePersistentStore()` (from `PersistentStore.js`) wraps one of five backends behind the same interface:
|
|
397
|
+
|
|
398
|
+
| Backend | Function |
|
|
399
|
+
|---|---|
|
|
400
|
+
| SQLite | `createSqliteStoreAdapter(opts)` |
|
|
401
|
+
| MongoDB | `createMongoStoreAdapter(opts)` |
|
|
402
|
+
| MySQL | `createMysqlStoreAdapter(opts)` |
|
|
403
|
+
| PostgreSQL | `createPostgresStoreAdapter(opts)` |
|
|
404
|
+
| Redis | `createRedisStoreAdapter(opts)` |
|
|
405
|
+
|
|
406
|
+
```js
|
|
407
|
+
import { makeWASocket, makeInMemoryStore } from '@vanzxy/baileys'
|
|
408
|
+
|
|
409
|
+
const store = makeInMemoryStore({})
|
|
410
|
+
store.readFromFile('./baileys_store.json')
|
|
411
|
+
setInterval(() => store.writeToFile('./baileys_store.json'), 10_000)
|
|
412
|
+
|
|
413
|
+
const sock = makeWASocket({ /* ...auth etc */ })
|
|
414
|
+
store.bind(sock.ev)
|
|
216
415
|
```
|
|
217
416
|
|
|
218
417
|
---
|
|
219
418
|
|
|
220
419
|
## 💡 Usage Examples
|
|
221
420
|
|
|
222
|
-
### Buttons
|
|
421
|
+
### Buttons & Native Flow
|
|
422
|
+
|
|
223
423
|
```js
|
|
224
424
|
import { Button } from '@vanzxy/baileys'
|
|
225
425
|
|
|
@@ -229,44 +429,153 @@ await new Button(sock)
|
|
|
229
429
|
.setFooter('@vanzxy/baileys')
|
|
230
430
|
.addReply('Klaim Sekarang', 'claim_promo')
|
|
231
431
|
.addUrl('Lihat Katalog', 'https://example.com/catalog')
|
|
432
|
+
.addCall('Hubungi Kami', '628123456789')
|
|
232
433
|
.send(jid)
|
|
233
434
|
```
|
|
234
435
|
|
|
235
|
-
###
|
|
436
|
+
### Poll
|
|
437
|
+
|
|
438
|
+
```js
|
|
439
|
+
import { Poll } from '@vanzxy/baileys'
|
|
440
|
+
|
|
441
|
+
await new Poll(sock)
|
|
442
|
+
.setName('Mau makan apa hari ini?')
|
|
443
|
+
.addOptions(['Nasi Goreng', 'Mie Ayam', 'Bakso'])
|
|
444
|
+
.setSelectable(1)
|
|
445
|
+
.send(jid)
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Carousel
|
|
449
|
+
|
|
450
|
+
> Each card must be built with `Button(...).toCard()` first — a carousel card is really just a button card with an image/video header.
|
|
451
|
+
|
|
452
|
+
```js
|
|
453
|
+
import { Button, Carousel } from '@vanzxy/baileys'
|
|
454
|
+
|
|
455
|
+
const cardA = await new Button(sock)
|
|
456
|
+
.setImage('https://example.com/a.jpg')
|
|
457
|
+
.setTitle('Produk A')
|
|
458
|
+
.addUrl('Lihat', 'https://example.com/a')
|
|
459
|
+
.toCard()
|
|
460
|
+
|
|
461
|
+
const cardB = await new Button(sock)
|
|
462
|
+
.setImage('https://example.com/b.jpg')
|
|
463
|
+
.setTitle('Produk B')
|
|
464
|
+
.addUrl('Lihat', 'https://example.com/b')
|
|
465
|
+
.toCard()
|
|
466
|
+
|
|
467
|
+
await new Carousel(sock)
|
|
468
|
+
.setBody('Pilih salah satu produk di bawah ini')
|
|
469
|
+
.addCard([cardA, cardB])
|
|
470
|
+
.send(jid)
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### AIRich — rich response cards
|
|
474
|
+
|
|
236
475
|
```js
|
|
237
476
|
import { AIRich } from '@vanzxy/baileys'
|
|
238
477
|
|
|
239
478
|
await new AIRich(sock)
|
|
240
479
|
.addHeading('Ringkasan Order')
|
|
241
480
|
.addText('Pesananmu sedang diproses.')
|
|
242
|
-
.addTable([
|
|
481
|
+
.addTable([
|
|
482
|
+
['Item', 'Qty'],
|
|
483
|
+
['Kopi Susu', '2']
|
|
484
|
+
])
|
|
485
|
+
.addTip('Pesanan biasanya siap dalam 15 menit')
|
|
243
486
|
.addSuggest('Lacak Order')
|
|
244
487
|
.send(jid)
|
|
245
488
|
```
|
|
246
489
|
|
|
247
|
-
|
|
490
|
+
`AIRich` supports `{ id, insertAt }` on every `add*()`/`set*()` call, so you can insert a block relative to one you added earlier instead of always appending to the end — handy for streaming/edit-in-place style responses combined with `sendEdit(jid, id)`.
|
|
491
|
+
|
|
492
|
+
Other builders worth knowing about: **`ButtonV2`** (simpler quick-reply-only buttons), **`ButtonV3`** (`loadFrom(msg)` to edit an existing template message in place), and **`Toolkit`** (static helpers: `Toolkit.resize()`, `Toolkit.fetchBuffer()`, `Toolkit.waitAllPromises()`, `Toolkit.extractIE()` for parsing `[label](url)` links/citations/LaTeX out of plain text).
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
## 📞 Voice & Video Calls
|
|
497
|
+
|
|
498
|
+
Experimental audio-call support (ported from ourin-baileys) via a WASM call stack + WebRTC relay. Requires the optional `@roamhq/wrtc` peer dependency.
|
|
499
|
+
|
|
248
500
|
```js
|
|
249
|
-
import {
|
|
501
|
+
import { VoipClient } from '@vanzxy/baileys'
|
|
250
502
|
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
.addCard({ title: 'Produk B', image: 'https://example.com/b.jpg' })
|
|
503
|
+
const voip = new VoipClient({ resourcesPath: './voip-resources' })
|
|
504
|
+
await voip.connectWithSocket(sock)
|
|
254
505
|
|
|
255
|
-
await
|
|
506
|
+
const call = await voip.call('628123456789')
|
|
507
|
+
|
|
508
|
+
call.on('ringing', () => console.log('Ringing...'))
|
|
509
|
+
call.on('connected', () => console.log('Call connected'))
|
|
510
|
+
call.on('ended', (reason) => console.log('Call ended:', reason))
|
|
256
511
|
```
|
|
257
512
|
|
|
513
|
+
`ActiveCall` (returned by `.call()`) and `CallState` are also exported directly if you need finer-grained control over call state.
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
## 🔎 User Sync Queries
|
|
518
|
+
|
|
519
|
+
`WAUSync` (`USyncQuery` / `USyncUser` + protocols) lets you check things like WhatsApp registration, device lists, status, and username info for a JID before you message it — the same mechanism behind `sock.onWhatsApp()`.
|
|
520
|
+
|
|
521
|
+
```js
|
|
522
|
+
import { USyncQuery, USyncUser, USyncContactProtocol } from '@vanzxy/baileys'
|
|
523
|
+
|
|
524
|
+
const query = new USyncQuery()
|
|
525
|
+
.withContext('interactive')
|
|
526
|
+
.withMode('query')
|
|
527
|
+
.withUser(new USyncUser().withPhone('628123456789'))
|
|
528
|
+
|
|
529
|
+
query.protocols.push(new USyncContactProtocol())
|
|
530
|
+
|
|
531
|
+
const result = await sock.executeUSyncQuery(query)
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
Available protocols: `USyncContactProtocol`, `USyncDeviceProtocol`, `USyncStatusProtocol`, `USyncUsernameProtocol`, `USyncDisappearingModeProtocol`, `UsyncBotProfileProtocol`, `UsyncLIDProtocol`.
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
## 🧩 Utility Modules
|
|
539
|
+
|
|
540
|
+
A sample of the utilities exported from `lib/Utils` beyond the message builders above:
|
|
541
|
+
|
|
542
|
+
| Module | What it does |
|
|
543
|
+
|---|---|
|
|
544
|
+
| `anti-delete` | Detect and recover messages the sender deleted for everyone |
|
|
545
|
+
| `auto-reply` | Simple keyword/pattern-based auto-responder engine |
|
|
546
|
+
| `message-search` | Search cached/stored messages, peeling off ephemeral/view-once wrappers first |
|
|
547
|
+
| `message-retry-manager` | Handles WhatsApp's retry-receipt protocol for undecryptable messages |
|
|
548
|
+
| `scheduling` | Schedule messages/actions for later delivery |
|
|
549
|
+
| `business` | Business-profile & catalog helpers |
|
|
550
|
+
| `chat-control` | Pin, mute, archive, and mark-read/unread helpers |
|
|
551
|
+
| `chat-history-helpers` | Work with synced chat history payloads |
|
|
552
|
+
| `link-preview` | Generate link preview metadata for outgoing messages |
|
|
553
|
+
| `stickerpack` | Build and send sticker packs (including animated/Lottie) |
|
|
554
|
+
| `templates` | Legacy WhatsApp Business template message helpers |
|
|
555
|
+
| `vcard` | Build vCard (contact card) payloads |
|
|
556
|
+
| `status` | Post and manage WhatsApp Status updates |
|
|
557
|
+
| `event-buffer` | Buffers/coalesces high-volume socket events for heavier bots |
|
|
558
|
+
|
|
559
|
+
Every module above ships a matching `.d.ts`, so your editor will show full hover-docs regardless of which ones you import.
|
|
560
|
+
|
|
258
561
|
---
|
|
259
562
|
|
|
260
563
|
## 🛠 Recommended Environment
|
|
261
564
|
|
|
262
565
|
| Requirement | Version |
|
|
263
566
|
|---|---|
|
|
264
|
-
| Node.js |
|
|
567
|
+
| Node.js | 20+ |
|
|
265
568
|
| Module system | ESM |
|
|
266
569
|
| WhatsApp | Latest Multi Device |
|
|
267
570
|
|
|
268
571
|
---
|
|
269
572
|
|
|
573
|
+
## 📘 TypeScript Support
|
|
574
|
+
|
|
575
|
+
Every file in `lib/` ships a matching `.d.ts`, including the message builders (`MessageBuilder_d.ts`) and all `Types/*` definitions (Auth, Chat, Contact, Events, GroupMetadata, Message, Product, Signal, USync, and more). No `@types/` package needed — plain `import { ... } from '@vanzxy/baileys'` gets full autocomplete in TS or JS-with-checkJS projects.
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
270
579
|
## 📚 Fork Lineage
|
|
271
580
|
|
|
272
581
|
```
|
|
@@ -279,38 +588,74 @@ Respect to all original maintainers and contributors.
|
|
|
279
588
|
|
|
280
589
|
---
|
|
281
590
|
|
|
282
|
-
##
|
|
591
|
+
## ❓ FAQ & Troubleshooting
|
|
283
592
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
- **WhiskeySockets/Baileys** & **@itsliaaa/baileys** — upstream base
|
|
593
|
+
<details>
|
|
594
|
+
<summary><b>Koneksi terus putus / reconnect loop</b></summary>
|
|
595
|
+
<br/>
|
|
288
596
|
|
|
289
|
-
|
|
597
|
+
Cek `connection.update` untuk field `lastDisconnect.error`. Kalau status code-nya `401` (loggedOut), sesi memang sudah invalid dan perlu scan ulang QR — jangan auto-reconnect di kondisi ini. Untuk status lain (`428`, `440`, dsb.), reconnect dengan backoff biasanya cukup.
|
|
290
598
|
|
|
291
|
-
|
|
599
|
+
</details>
|
|
292
600
|
|
|
293
|
-
|
|
601
|
+
<details>
|
|
602
|
+
<summary><b>QR tidak muncul / tidak ke-scan</b></summary>
|
|
603
|
+
<br/>
|
|
294
604
|
|
|
295
|
-
|
|
605
|
+
`printQRInTerminal` sudah deprecated di upstream Baileys — pastikan kamu render QR sendiri dari event `qr` (lihat contoh di [Quick Start](#-quick-start)). Kalau QR muncul tapi gagal linking, biasanya karena versi WA Web (`version` di `makeWASocket`) sudah kedaluwarsa; fetch versi terbaru lewat `fetchLatestBaileysVersion()`.
|
|
296
606
|
|
|
297
|
-
|
|
607
|
+
</details>
|
|
298
608
|
|
|
299
|
-
|
|
609
|
+
<details>
|
|
610
|
+
<summary><b>Error "Bad MAC" / pesan gagal didekripsi</b></summary>
|
|
611
|
+
<br/>
|
|
612
|
+
|
|
613
|
+
Umumnya terjadi kalau folder auth state korup atau sesi dipakai di lebih dari satu proses secara bersamaan. Pastikan hanya satu instance yang menulis ke folder auth state yang sama, dan pertimbangkan `pruneStaleAuthFiles()` untuk membersihkan sender-key lama secara berkala.
|
|
300
614
|
|
|
301
|
-
>
|
|
615
|
+
</details>
|
|
302
616
|
|
|
303
617
|
<details>
|
|
304
|
-
<summary
|
|
618
|
+
<summary><b>Memory terus naik di bot yang jalan lama</b></summary>
|
|
619
|
+
<br/>
|
|
620
|
+
|
|
621
|
+
Kalau pakai `makeInMemoryStore()`, cache chat/message/contact akan terus tumbuh tanpa batas. Untuk bot yang jalan lama, pertimbangkan pindah ke salah satu backend `makePersistentStore()` (SQLite/Redis/dst) dan pakai `event-buffer` untuk meredam lonjakan event di trafik tinggi.
|
|
622
|
+
|
|
623
|
+
</details>
|
|
305
624
|
|
|
625
|
+
<details>
|
|
626
|
+
<summary><b>Voice call gagal connect</b></summary>
|
|
306
627
|
<br/>
|
|
307
628
|
|
|
308
|
-
|
|
629
|
+
Fitur ini masih experimental dan butuh peer dependency `@roamhq/wrtc` — pastikan sudah terinstall dan platform kamu didukung native binding-nya. Cek event `call.on('ended', reason => ...)` untuk detail penyebab gagalnya.
|
|
309
630
|
|
|
310
631
|
</details>
|
|
311
632
|
|
|
312
633
|
---
|
|
313
634
|
|
|
635
|
+
## 🤝 Contributing
|
|
636
|
+
|
|
637
|
+
Kontribusi dipersilakan, terutama untuk perbaikan bug, dokumentasi, dan enhancement pada `MessageBuilder` / `AIRich`.
|
|
638
|
+
|
|
639
|
+
1. Fork repo ini, buat branch dari `main` (`feat/nama-fitur` atau `fix/nama-bug`)
|
|
640
|
+
2. Pastikan perubahan tetap ESM-only dan menyertakan/menyesuaikan `.d.ts` terkait
|
|
641
|
+
3. Uji perubahan pada minimal satu jalur auth state + satu store backend sebelum PR
|
|
642
|
+
4. Buka Pull Request dengan deskripsi singkat: apa yang berubah dan kenapa
|
|
643
|
+
|
|
644
|
+
Untuk laporan bug, sertakan versi Node.js, cara reproduksi, dan potongan log `lastDisconnect.error` bila relevan.
|
|
645
|
+
|
|
646
|
+
---
|
|
647
|
+
|
|
648
|
+
## 🙏 Credits
|
|
649
|
+
|
|
650
|
+
- **Nixel** (with contributions from **Ahmad tumbuh kembang**) — base implementation of the `MessageBuilder` (AIRich / Button / Carousel / Toolkit), originally "NIXCODE — Advanced WhatsApp Interactive Message Builder"
|
|
651
|
+
- **vinikjkkj** ([zapo](https://github.com/vinikjkkj/zapo)) — button/list addon-kind resolution logic
|
|
652
|
+
- **QueenAnya** (`@queenanya/baileys`) — interactive/native-flow button send layer
|
|
653
|
+
- **WhiskeySockets/Baileys** & **@itsliaaa/baileys** — upstream base
|
|
654
|
+
|
|
655
|
+
Full details and license terms per component: see [`NOTICE.md`](./NOTICE.md).
|
|
656
|
+
|
|
657
|
+
---
|
|
658
|
+
|
|
314
659
|
## 👑 Maintainer
|
|
315
660
|
|
|
316
661
|
**Vanzxy**
|
|
@@ -334,12 +679,14 @@ Use responsibly and follow WhatsApp Terms of Service.
|
|
|
334
679
|
- Existing guarded fallbacks for platforms where the native bridge cannot load remain in place.
|
|
335
680
|
- ESM-only package metadata is preserved; no CommonJS build is included.
|
|
336
681
|
|
|
337
|
-
Reference audit: the supplied Ourin, Elaina, ItsLiaaa, and Noxleyss packages were compared before this patch. Their broader core changes were not copied wholesale because the current Vanzxy tree already contains additional LID, retry, media, interactive,
|
|
682
|
+
Reference audit: the supplied Ourin, Elaina, ItsLiaaa, and Noxleyss packages were compared before this patch. Their broader core changes were not copied wholesale because the current Vanzxy tree already contains additional LID, retry, media, interactive, angd AIRich fixes that would risk regressions if replaced.
|
|
338
683
|
|
|
339
684
|
---
|
|
340
685
|
|
|
341
686
|
<div align="center">
|
|
342
687
|
|
|
688
|
+
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:2ecc71,100:1d6a23&height=100§ion=footer" width="100%"/>
|
|
689
|
+
|
|
343
690
|
Made with 🍃 by **Vanzxy**
|
|
344
691
|
|
|
345
692
|
Thanks for stopping by! ✌️
|
package/WAProto/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import $protobuf from "protobufjs/minimal.js";
|
|
|
3
3
|
|
|
4
4
|
const $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
|
5
5
|
|
|
6
|
-
const $root = $protobuf.roots["
|
|
6
|
+
const $root = $protobuf.roots["vanzxy_baileys_wa_proto"] || ($protobuf.roots["vanzxy_baileys_wa_proto"] = {});
|
|
7
7
|
|
|
8
8
|
function longToString(value, unsigned) {
|
|
9
9
|
if (typeof value === "string") {
|
|
@@ -2977,6 +2977,14 @@ class AIRich extends BaseBuilder {
|
|
|
2977
2977
|
addWidget(data = {}, { layout } = {}) {
|
|
2978
2978
|
const items = Array.isArray(data) ? data : [data];
|
|
2979
2979
|
|
|
2980
|
+
// Vanz@Fix (bug 44) --- layout: 'Single' forces `widgets[0]` below (a "Single" layout's
|
|
2981
|
+
// view_model can only ever hold one `primitive`, never a `primitives` array — see
|
|
2982
|
+
// newLayout()). Previously an explicit { layout: 'Single' } combined with a multi-item
|
|
2983
|
+
// array silently dropped every item past the first with no error. Fail loud instead.
|
|
2984
|
+
if (layout === 'Single' && items.length > 1) {
|
|
2985
|
+
throw new TypeError(`addWidget(): layout "Single" can only hold one widget (got ${items.length}) — use "HScroll"/"ActionRow" (or omit layout) for multiple`);
|
|
2986
|
+
}
|
|
2987
|
+
|
|
2980
2988
|
items.forEach((item, i) => {
|
|
2981
2989
|
// header.title or top-level title required
|
|
2982
2990
|
const hasTitle = item?.title || item?.header?.title;
|
|
@@ -2994,6 +3002,13 @@ class AIRich extends BaseBuilder {
|
|
|
2994
3002
|
messageText: items.map((item) => item.header?.title ?? item.title).join(', '),
|
|
2995
3003
|
});
|
|
2996
3004
|
|
|
3005
|
+
// Vanz@Fix (bug 45) --- auto tool_call_id used to be `idx` scoped per-item (ctas.map's own
|
|
3006
|
+
// index), resetting to 0 for every widget item. Two items (or two separate addWidget()
|
|
3007
|
+
// calls) that both omit tool_call_id/id ended up minting the identical auto id ("00"),
|
|
3008
|
+
// so a CTA tap could route to the wrong widget's tool call. Track the counter on the
|
|
3009
|
+
// instance instead so every auto-generated id is unique for this AIRich's lifetime.
|
|
3010
|
+
this._widgetCtaCounter ??= 0;
|
|
3011
|
+
|
|
2997
3012
|
const widgets = items.map((item) => {
|
|
2998
3013
|
const ctas = item.ctas ?? item.actions;
|
|
2999
3014
|
// header accepts either a string title (legacy) or an object { title, subtitle }
|
|
@@ -3007,11 +3022,11 @@ class AIRich extends BaseBuilder {
|
|
|
3007
3022
|
},
|
|
3008
3023
|
body: {
|
|
3009
3024
|
sections: item.sections ?? [],
|
|
3010
|
-
ctas: ctas.map((cta
|
|
3025
|
+
ctas: ctas.map((cta) => ({
|
|
3011
3026
|
label: cta.label ?? '',
|
|
3012
3027
|
state: cta.state ?? 'PENDING',
|
|
3013
3028
|
kind: cta.kind ?? 'OTHER',
|
|
3014
|
-
tool_call_id: cta.tool_call_id ?? cta.id ?? String(
|
|
3029
|
+
tool_call_id: cta.tool_call_id ?? cta.id ?? String(this._widgetCtaCounter++).padStart(2, '0'),
|
|
3015
3030
|
...(cta.toast !== false && {
|
|
3016
3031
|
toast: { label: typeof cta.toast === 'string' ? cta.toast : headerTitle, __typename: 'GenAI3PExtWidgetToast' },
|
|
3017
3032
|
}),
|
package/lib/Utils/anti-delete.js
CHANGED
|
@@ -80,12 +80,20 @@ export class MessageStore {
|
|
|
80
80
|
stored.isDeleted = true;
|
|
81
81
|
stored.deletedAt = now;
|
|
82
82
|
stored.deletedBy = deletedBy;
|
|
83
|
+
// Vanz@Fix (bug 66): the old check (`deletedBy === stored.message.key.participant`)
|
|
84
|
+
// only works in groups, where `participant` identifies who sent/revoked a message.
|
|
85
|
+
// In a private chat `key.participant` is always undefined (it's a group-only field),
|
|
86
|
+
// while `deletedBy` there falls back to `remoteJid` — so the comparison could never
|
|
87
|
+
// match and isRevokedBySender was always false for every DM, even though
|
|
88
|
+
// delete-for-everyone in a DM can only be done by the original sender. Treat a
|
|
89
|
+
// missing `participant` (i.e. not a group message) as "revoked by sender" by definition.
|
|
90
|
+
const isGroupMessage = !!stored.message.key.participant;
|
|
83
91
|
const info = {
|
|
84
92
|
originalMessage: stored.message,
|
|
85
93
|
key,
|
|
86
94
|
deletedAt: now,
|
|
87
95
|
deletedBy,
|
|
88
|
-
isRevokedBySender: !deletedBy || deletedBy === stored.message.key.participant
|
|
96
|
+
isRevokedBySender: !deletedBy || !isGroupMessage || deletedBy === stored.message.key.participant
|
|
89
97
|
};
|
|
90
98
|
this.deletedMessages.set(this.getKey(key), info);
|
|
91
99
|
return info;
|
package/lib/Utils/generics.js
CHANGED
|
@@ -71,7 +71,25 @@ export const encodeBigEndian = (e, t = 4) => {
|
|
|
71
71
|
};
|
|
72
72
|
export const toNumber = (t) => typeof t === 'object' && t ? ('toNumber' in t ? t.toNumber() : t.low) : t || 0;
|
|
73
73
|
/** unix timestamp of a date in seconds */
|
|
74
|
-
|
|
74
|
+
// Vanz@Fix (bug 69): unixTimestampSeconds(date) assumed `date` is always a real Date
|
|
75
|
+
// instance and called date.getTime() unconditionally. Any caller that passed a raw
|
|
76
|
+
// number (Date.now(), or an already-converted unix timestamp) or an ISO string instead
|
|
77
|
+
// of a Date crashed here with "date.getTime is not a function" — this is a coercion
|
|
78
|
+
// bug in THIS function, not a proto/BloksWidget/InteractiveMessage issue (traced and
|
|
79
|
+
// confirmed: normalizeMessageContent/getContentType never touch nested message content,
|
|
80
|
+
// and this function is called before any encode/serialize step even starts). Coerce the
|
|
81
|
+
// common input shapes instead of assuming Date, but keep throwing on genuinely invalid
|
|
82
|
+
// input (NaN) so silent bad-timestamp bugs don't get hidden.
|
|
83
|
+
export const unixTimestampSeconds = (date) => {
|
|
84
|
+
if (date == null) date = new Date(); // null AND undefined both mean "now" (default params only catch undefined)
|
|
85
|
+
const d = date instanceof Date
|
|
86
|
+
? date
|
|
87
|
+
: new Date(typeof date === 'number' && date < 1e12 ? date * 1000 : date); // treat sub-1e12 numbers as already-seconds
|
|
88
|
+
if (Number.isNaN(d.getTime())) {
|
|
89
|
+
throw new TypeError(`unixTimestampSeconds: invalid timestamp input (${typeof date}): ${date}`);
|
|
90
|
+
}
|
|
91
|
+
return d.getTime() / 1000 | 0;
|
|
92
|
+
};
|
|
75
93
|
export const debouncedTimeout = (intervalMs = 1000, task) => {
|
|
76
94
|
let timeout;
|
|
77
95
|
return {
|
package/lib/Utils/media-set.js
CHANGED
|
@@ -145,7 +145,11 @@ export const groupLabel = async (jid, text, sock) => {
|
|
|
145
145
|
type: 30,
|
|
146
146
|
memberLabel: {
|
|
147
147
|
label: text.slice(0, 30),
|
|
148
|
-
|
|
148
|
+
// Vanz@Fix (bug 67): this used Date.now() (milliseconds) while the
|
|
149
|
+
// sibling groupSetMemberLabel() correctly uses unixTimestampSeconds()
|
|
150
|
+
// for the same proto field — WA's *Timestamp fields are unix-seconds,
|
|
151
|
+
// so this was sending a timestamp ~1000x too large.
|
|
152
|
+
labelTimestamp: unixTimestampSeconds() || Date.now()
|
|
149
153
|
}
|
|
150
154
|
}
|
|
151
155
|
}, {
|
|
@@ -160,7 +160,9 @@ const FLOWS_MAP = {
|
|
|
160
160
|
// routed anything real; kept as a harmless alias in case any external caller
|
|
161
161
|
// is still constructing a raw button object with the old (wrong) name.
|
|
162
162
|
flow: true,
|
|
163
|
-
flow_action: true
|
|
163
|
+
// Vanz@Fix (bug 68): removed duplicate `flow_action: true` key — already declared
|
|
164
|
+
// above (Vanzxy extended button types block); this was a leftover copy-paste dupe,
|
|
165
|
+
// harmless (same value) but confusing on re-read.
|
|
164
166
|
// Vanz@Fix (single_select never renders alone) --- single_select must NEVER get
|
|
165
167
|
// its own dedicated native_flow node here. WhatsApp only renders a single_select
|
|
166
168
|
// button through the generic <native_flow v='9' name='mixed'> node — the same one
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vanzxy/baileys",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.8",
|
|
4
4
|
"description": "Enhanced Baileys fork by Vanzxy \u2014 based on @itsliaaa/baileys + @whiskeysockets/baileys with fixes for audio group status and clean media without newsletter button.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -34,16 +34,39 @@
|
|
|
34
34
|
"NOTICE.md"
|
|
35
35
|
],
|
|
36
36
|
"keywords": [
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
"vanzxy",
|
|
38
|
+
"vanzxybaileys",
|
|
39
|
+
"vanzxy-baileys",
|
|
40
|
+
"vanzxy-whatsapp",
|
|
41
|
+
"vanzxy-baileys-md",
|
|
42
|
+
"baileys-fork-vanzxy",
|
|
43
|
+
"baileys",
|
|
44
|
+
"baileys-md",
|
|
45
|
+
"baileys-multi-device",
|
|
46
|
+
"baileys-multidevice",
|
|
47
|
+
"baileys-whatsapp",
|
|
48
|
+
"baileys-whatsapp-api",
|
|
49
|
+
"baileys-whatsapp-bot",
|
|
50
|
+
"baileys-bot",
|
|
51
|
+
"baileys-api",
|
|
52
|
+
"baileys-library",
|
|
53
|
+
"baileys-node",
|
|
54
|
+
"baileys-nodejs",
|
|
55
|
+
"baileys-javascript",
|
|
56
|
+
"baileys-js",
|
|
57
|
+
"baileys-esm",
|
|
58
|
+
"baileys-fork",
|
|
59
|
+
"whatsapp-baileys",
|
|
60
|
+
"whatsapp-bot-baileys",
|
|
61
|
+
"whatsapp-api-baileys",
|
|
62
|
+
"whatsapp-web-baileys",
|
|
63
|
+
"whatsapp-multi-device",
|
|
64
|
+
"whatsapp-automation",
|
|
65
|
+
"whatsapp-bot",
|
|
66
|
+
"whatsapp-api",
|
|
67
|
+
"whatsapp-web",
|
|
68
|
+
"multi-device",
|
|
69
|
+
"interactive-messages"
|
|
47
70
|
],
|
|
48
71
|
"homepage": "https://github.com/vanzxysenpai/vanzxybaileys#readme",
|
|
49
72
|
"author": "Vanzxy",
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# WAProto upgrade — progress checkpoint
|
|
2
|
-
|
|
3
|
-
Base: @vanzxy/baileys 1.6.6 WAProto (already the most complete of the 4 sources compared:
|
|
4
|
-
716 types vs wa-proto-main 603 / Baileys-5 570 / raphaelvserafim 569).
|
|
5
|
-
Diffed field-by-field against wa-proto-main (WA 2.3000.1046350168, newest available) to find real gaps.
|
|
6
|
-
|
|
7
|
-
## ✅ Applied in this checkpoint (session 1)
|
|
8
|
-
- `AIRichResponseMessage.originalRecipientMetadata` (field 5, type `AIRichResponseUnifiedResponse`)
|
|
9
|
-
— direct "airich" gap, full encode/decode/verify/fromObject/toObject wired.
|
|
10
|
-
- `BotMetadata.responseStoppedByUser` (field 44, bool) — full round-trip wired.
|
|
11
|
-
|
|
12
|
-
## ✅ Applied in this checkpoint (session 2 — pending queue cleared)
|
|
13
|
-
- `Message.VideoMessage.dashManifestUrl` (field 33, string) — full encode/decode/fromObject/toObject
|
|
14
|
-
wired alongside the existing `videoSourceType` enum field (30/31).
|
|
15
|
-
- `ContextInfo.experienceIds` (field 82, repeated packed uint32) — wired using the same packed-varint
|
|
16
|
-
pattern as `ADVKeyIndexList.validIndexes` (fork/ldelim on encode, packed-or-single fallback on decode).
|
|
17
|
-
- `DeviceCapabilities.BusinessBroadcast.proCompanionSupportEnabled` (field 6, bool) — full round-trip
|
|
18
|
-
wired next to the existing `recipientLimit` field.
|
|
19
|
-
- `Message.newsletterScheduledMessage` (field 132, reuses existing `FutureProofMessage` type) — wired
|
|
20
|
-
next to `botPlatformRegistrationSuccessMessage` (field 131).
|
|
21
|
-
- 3 new nested types under `SyncActionValue`, each a single-bool message built from scratch off the
|
|
22
|
-
`StarAction`/`CtwaMessageReceivedAction` template, then wired into the parent message at fields 94–96:
|
|
23
|
-
- `SharedDeviceAllowlistAction` (bool `allowed`) — field 94
|
|
24
|
-
- `ContactManagerMetadataAction` (bool `isHidden`) — field 95
|
|
25
|
-
- `BusinessFolderActivationAction` (bool `activated`) — field 96
|
|
26
|
-
|
|
27
|
-
**Pending queue is now empty** — every gap identified in the wa-proto-main diff has been applied.
|
|
28
|
-
|
|
29
|
-
## Already confirmed complete, no changes needed
|
|
30
|
-
Buttons (ButtonsMessage, TemplateButton, HydratedTemplateButton, ButtonsResponseMessage),
|
|
31
|
-
InteractiveMessage + NativeFlowMessage (incl. bloksWidget/A2UI), TemplateMessage,
|
|
32
|
-
ExtendedContentMessage (CTA buttons, XMA), ListMessage, all AIRichResponse* submessage types,
|
|
33
|
-
MessageContextInfo — all field-complete vs every reference source checked.
|
|
34
|
-
|
|
35
|
-
## Validation
|
|
36
|
-
- `node --check WAProto/index.js` — syntax clean after all edits.
|
|
37
|
-
- Functional round-trip (encode → decode → toObject) verified for all 5 session-2 fields, plus
|
|
38
|
-
regression checks confirming neighboring pre-existing fields (`videoSourceType`, `aiProvenance`,
|
|
39
|
-
`posterStatusId`, `botPlatformRegistrationSuccessMessage`, `ctwaMessageReceivedAction`, and
|
|
40
|
-
`BusinessBroadcast`'s other bool fields) still encode/decode correctly after the inserts.
|
|
41
|
-
Run against a hand-written wire-format shim (varint/string/bool/length-delimited), not the real
|
|
42
|
-
`protobufjs` package, since this sandbox has no network/registry access to install it — the shim
|
|
43
|
-
implements the exact subset of the protobufjs runtime API (`Writer`/`Reader`/`util`) that the
|
|
44
|
-
generated code calls, so it validates wire-format correctness but not protobufjs's own internals.
|
|
45
|
-
**Recommend re-running a quick smoke test against the real `protobufjs` package once installed in
|
|
46
|
-
your environment before shipping to production**, though the generated code path itself is
|
|
47
|
-
mechanically identical to every other field in this file.
|
|
48
|
-
|
|
49
|
-
index.js syntax-validated with `node --check` after this checkpoint's edits.
|
|
50
|
-
|
|
51
|
-
## Session 3 — full Button/AIRich/A2UI field audit (no gaps found)
|
|
52
|
-
Ran an exhaustive field-by-field diff of every Button-, AIRich-, and Interactive/NativeFlow (A2UI)
|
|
53
|
-
-related message against `wa-proto-main` (the newest reference in this bundle) and cross-checked
|
|
54
|
-
against `Baileys-5`:
|
|
55
|
-
|
|
56
|
-
- **Buttons**: `ButtonsMessage` (+ nested `Button`/`ButtonText`/`NativeFlowInfo`), `ButtonsResponseMessage`,
|
|
57
|
-
`TemplateButton`/`HydratedTemplateButton` (+ `QuickReplyButton`/`URLButton`/`CallButton` variants) —
|
|
58
|
-
field-complete, 1:1 match.
|
|
59
|
-
- **AIRich**: all 12 top-level `AIRichResponse*` messages (`Message`, `SubMessage`, `CodeMetadata`,
|
|
60
|
-
`ContentItemsMetadata`, `DynamicMetadata`, `GridImageMetadata`, `ImageURL`, `InlineImageMetadata`,
|
|
61
|
-
`LatexMetadata`, `MapMetadata`, `TableMetadata`, `UnifiedResponse`) — field-complete, including the
|
|
62
|
-
`originalRecipientMetadata` field added in session 1.
|
|
63
|
-
- **A2UI / Interactive**: `InteractiveMessage` (+ `BloksWidget`, `Header` incl. its own nested
|
|
64
|
-
`bloksWidget` field 10, `Footer`, `Body`, `CarouselMessage`, `CollectionMessage`, `NativeFlowMessage`
|
|
65
|
-
+ `NativeFlowButton`, `ShopMessage`), `InteractiveResponseMessage` (+ `Body`, `NativeFlowResponseMessage`),
|
|
66
|
-
`InteractiveAnnotation` — field-complete.
|
|
67
|
-
- `Baileys-5` (older/less complete source per this file's header) contributes nothing extra relevant —
|
|
68
|
-
its only two extra top-level messages (`LIDMigrationMapping`/`LIDMigrationMappingSyncPayload`) are the
|
|
69
|
-
deprecated pre-migration types already superseded and handled in session 26-08-26.
|
|
70
|
-
|
|
71
|
-
**Conclusion: the WAProto layer for Button/AIRich/A2UI is fully caught up — no further proto-level
|
|
72
|
-
patches identified.** Next stage for these features is JS-level (`lib/Utils/MessageBuilder.js`,
|
|
73
|
-
`lib/Utils/A2UI.js`) — wiring the newly-added fields (`dashManifestUrl`, `experienceIds`,
|
|
74
|
-
`newsletterScheduledMessage`, etc.) into builder APIs where relevant, not further WAProto edits.
|
|
75
|
-
|
|
76
|
-
## Session 4 — JS-level integration check
|
|
77
|
-
Checked whether `MessageBuilder.js`/`A2UI.js` need whitelist updates to expose the new proto fields:
|
|
78
|
-
|
|
79
|
-
- `dashManifestUrl` (VideoMessage) and `experienceIds` (ContextInfo): no gap. `setContextInfo(obj)`
|
|
80
|
-
merges the object verbatim (no field whitelist), and video-message construction elsewhere
|
|
81
|
-
(`sendPairedMedia`) spreads a plain object straight into `relayMessage` — any proto-valid field,
|
|
82
|
-
including these two, is already usable with zero code changes.
|
|
83
|
-
- `DeviceCapabilities.proCompanionSupportEnabled`: no gap, but not because it's already wired —
|
|
84
|
-
`DeviceCapabilities` isn't referenced anywhere in `lib/` (not part of this fork's companion
|
|
85
|
-
registration flow), so there's nothing to update.
|
|
86
|
-
- **Real gap found**: `lib/Utils/messages.js`'s `getFutureProofMessage()` — the whitelist function
|
|
87
|
-
`normalizeMessageContent()` uses to unwrap `FutureProofMessage`-typed fields — was missing
|
|
88
|
-
`botPlatformRegistrationSuccessMessage` (field 131, pre-existing) and `newsletterScheduledMessage`
|
|
89
|
-
(field 132, added this session). Both would have silently failed to unwrap: a message using either
|
|
90
|
-
wrapper would pass through `normalizeMessageContent()` unchanged instead of resolving to its inner
|
|
91
|
-
`message`. **Fixed** — both added to the whitelist. Syntax-checked (`node --check`) and functionally
|
|
92
|
-
verified both fields now correctly unwrap.
|
|
93
|
-
|
|
94
|
-
Bumped package version 1.6.6 → 1.6.7.
|
|
95
|
-
|
|
96
|
-
## Session 5 — resolved the standing "verify against live traffic" TODO
|
|
97
|
-
`lib/Utils/process-message.js`'s `decodeLidMigrationMappingSyncPayload()` (the hand-written decoder
|
|
98
|
-
from session 26-08-26, flagged since then as needing live-traffic verification) has now been
|
|
99
|
-
cross-checked against an independent source: `Baileys-5`'s bundled `WAProto.proto`, an older compiled
|
|
100
|
-
schema dump from before Meta stopped publishing this type's inner structure. It's an exact
|
|
101
|
-
field-for-field match:
|
|
102
|
-
- `LIDMigrationMappingSyncPayload { repeated pnToLidMappings = 1; optional chatDbMigrationTimestamp = 2 (uint64); }`
|
|
103
|
-
- `LIDMigrationMapping { pn = 1; assignedLid = 2; latestLid = 3; all uint64 }`
|
|
104
|
-
|
|
105
|
-
This isn't literal live WhatsApp traffic, but it is a real independent extraction agreeing byte-for-byte
|
|
106
|
-
with the from-scratch guess — meaningfully stronger evidence than "seems plausible," since an
|
|
107
|
-
independent tool derived the same field layout separately. Also ran a functional round-trip test
|
|
108
|
-
(hand-encoded a payload matching this exact structure, fed it through the actual decoder function) —
|
|
109
|
-
PASS. Updated the code comment to reflect this and removed the "TODO: verify" marker; the residual risk
|
|
110
|
-
(Meta silently changing the inner layout with zero signal) is unchanged and can only be closed by
|
|
111
|
-
actual live traffic, but the decoder is no longer running on-guess. Bumped package version 1.6.7 → 1.6.8.
|