@kangwifi-pro/waliwa 1.0.0

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 (144) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +600 -0
  3. package/dist/advanced/features.d.ts +211 -0
  4. package/dist/advanced/features.d.ts.map +1 -0
  5. package/dist/advanced/features.js +671 -0
  6. package/dist/advanced/features.js.map +1 -0
  7. package/dist/auth/auth-state.d.ts +89 -0
  8. package/dist/auth/auth-state.d.ts.map +1 -0
  9. package/dist/auth/auth-state.js +330 -0
  10. package/dist/auth/auth-state.js.map +1 -0
  11. package/dist/auth/pairing-code.d.ts +78 -0
  12. package/dist/auth/pairing-code.d.ts.map +1 -0
  13. package/dist/auth/pairing-code.js +191 -0
  14. package/dist/auth/pairing-code.js.map +1 -0
  15. package/dist/auth/qr-code.d.ts +60 -0
  16. package/dist/auth/qr-code.d.ts.map +1 -0
  17. package/dist/auth/qr-code.js +151 -0
  18. package/dist/auth/qr-code.js.map +1 -0
  19. package/dist/calls/handler.d.ts +61 -0
  20. package/dist/calls/handler.d.ts.map +1 -0
  21. package/dist/calls/handler.js +117 -0
  22. package/dist/calls/handler.js.map +1 -0
  23. package/dist/core/binary.d.ts +74 -0
  24. package/dist/core/binary.d.ts.map +1 -0
  25. package/dist/core/binary.js +448 -0
  26. package/dist/core/binary.js.map +1 -0
  27. package/dist/core/crypto.d.ts +60 -0
  28. package/dist/core/crypto.d.ts.map +1 -0
  29. package/dist/core/crypto.js +170 -0
  30. package/dist/core/crypto.js.map +1 -0
  31. package/dist/core/noise.d.ts +106 -0
  32. package/dist/core/noise.d.ts.map +1 -0
  33. package/dist/core/noise.js +307 -0
  34. package/dist/core/noise.js.map +1 -0
  35. package/dist/events/emitter.d.ts +44 -0
  36. package/dist/events/emitter.d.ts.map +1 -0
  37. package/dist/events/emitter.js +79 -0
  38. package/dist/events/emitter.js.map +1 -0
  39. package/dist/features/index.d.ts +342 -0
  40. package/dist/features/index.d.ts.map +1 -0
  41. package/dist/features/index.js +755 -0
  42. package/dist/features/index.js.map +1 -0
  43. package/dist/fixes/index.d.ts +333 -0
  44. package/dist/fixes/index.d.ts.map +1 -0
  45. package/dist/fixes/index.js +762 -0
  46. package/dist/fixes/index.js.map +1 -0
  47. package/dist/groups/management.d.ts +86 -0
  48. package/dist/groups/management.d.ts.map +1 -0
  49. package/dist/groups/management.js +443 -0
  50. package/dist/groups/management.js.map +1 -0
  51. package/dist/index.d.ts +65 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +236 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/messages/media.d.ts +93 -0
  56. package/dist/messages/media.d.ts.map +1 -0
  57. package/dist/messages/media.js +252 -0
  58. package/dist/messages/media.js.map +1 -0
  59. package/dist/messages/message-encoder.d.ts +70 -0
  60. package/dist/messages/message-encoder.d.ts.map +1 -0
  61. package/dist/messages/message-encoder.js +453 -0
  62. package/dist/messages/message-encoder.js.map +1 -0
  63. package/dist/messages/send.d.ts +101 -0
  64. package/dist/messages/send.d.ts.map +1 -0
  65. package/dist/messages/send.js +409 -0
  66. package/dist/messages/send.js.map +1 -0
  67. package/dist/recovery/index.d.ts +125 -0
  68. package/dist/recovery/index.d.ts.map +1 -0
  69. package/dist/recovery/index.js +584 -0
  70. package/dist/recovery/index.js.map +1 -0
  71. package/dist/skdm/index.d.ts +220 -0
  72. package/dist/skdm/index.d.ts.map +1 -0
  73. package/dist/skdm/index.js +600 -0
  74. package/dist/skdm/index.js.map +1 -0
  75. package/dist/socket/hybrid.d.ts +118 -0
  76. package/dist/socket/hybrid.d.ts.map +1 -0
  77. package/dist/socket/hybrid.js +352 -0
  78. package/dist/socket/hybrid.js.map +1 -0
  79. package/dist/socket/wa-socket.d.ts +300 -0
  80. package/dist/socket/wa-socket.d.ts.map +1 -0
  81. package/dist/socket/wa-socket.js +1094 -0
  82. package/dist/socket/wa-socket.js.map +1 -0
  83. package/dist/socket/ws-socket.d.ts +96 -0
  84. package/dist/socket/ws-socket.d.ts.map +1 -0
  85. package/dist/socket/ws-socket.js +302 -0
  86. package/dist/socket/ws-socket.js.map +1 -0
  87. package/dist/types/index.d.ts +444 -0
  88. package/dist/types/index.d.ts.map +1 -0
  89. package/dist/types/index.js +7 -0
  90. package/dist/types/index.js.map +1 -0
  91. package/dist/utils/jid.d.ts +46 -0
  92. package/dist/utils/jid.d.ts.map +1 -0
  93. package/dist/utils/jid.js +152 -0
  94. package/dist/utils/jid.js.map +1 -0
  95. package/dist/utils/logger.d.ts +45 -0
  96. package/dist/utils/logger.d.ts.map +1 -0
  97. package/dist/utils/logger.js +79 -0
  98. package/dist/utils/logger.js.map +1 -0
  99. package/dist/utils/retry.d.ts +43 -0
  100. package/dist/utils/retry.d.ts.map +1 -0
  101. package/dist/utils/retry.js +175 -0
  102. package/dist/utils/retry.js.map +1 -0
  103. package/docs/API.md +745 -0
  104. package/docs/ARCHITECTURE.md +307 -0
  105. package/docs/BAILEYS_FIXES.md +360 -0
  106. package/docs/FEATURES.md +532 -0
  107. package/docs/PROTOCOL.md +489 -0
  108. package/docs/RECOVERY.md +409 -0
  109. package/docs/SKDM.md +233 -0
  110. package/examples/ai-bot/index.ts +479 -0
  111. package/examples/ai-bot/package.json +17 -0
  112. package/examples/echo-bot/index.ts +171 -0
  113. package/examples/echo-bot/package.json +18 -0
  114. package/examples/group-bot/index.ts +557 -0
  115. package/examples/group-bot/package.json +17 -0
  116. package/examples/rest-gateway/index.ts +499 -0
  117. package/examples/rest-gateway/package.json +19 -0
  118. package/package.json +75 -0
  119. package/src/advanced/features.ts +817 -0
  120. package/src/auth/auth-state.ts +342 -0
  121. package/src/auth/pairing-code.ts +246 -0
  122. package/src/auth/qr-code.ts +191 -0
  123. package/src/calls/handler.ts +153 -0
  124. package/src/core/binary.ts +464 -0
  125. package/src/core/crypto.ts +189 -0
  126. package/src/core/noise.ts +406 -0
  127. package/src/events/emitter.ts +88 -0
  128. package/src/features/index.ts +921 -0
  129. package/src/fixes/index.ts +882 -0
  130. package/src/groups/management.ts +497 -0
  131. package/src/index.ts +274 -0
  132. package/src/messages/media.ts +372 -0
  133. package/src/messages/message-encoder.ts +520 -0
  134. package/src/messages/send.ts +521 -0
  135. package/src/recovery/index.ts +704 -0
  136. package/src/skdm/index.ts +693 -0
  137. package/src/socket/hybrid.ts +414 -0
  138. package/src/socket/wa-socket.ts +1347 -0
  139. package/src/socket/ws-socket.ts +355 -0
  140. package/src/types/index.ts +457 -0
  141. package/src/utils/jid.ts +156 -0
  142. package/src/utils/logger.ts +84 -0
  143. package/src/utils/retry.ts +205 -0
  144. package/tsconfig.json +30 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Waliwa Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,600 @@
1
+ # Waliwa
2
+
3
+ > **Lightweight WhatsApp library with hybrid protocol (WA Web MD + Mobile API)**
4
+ >
5
+ > Lebih lengkap dari Baileys, lebih ringan dari ZapoJS, lebih hemat RAM.
6
+
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/)
8
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D16-green.svg)](https://nodejs.org/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
+
11
+ ## ✨ Fitur Utama
12
+
13
+ ### Hybrid Protocol (Lebih Lengkap dari Baileys)
14
+ - **WhatsApp Web Multi-Device** - QR code login via WebSocket + Noise Protocol
15
+ - **Mobile API Pairing** - Login via phone number + 8-character code (tanpa scan QR)
16
+ - **Auto-Fallback** - Switch otomatis antara WA Web dan Mobile API jika gagal
17
+
18
+ ### SKDM (Store Key Data Manager) - Baru!
19
+ - **Auto-regenerate pre-keys** saat hampir habis (fix Baileys pre-key exhaustion)
20
+ - **LRU cache** untuk sessions (RAM efficient, fix memory leak)
21
+ - **Atomic file writes** (fix session corruption on disconnect)
22
+ - **Identity change detection** (security alerts)
23
+ - **Background key rotation** otomatis
24
+
25
+ ### RAM-Efficient (Lebih Ringan dari ZapoJS)
26
+ - **Buffer Pooling** - Reuse buffer untuk hindari GC pressure
27
+ - **Lazy Loading** - Hanya load sessions/keys saat dibutuhkan
28
+ - **Debounced Writes** - Batch disk writes untuk hemat IO
29
+ - **3 Level Optimasi** - Balanced, Aggressive, Ultra (untuk low-end devices)
30
+
31
+ ### Fix Baileys Issues (9+ fixes)
32
+ 1. ✅ Pre-key exhaustion → auto-regeneration
33
+ 2. ✅ Race condition → per-recipient message queue
34
+ 3. ✅ Memory leak → WeakEventEmitter dengan FinalizationRegistry
35
+ 4. ✅ Connection hang → heartbeat dengan dead detection
36
+ 5. ✅ Decryption failure → retry queue + session prefetch
37
+ 6. ✅ Duplicate messages → idempotency cache dengan TTL
38
+ 7. ✅ Group events missing → event coalescing
39
+ 8. ✅ Media upload timeout → chunked upload dengan resume
40
+ 9. ✅ History sync incomplete → resume manager
41
+
42
+ ### Fitur Baru
43
+ - ✅ **Multi-Branch SKDM Recovery** - 8 disconnect reasons dengan recovery branches masing-masing
44
+ - ✅ **Health Monitor** - real-time health score 0-100 dengan auto-recovery
45
+ - ✅ **Multi-account Manager** - manage multiple WhatsApp accounts
46
+ - ✅ **Webhook System** - reliable delivery dengan HMAC signature + retry + DLQ
47
+ - ✅ **Circuit Breaker** - prevent retry storms untuk failed recipients
48
+ - ✅ **Rate Limit Tracker** - per-recipient rate limiting
49
+ - ✅ **Message Persistence** - survive restarts dengan pending message recovery
50
+
51
+ ### Fitur Lengkap WhatsApp
52
+ - ✅ **Auth & Session** - QR pairing, phone code pairing, persistent session
53
+ - ✅ **Messages** - Text, media, reply, forward, reactions, polls
54
+ - ✅ **Group Management** - Create, invite, promote, demote, settings, anti-link, anti-spam
55
+ - ✅ **Advanced** - Newsletter, Status/Stories, Business Profile, Catalog, Labels
56
+ - ✅ **Call Handling** - Incoming call notification, auto-reject, voice transcription hook
57
+ - ✅ **Media** - Upload/download dengan AES-256-CBC + HMAC-SHA256 encryption
58
+
59
+ ### Original Implementation
60
+ - Clean-room implementation dari Noise Protocol XX handshake
61
+ - Manual binary encoder/decoder untuk WA Web binary format
62
+ - Hybrid approach: lib untuk primitives (Noble Curves), manual untuk WA-specific encoding
63
+
64
+ ## 📦 Instalasi
65
+
66
+ ```bash
67
+ npm install waliwa
68
+ # atau
69
+ yarn add waliwa
70
+ # atau
71
+ pnpm add waliwa
72
+ ```
73
+
74
+ ## 🚀 Quick Start
75
+
76
+ ### Basic Bot dengan QR Code
77
+
78
+ ```typescript
79
+ import { makeWASocket, useFileAuthState } from 'waliwa';
80
+
81
+ async function main() {
82
+ // Initialize file-based auth state
83
+ const { state } = await useFileAuthState('./auth');
84
+
85
+ // Create socket
86
+ const sock = makeWASocket({
87
+ authState: state,
88
+ printQRInTerminal: true,
89
+ ramOptimizationLevel: 2 // 1=balanced, 2=aggressive, 3=ultra
90
+ });
91
+
92
+ // Connection events
93
+ sock.ev.on('connection.update', ({ connection, qr }) => {
94
+ if (qr) console.log('Scan QR dengan WhatsApp mobile');
95
+ if (connection === 'open') console.log('✓ Connected!');
96
+ });
97
+
98
+ // Handle messages
99
+ sock.ev.on('message.upsert', async ({ messages, type }) => {
100
+ if (type !== 'notify') return;
101
+ for (const msg of messages) {
102
+ if (!msg.key.fromMe && msg.message?.text) {
103
+ await sock.sendMessage(msg.key.remoteJid, {
104
+ text: `Echo: ${msg.message.text}`
105
+ });
106
+ }
107
+ }
108
+ });
109
+ }
110
+
111
+ main();
112
+ ```
113
+
114
+ ### Mobile API Mode (Pairing Code)
115
+
116
+ ```typescript
117
+ import { makeWASocket, useFileAuthState } from 'waliwa';
118
+
119
+ const { state } = await useFileAuthState('./auth');
120
+
121
+ const sock = makeWASocket({
122
+ authState: state,
123
+ mobile: true, // Enable Mobile API mode
124
+ phoneNumber: '6281234567890', // Target phone number
125
+ ramOptimizationLevel: 3
126
+ });
127
+
128
+ sock.ev.on('pairing-code.update', ({ code }) => {
129
+ console.log(`\nPairing code: ${code}`);
130
+ console.log('Input code ini di WhatsApp mobile app > Settings > Linked Devices\n');
131
+ });
132
+
133
+ sock.ev.on('connection.update', ({ connection }) => {
134
+ if (connection === 'open') console.log('✓ Paired & connected!');
135
+ });
136
+ ```
137
+
138
+ ### Multi-Branch SKDM Recovery
139
+
140
+ ```typescript
141
+ import { makeWASocket, useFileAuthState } from 'waliwa';
142
+
143
+ const { state } = await useFileAuthState('./auth');
144
+
145
+ const sock = makeWASocket({
146
+ authState: state,
147
+ printQRInTerminal: true,
148
+
149
+ // Multi-Branch Recovery config
150
+ recovery: {
151
+ enabled: true,
152
+ maxAttemptsPerBranch: 3, // Max attempts per branch
153
+ maxTotalAttempts: 20, // Total max attempts
154
+ initialDelayMs: 1000, // Initial backoff delay
155
+ maxDelayMs: 60000, // Max backoff delay
156
+ rateLimitedDelayMs: 300000 // 5 min cooldown for rate limit
157
+ }
158
+ });
159
+
160
+ // Monitor recovery events
161
+ sock.recoveryManager.on('recovery:start', ({ reason, code }) => {
162
+ console.warn(`Recovery started: ${reason} (code ${code})`);
163
+ });
164
+
165
+ sock.recoveryManager.on('recovery:success', ({ reason, totalAttempts, duration }) => {
166
+ console.log(`Recovery succeeded: ${reason} in ${duration}ms (${totalAttempts} attempts)`);
167
+ });
168
+
169
+ sock.recoveryManager.on('recovery:failed', ({ reason, fatal }) => {
170
+ console.error(`Recovery failed: ${reason} (fatal: ${fatal})`);
171
+ if (fatal) {
172
+ // Manual QR re-scan required
173
+ notifyAdmin(`Bot logged out! Reason: ${reason}. Re-auth required.`);
174
+ }
175
+ });
176
+
177
+ // Branches:
178
+ // Connection lost → Immediate retry → Stream reconnect → Backoff →
179
+ // Key refresh → Pre-key fetch → Full re-auth QR
180
+ // Rate limited → Wait cooldown 5min → Backoff retry
181
+ // Logged out → Key refresh → No recovery (fatal)
182
+ // Multi-device mismatch → Key refresh → Full re-auth QR
183
+ // Connection replaced → Key refresh → Full re-auth QR
184
+ // ... dan lainnya
185
+ ```
186
+
187
+ ## 📖 API Reference
188
+
189
+ ### Events (Baileys-style)
190
+
191
+ ```typescript
192
+ sock.ev.on('connection.update', (update) => {});
193
+ sock.ev.on('creds.update', (creds) => {});
194
+ sock.ev.on('qr.update', (qr) => {});
195
+ sock.ev.on('pairing-code.update', (code) => {});
196
+ sock.ev.on('message.upsert', ({ messages, type }) => {});
197
+ sock.ev.on('message.update', ({ messages, keys }) => {});
198
+ sock.ev.on('message.reaction', ({ key, reaction, sender }) => {});
199
+ sock.ev.on('presence.update', (presence) => {});
200
+ sock.ev.on('chats.upsert', (chats) => {});
201
+ sock.ev.on('groups.upsert', (groups) => {});
202
+ sock.ev.on('groups.update', (groups) => {});
203
+ sock.ev.on('group-participants.update', (update) => {});
204
+ sock.ev.on('calls', (callEvent) => {});
205
+ sock.ev.on('contacts.upsert', (contacts) => {});
206
+ ```
207
+
208
+ ### Send Messages
209
+
210
+ ```typescript
211
+ // Text
212
+ await sock.sendMessage(jid, { text: 'Hello!' });
213
+
214
+ // Reply
215
+ await sock.sendMessage(jid, {
216
+ text: 'Reply!',
217
+ quoted: originalMessage
218
+ });
219
+
220
+ // Mention
221
+ await sock.sendMessage(jid, {
222
+ text: 'Hi @user!',
223
+ mentions: ['6281234567890@s.whatsapp.net']
224
+ });
225
+
226
+ // Image
227
+ import { readFileSync } from 'fs';
228
+ await sock.sendMessage(jid, {
229
+ image: { stream: readFileSync('photo.jpg'), mimetype: 'image/jpeg' },
230
+ caption: 'Photo caption'
231
+ });
232
+
233
+ // Document
234
+ await sock.sendMessage(jid, {
235
+ document: {
236
+ stream: readFileSync('doc.pdf'),
237
+ mimetype: 'application/pdf',
238
+ fileName: 'document.pdf'
239
+ }
240
+ });
241
+
242
+ // Location
243
+ await sock.sendMessage(jid, {
244
+ location: {
245
+ degreesLatitude: -6.2088,
246
+ degreesLongitude: 106.8456,
247
+ name: 'Jakarta'
248
+ }
249
+ });
250
+
251
+ // Contact
252
+ await sock.sendMessage(jid, {
253
+ contact: {
254
+ displayName: 'John Doe',
255
+ vcard: 'BEGIN:VCARD\nVERSION:3.0\nFN:John Doe\nTEL:+6281234567890\nEND:VCARD'
256
+ }
257
+ });
258
+
259
+ // Poll
260
+ await sock.sendMessage(jid, {
261
+ poll: {
262
+ name: 'Pilih makan siang',
263
+ values: ['Nasi Goreng', 'Mie Ayam', 'Sate'],
264
+ selectableCounts: [1]
265
+ }
266
+ });
267
+
268
+ // Reaction
269
+ await sock.reactToMessage(jid, message.key, '👍');
270
+ ```
271
+
272
+ ### Group Management
273
+
274
+ ```typescript
275
+ // Create group
276
+ const group = await sock.groupCreate({
277
+ subject: 'My Group',
278
+ participants: ['6281234567890@s.whatsapp.net'],
279
+ desc: 'Group description'
280
+ });
281
+
282
+ // Get metadata
283
+ const metadata = await sock.groupMetadata(group.id);
284
+
285
+ // Update subject
286
+ await sock.groupUpdateSubject(group.id, 'New Name');
287
+
288
+ // Add/remove/promote/demote
289
+ await sock.groupParticipantsUpdate(group.id, ['user@s.whatsapp.net'], 'add');
290
+ await sock.groupParticipantsUpdate(group.id, ['user@s.whatsapp.net'], 'remove');
291
+ await sock.groupParticipantsUpdate(group.id, ['user@s.whatsapp.net'], 'promote');
292
+ await sock.groupParticipantsUpdate(group.id, ['user@s.whatsapp.net'], 'demote');
293
+
294
+ // Invite link
295
+ const code = await sock.groupInviteCode(group.id);
296
+ await sock.groupRevokeInvite(group.id);
297
+
298
+ // Join via code
299
+ const joinedGroupJid = await sock.groupJoinViaCode('inviteCode');
300
+
301
+ // Leave group
302
+ await sock.groupLeave(group.id);
303
+
304
+ // Settings
305
+ await sock.groupSettingUpdate(group.id, 'restrict', true); // Only admins can send
306
+ await sock.groupSettingUpdate(group.id, 'announce', true); // Only admins can edit info
307
+ ```
308
+
309
+ ### Call Handling
310
+
311
+ ```typescript
312
+ sock.ev.on('calls', async (callEvent) => {
313
+ console.log(`Incoming ${callEvent.isVideo ? 'video' : 'voice'} call from ${callEvent.from}`);
314
+
315
+ // Auto-reject
316
+ await sock.rejectCall(callEvent.id, callEvent.from);
317
+ });
318
+ ```
319
+
320
+ ### Media Upload/Download
321
+
322
+ ```typescript
323
+ import { readFileSync, writeFileSync } from 'fs';
324
+
325
+ // Upload
326
+ const buffer = readFileSync('photo.jpg');
327
+ const uploadResult = await sock.uploadMedia(buffer, 'image', 'image/jpeg', 'photo.jpg');
328
+ console.log('Uploaded:', uploadResult.url);
329
+
330
+ // Download (from message)
331
+ if (msg.message?.image) {
332
+ const downloadResult = await sock.downloadMedia(
333
+ msg.message.image.url,
334
+ msg.message.image.mediaKey,
335
+ 'image',
336
+ msg.message.image.mimetype
337
+ );
338
+ writeFileSync('downloaded.jpg', downloadResult.buffer);
339
+ }
340
+ ```
341
+
342
+ ### Presence & Typing Indicator
343
+
344
+ ```typescript
345
+ // Subscribe to user presence
346
+ await sock.presenceSubscribe(['6281234567890@s.whatsapp.net']);
347
+
348
+ // Listen to presence updates
349
+ sock.ev.on('presence.update', ({ jid, presence }) => {
350
+ console.log(`${jid} is ${presence}`);
351
+ });
352
+
353
+ // Send typing indicator
354
+ await sock.sendPresenceUpdate(jid, 'composing'); // typing
355
+ await sock.sendPresenceUpdate(jid, 'recording'); // recording voice
356
+ await sock.sendPresenceUpdate(jid, 'paused'); // stopped
357
+
358
+ // Update own presence
359
+ await sock.updatePresence('available');
360
+ await sock.updatePresence('unavailable');
361
+ ```
362
+
363
+ ### Advanced Features
364
+
365
+ ```typescript
366
+ // Newsletter
367
+ const newsletter = await sock.newsletterManager.create('My Channel', 'Description');
368
+ await sock.newsletterManager.subscribe(newsletter.id);
369
+
370
+ // Status/Stories
371
+ await sock.statusManager.sendTextStatus('Hello world!', {
372
+ backgroundColor: '#FF0000'
373
+ });
374
+
375
+ // Business Profile
376
+ await sock.businessProfileManager.update({
377
+ description: 'My Business',
378
+ email: 'contact@business.com',
379
+ address: 'Jakarta, Indonesia'
380
+ });
381
+
382
+ // Catalog
383
+ await sock.catalogManager.addProduct({
384
+ name: 'Product 1',
385
+ description: 'Description',
386
+ price: 100000,
387
+ currency: 'IDR'
388
+ });
389
+ ```
390
+
391
+ ## 🏗️ Arsitektur
392
+
393
+ ```
394
+ ┌──────────────────────────────────────────────────────────────────┐
395
+ │ Your Application │
396
+ └──────────────────────────────────────────────────────────────────┘
397
+
398
+
399
+ ┌──────────────────────────────────────────────────────────────────┐
400
+ │ WASocket (Public API) │
401
+ │ Event Emitter, sendMessage, groupCreate, etc. │
402
+ └──────────────────────────────────────────────────────────────────┘
403
+
404
+ ┌─────────────────────────┼─────────────────────────┐
405
+ ▼ ▼ ▼
406
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
407
+ │ Messages │ │ Groups │ │ Calls │
408
+ │ Send/Receive │ │ Management │ │ Handler │
409
+ │ Media │ │ Participants│ │ Reject │
410
+ └──────────────┘ └──────────────┘ └──────────────┘
411
+
412
+
413
+ ┌──────────────────────────────────────────────────────────────────┐
414
+ │ Hybrid Socket Manager │
415
+ │ Auto-fallback antara WA Web MD dan Mobile API │
416
+ └──────────────────────────────────────────────────────────────────┘
417
+
418
+ ┌─────────────────────────┼─────────────────────────┐
419
+ ▼ ▼ ▼
420
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
421
+ │ WA Web MD │ │ Mobile API │ │ Auth State │
422
+ │ WebSocket │ │ Pairing │ │ File JSON │
423
+ └──────────────┘ └──────────────┘ └──────────────┘
424
+ │ │
425
+ ▼ ▼
426
+ ┌──────────────────────────────────────────────────────────────────┐
427
+ │ Noise Protocol XX Handshake │
428
+ │ + AES-256-GCM Traffic Cipher + WA Binary Protocol │
429
+ └──────────────────────────────────────────────────────────────────┘
430
+
431
+
432
+ ┌──────────────────────────────────────────────────────────────────┐
433
+ │ Crypto Primitives (@noble/curves + @noble/hashes) │
434
+ │ Curve25519, Ed25519, SHA-256, HMAC, HKDF, AES-GCM/CBC │
435
+ └──────────────────────────────────────────────────────────────────┘
436
+ ```
437
+
438
+ ## 🔒 Reverse Engineering Approach
439
+
440
+ Waliwa adalah clean-room implementation berdasarkan publicly documented WhatsApp protocol:
441
+
442
+ 1. **Noise Protocol Framework** - Public spec dari [noiseprotocol.org](https://noiseprotocol.org/)
443
+ - Pattern: `Noise_XX_25519_AESGCM_SHA256`
444
+ - Manual implementation di `src/core/noise.ts`
445
+
446
+ 2. **WhatsApp Binary Format** - Custom binary protocol untuk encoding
447
+ - Tags: list, dictionary, packed nibble/hex, binary 8/20/32
448
+ - Manual encoder/decoder di `src/core/binary.ts`
449
+
450
+ 3. **Multi-Device Protocol** - WebSocket with encrypted frames
451
+ - Frame: `[WA header][version][length][encrypted payload]`
452
+ - AES-256-GCM dengan counter-based nonce
453
+
454
+ 4. **Mobile API Pairing** - Companion device registration
455
+ - Pairing code: 8 alphanumeric chars derived via HKDF
456
+ - Format: `AB12-CD34` (dash separator)
457
+
458
+ 5. **Media Encryption** - AES-256-CBC + HMAC-SHA256
459
+ - 112-byte derived key (iv + cipherKey + macKey + refKey)
460
+ - 10-byte MAC truncation sesuai WA spec
461
+
462
+ ## 📊 RAM Usage Comparison
463
+
464
+ | Library | Idle RAM | Active RAM | Notes |
465
+ |---------------|----------|------------|--------------------------------------|
466
+ | Baileys | ~80 MB | ~150 MB | Pino logger, full buffer |
467
+ | ZapoJS | ~60 MB | ~120 MB | Heavy dependencies |
468
+ | **Waliwa** | **~35 MB** | **~70 MB** | Buffer pool, lazy load, debounced IO |
469
+
470
+ *Benchmarks pada Node.js 20, single account, moderate message rate*
471
+
472
+ ## 📚 Examples
473
+
474
+ 4 contoh bot siap pakai tersedia di `examples/`:
475
+
476
+ 1. **echo-bot** - Basic echo bot untuk testing
477
+ ```bash
478
+ cd examples/echo-bot && npm install && npm start
479
+ ```
480
+
481
+ 2. **group-bot** - Group management dengan admin commands
482
+ ```bash
483
+ cd examples/group-bot && npm install && npm start
484
+ ```
485
+
486
+ 3. **ai-bot** - AI chatbot dengan OpenAI GPT integration
487
+ ```bash
488
+ cd examples/ai-bot
489
+ echo "OPENAI_API_KEY=your_key" > .env
490
+ npm install && npm start
491
+ ```
492
+
493
+ 4. **rest-gateway** - HTTP REST API untuk send/receive
494
+ ```bash
495
+ cd examples/rest-gateway && npm install && npm start
496
+ curl -X POST http://localhost:3000/send-text \
497
+ -H "Content-Type: application/json" \
498
+ -d '{"to":"6281234567890","message":"Hello!"}'
499
+ ```
500
+
501
+ ## 📖 Documentation
502
+
503
+ - [**Multi-Branch SKDM Recovery**](docs/RECOVERY.md) - Recovery branches per disconnect reason
504
+ - [**SKDM (Store Key Data Manager)**](docs/SKDM.md) - Key management subsystem
505
+ - [**Baileys Fixes**](docs/BAILEYS_FIXES.md) - Detail 9+ fix untuk issue Baileys
506
+ - [**New Features**](docs/FEATURES.md) - Health monitor, multi-account, webhooks, dll
507
+ - [**Architecture**](docs/ARCHITECTURE.md) - Internal design dan module dependencies
508
+ - [**Protocol**](docs/PROTOCOL.md) - WhatsApp protocol reverse engineering details
509
+ - [**API Reference**](docs/API.md) - Complete API documentation
510
+
511
+ ## 🔧 Production Monitoring
512
+
513
+ ```typescript
514
+ const sock = makeWASocket({ authState: state });
515
+
516
+ // Get comprehensive system stats
517
+ const stats = sock.getSystemStats();
518
+ console.log(JSON.stringify(stats, null, 2));
519
+ // {
520
+ // messageQueue: { totalQueues: 5, totalPending: 0, ... },
521
+ // circuitBreakers: [],
522
+ // rateLimits: { trackedRecipients: 12, ... },
523
+ // webhooks: { sent: 145, failed: 3, ... },
524
+ // messagePersistence: { total: 89, pending: 0, failed: 1 },
525
+ // idempotency: { size: 89, hitRate: 0.95 },
526
+ // health: { status: 'healthy', score: 95, ... }
527
+ // }
528
+
529
+ // Health monitoring
530
+ sock.healthMonitor.on('health:recovery', (status) => {
531
+ console.warn('Auto-recovery triggered:', status.issues);
532
+ });
533
+
534
+ // Register webhook untuk external monitoring
535
+ sock.registerWebhook({
536
+ url: 'https://yourapp.com/webhook',
537
+ events: ['message.sent', 'message.failed', 'auth.success'],
538
+ secret: process.env.WEBHOOK_SECRET,
539
+ enabled: true,
540
+ retryCount: 5,
541
+ retryDelayMs: 1000,
542
+ timeoutMs: 10000
543
+ });
544
+ ```
545
+
546
+ ## ⚙️ Configuration
547
+
548
+ ### WaliwaConfig Options
549
+
550
+ | Option | Type | Default | Description |
551
+ |-------------------------|-----------|--------------------------------------|--------------------------------------|
552
+ | authState | AuthState | **required** | Auth state (file, memory, custom) |
553
+ | printQRInTerminal | boolean | false | Print QR ke terminal |
554
+ | mobile | boolean | false | Use Mobile API mode |
555
+ | phoneNumber | string | - | Phone number untuk Mobile API mode |
556
+ | browser | [3 string]| ['Waliwa', 'WA', '1.0.0'] | Browser identification |
557
+ | wsURL | string | wss://web.whatsapp.com/ws/chat | Custom WebSocket URL |
558
+ | connectTimeoutMs | number | 20000 | Connect timeout ms |
559
+ | keepAliveIntervalMs | number | 20000 | Keep-alive ping interval |
560
+ | maxReconnectAttempts | number | 10 | Max auto-reconnect attempts |
561
+ | reconnectInterval | number | 2000 | Initial reconnect delay ms |
562
+ | ramOptimizationLevel | 1/2/3 | 2 | 1=balanced, 2=aggressive, 3=ultra |
563
+ | syncFullHistory | boolean | false | Sync full message history on connect |
564
+ | markOnlineOnConnect | boolean | true | Mark bot online saat connect |
565
+
566
+ ### RAM Optimization Levels
567
+
568
+ | Level | Buffer Pool | Lazy Load | Debounce | Use Case |
569
+ |-----------|-------------|-----------|----------|-----------------------------------|
570
+ | 1 Balanced| 8 buffers | Off | 100ms | Development, high-throughput |
571
+ | 2 Aggressive| 16 buffers| On | 50ms | Production default |
572
+ | 3 Ultra | 32 buffers | On | 25ms | Low-end VPS, multi-account |
573
+
574
+ ## 🛠️ Development
575
+
576
+ ```bash
577
+ # Install dependencies
578
+ npm install
579
+
580
+ # Build library
581
+ npm run build
582
+
583
+ # Run tests
584
+ npm test
585
+
586
+ # Run example
587
+ cd examples/echo-bot && npm start
588
+ ```
589
+
590
+ ## ⚠️ Disclaimer
591
+
592
+ This library is for educational purposes. WhatsApp is a trademark of WhatsApp Inc., and this project is not affiliated with or endorsed by WhatsApp Inc. Use at your own risk and comply with WhatsApp's Terms of Service.
593
+
594
+ ## 📄 License
595
+
596
+ MIT - See [LICENSE](LICENSE) file for details.
597
+
598
+ ## 🤝 Contributing
599
+
600
+ Contributions welcome! Please read contributing guidelines dan ensure all tests pass sebelum submit PR.