whalibmob 3.3.1 → 4.4.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.
package/README.md CHANGED
@@ -1,297 +1,753 @@
1
- # whalibmob
1
+ <div align='center'>whalibmob is a pure JavaScript Node.js library for interacting with the WhatsApp Mobile API.</div>
2
2
 
3
- > Pure JavaScript Node.js WhatsApp client library and CLI. Operates as a real mobile iOS device with full **Signal Protocol** end-to-end encryption, SenderKey group messaging, multi-device fanout, persistent sessions, and automatic reconnection. No native binaries — runs anywhere Node.js runs.
3
+ ##
4
4
 
5
- ---
5
+ > [!CAUTION]
6
+ > Use a dedicated phone number with this library. Connecting with a number that is already active on a real device will cause WhatsApp to log that device out.
6
7
 
7
- > **⚠️ IMPORTANT:** Use a **brand-new phone number** dedicated exclusively to this library. Using an existing WhatsApp account already active on a real phone will cause WhatsApp to revoke the session. Register a fresh number that has never been used with WhatsApp before.
8
+ > [!IMPORTANT]
9
+ > This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or affiliates. "WhatsApp" and related names are registered trademarks of their respective owners. Use at your own discretion.
8
10
 
9
- ---
11
+ - whalibmob does not require a browser, Selenium, or any other external runtime — it communicates directly with WhatsApp using a **TCP socket** and the **Noise Protocol** handshake.
12
+ - The library operates as a real **iOS mobile device**, not as WhatsApp Web. It uses the Mobile API endpoint, which behaves differently from the Web API.
13
+ - Signal Protocol encryption is **fully inlined** in pure JavaScript — no native binaries, no node-gyp, runs anywhere Node.js runs.
10
14
 
11
- ## Requirements
15
+ ## Install
12
16
 
13
- - **Node.js 18** or higher
14
- - A phone number that can receive SMS or voice calls
17
+ ```sh
18
+ npm install whalibmob
19
+ ```
15
20
 
16
- ---
21
+ Install the CLI globally:
17
22
 
18
- ## Global Installation
23
+ ```sh
24
+ npm install -g whalibmob
25
+ ```
19
26
 
20
- Install once, use the `wa` command from anywhere on your system:
27
+ ## Index
28
+
29
+ - [Connecting Account](#connecting-account)
30
+ - [Register a New Number](#register-a-new-number)
31
+ - [Connect](#connect)
32
+ - [Saving & Restoring Sessions](#saving--restoring-sessions)
33
+ - [Handling Events](#handling-events)
34
+ - [Example to Start](#example-to-start)
35
+ - [All Events](#all-events)
36
+ - [Sending Messages](#sending-messages)
37
+ - [Text Message](#text-message)
38
+ - [Quote Message](#quote-message)
39
+ - [Mention User](#mention-user)
40
+ - [Reaction Message](#reaction-message)
41
+ - [Edit Message](#edit-message)
42
+ - [Delete Message](#delete-message)
43
+ - [Forward Message](#forward-message)
44
+ - [Media Messages](#media-messages)
45
+ - [Image Message](#image-message)
46
+ - [Video Message](#video-message)
47
+ - [Audio Message](#audio-message)
48
+ - [Voice Note](#voice-note)
49
+ - [Document Message](#document-message)
50
+ - [Sticker Message](#sticker-message)
51
+ - [Status / Stories](#status--stories)
52
+ - [Send States in Chat](#send-states-in-chat)
53
+ - [Reading Messages](#reading-messages)
54
+ - [Update Presence](#update-presence)
55
+ - [Modifying Chats](#modifying-chats)
56
+ - [Archive / Unarchive a Chat](#archive--unarchive-a-chat)
57
+ - [Mute / Unmute a Chat](#mute--unmute-a-chat)
58
+ - [Mark a Chat Read / Unread](#mark-a-chat-read--unread)
59
+ - [Pin / Unpin a Chat](#pin--unpin-a-chat)
60
+ - [Star / Unstar a Message](#star--unstar-a-message)
61
+ - [Disappearing Messages](#disappearing-messages)
62
+ - [User Queries](#user-queries)
63
+ - [Check If a Number Has WhatsApp](#check-if-a-number-has-whatsapp)
64
+ - [Fetch Profile About](#fetch-profile-about)
65
+ - [Fetch Profile Picture](#fetch-profile-picture)
66
+ - [Subscribe to Presence](#subscribe-to-presence)
67
+ - [Change Profile](#change-profile)
68
+ - [Change Display Name](#change-display-name)
69
+ - [Change About Text](#change-about-text)
70
+ - [Change Profile Picture](#change-profile-picture)
71
+ - [Privacy](#privacy)
72
+ - [Block / Unblock User](#block--unblock-user)
73
+ - [Get Block List](#get-block-list)
74
+ - [Update Privacy Settings](#update-privacy-settings)
75
+ - [Update Default Disappearing Mode](#update-default-disappearing-mode)
76
+ - [Groups](#groups)
77
+ - [Create a Group](#create-a-group)
78
+ - [Add / Remove or Demote / Promote](#add--remove-or-demote--promote)
79
+ - [Change Subject](#change-subject)
80
+ - [Change Description](#change-description)
81
+ - [Change Settings](#change-settings)
82
+ - [Leave a Group](#leave-a-group)
83
+ - [Get Invite Code](#get-invite-code)
84
+ - [Revoke Invite Code](#revoke-invite-code)
85
+ - [Join Using Invitation Code](#join-using-invitation-code)
86
+ - [Query Metadata](#query-metadata)
87
+ - [Get Request Join List](#get-request-join-list)
88
+ - [Approve / Reject Request Join](#approve--reject-request-join)
89
+ - [Toggle Ephemeral in Group](#toggle-ephemeral-in-group)
90
+ - [CLI Reference](#cli-reference)
91
+ - [Interactive Shell](#interactive-shell)
92
+ - [WhatsApp IDs](#whatsapp-ids)
93
+ - [Transport](#transport)
94
+ - [Media Encryption](#media-encryption)
95
+
96
+ ## Connecting Account
97
+
98
+ ### Register a New Number
99
+
100
+ Registration is a one-time process. You need a phone number that can receive an SMS or voice call.
101
+
102
+ **Step 1 — request a verification code**
21
103
 
22
- ```bash
23
- npm install -g whalibmob
104
+ ```js
105
+ const {
106
+ createNewStore, saveStore, requestSmsCode
107
+ } = require('whalibmob')
108
+ const path = require('path')
109
+ const fs = require('fs')
110
+
111
+ const phone = '919634847671' // country code + number, no '+'
112
+ const sessDir = path.join(process.env.HOME, '.waSession')
113
+ const sessFile = path.join(sessDir, phone + '.json')
114
+
115
+ fs.mkdirSync(sessDir, { recursive: true })
116
+
117
+ const store = createNewStore(phone)
118
+ saveStore(store, sessFile)
119
+
120
+ await requestSmsCode(store, 'sms') // 'sms' | 'voice' | 'wa_old'
24
121
  ```
25
122
 
26
- Verify it works:
123
+ **Step 2 — verify the code**
27
124
 
28
- ```bash
29
- wa version
125
+ ```js
126
+ const { loadStore, saveStore, verifyCode } = require('whalibmob')
127
+
128
+ const store = loadStore(sessFile)
129
+ const result = await verifyCode(store, '123456')
130
+
131
+ if (result.status === 'ok') {
132
+ saveStore(result.store, sessFile)
133
+ console.log('registered')
134
+ }
30
135
  ```
31
136
 
32
- ---
137
+ ### Connect
33
138
 
34
- ## Quick Start
139
+ ```js
140
+ const { WhalibmobClient } = require('whalibmob')
141
+ const path = require('path')
142
+
143
+ const client = new WhalibmobClient({
144
+ sessionDir: path.join(process.env.HOME, '.waSession')
145
+ })
35
146
 
36
- ### 1 Check if a number has WhatsApp
147
+ client.on('connected', () => {
148
+ console.log('connected')
149
+ })
37
150
 
38
- ```bash
39
- wa registration --check 919634847671
151
+ await client.init('919634847671')
40
152
  ```
41
153
 
42
- ### 2 Request a verification code
154
+ ## Saving & Restoring Sessions
155
+
156
+ Sessions are automatically persisted to disk as JSON files under the `sessionDir` you provide. The file is named `<phone>.json`. On the next `client.init()` call the session is restored and no re-registration is needed.
157
+
158
+ ```js
159
+ const client = new WhalibmobClient({
160
+ sessionDir: path.join(process.env.HOME, '.waSession')
161
+ })
162
+
163
+ // no need to register again — just connect
164
+ await client.init('919634847671')
165
+ ```
166
+
167
+ > [!NOTE]
168
+ > Each phone number uses its own session file. The library handles Signal Protocol key persistence automatically.
169
+
170
+ ## Handling Events
171
+
172
+ whalibmob uses the EventEmitter syntax for events.
173
+
174
+ ### Example to Start
175
+
176
+ ```js
177
+ const { WhalibmobClient } = require('whalibmob')
178
+ const path = require('path')
179
+
180
+ async function connect() {
181
+ const client = new WhalibmobClient({
182
+ sessionDir: path.join(process.env.HOME, '.waSession')
183
+ })
184
+
185
+ client.on('connected', async () => {
186
+ console.log('connected')
187
+ await client.sendText('919634847671@s.whatsapp.net', 'Hello!')
188
+ })
189
+
190
+ client.on('disconnected', () => {
191
+ console.log('disconnected — reconnecting...')
192
+ setTimeout(() => connect(), 3000)
193
+ })
194
+
195
+ client.on('message', msg => {
196
+ console.log('message from', msg.from, msg.text)
197
+ })
43
198
 
44
- ```bash
45
- # Via SMS (default)
46
- wa registration --request-code 919634847671
199
+ client.on('auth_failure', ({ reason }) => {
200
+ console.error('session revoked:', reason)
201
+ // re-register the number
202
+ })
47
203
 
48
- # Via voice call
49
- wa registration --request-code 919634847671 --method voice
204
+ await client.init('919634847671')
205
+ }
50
206
 
51
- # Via an old WhatsApp account
52
- wa registration --request-code 919634847671 --method wa_old
207
+ connect()
53
208
  ```
54
209
 
55
- ### 3 — Register with the code you received
210
+ ### All Events
211
+
212
+ | Event | Payload | Description |
213
+ |---|---|---|
214
+ | `connected` | — | Session authenticated and ready |
215
+ | `disconnected` | — | Connection closed |
216
+ | `reconnecting` | `{ attempt, delay }` | Lost connection, will retry |
217
+ | `reconnected` | — | Connection restored |
218
+ | `auth_failure` | `{ reason }` | Session revoked or banned |
219
+ | `message` | message object | Incoming message received |
220
+ | `receipt` | `{ type, id, from }` | Delivery / read / played receipt |
221
+ | `presence` | `{ from, available, lastSeen }` | Contact came online or went offline |
222
+ | `notification` | node object | Group or contact update notification |
223
+ | `call` | `{ from }` | Incoming call event |
224
+ | `error` | Error | Unhandled transport error |
225
+
226
+ The message object contains:
56
227
 
57
- ```bash
58
- wa registration --register 919634847671 --code 123456
228
+ ```js
229
+ {
230
+ id: string, // message ID
231
+ from: string, // sender JID
232
+ participant: string, // group sender JID (groups only)
233
+ ts: number, // Unix timestamp
234
+ text: string, // text body (plain text messages)
235
+ plaintext: Buffer, // decrypted raw payload
236
+ mediaType: string // 'image' | 'video' | 'audio' | 'document' | 'sticker'
237
+ }
59
238
  ```
60
239
 
61
- ### 4 — Connect
240
+ ## Sending Messages
241
+
242
+ ### Text Message
62
243
 
63
- ```bash
64
- wa connect 919634847671
244
+ ```js
245
+ await client.sendText('919634847671@s.whatsapp.net', 'Hello!')
65
246
  ```
66
247
 
67
- You will enter an interactive shell:
248
+ ### Quote Message
68
249
 
250
+ ```js
251
+ // pass { quotedMsgId, quotedParticipant } in options
252
+ await client.sendText(
253
+ '919634847671@s.whatsapp.net',
254
+ 'This is a reply',
255
+ { quotedMsgId: 'ABCDEF123456', quotedParticipant: '919634847671@s.whatsapp.net' }
256
+ )
69
257
  ```
70
- wa> /send 911234567890@s.whatsapp.net Hello!
71
- wa> /presence
72
- wa> /presence away
73
- wa> /quit
258
+
259
+ ### Mention User
260
+
261
+ ```js
262
+ await client.sendText(
263
+ '120363000000000000@g.us',
264
+ '@919634847671 hello!',
265
+ { mentions: ['919634847671@s.whatsapp.net'] }
266
+ )
74
267
  ```
75
268
 
76
- ---
269
+ ### Reaction Message
77
270
 
78
- ## CLI Reference
271
+ ```js
272
+ // react to a message
273
+ await client.sendReaction('919634847671@s.whatsapp.net', 'MSGID123', '👍')
79
274
 
80
- ### Registration
275
+ // remove a reaction — pass empty string
276
+ await client.sendReaction('919634847671@s.whatsapp.net', 'MSGID123', '')
277
+ ```
81
278
 
82
- | Command | Description |
83
- |---|---|
84
- | `wa registration --check <phone>` | Check if a number has WhatsApp |
85
- | `wa registration --request-code <phone>` | Request SMS verification code |
86
- | `wa registration --request-code <phone> --method voice` | Request code via voice call |
87
- | `wa registration --request-code <phone> --method wa_old` | Request code via old WA account |
88
- | `wa registration --register <phone> --code <code>` | Complete registration |
279
+ ### Edit Message
89
280
 
90
- ### Connection
281
+ > [!NOTE]
282
+ > Editing is only possible within 15 minutes of the original send.
91
283
 
92
- | Command | Description |
93
- |---|---|
94
- | `wa connect <phone>` | Connect and open interactive shell |
95
- | `wa listen <phone>` | Connect and print all incoming messages |
284
+ ```js
285
+ await client.editMessage(
286
+ 'MSGID123', // original message ID
287
+ '919634847671@s.whatsapp.net',
288
+ 'Corrected text here'
289
+ )
290
+ ```
291
+
292
+ ### Delete Message
293
+
294
+ ```js
295
+ // delete for yourself only
296
+ await client.deleteMessage('MSGID123', '919634847671@s.whatsapp.net', true, false)
297
+
298
+ // delete for everyone (revoke)
299
+ await client.deleteMessage('MSGID123', '919634847671@s.whatsapp.net', true, true)
300
+ ```
301
+
302
+ ### Forward Message
303
+
304
+ ```js
305
+ await client.forwardMessage('919634847671@s.whatsapp.net', 'text to forward')
306
+ ```
307
+
308
+ ## Media Messages
309
+
310
+ ### Image Message
311
+
312
+ ```js
313
+ // from file path
314
+ await client.sendImage('919634847671@s.whatsapp.net', './photo.jpg', { caption: 'Look at this' })
315
+
316
+ // from Buffer
317
+ await client.sendImage('919634847671@s.whatsapp.net', buffer, {
318
+ caption: 'Photo',
319
+ mimetype: 'image/jpeg'
320
+ })
321
+ ```
322
+
323
+ ### Video Message
324
+
325
+ ```js
326
+ await client.sendVideo('919634847671@s.whatsapp.net', './clip.mp4', { caption: 'Watch this' })
327
+ ```
328
+
329
+ ### Audio Message
330
+
331
+ ```js
332
+ await client.sendAudio('919634847671@s.whatsapp.net', './song.mp3')
333
+ ```
334
+
335
+ ### Voice Note
336
+
337
+ ```js
338
+ // ptt: true renders the audio as a push-to-talk voice note with waveform
339
+ await client.sendAudio('919634847671@s.whatsapp.net', './voice.ogg', { ptt: true })
340
+ ```
341
+
342
+ ### Document Message
343
+
344
+ ```js
345
+ await client.sendDocument('919634847671@s.whatsapp.net', './report.pdf', {
346
+ fileName: 'Q1 Report.pdf'
347
+ })
348
+ ```
349
+
350
+ ### Sticker Message
96
351
 
97
- ### Sending Messages
352
+ ```js
353
+ await client.sendSticker('919634847671@s.whatsapp.net', './sticker.webp')
354
+ ```
98
355
 
99
- ```bash
100
- # Text message
101
- wa send <phone> --to <jid> --text "Hello!"
356
+ ## Status / Stories
357
+
358
+ ```js
359
+ // post a text Status to status@broadcast
360
+ await client.sendStatus('Good morning!')
361
+ ```
102
362
 
103
- # Image (with optional caption)
104
- wa send <phone> --to <jid> --image ./photo.jpg --caption "Check this out"
363
+ ## Send States in Chat
105
364
 
106
- # Video (with optional caption)
107
- wa send <phone> --to <jid> --video ./clip.mp4 --caption "Watch this"
365
+ ### Reading Messages
108
366
 
109
- # Voice note (push-to-talk)
110
- wa send <phone> --to <jid> --ptt ./voice.ogg
367
+ ```js
368
+ // mark the last message in a chat as read
369
+ client.markChatRead('919634847671@s.whatsapp.net')
370
+ ```
111
371
 
112
- # Audio file
113
- wa send <phone> --to <jid> --audio ./song.mp3
372
+ ### Update Presence
114
373
 
115
- # Document
116
- wa send <phone> --to <jid> --document ./report.pdf
374
+ ```js
375
+ // set yourself as online / offline globally
376
+ client.setOnline(true)
377
+ client.setOnline(false)
378
+
379
+ // show typing or recording in a specific chat
380
+ client.setChatPresence('919634847671@s.whatsapp.net', 'composing') // typing
381
+ client.setChatPresence('919634847671@s.whatsapp.net', 'recording') // recording audio
382
+ client.setChatPresence('919634847671@s.whatsapp.net', 'paused') // stopped
383
+ ```
117
384
 
118
- # Sticker
119
- wa send <phone> --to <jid> --sticker ./sticker.webp
385
+ ## Modifying Chats
120
386
 
121
- # Emoji reaction
122
- wa send <phone> --to <jid> --reaction 👍 --msg-id 3EB0ABCDEF123456
387
+ ### Archive / Unarchive a Chat
123
388
 
124
- # Group message
125
- wa send <phone> --to 120363000000000000@g.us --text "Hi everyone!"
389
+ ```js
390
+ client.archiveChat('919634847671@s.whatsapp.net')
391
+ client.unarchiveChat('919634847671@s.whatsapp.net')
126
392
  ```
127
393
 
128
- ### JID Format
394
+ ### Mute / Unmute a Chat
395
+
396
+ ```js
397
+ client.muteChat('919634847671@s.whatsapp.net', 8 * 60 * 60 * 1000) // mute for 8 hours (ms)
398
+ client.muteChat('919634847671@s.whatsapp.net', 0) // mute indefinitely
399
+ client.unmuteChat('919634847671@s.whatsapp.net')
400
+ ```
401
+
402
+ ### Mark a Chat Read / Unread
403
+
404
+ ```js
405
+ client.markChatRead('919634847671@s.whatsapp.net')
406
+ client.markChatUnread('919634847671@s.whatsapp.net')
407
+ ```
408
+
409
+ ### Pin / Unpin a Chat
410
+
411
+ ```js
412
+ client.pinChat('919634847671@s.whatsapp.net')
413
+ client.unpinChat('919634847671@s.whatsapp.net')
414
+ ```
415
+
416
+ ### Star / Unstar a Message
417
+
418
+ ```js
419
+ client.starMessage('MSGID123', '919634847671@s.whatsapp.net')
420
+ client.unstarMessage('MSGID123', '919634847671@s.whatsapp.net')
421
+ ```
129
422
 
130
- | Target | JID |
423
+ ### Disappearing Messages
424
+
425
+ | Duration | Seconds |
131
426
  |---|---|
132
- | Individual | `919634847671@s.whatsapp.net` |
133
- | Group | `120363000000000000@g.us` |
427
+ | Off | 0 |
428
+ | 24 hours | 86 400 |
429
+ | 7 days | 604 800 |
430
+ | 90 days | 7 776 000 |
134
431
 
135
- > Phone numbers must include the country code, without the `+` prefix.
432
+ ```js
433
+ // set disappearing timer for a specific chat (DM or group)
434
+ await client.changeEphemeralTimer('919634847671@s.whatsapp.net', 86400)
435
+ await client.changeEphemeralTimer('120363000000000000@g.us', 604800)
136
436
 
137
- ### All Options
437
+ // remove disappearing messages
438
+ await client.changeEphemeralTimer('919634847671@s.whatsapp.net', 0)
439
+ ```
138
440
 
139
- | Flag | Default | Description |
140
- |---|---|---|
141
- | `--session <dir>` | `~/.waSession` | Directory where session files are stored |
142
- | `--method` | `sms` | Verification method: `sms`, `voice`, or `wa_old` |
143
- | `--code` | — | Verification code received via SMS/voice |
144
- | `--to` | — | Recipient JID |
145
- | `--text` | — | Text message body |
146
- | `--caption` | — | Caption for image or video |
147
- | `--reaction` | — | Emoji to react with |
148
- | `--msg-id` | — | Message ID to react to (required with `--reaction`) |
441
+ ## User Queries
149
442
 
150
- ---
443
+ ### Check If a Number Has WhatsApp
151
444
 
152
- ## Sessions
445
+ ```js
446
+ const { checkNumberStatus } = require('whalibmob')
153
447
 
154
- Sessions are stored as JSON files in `~/.waSession/` by default.
155
- Each phone number gets its own file: `~/.waSession/<phone>.json`.
448
+ const result = await checkNumberStatus('919634847671')
449
+ // result.status: 'registered' | 'registered_blocked' | 'not_registered' | 'cooldown' | 'unknown'
450
+ console.log(result.status)
451
+ ```
156
452
 
157
- You only register once. After that, just connect:
453
+ Check multiple numbers at once while connected:
158
454
 
159
- ```bash
160
- wa connect 919634847671
455
+ ```js
456
+ const results = await client.hasWhatsapp(['919634847671', '12345678901'])
457
+ // returns array of JIDs that have WhatsApp
161
458
  ```
162
459
 
163
- To use a custom session directory:
460
+ ### Fetch Profile About
164
461
 
165
- ```bash
166
- wa connect 919634847671 --session /data/my-sessions
167
- wa send 919634847671 --session /data/my-sessions --to 911234567890@s.whatsapp.net --text "Hi"
462
+ ```js
463
+ const about = await client.queryAbout('919634847671@s.whatsapp.net')
464
+ console.log(about)
168
465
  ```
169
466
 
170
- ---
467
+ ### Fetch Profile Picture
468
+
469
+ ```js
470
+ const url = await client.queryPicture('919634847671@s.whatsapp.net')
471
+ // also works for groups
472
+ const groupUrl = await client.queryPicture('120363000000000000@g.us')
473
+ ```
171
474
 
172
- ## Library API
475
+ ### Subscribe to Presence
173
476
 
174
477
  ```js
175
- const {
176
- WhalibmobClient,
177
- loadStore,
178
- checkNumberStatus,
179
- makeJid,
180
- generateMessageId
181
- } = require('whalibmob');
478
+ // triggers 'presence' events when the contact comes online or goes offline
479
+ client.subscribeToPresence('919634847671@s.whatsapp.net')
480
+
481
+ client.on('presence', ({ from, available, lastSeen }) => {
482
+ console.log(from, available ? 'online' : 'offline')
483
+ })
182
484
  ```
183
485
 
184
- ### Connect and send a message
486
+ ## Change Profile
487
+
488
+ ### Change Display Name
185
489
 
186
490
  ```js
187
- const { WhalibmobClient, loadStore } = require('whalibmob');
188
- const path = require('path');
491
+ client.changeName('My Bot')
492
+ ```
189
493
 
190
- const sessionDir = path.join(process.env.HOME, '.waSession');
191
- const store = loadStore('919634847671', sessionDir);
494
+ ### Change About Text
192
495
 
193
- const client = new WhalibmobClient(store, { sessionDir });
496
+ ```js
497
+ await client.changeAbout('Available 24/7')
498
+ ```
194
499
 
195
- client.on('connected', async () => {
196
- await client.sendText('911234567890@s.whatsapp.net', 'Hello from whalibmob!');
197
- });
500
+ ### Change Profile Picture
198
501
 
199
- client.on('message', msg => {
200
- console.log('Received:', msg);
201
- });
502
+ ```js
503
+ // groups are also supported
504
+ await client.changeProfilePicture('./avatar.jpg')
505
+ await client.changeGroupPicture('120363000000000000@g.us', './group.jpg')
506
+ ```
507
+
508
+ ## Privacy
202
509
 
203
- client.on('disconnected', ({ reason }) => {
204
- console.log('Disconnected:', reason);
205
- });
510
+ ### Block / Unblock User
206
511
 
207
- await client.connect();
512
+ ```js
513
+ await client.blockContact('919634847671@s.whatsapp.net')
514
+ await client.unblockContact('919634847671@s.whatsapp.net')
208
515
  ```
209
516
 
210
- ### Send media
517
+ ### Get Block List
211
518
 
212
519
  ```js
213
- await client.sendImage ('911234567890@s.whatsapp.net', './photo.jpg', 'Caption');
214
- await client.sendVideo ('911234567890@s.whatsapp.net', './clip.mp4', 'Caption');
215
- await client.sendPtt ('911234567890@s.whatsapp.net', './voice.ogg');
216
- await client.sendAudio ('911234567890@s.whatsapp.net', './song.mp3');
217
- await client.sendDocument('911234567890@s.whatsapp.net', './report.pdf');
218
- await client.sendSticker ('911234567890@s.whatsapp.net', './sticker.webp');
520
+ const list = await client.queryBlockList()
521
+ console.log(list) // [ '919634847671@s.whatsapp.net', ... ]
219
522
  ```
220
523
 
221
- ### Check a number
524
+ ### Update Privacy Settings
222
525
 
223
526
  ```js
224
- const { checkNumberStatus } = require('whalibmob');
527
+ // type: 'last_seen' | 'profile_picture' | 'status' | 'online' | 'read_receipts' | 'groups_add'
528
+ // value: 'all' | 'contacts' | 'contact_blacklist' | 'none' | 'match_last_seen'
529
+
530
+ await client.changePrivacySetting('last_seen', 'contacts')
531
+ await client.changePrivacySetting('profile_picture', 'contacts')
532
+ await client.changePrivacySetting('status', 'contacts')
533
+ await client.changePrivacySetting('online', 'match_last_seen')
534
+ await client.changePrivacySetting('read_receipts', 'none')
535
+ await client.changePrivacySetting('groups_add', 'contacts')
536
+ ```
537
+
538
+ ### Update Default Disappearing Mode
225
539
 
226
- const result = await checkNumberStatus('919634847671');
227
- // result.status 'registered' | 'registered_blocked' | 'not_registered' | 'cooldown' | 'unknown'
228
- console.log(result.status);
540
+ ```js
541
+ // sets the default ephemeral timer for all new chats
542
+ await client.changeNewChatsEphemeralTimer(86400) // 1 day
543
+ await client.changeNewChatsEphemeralTimer(0) // off
229
544
  ```
230
545
 
231
- ### Events
546
+ ## Groups
232
547
 
233
- | Event | Payload | Description |
234
- |---|---|---|
235
- | `connected` | — | Session authenticated and ready |
236
- | `disconnected` | `{ reason }` | Connection closed |
237
- | `auth_failure` | `{ reason }` | Auth failed (banned or session revoked) |
238
- | `message` | message object | Incoming message received |
239
- | `message.sent` | message object | Outgoing message confirmed by server |
240
- | `error` | Error | Unhandled transport error |
548
+ ### Create a Group
241
549
 
242
- ---
550
+ ```js
551
+ const group = await client.createGroup('My Group', [
552
+ '919634847671@s.whatsapp.net',
553
+ '12345678901@s.whatsapp.net'
554
+ ])
555
+ console.log('created group', group)
556
+ ```
243
557
 
244
- ## Features
558
+ ### Add / Remove or Demote / Promote
245
559
 
246
- - **Mobile iOS fingerprint** — authentic iOS headers; WhatsApp servers treat it as an iPhone
247
- - **Signal Protocol E2E encryption** — X3DH key agreement, Double Ratchet for 1-to-1 messages, fully inlined (no native binaries, no GitHub dependencies)
248
- - **SenderKey group encryption** — efficient group messaging with chain-key advance and SKDM distribution
249
- - **Multi-device fanout** — messages delivered to every linked device of each recipient
250
- - **All media types** — images, video, audio, voice notes, documents, stickers
251
- - **Media encryption** — AES-256-CBC + HKDF-SHA256; files uploaded to WhatsApp CDN
252
- - **Emoji reactions** — react to any message by its ID
253
- - **Automatic reconnection** — exponential backoff (1 s → 2 → 4 → 8 → 15 → 30 s cap)
254
- - **Pre-key replenishment** — automatic upload when supply drops below threshold
255
- - **Persistent sessions** — JSON files on disk; no re-registration after restart
256
- - **Zero native dependencies** — pure JavaScript; works on Linux, macOS, Windows, Termux (Android)
560
+ ```js
561
+ const groupJid = '120363000000000000@g.us'
257
562
 
258
- ---
563
+ await client.addGroupParticipants(groupJid, ['919634847671@s.whatsapp.net'])
564
+ await client.removeGroupParticipants(groupJid, ['919634847671@s.whatsapp.net'])
565
+ await client.promoteGroupParticipants(groupJid, ['919634847671@s.whatsapp.net'])
566
+ await client.demoteGroupParticipants(groupJid, ['919634847671@s.whatsapp.net'])
567
+ ```
259
568
 
260
- ## Reconnection Backoff
569
+ ### Change Subject
261
570
 
262
- | Attempt | Delay |
263
- |---|---|
264
- | 1 | 1 s |
265
- | 2 | 2 s |
266
- | 3 | 4 s |
267
- | 4 | 8 s |
268
- | 5 | 15 s |
269
- | 6+ | 30 s |
571
+ ```js
572
+ await client.changeGroupSubject('120363000000000000@g.us', 'New Group Name')
573
+ ```
270
574
 
271
- ---
575
+ ### Change Description
272
576
 
273
- ## Media Encryption Scheme
577
+ ```js
578
+ await client.changeGroupDescription('120363000000000000@g.us', 'This is the group description')
579
+ ```
274
580
 
275
- 1. A random 32-byte media key is generated.
276
- 2. HKDF-SHA256 expands it into an IV, cipher key, and MAC key.
277
- 3. The file is encrypted with AES-256-CBC.
278
- 4. A 10-byte HMAC-SHA256 MAC is appended.
279
- 5. The ciphertext is uploaded to WhatsApp CDN.
280
- 6. The media key and CDN URL are embedded in the message envelope.
581
+ ### Change Settings
281
582
 
282
- ---
583
+ ```js
584
+ // setting: 'edit_group_info' | 'send_messages' | 'add_participants' | 'approve_participants'
585
+ // policy: 'admins' | 'all'
586
+
587
+ await client.changeGroupSetting('120363000000000000@g.us', 'send_messages', 'admins')
588
+ await client.changeGroupSetting('120363000000000000@g.us', 'edit_group_info', 'admins')
589
+ await client.changeGroupSetting('120363000000000000@g.us', 'add_participants', 'all')
590
+ ```
591
+
592
+ ### Leave a Group
593
+
594
+ ```js
595
+ await client.leaveGroup('120363000000000000@g.us')
596
+ ```
597
+
598
+ ### Get Invite Code
599
+
600
+ ```js
601
+ const link = await client.queryGroupInviteLink('120363000000000000@g.us')
602
+ // e.g. 'https://chat.whatsapp.com/AbCdEfGhIjK'
603
+ console.log(link)
604
+ ```
605
+
606
+ ### Revoke Invite Code
607
+
608
+ ```js
609
+ await client.revokeGroupInvite('120363000000000000@g.us')
610
+ ```
611
+
612
+ ### Join Using Invitation Code
613
+
614
+ > [!NOTE]
615
+ > Pass only the code portion — do not include `https://chat.whatsapp.com/`
616
+
617
+ ```js
618
+ const jid = await client.acceptGroupInvite('AbCdEfGhIjK')
619
+ console.log('joined', jid)
620
+ ```
621
+
622
+ ### Query Metadata
623
+
624
+ ```js
625
+ const meta = await client.getGroupMetadata('120363000000000000@g.us')
626
+ console.log(meta)
627
+ ```
628
+
629
+ ### Get Request Join List
630
+
631
+ ```js
632
+ const pending = await client.queryGroupPendingParticipants('120363000000000000@g.us')
633
+ console.log(pending)
634
+ ```
635
+
636
+ ### Approve / Reject Request Join
637
+
638
+ ```js
639
+ await client.approveGroupParticipants('120363000000000000@g.us', [
640
+ '919634847671@s.whatsapp.net'
641
+ ])
642
+ ```
643
+
644
+ ### Toggle Ephemeral in Group
645
+
646
+ ```js
647
+ await client.changeEphemeralTimer('120363000000000000@g.us', 86400) // 1 day
648
+ await client.changeEphemeralTimer('120363000000000000@g.us', 0) // off
649
+ ```
650
+
651
+ ## CLI Reference
652
+
653
+ ```sh
654
+ wa open interactive shell
655
+ wa connect <phone> connect and open interactive shell
656
+ wa listen <phone> connect and listen for messages (stay-alive)
657
+ wa registration --request-code <phone> request SMS verification code
658
+ wa registration --request-code <phone> --method voice
659
+ wa registration --request-code <phone> --method wa_old
660
+ wa registration --register <phone> --code <code>
661
+ wa registration --check <phone>
662
+ wa version
663
+
664
+ options:
665
+ --session <dir> session directory (default: ~/.waSession)
666
+ --method sms | voice | wa_old (default: sms)
667
+ ```
668
+
669
+ > [!TIP]
670
+ > **The CLI shell never exits on its own.** It stays open after every command until you type `/quit` or press Ctrl+C. This includes after requesting or confirming a registration code.
671
+
672
+ ### Interactive Shell
673
+
674
+ After connecting with `wa connect <phone>` a persistent prompt appears. All features of the library are available as commands:
675
+
676
+ ```
677
+ /send <jid> <text> send text message
678
+ /image <jid> <file> [caption] send image
679
+ /video <jid> <file> [caption] send video
680
+ /audio <jid> <file> send audio file
681
+ /ptt <jid> <file> send voice note
682
+ /doc <jid> <file> [name] send document
683
+ /sticker <jid> <file> send sticker
684
+ /react <jid> <msgId> <emoji> react to message
685
+ /edit <jid> <msgId> <text> edit a sent message
686
+ /delete <jid> <msgId> [all] delete (add 'all' for everyone)
687
+ /status <text> post Status/Story
688
+ /online /offline set presence
689
+ /typing /recording /stop <jid> typing indicators
690
+ /read /unread <jid> mark chat
691
+ /mute /unmute <jid> mute / unmute
692
+ /pin /unpin <jid> pin / unpin
693
+ /archive /unarchive <jid> archive / unarchive
694
+ /star /unstar <jid> <msgId> star / unstar message
695
+ /ephemeral <jid> <seconds> set disappearing timer
696
+ /block /unblock <jid> block / unblock
697
+ /blocklist show blocked contacts
698
+ /group create|leave|add|remove
699
+ |promote|demote|subject|desc
700
+ |invite|revoke|join|meta|settings ...
701
+ /reg check|code|confirm ... registration commands
702
+ /privacy <type> <value> change privacy setting
703
+ /name <text> /about <text> update profile
704
+ /session show session info
705
+ /reconnect force reconnect
706
+ /help show all commands
707
+ /quit disconnect and exit
708
+ ```
709
+
710
+ ## WhatsApp IDs
711
+
712
+ - Individual contacts: `[countrycode][number]@s.whatsapp.net`
713
+ - Example: `919634847671@s.whatsapp.net`
714
+ - Groups: `[groupid]@g.us`
715
+ - Example: `120363000000000000@g.us`
716
+ - Status broadcast: `status@broadcast`
717
+ - Broadcast lists: `[timestamp]@broadcast`
718
+
719
+ > [!NOTE]
720
+ > Phone numbers must include the country code without the `+` prefix.
283
721
 
284
722
  ## Transport
285
723
 
286
- Uses **Noise_XX_25519_AESGCM_SHA256** over TCP to `g.whatsapp.net:443`:
724
+ whalibmob uses **Noise_XX_25519_AESGCM_SHA256** over TCP to `g.whatsapp.net:443`:
287
725
 
288
726
  1. Client sends `ClientHello` with an ephemeral X25519 public key.
289
727
  2. Server replies `ServerHello` (ephemeral + encrypted static + payload).
290
728
  3. Three DH steps (EE, SE, SS) derive the final session keys.
291
729
  4. Client sends `ClientFinish` (encrypted static + encrypted payload).
292
- 5. Library waits for server `<success>` before emitting `connected`, or `<failure>` for `auth_failure`.
730
+ 5. The library waits for a `<success>` stanza before emitting `connected`, or `<failure>` for `auth_failure`.
731
+
732
+ Automatic reconnection uses exponential backoff:
733
+
734
+ | Attempt | Delay |
735
+ |---|---|
736
+ | 1 | 1 s |
737
+ | 2 | 2 s |
738
+ | 3 | 4 s |
739
+ | 4 | 8 s |
740
+ | 5 | 15 s |
741
+ | 6+ | 30 s |
742
+
743
+ ## Media Encryption
293
744
 
294
- ---
745
+ 1. A random 32-byte **media key** is generated.
746
+ 2. HKDF-SHA256 expands it into IV, cipher key, and MAC key.
747
+ 3. The file is encrypted with **AES-256-CBC**.
748
+ 4. A 10-byte **HMAC-SHA256** MAC is appended.
749
+ 5. The ciphertext is uploaded to the WhatsApp CDN.
750
+ 6. The media key and CDN URL are embedded in the encrypted message envelope sent to the recipient.
295
751
 
296
752
  ## License
297
753