@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
@@ -0,0 +1,307 @@
1
+ # Architecture
2
+
3
+ This document describes the internal architecture of Waliwa library.
4
+
5
+ ## Design Principles
6
+
7
+ ### 1. Hybrid Protocol
8
+ Waliwa implements **two distinct WhatsApp protocols** with seamless switching:
9
+
10
+ - **WhatsApp Web Multi-Device (MD)** - The primary protocol used by WhatsApp Web. Uses WebSocket + Noise Protocol Framework (XX pattern) + custom binary format.
11
+ - **Mobile API Pairing** - Companion device registration via phone number + pairing code. Used by official WhatsApp Business API clients.
12
+
13
+ The `HybridSocketManager` automatically falls back between these protocols when one fails.
14
+
15
+ ### 2. RAM-Efficient Design
16
+ Three key strategies to minimize memory usage:
17
+
18
+ - **Buffer Pooling** - Reuse pre-allocated Uint8Array buffers for WebSocket frames instead of allocating new ones per message
19
+ - **Lazy Loading** - Signal keys/sessions loaded on-demand, not all at startup
20
+ - **Debounced Disk IO** - Batch credential file writes every 50-100ms instead of per-update
21
+
22
+ ### 3. Clean-Room Implementation
23
+ All protocol-specific code is written from scratch based on publicly documented specs:
24
+ - Noise Protocol Framework (noiseprotocol.org)
25
+ - WhatsApp binary format (publicly documented through reverse engineering)
26
+ - Signal protocol (open source spec)
27
+
28
+ No code is copied from Baileys, ZapoJS, or any other WhatsApp library.
29
+
30
+ ## Layer Architecture
31
+
32
+ ```
33
+ ┌─────────────────────────────────────────────────────────────┐
34
+ │ Application Layer │
35
+ │ (User code using WASocket) │
36
+ └─────────────────────────────────────────────────────────────┘
37
+
38
+
39
+ ┌─────────────────────────────────────────────────────────────┐
40
+ │ Public API Layer │
41
+ │ makeWASocket(), sendMessage(), groupCreate(), ev.on() │
42
+ └─────────────────────────────────────────────────────────────┘
43
+
44
+ ┌─────────────────────┼─────────────────────┐
45
+ ▼ ▼ ▼
46
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
47
+ │ Messages │ │ Groups │ │ Calls │
48
+ │ Sender │ │ Manager │ │ Handler │
49
+ │ Receiver │ │ │ │ │
50
+ │ Media │ │ │ │ │
51
+ └──────────────┘ └──────────────┘ └──────────────┘
52
+
53
+
54
+ ┌─────────────────────────────────────────────────────────────┐
55
+ │ Socket Layer │
56
+ │ WAWebSocket (Noise-encrypted WebSocket frames) │
57
+ │ MobileAPISocket (Pairing code flow) │
58
+ │ HybridSocketManager (Auto-fallback) │
59
+ └─────────────────────────────────────────────────────────────┘
60
+
61
+
62
+ ┌─────────────────────────────────────────────────────────────┐
63
+ │ Core Layer │
64
+ │ NoiseHandshake (XX pattern implementation) │
65
+ │ TrafficCipher (AES-256-GCM post-handshake) │
66
+ │ BinaryEncoder/Decoder (WA binary format) │
67
+ │ Crypto utilities (Curve25519, HKDF, AES, HMAC) │
68
+ └─────────────────────────────────────────────────────────────┘
69
+
70
+
71
+ ┌─────────────────────────────────────────────────────────────┐
72
+ │ Auth Layer │
73
+ │ FileAuthState (JSON file storage) │
74
+ │ QR Code generator (WA Web pairing) │
75
+ │ Pairing Code generator (Mobile API) │
76
+ │ Signal Key Store (pre-keys, sessions, identity) │
77
+ └─────────────────────────────────────────────────────────────┘
78
+
79
+
80
+ ┌─────────────────────────────────────────────────────────────┐
81
+ │ Utilities Layer │
82
+ │ Logger (lightweight alternative to pino) │
83
+ │ JID utilities (parse, normalize, validate) │
84
+ │ Retry/Throttle (exponential backoff, rate limiter) │
85
+ │ Event Emitter (typed, Baileys-compatible) │
86
+ └─────────────────────────────────────────────────────────────┘
87
+ ```
88
+
89
+ ## Module Dependencies
90
+
91
+ ```
92
+ src/index.ts
93
+ ├── socket/wa-socket.ts (main entry point)
94
+ │ ├── socket/ws-socket.ts (WebSocket layer)
95
+ │ │ ├── core/noise.ts (Noise protocol)
96
+ │ │ │ └── core/crypto.ts (crypto primitives)
97
+ │ │ └── core/binary.ts (binary encoding)
98
+ │ ├── socket/hybrid.ts (Mobile API + fallback)
99
+ │ ├── auth/auth-state.ts (file storage)
100
+ │ ├── auth/qr-code.ts (QR pairing)
101
+ │ ├── auth/pairing-code.ts (Mobile pairing)
102
+ │ ├── messages/send.ts (message operations)
103
+ │ │ └── messages/message-encoder.ts (encoding)
104
+ │ ├── messages/media.ts (upload/download)
105
+ │ ├── groups/management.ts (group operations)
106
+ │ ├── calls/handler.ts (call handling)
107
+ │ ├── advanced/features.ts (polls, newsletter, etc)
108
+ │ ├── events/emitter.ts (typed events)
109
+ │ └── utils/{jid,logger,retry}.ts (utilities)
110
+ └── types/index.ts (all type definitions)
111
+ ```
112
+
113
+ ## Connection Lifecycle
114
+
115
+ ```
116
+ 1. User calls makeWASocket(config)
117
+
118
+ 2. WASocketImpl created with config
119
+
120
+ 3. connect() called automatically
121
+
122
+ 4. WAWebSocket established to wss://web.whatsapp.com/ws/chat
123
+
124
+ 5. Noise Protocol XX handshake performed
125
+ - Client sends: ephemeral + encrypted static + payload
126
+ - Server responds: ephemeral + encrypted static + ES + payload
127
+ - Both derive traffic keys via HKDF
128
+
129
+ 6. Traffic cipher initialized (AES-256-GCM)
130
+
131
+ 7. Auth flow starts:
132
+ - If creds.registered = true: send login IQ
133
+ - If mobile mode: request pairing code
134
+ - Else: generate QR code, start refresh cycle
135
+
136
+ 8. Server sends success/failure node
137
+ - On success: emit 'connection.update' with connection='open'
138
+ - On failure: emit error, retry with exponential backoff
139
+
140
+ 9. Keep-alive ping every 20s
141
+
142
+ 10. Incoming messages processed by MessageReceiver
143
+ - Decode binary node
144
+ - Parse message type (text, image, video, etc)
145
+ - Emit 'message.upsert' event
146
+
147
+ 11. On disconnect:
148
+ - Reject all pending messages
149
+ - Auto-reconnect with exponential backoff
150
+ - Switch protocol mode if max retries reached
151
+ ```
152
+
153
+ ## Message Encoding Flow
154
+
155
+ ```
156
+ User: sock.sendMessage(jid, { text: 'Hello' })
157
+
158
+ 1. MessageSender.sendMessage() called
159
+
160
+ 2. generateMessageId() returns "3EB0..."
161
+
162
+ 3. encodeMessageNode() builds BinaryNode:
163
+ {
164
+ tag: 'message',
165
+ attrs: { to: jid, type: 'text', id: msgId },
166
+ content: [{ tag: 'conversation', attrs: {}, content: 'Hello' }]
167
+ }
168
+
169
+ 4. encodeBinaryNode() serializes to Uint8Array:
170
+ - Tag header byte
171
+ - Tag string (looked up in dictionary, packed nibble, or raw bytes)
172
+ - Attributes (key-value pairs)
173
+ - Content (recursive children)
174
+
175
+ 5. WAWebSocket.send():
176
+ - TrafficCipher.encrypt() with AES-256-GCM (counter nonce)
177
+ - Prepend WA frame header: [0x57 0x41] [version] [3-byte length]
178
+ - ws.send(Buffer.from(frame))
179
+
180
+ 6. Server ACKs message with 'ack' node
181
+ - MessageTracker resolves pending Promise
182
+ - Returns SendMessageResult to user
183
+ ```
184
+
185
+ ## File Layout
186
+
187
+ ```
188
+ waliwa/
189
+ ├── src/
190
+ │ ├── index.ts # Public exports
191
+ │ ├── types/index.ts # All TypeScript types
192
+ │ ├── core/
193
+ │ │ ├── crypto.ts # Curve25519, AES, HKDF, HMAC
194
+ │ │ ├── binary.ts # WA binary encoder/decoder
195
+ │ │ └── noise.ts # Noise Protocol XX handshake
196
+ │ ├── socket/
197
+ │ │ ├── ws-socket.ts # WA WebSocket layer
198
+ │ │ ├── wa-socket.ts # Main WASocket interface
199
+ │ │ └── hybrid.ts # Mobile API + Hybrid manager
200
+ │ ├── auth/
201
+ │ │ ├── auth-state.ts # File-based auth state
202
+ │ │ ├── qr-code.ts # QR code generation
203
+ │ │ └── pairing-code.ts # Mobile pairing code
204
+ │ ├── messages/
205
+ │ │ ├── message-encoder.ts # Message encoding/decoding
206
+ │ │ ├── send.ts # Send/receive operations
207
+ │ │ └── media.ts # Media upload/download
208
+ │ ├── groups/management.ts # Group operations
209
+ │ ├── calls/handler.ts # Call handling
210
+ │ ├── advanced/features.ts # Polls, newsletter, etc
211
+ │ ├── events/emitter.ts # Typed event emitter
212
+ │ └── utils/
213
+ │ ├── jid.ts # JID utilities
214
+ │ ├── logger.ts # Logger
215
+ │ └── retry.ts # Retry/throttle
216
+ ├── examples/
217
+ │ ├── echo-bot/ # Basic echo bot
218
+ │ ├── group-bot/ # Group management bot
219
+ │ ├── ai-bot/ # AI chatbot with GPT
220
+ │ └── rest-gateway/ # REST API gateway
221
+ ├── docs/ # Documentation
222
+ ├── package.json
223
+ ├── tsconfig.json
224
+ ├── LICENSE
225
+ └── README.md
226
+ ```
227
+
228
+ ## Performance Considerations
229
+
230
+ ### Memory Usage
231
+ - BufferPool: Pre-allocate 16 buffers of 8KB each (configurable)
232
+ - Lazy session loading: Only load Signal sessions when first message exchanged
233
+ - Conversation history: Optional, max 10 messages per user (configurable)
234
+ - Debounced writes: Coalesce 100ms of state changes into single disk write
235
+
236
+ ### Network Usage
237
+ - WebSocket compression disabled (perMessageDeflate: false) - avoids CPU overhead
238
+ - Keep-alive ping every 20s (configurable)
239
+ - Max payload: 16MB (matches WhatsApp server limit)
240
+ - HTTP/2 used for media upload/download (via axios)
241
+
242
+ ### CPU Usage
243
+ - AES-GCM via @noble/ciphers (no native bindings, pure JS)
244
+ - Curve25519 via @noble/curves (constant-time, audited)
245
+ - Binary encoding with dictionary lookup (O(1) for common tags)
246
+ - No protobuf runtime reflection - all encoding done manually
247
+
248
+ ## Error Handling
249
+
250
+ ### Reconnection Strategy
251
+ ```
252
+ Disconnect detected
253
+
254
+ Increment retry counter
255
+
256
+ Delay = min(baseInterval * 2^retries, 60000)
257
+
258
+ Reconnect attempt
259
+
260
+ ┌──→ Success → Reset counter
261
+
262
+ └──→ Failure → Loop back if counter < maxRetries
263
+
264
+ If counter >= maxRetries:
265
+ - Switch protocol mode (Web ↔ Mobile)
266
+ - Reset counter
267
+ - Try again
268
+ ```
269
+
270
+ ### Message Retry Strategy
271
+ - Max 5 retries per message (configurable)
272
+ - Exponential backoff: 500ms → 1s → 2s → 4s → 8s
273
+ - On final failure: emit 'message.update' with status='error'
274
+ - Pending messages cleared on disconnect (rejected with 'Connection closed' error)
275
+
276
+ ## Extension Points
277
+
278
+ ### Custom Auth State
279
+ ```typescript
280
+ import { AuthState, AuthenticationCreds, SignalKeyStore } from 'waliwa';
281
+
282
+ class RedisAuthState implements AuthState {
283
+ creds: AuthenticationCreds;
284
+ keys: SignalKeyStore;
285
+ // Implement with Redis backend
286
+ }
287
+
288
+ const sock = makeWASocket({
289
+ authState: new RedisAuthState(redisClient)
290
+ });
291
+ ```
292
+
293
+ ### Custom Logger
294
+ ```typescript
295
+ import { WALogger } from 'waliwa';
296
+
297
+ class MyLogger implements WALogger {
298
+ // Implement with your logging system (Winston, Bunyan, etc.)
299
+ }
300
+
301
+ const sock = makeWASocket({
302
+ logger: new MyLogger()
303
+ });
304
+ ```
305
+
306
+ ### Custom Media Storage
307
+ The MediaUploader/MediaDownloader classes can be extended to use S3, Google Cloud Storage, or other backends instead of WhatsApp CDN.
@@ -0,0 +1,360 @@
1
+ # Baileys Issues Fixes
2
+
3
+ Waliwa mengatasi 9+ issues yang sering dikeluhkan di Baileys. Setiap fix dijelaskan dengan masalah, solusi, dan cara pakai.
4
+
5
+ ## Daftar Fix
6
+
7
+ ### 1. Pre-key Exhaustion (Baileys Issue)
8
+
9
+ **Masalah:** Pre-keys habis tanpa warning, bot tiba-tiba tidak bisa menerima pesan baru.
10
+
11
+ **Solusi:** `PreKeyManager` di SKDM dengan auto-regeneration.
12
+
13
+ ```typescript
14
+ // Otomatis di SKDM - pre-keys di-regenerate saat < minPreKeys (default: 5)
15
+ const skdm = sock.getSKDM();
16
+ console.log(skdm.preKeyManager.getStats());
17
+ // { total: 95, needsRegen: false, ... }
18
+
19
+ // Manual check
20
+ if (skdm.preKeyManager.needsRegeneration()) {
21
+ await skdm.preKeyManager.regeneratePreKeys();
22
+ }
23
+ ```
24
+
25
+ **Lihat:** [SKDM documentation](./SKDM.md) untuk detail lengkap.
26
+
27
+ ---
28
+
29
+ ### 2. Race Condition di Message Sending
30
+
31
+ **Masalah:** Concurrent sends ke same chat cause duplicate messages, wrong order, atau message ID collision.
32
+
33
+ **Solusi:** `MessageQueue` dengan per-recipient serialization.
34
+
35
+ ```typescript
36
+ // Otomatis di WASocket.sendMessage() - tiap recipient punya queue sendiri
37
+ // Concurrent across different recipients (parallelism)
38
+ // Sequential per recipient (order guarantee)
39
+
40
+ // Manual usage untuk custom operations:
41
+ import { MessageQueue } from 'waliwa';
42
+
43
+ const queue = new MessageQueue(10); // Max 10 concurrent recipients
44
+ await queue.enqueue('user1@s.whatsapp.net', async () => {
45
+ return await sock.sendMessage('user1@s.whatsapp.net', { text: 'Hi' });
46
+ });
47
+
48
+ // Stats
49
+ console.log(queue.getStats());
50
+ // { totalQueues: 1, totalPending: 0, activeCount: 0, maxConcurrency: 10 }
51
+ ```
52
+
53
+ ---
54
+
55
+ ### 3. Memory Leak dari Event Listeners
56
+
57
+ **Masalah:** Listeners tidak di-cleanup properly saat objects di-destroy, menyebabkan memory leak overtime.
58
+
59
+ **Solusi:** `WeakEventEmitter` dengan FinalizationRegistry untuk auto-cleanup.
60
+
61
+ ```typescript
62
+ import { WeakEventEmitter } from 'waliwa';
63
+
64
+ const emitter = new WeakEventEmitter();
65
+
66
+ class MyComponent {
67
+ private data: any[] = [];
68
+
69
+ constructor() {
70
+ // Auto-cleanup saat MyComponent di-GC
71
+ emitter.subscribeWeak(this, 'message', (msg) => {
72
+ this.data.push(msg);
73
+ });
74
+ }
75
+ }
76
+
77
+ // Atau manual cleanup
78
+ emitter.cleanupTarget(myComponentInstance);
79
+ ```
80
+
81
+ ---
82
+
83
+ ### 4. Connection Hang
84
+
85
+ **Masalah:** WebSocket connection hang, tidak detect disconnect, bot "appear online" tapi tidak receive/send messages.
86
+
87
+ **Solusi:** `ConnectionHeartbeat` dengan proper dead detection.
88
+
89
+ ```typescript
90
+ import { ConnectionHeartbeat } from 'waliwa';
91
+
92
+ const heartbeat = new ConnectionHeartbeat({
93
+ sendPing: async () => {
94
+ // Send WA ping
95
+ await sock.send(encodeBinaryNode({
96
+ tag: 'iq',
97
+ attrs: { type: 'get', id: `ping-${Date.now()}` },
98
+ content: [{ tag: 'ping', attrs: {} }]
99
+ }));
100
+ },
101
+ onDead: () => {
102
+ console.error('Connection dead, triggering reconnect');
103
+ // Custom recovery logic
104
+ },
105
+ pingIntervalMs: 20000, // Ping every 20s
106
+ pongTimeoutMs: 10000, // Wait 10s for pong
107
+ maxMissedPongs: 3 // Mark dead after 3 misses
108
+ });
109
+
110
+ heartbeat.start();
111
+
112
+ // When pong received (di WA message handler):
113
+ heartbeat.receivedPong();
114
+
115
+ // Check health
116
+ console.log(heartbeat.isHealthy()); // true/false
117
+ ```
118
+
119
+ **Otomatis di WASocket:** Heartbeat aktif secara default, mengirim ping setiap 20 detik.
120
+
121
+ ---
122
+
123
+ ### 5. Decryption Failure untuk Old Messages
124
+
125
+ **Masalah:** Messages dari long-time-no-chat contacts fail to decrypt karena session keys expired/missing.
126
+
127
+ **Solusi:** `SessionManager.prefetchSessions()` + `DecryptionRetryQueue`.
128
+
129
+ ```typescript
130
+ const skdm = sock.getSKDM();
131
+
132
+ // Prefetch sessions sebelum bulk decrypt group messages
133
+ skdm.sessionManager.prefetchSessions([
134
+ 'user1@s.whatsapp.net',
135
+ 'user2@s.whatsapp.net'
136
+ ]);
137
+
138
+ // Decryption retry queue - retry failed decryptions after key sync
139
+ import { DecryptionRetryQueue } from 'waliwa';
140
+
141
+ const retryQueue = new DecryptionRetryQueue({
142
+ maxAttempts: 3,
143
+ maxQueueSize: 1000,
144
+ retryHandler: async (item) => {
145
+ // Custom retry logic - request key sync, then retry
146
+ await requestKeySync(item.senderJid);
147
+ return await retryDecryption(item.encryptedData);
148
+ }
149
+ });
150
+
151
+ // Enqueue failed decryption
152
+ retryQueue.enqueue('msg-123', '6281@s.whatsapp.net', encryptedData);
153
+
154
+ // Trigger immediate retry (e.g., after key sync complete)
155
+ await retryQueue.retryNow();
156
+ ```
157
+
158
+ ---
159
+
160
+ ### 6. Duplicate Messages
161
+
162
+ **Masalah:** Messages diterima multiple times, bot reply 2x, confusing user.
163
+
164
+ **Solusi:** `IdempotencyCache` dengan TTL.
165
+
166
+ ```typescript
167
+ // Otomatis di WASocket - incoming message IDs di-check
168
+ // Jika ID sudah pernah dilihat dalam 24 jam, skip
169
+
170
+ import { IdempotencyCache } from 'waliwa';
171
+
172
+ const cache = new IdempotencyCache(10000, 24 * 60 * 60 * 1000);
173
+
174
+ // Check duplicate
175
+ if (cache.isDuplicate(messageId)) {
176
+ console.log('Skipping duplicate message');
177
+ return;
178
+ }
179
+
180
+ // Filter batch
181
+ const uniqueMessages = cache.filterDuplicates(messages);
182
+ ```
183
+
184
+ ---
185
+
186
+ ### 7. Group Events Missing
187
+
188
+ **Masalah:** Group participant events (join/leave) kadang tidak fired, atau fired multiple times rapidly.
189
+
190
+ **Solusi:** `GroupEventCoalescer` - merge rapid events dalam window 100ms.
191
+
192
+ ```typescript
193
+ import { GroupEventCoalescer } from 'waliwa';
194
+
195
+ const coalescer = new GroupEventCoalescer(
196
+ (events) => {
197
+ // Receive coalesced events
198
+ for (const event of events) {
199
+ console.log(`Group ${event.id}: ${event.action} ${event.participants.length} users`);
200
+ }
201
+ },
202
+ 100 // Window 100ms
203
+ );
204
+
205
+ // Add events
206
+ coalescer.addEvent({
207
+ id: 'group@g.us',
208
+ participants: ['user1@s.whatsapp.net'],
209
+ action: 'add',
210
+ timestamp: Date.now()
211
+ });
212
+
213
+ // Multiple rapid events akan di-merge
214
+ ```
215
+
216
+ ---
217
+
218
+ ### 8. Media Upload Timeout
219
+
220
+ **Masalah:** Large files (>5MB) sering timeout saat upload, no resume support.
221
+
222
+ **Solusi:** `ChunkedMediaUploader` dengan chunking + resume.
223
+
224
+ ```typescript
225
+ import { ChunkedMediaUploader } from 'waliwa';
226
+
227
+ const uploader = new ChunkedMediaUploader({
228
+ chunkSize: 1024 * 1024, // 1MB chunks
229
+ maxRetries: 3
230
+ });
231
+
232
+ // Upload dengan resume support
233
+ const uploadId = 'upload-123';
234
+ const fileBuffer = await readFile('large-video.mp4'); // 50MB
235
+
236
+ await uploader.uploadChunked(fileBuffer, uploadId, async (chunk, chunkIndex, totalChunks) => {
237
+ console.log(`Uploading chunk ${chunkIndex + 1}/${totalChunks}`);
238
+ // Upload chunk ke WhatsApp CDN
239
+ await uploadChunkToCDN(chunk, chunkIndex);
240
+ });
241
+
242
+ // Jika upload interrupted, resume dari last successful chunk
243
+ const resumePoint = uploader.getResumePoint(uploadId);
244
+ console.log(`Resume from chunk ${resumePoint}`);
245
+ ```
246
+
247
+ ---
248
+
249
+ ### 9. History Sync Incomplete
250
+
251
+ **Masalah:** Initial history sync tidak complete, messages lost saat bot start.
252
+
253
+ **Solusi:** `HistorySyncManager` dengan resume support.
254
+
255
+ ```typescript
256
+ import { HistorySyncManager } from 'waliwa';
257
+
258
+ const syncManager = new HistorySyncManager();
259
+
260
+ // Start sync
261
+ syncManager.startSync();
262
+
263
+ // Track progress per chat
264
+ syncManager.trackProgress('user1@s.whatsapp.net', 'msg-123', Date.now());
265
+
266
+ // Get resume state untuk specific chat
267
+ const resume = syncManager.getResumeState('user1@s.whatsapp.net');
268
+ if (resume) {
269
+ // Request sync from lastMessageId onwards
270
+ await requestHistorySync('user1@s.whatsapp.net', resume.lastMessageId);
271
+ }
272
+
273
+ // Complete sync
274
+ syncManager.completeSync();
275
+
276
+ // Persist untuk survive restart
277
+ const state = syncManager.serialize();
278
+ await fs.writeFile('./auth/sync-state.json', state);
279
+
280
+ // Restore on next start
281
+ const saved = await fs.readFile('./auth/sync-state.json', 'utf-8');
282
+ syncManager.deserialize(saved);
283
+ ```
284
+
285
+ ---
286
+
287
+ ### 10. Smarter Reconnection Strategy
288
+
289
+ **Masalah:** Baileys pakai exponential backoff yang sama untuk semua scenarios. Flood server, dapat banned.
290
+
291
+ **Solusi:** `SmarterReconnector` dengan phased backoff.
292
+
293
+ ```typescript
294
+ import { SmarterReconnector } from 'waliwa';
295
+
296
+ const reconnector = new SmarterReconnector(
297
+ async () => {
298
+ // Reconnect logic
299
+ await sock.connect();
300
+ },
301
+ { maxAttempts: 20 }
302
+ );
303
+
304
+ // Schedule next reconnect
305
+ reconnector.scheduleNext();
306
+
307
+ // Phases:
308
+ // Phase 1 (attempts 1-3): Fast retry - 1s, 2s, 4s (network blip)
309
+ // Phase 2 (attempts 4-6): Medium - 10s, 20s, 30s (server issues)
310
+ // Phase 3 (attempts 7+): Slow - 60s+ (long-term issues, with jitter)
311
+
312
+ console.log(reconnector.getCurrentPhase()); // 1, 2, or 3
313
+ ```
314
+
315
+ ---
316
+
317
+ ## All-in-One Usage
318
+
319
+ Semua fix aktif secara default di WASocket:
320
+
321
+ ```typescript
322
+ const sock = makeWASocket({
323
+ authState: state,
324
+ printQRInTerminal: true,
325
+ // Semua fix aktif otomatis:
326
+ // - Pre-key auto-regen
327
+ // - Message queue (race condition fix)
328
+ // - Idempotency cache (duplicate fix)
329
+ // - Heartbeat (connection hang fix)
330
+ // - Health monitor
331
+ // - Circuit breaker
332
+ // - Rate limit tracker
333
+ // - Message persistence
334
+ // - Webhook system
335
+ });
336
+
337
+ // Check system stats
338
+ console.log(sock.getSystemStats());
339
+
340
+ // Check health
341
+ console.log(sock.getHealth());
342
+
343
+ // Get SKDM stats
344
+ console.log(sock.getSKDMStats());
345
+ ```
346
+
347
+ ## Comparison: Baileys vs Waliwa
348
+
349
+ | Issue | Baileys | Waliwa |
350
+ |-------|---------|--------|
351
+ | Pre-key exhaustion | Manual regen required | ✅ Auto-regen |
352
+ | Race condition | No built-in queue | ✅ Per-recipient queue |
353
+ | Memory leak | Listeners accumulate | ✅ WeakEventEmitter |
354
+ | Connection hang | No detection | ✅ Heartbeat + dead detection |
355
+ | Decryption failure | Lost forever | ✅ Retry queue + prefetch |
356
+ | Duplicate messages | Process 2x | ✅ Idempotency cache |
357
+ | Group events | Missing/duplicate | ✅ Event coalescing |
358
+ | Media upload timeout | No resume | ✅ Chunked upload |
359
+ | History sync | Incomplete | ✅ Resume support |
360
+ | Reconnect strategy | Same backoff | ✅ Phased backoff |