@n4tzz/n4lyx 2.7.8 → 2.7.10

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,776 +1,1295 @@
1
- # n4lyx
1
+ # <div align='center'>Wileys</div>
2
2
 
3
- > WhatsApp Web API — multi-device, TypeScript-first, built different.
3
+ <div align='center'>
4
4
 
5
- [![npm](https://img.shields.io/npm/v/@n4tzz/n4lyx?color=black&labelColor=000)](https://npmjs.com/package/@n4tzz/n4lyx)
6
- [![license](https://img.shields.io/badge/license-MIT-black?labelColor=000)](LICENSE)
7
- [![downloads](https://img.shields.io/npm/dm/@n4tzz/n4lyx?color=black&labelColor=000)](https://npmjs.com/package/@n4tzz/n4lyx)
8
- [![node](https://img.shields.io/badge/node-%3E%3D20-black?labelColor=000)](package.json)
5
+ [![npm version](https://img.shields.io/npm/v/wileys.svg)](https://www.npmjs.com/package/wileys)
6
+ [![License](https://img.shields.io/badge/license-GPL%203-blue.svg)](LICENSE)
7
+ [![Downloads](https://img.shields.io/npm/dm/wileys.svg)](https://www.npmjs.com/package/wileys)
9
8
 
10
- ---
9
+ </div>
10
+
11
+ ## 💝 Donasi
11
12
 
12
- **n4lyx** is a WhatsApp Web API library built for real projects. Proper `@lid → @pn` resolution, full multi-device support, clean TypeScript API. Fast, minimal, no bloat. Ships with exclusive features like tag-all and group status v2 that upstream doesn't have.
13
+ Dukung pengembangan proyek ini:
13
14
 
14
- > Not affiliated with WhatsApp Inc. Don't spam. Don't abuse. You're responsible for how you use this.
15
+ **Salin and paste di browser :**
16
+ ```
17
+ https://cdn.yupra.my.id/yp/eocz6gnv.html
18
+ ```
15
19
 
16
20
  ---
17
21
 
18
- ## Install
22
+ ## ✨ Fitur Utama
23
+
24
+ - 🚀 **Modern & Cepat** - Dibangun dengan TypeScript dan teknologi terbaru
25
+ - 🔧 **Perbaikan @lid & @jid** - Mengatasi masalah @lid ke @pn di grup WhatsApp
26
+ - 📱 **Dukungan Multi-Device** - Mendukung koneksi multi-device WhatsApp
27
+ - 🔐 **Enkripsi End-to-End** - Komunikasi terenkripsi penuh
28
+ - 📨 **Semua Jenis Pesan** - Dukung teks, media, polling, dll.
29
+
30
+ ## ⚠️ Peringatan
31
+
32
+ Proyek ini tidak berafiliasi, terkait, diotorisasi, didukung, atau terhubung secara resmi dengan WhatsApp atau anak perusahaannya. Situs resmi WhatsApp ada di whatsapp.com.
33
+
34
+ Pengelola Wileys tidak mendukung penggunaan aplikasi ini untuk melanggar Ketentuan Layanan WhatsApp. Kami menekankan tanggung jawab pribadi pengguna untuk menggunakan secara adil dan bertanggung jawab.
35
+
36
+ Gunakan dengan bijak. Hindari spam. Jangan gunakan otomatisasi berlebihan.
37
+
38
+ ## 📦 Instalasi
39
+
40
+ ### Versi Stabil (Direkomendasikan)
19
41
 
20
42
  ```bash
21
- npm i @n4tzz/n4lyx
43
+ npm i wileys
22
44
  ```
23
45
 
24
- ```js
25
- const { default: makeWASocket } = require('@n4tzz/n4lyx')
26
- // ESM
27
- import makeWASocket from '@n4tzz/n4lyx'
46
+ ### Versi Edge (Fitur Terbaru)
47
+
48
+ ```bash
49
+ npm i wileys@latest
50
+ # atau
51
+ yarn add wileys@latest
28
52
  ```
29
53
 
30
- ---
54
+ ### Impor di Kode
31
55
 
32
- ## Quick Start
56
+ ```javascript
57
+ const { default: makeWASocket } = require("wileys")
58
+ // atau ES6
59
+ import makeWASocket from "wileys"
60
+ ```
33
61
 
34
- ```js
35
- const {
36
- default: makeWASocket,
37
- DisconnectReason,
38
- useMultiFileAuthState
39
- } = require('@n4tzz/n4lyx')
40
- const { Boom } = require('@hapi/boom')
62
+ ## 🚀 Mulai Cepat
41
63
 
42
- async function connect() {
43
- const { state, saveCreds } = await useMultiFileAuthState('auth')
44
-
45
- const sock = makeWASocket({
46
- auth: state,
47
- printQRInTerminal: true,
48
- browser: ['n4lyx', 'Desktop', '1.0.0']
49
- })
50
-
51
- sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
52
- if (connection === 'close') {
53
- const code = (lastDisconnect?.error as Boom)?.output?.statusCode
54
- if (code !== DisconnectReason.loggedOut) connect()
55
- } else if (connection === 'open') {
56
- console.log('connected')
57
- }
58
- })
64
+ ### Contoh Dasar
59
65
 
60
- sock.ev.on('messages.upsert', async ({ messages }) => {
61
- for (const msg of messages) {
62
- if (!msg.message) continue
63
- await sock.sendMessage(msg.key.remoteJid!, { text: 'pong' })
64
- }
65
- })
66
+ ```javascript
67
+ const { default: makeWASocket, DisconnectReason, useMultiFileAuthState } = require('wileys')
68
+ const { Boom } = require('@hapi/boom')
66
69
 
67
- sock.ev.on('creds.update', saveCreds)
70
+ async function connectToWhatsApp() {
71
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info_wileys')
72
+
73
+ const sock = makeWASocket({
74
+ auth: state,
75
+ printQRInTerminal: true,
76
+ browser: ['Wileys', 'Desktop', '3.0']
77
+ })
78
+
79
+ sock.ev.on('connection.update', (update) => {
80
+ const { connection, lastDisconnect } = update
81
+ if(connection === 'close') {
82
+ const shouldReconnect = (lastDisconnect?.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
83
+ console.log('Koneksi tertutup karena ', lastDisconnect.error, ', reconnecting ', shouldReconnect)
84
+ if(shouldReconnect) {
85
+ connectToWhatsApp()
86
+ }
87
+ } else if(connection === 'open') {
88
+ console.log('✅ Berhasil terhubung ke WhatsApp!')
89
+ }
90
+ })
91
+
92
+ sock.ev.on('messages.upsert', async ({ messages }) => {
93
+ for (const m of messages) {
94
+ if (!m.message) continue
95
+
96
+ console.log('📱 Pesan baru:', JSON.stringify(m, undefined, 2))
97
+
98
+ // Balas otomatis
99
+ await sock.sendMessage(m.key.remoteJid!, {
100
+ text: 'Halo! Saya bot WhatsApp menggunakan Wileys 🤖'
101
+ })
102
+ }
103
+ })
104
+
105
+ sock.ev.on('creds.update', saveCreds)
68
106
  }
69
107
 
70
- connect()
108
+ connectToWhatsApp()
71
109
  ```
72
110
 
73
- ---
111
+ ## 📋 Daftar Isi
112
+
113
+ Disclaimer : Docs ini masih dalam tahap beta, jadi ada kesalahan atau ketidaksesuaian
114
+
115
+ ## 🔌 Koneksi Akun
74
116
 
75
- ## Authentication
117
+ WhatsApp menyediakan API multi-device yang memungkinkan Wileys terautentikasi sebagai klien WhatsApp sekunder melalui QR code atau pairing code.
76
118
 
77
- ### QR Code
119
+ ### Hubungkan dengan QR Code
78
120
 
79
- ```js
80
- const { default: makeWASocket, Browsers } = require('@n4tzz/n4lyx')
121
+ > [!TIP]
122
+ > Sesuaikan nama browser menggunakan konstanta `Browsers`. Lihat konfigurasi yang tersedia di bawah.
123
+
124
+ ```javascript
125
+ const { default: makeWASocket, Browsers } = require("wileys")
81
126
 
82
127
  const sock = makeWASocket({
83
- browser: Browsers.ubuntu('n4lyx'),
84
- printQRInTerminal: true
128
+ browser: Browsers.ubuntu('My App'),
129
+ printQRInTerminal: true
85
130
  })
86
131
  ```
87
132
 
88
- ### Pairing Code
133
+ Setelah koneksi berhasil, QR code akan muncul di terminal. Pindai dengan WhatsApp di ponsel Anda untuk login.
134
+
135
+ ### Hubungkan dengan Pairing Code
89
136
 
90
- Phone number must include country code — no spaces, no symbols.
137
+ > [!IMPORTANT]
138
+ > Pairing code bukan bagian dari Mobile API. Ini memungkinkan koneksi WhatsApp Web tanpa QR code, tapi hanya satu perangkat. Lihat [FAQ WhatsApp](https://faq.whatsapp.com/).
91
139
 
92
- ```js
93
- const sock = makeWASocket({ printQRInTerminal: false })
140
+ Nomor telepon harus tanpa `+`, `()`, atau `-`, dan sertakan kode negara.
94
141
 
142
+ ```javascript
143
+ const { default: makeWASocket } = require("wileys")
144
+
145
+ const sock = makeWASocket({
146
+ printQRInTerminal: false
147
+ })
148
+
149
+ // Pairing Normal
95
150
  if (!sock.authState.creds.registered) {
96
- const code = await sock.requestPairingCode('628XXXXXXXXX')
97
- console.log('Pairing code:', code)
151
+ const number = '6285134816783'
152
+ const code = await sock.requestPairingCode(number)
153
+ console.log('🔑 Kode Pairing:', code)
98
154
  }
99
155
 
100
- // Custom pairing code (exactly 8 chars)
156
+ // Pairing Kustom
101
157
  if (!sock.authState.creds.registered) {
102
- const code = await sock.requestPairingCode('628XXXXXXXXX', 'N4LYX001')
103
- console.log('Pairing code:', code)
158
+ const pair = "YP240125" // 8 karakter
159
+ const number = '6285134816783'
160
+ const code = await sock.requestPairingCode(number, pair)
161
+ console.log('🔑 Kode Pairing Kustom:', code)
104
162
  }
105
163
  ```
106
164
 
107
- ### Persist Auth
108
-
109
- ```js
110
- const { useMultiFileAuthState } = require('@n4tzz/n4lyx')
165
+ ### Terima Riwayat Lengkap
111
166
 
112
- const { state, saveCreds } = await useMultiFileAuthState('auth')
113
- const sock = makeWASocket({ auth: state })
114
- sock.ev.on('creds.update', saveCreds)
115
- ```
116
-
117
- > For production, store credentials in a real database (PostgreSQL, MongoDB, Redis) — not on disk.
167
+ 1. Setel `syncFullHistory` ke `true`.
168
+ 2. Secara default, Wileys menggunakan konfigurasi Chrome. Untuk koneksi seperti desktop (untuk riwayat pesan lebih banyak), gunakan:
118
169
 
119
- ### Full History Sync
170
+ ```javascript
171
+ const { default: makeWASocket, Browsers } = require("wileys")
120
172
 
121
- ```js
122
173
  const sock = makeWASocket({
123
- browser: Browsers.macOS('Desktop'),
124
- syncFullHistory: true
174
+ browser: Browsers.macOS('Desktop'),
175
+ syncFullHistory: true
125
176
  })
126
177
  ```
127
178
 
128
- ---
179
+ ## ⚙️ Catatan Penting Konfigurasi Socket
129
180
 
130
- ## Configuration
181
+ ### Caching Metadata Grup (Direkomendasikan)
131
182
 
132
- ### Group Metadata Cache
183
+ Untuk penggunaan grup, implementasikan caching metadata grup:
133
184
 
134
- Required for group-heavy bots. Cuts down repeated API calls significantly.
135
-
136
- ```js
185
+ ```javascript
186
+ const { default: makeWASocket } = require("wileys")
137
187
  const NodeCache = require('node-cache')
188
+
138
189
  const groupCache = new NodeCache({ stdTTL: 5 * 60, useClones: false })
139
190
 
140
191
  const sock = makeWASocket({
141
- cachedGroupMetadata: async (jid) => groupCache.get(jid)
192
+ cachedGroupMetadata: async (jid) => groupCache.get(jid)
142
193
  })
143
194
 
144
195
  sock.ev.on('groups.update', async ([event]) => {
145
- groupCache.set(event.id, await sock.groupMetadata(event.id))
196
+ const metadata = await sock.groupMetadata(event.id)
197
+ groupCache.set(event.id, metadata)
146
198
  })
147
199
 
148
200
  sock.ev.on('group-participants.update', async (event) => {
149
- groupCache.set(event.id, await sock.groupMetadata(event.id))
201
+ const metadata = await sock.groupMetadata(event.id)
202
+ groupCache.set(event.id, metadata)
150
203
  })
151
204
  ```
152
205
 
153
- ### Message Store
206
+ ### Perbaiki Sistem Retry & Dekripsi Vote Poll
154
207
 
155
- Needed for message retry and poll vote decryption.
208
+ Tingkatkan pengiriman pesan dan dekripsi vote poll dengan store:
156
209
 
157
- ```js
210
+ ```javascript
158
211
  const sock = makeWASocket({
159
- getMessage: async (key) => await getMessageFromStore(key)
212
+ getMessage: async (key) => await getMessageFromStore(key)
160
213
  })
161
214
  ```
162
215
 
163
- ### Background Mode
216
+ ### Terima Notifikasi di Aplikasi WhatsApp
164
217
 
165
- Disable online status to receive push notifications while "offline".
218
+ Nonaktifkan status online untuk menerima notifikasi:
166
219
 
167
- ```js
168
- const sock = makeWASocket({ markOnlineOnConnect: false })
220
+ ```javascript
221
+ const sock = makeWASocket({
222
+ markOnlineOnConnect: false
223
+ })
169
224
  ```
170
225
 
171
- ---
226
+ ## 💾 Simpan Info Auth
172
227
 
173
- ## In-Memory Store
228
+ Hindari pemindaian QR code berulang dengan menyimpan kredensial:
174
229
 
175
- n4lyx doesn't ship a default persistent store. A basic in-memory store is available for local dev and testing — not recommended for production.
230
+ ```javascript
231
+ const makeWASocket = require("wileys").default
232
+ const { useMultiFileAuthState } = require("wileys")
176
233
 
177
- ```js
178
- const { makeInMemoryStore } = require('@n4tzz/n4lyx')
234
+ async function connect() {
235
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info_wileys')
236
+ const sock = makeWASocket({ auth: state })
237
+ sock.ev.on('creds.update', saveCreds)
238
+ }
179
239
 
180
- const store = makeInMemoryStore({})
181
- store.readFromFile('./store.json')
182
- setInterval(() => store.writeToFile('./store.json'), 10_000)
240
+ connect()
241
+ ```
183
242
 
184
- const sock = makeWASocket({})
185
- store.bind(sock.ev)
243
+ > [!IMPORTANT]
244
+ > `useMultiFileAuthState` menyimpan status auth di folder. Untuk produksi, gunakan database SQL/No-SQL dan kelola update kunci dengan hati-hati.
186
245
 
187
- sock.ev.on('chats.upsert', () => console.log(store.chats.all()))
188
- sock.ev.on('contacts.upsert', () => console.log(Object.values(store.contacts)))
246
+ ```javascript
247
+ const sock = makeWASocket()
248
+ sock.ev.on('messages.upsert', ({ messages }) => {
249
+ console.log('Dapat pesan:', messages)
250
+ })
189
251
  ```
190
252
 
191
- > Build your own store backed by a proper DB for anything in production.
253
+ ### Contoh Mulai
192
254
 
193
- ---
255
+ ```javascript
256
+ const makeWASocket = require("wileys").default
257
+ const { DisconnectReason, useMultiFileAuthState } = require("wileys")
258
+ const { Boom } = require('@hapi/boom')
194
259
 
195
- ## Sending Messages
260
+ async function connectToWhatsApp() {
261
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info_wileys')
262
+ const sock = makeWASocket({
263
+ auth: state,
264
+ printQRInTerminal: true
265
+ })
266
+
267
+ sock.ev.on('connection.update', (update) => {
268
+ const { connection, lastDisconnect } = update
269
+ if(connection === 'close') {
270
+ const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
271
+ console.log('Koneksi tertutup karena ', lastDisconnect.error, ', reconnecting ', shouldReconnect)
272
+ if(shouldReconnect) {
273
+ connectToWhatsApp()
274
+ }
275
+ } else if(connection === 'open') {
276
+ console.log('Koneksi terbuka')
277
+ }
278
+ })
279
+
280
+ sock.ev.on('messages.upsert', async ({ messages }) => {
281
+ for (const m of messages) {
282
+ console.log(JSON.stringify(m, undefined, 2))
283
+ console.log('Balas ke', m.key.remoteJid)
284
+ await sock.sendMessage(m.key.remoteJid!, { text: 'Halo Dunia' })
285
+ }
286
+ })
287
+
288
+ sock.ev.on('creds.update', saveCreds)
289
+ }
196
290
 
197
- ```js
198
- await sock.sendMessage(jid, content, options?)
291
+ connectToWhatsApp()
199
292
  ```
200
293
 
201
- ### Text
202
-
203
- ```js
204
- await sock.sendMessage(jid, { text: 'hello' })
294
+ ### Dekripsi Vote Poll
295
+
296
+ Secara default, vote poll terenkripsi dan ditangani di `messages.update`:
297
+
298
+ ```javascript
299
+ sock.ev.on('messages.update', event => {
300
+ for(const { key, update } of event) {
301
+ if(update.pollUpdates) {
302
+ const pollCreation = await getMessage(key)
303
+ if(pollCreation) {
304
+ console.log(
305
+ 'update poll diterima, agregasi: ',
306
+ getAggregateVotesInPollMessage({
307
+ message: pollCreation,
308
+ pollUpdates: update.pollUpdates,
309
+ })
310
+ )
311
+ }
312
+ }
313
+ }
314
+ })
205
315
  ```
206
316
 
207
- ### Reply / Quote
317
+ `getMessage` adalah implementasi store (di pihak Anda).
208
318
 
209
- ```js
210
- await sock.sendMessage(jid, { text: 'hello' }, { quoted: message })
211
- ```
319
+ ### Ringkasan Event Koneksi Pertama
212
320
 
213
- ### Mention
321
+ 1. Saat koneksi pertama, `connection.update` akan dipicu meminta restart sock.
322
+ 2. Kemudian, pesan riwayat diterima di `messaging.history-set`.
214
323
 
215
- ```js
216
- await sock.sendMessage(jid, {
217
- text: '@628XXXXXXXXX',
218
- mentions: ['628XXXXXXXXX@s.whatsapp.net']
219
- })
220
- ```
324
+ ## 🗄️ Implementasi Data Store
221
325
 
222
- ### Tag All n4lyx exclusive
326
+ Wileys tidak menyertakan penyimpanan default untuk obrolan, kontak, atau pesan. Namun, implementasi in-memory sederhana disediakan. Store mendengarkan update obrolan, pesan baru, dll., untuk menjaga data tetap terkini.
223
327
 
224
- Mention every member in a group. Automatically fetches participant list — no manual work.
328
+ > [!IMPORTANT]
329
+ > Saya sangat merekomendasikan membangun data store sendiri, karena menyimpan seluruh riwayat obrolan di memori sangat boros RAM.
225
330
 
226
- ```js
227
- // Tag all members
228
- await sock.sendMessage(jid, {
229
- text: '@everyone listen up',
230
- tagAll: true
231
- })
331
+ ```javascript
332
+ const makeWASocket = require("wileys").default
333
+ const { makeInMemoryStore } = require("wileys")
232
334
 
233
- // Tag admins only
234
- await sock.sendMessage(jid, {
235
- text: 'admins only',
236
- tagAll: true,
237
- tagAllScope: 'admins'
335
+ const store = makeInMemoryStore({ })
336
+
337
+ store.readFromFile('./wileys_store.json')
338
+
339
+ setInterval(() => {
340
+ store.writeToFile('./wileys_store.json')
341
+ }, 10_000)
342
+
343
+ const sock = makeWASocket({ })
344
+ store.bind(sock.ev)
345
+
346
+ sock.ev.on('chats.upsert', () => {
347
+ console.log('dapat obrolan', store.chats.all())
238
348
  })
239
349
 
240
- // Tag non-admins only
241
- await sock.sendMessage(jid, {
242
- text: 'members',
243
- tagAll: true,
244
- tagAllScope: 'non_admins'
350
+ sock.ev.on('contacts.upsert', () => {
351
+ console.log('dapat kontak', Object.values(store.contacts))
245
352
  })
246
353
  ```
247
354
 
248
- `tagAllScope` options: `'all'` (default) | `'admins'` | `'non_admins'`
355
+ Store juga menyediakan fungsi sederhana seperti `loadMessages` untuk mempercepat pengambilan data.
356
+
357
+ ## 🆔 Penjelasan ID WhatsApp
358
+
359
+ `id` adalah ID WhatsApp, disebut juga `jid`, untuk orang atau grup tujuan pesan.
360
+
361
+ Format: `[kode negara][nomor telepon]@s.whatsapp.net`
362
+ Contoh untuk orang: `+19999999999@s.whatsapp.net`.
363
+
364
+ Untuk grup: `123456789-123345@g.us`.
365
+
366
+ Untuk daftar siaran: `[timestamp pembuatan]@broadcast`.
367
+
368
+ Untuk cerita: `status@broadcast`.
369
+
370
+ ## 🔧 Fungsi Utilitas
371
+
372
+ - `getContentType` - Mengembalikan tipe konten pesan
373
+ - `getDevice` - Mengembalikan perangkat dari pesan
374
+ - `makeCacheableSignalKeyStore` - Mempercepat store auth
375
+ - `downloadContentFromMessage` - Unduh konten dari pesan
376
+
377
+ ## 📤 Kirim Pesan
378
+
379
+ Kirim semua jenis pesan dengan satu fungsi.
380
+
381
+ Lihat konten pesan yang didukung di bagian di bawah.
382
+ Lihat opsi seperti quote di contoh di bawah.
383
+
384
+ ```javascript
385
+ const jid: string
386
+ const content: AnyMessageContent
387
+ const options: MiscMessageGenerationOptions
388
+
389
+ sock.sendMessage(jid, content, options)
390
+ ```
391
+
392
+ ### Pesan Non-Media
393
+
394
+ #### Pesan Teks
395
+
396
+ ```javascript
397
+ await sock.sendMessage(jid, { text: 'halo dunia' })
398
+ ```
399
+
400
+ #### Pesan Kutipan (bekerja dengan semua tipe)
401
+
402
+ ```javascript
403
+ await sock.sendMessage(jid, { text: 'halo dunia' }, { quoted: message })
404
+ ```
405
+
406
+ #### Sebut Pengguna (bekerja dengan sebagian besar tipe)
249
407
 
250
- You can also get the jid list directly:
408
+ `@number` untuk sebut di teks, opsional.
251
409
 
252
- ```js
253
- const jids = await sock.groupTagAll(groupJid, 'all')
254
- // returns: ['628XXX@s.whatsapp.net', ...]
410
+ ```javascript
411
+ await sock.sendMessage(
412
+ jid,
413
+ {
414
+ text: '@12345678901',
415
+ mentions: ['12345678901@s.whatsapp.net']
416
+ }
417
+ )
255
418
  ```
256
419
 
257
- ### Forward
420
+ #### Teruskan Pesan
421
+
422
+ Butuh objek pesan, ambil dari store atau gunakan objek pesan.
258
423
 
259
- ```js
424
+ ```javascript
425
+ const msg = getMessageFromStore() // implementasikan sendiri
260
426
  await sock.sendMessage(jid, { forward: msg })
261
427
  ```
262
428
 
263
- ### Location
429
+ #### Pesan Lokasi
264
430
 
265
- ```js
266
- await sock.sendMessage(jid, {
267
- location: { degreesLatitude: -6.2, degreesLongitude: 106.8 }
268
- })
431
+ ```javascript
432
+ await sock.sendMessage(
433
+ jid,
434
+ {
435
+ location: {
436
+ degreesLatitude: 24.121231,
437
+ degreesLongitude: 55.1121221
438
+ }
439
+ }
440
+ )
269
441
  ```
270
442
 
271
- ### Contact
443
+ #### Pesan Kontak
272
444
 
273
- ```js
274
- const vcard = [
275
- 'BEGIN:VCARD',
276
- 'VERSION:3.0',
277
- 'FN:John Doe',
278
- 'TEL;type=CELL;waid=628XXXXXXXXX:+62 8XX-XXXX-XXXX',
279
- 'END:VCARD'
280
- ].join('\n')
445
+ ```javascript
446
+ const vcard = 'BEGIN:VCARD\n'
447
+ + 'VERSION:3.0\n'
448
+ + 'FN:Jeff Singh\n'
449
+ + 'ORG:Ashoka Uni;\n'
450
+ + 'TEL;type=CELL;type=VOICE;waid=911234567890:+91 12345 67890\n'
451
+ + 'END:VCARD'
281
452
 
282
- await sock.sendMessage(jid, {
283
- contacts: { displayName: 'John', contacts: [{ vcard }] }
284
- })
453
+ await sock.sendMessage(
454
+ id,
455
+ {
456
+ contacts: {
457
+ displayName: 'Jeff',
458
+ contacts: [{ vcard }]
459
+ }
460
+ }
461
+ )
285
462
  ```
286
463
 
287
- ### Reaction
464
+ #### Pesan Reaksi
288
465
 
289
- ```js
290
- await sock.sendMessage(jid, {
291
- react: { text: '🔥', key: message.key }
292
- })
293
- // Remove: text: ''
466
+ Butuh kunci pesan, ambil dari store atau gunakan objek kunci.
467
+
468
+ ```javascript
469
+ await sock.sendMessage(
470
+ jid,
471
+ {
472
+ react: {
473
+ text: '💖', // kosongkan untuk hapus reaksi
474
+ key: message.key
475
+ }
476
+ }
477
+ )
294
478
  ```
295
479
 
296
- ### Poll
480
+ #### Pin Pesan
297
481
 
298
- ```js
299
- await sock.sendMessage(jid, {
300
- poll: {
301
- name: 'Pick one',
302
- values: ['Option A', 'Option B'],
303
- selectableCount: 1
304
- }
305
- })
482
+ Butuh kunci pesan.
483
+
484
+ Waktu:
485
+
486
+ | Waktu | Detik |
487
+ |-------|------------|
488
+ | 24j | 86.400 |
489
+ | 7h | 604.800 |
490
+ | 30h | 2.592.000 |
491
+
492
+ ```javascript
493
+ await sock.sendMessage(
494
+ jid,
495
+ {
496
+ pin: {
497
+ type: 1, // 0 untuk hapus
498
+ time: 86400,
499
+ key: message.key
500
+ }
501
+ }
502
+ )
306
503
  ```
307
504
 
308
- ### Pin Message
505
+ #### Pesan Poll
309
506
 
310
- ```js
311
- await sock.sendMessage(jid, {
312
- pin: {
313
- type: 1, // 0 = unpin
314
- time: 86400, // 86400 = 24h | 604800 = 7d | 2592000 = 30d
315
- key: message.key
316
- }
317
- })
507
+ ```javascript
508
+ await sock.sendMessage(
509
+ jid,
510
+ {
511
+ poll: {
512
+ name: 'Poll Saya',
513
+ values: ['Opsi 1', 'Opsi 2', ...],
514
+ selectableCount: 1,
515
+ toAnnouncementGroup: false // atau true
516
+ }
517
+ }
518
+ )
318
519
  ```
319
520
 
320
- ### Media
521
+ ### Kirim dengan Pratinjau Tautan
321
522
 
322
- All media supports `Buffer`, `{ url: '...' }`, or `{ stream: Stream }`.
523
+ 1. Secara default, WA tidak punya generasi tautan dari web.
524
+ 2. Wileys punya fungsi untuk pratinjau tautan.
525
+ 3. Tambahkan `link-preview-js` dengan `npm i link-preview-js`.
526
+ 4. Kirim tautan:
323
527
 
324
- ```js
325
- // Image
326
- await sock.sendMessage(jid, {
327
- image: { url: './photo.png' },
328
- caption: 'caption'
329
- })
528
+ ```javascript
529
+ await sock.sendMessage(
530
+ jid,
531
+ {
532
+ text: 'Halo, ini dikirim menggunakan https://npmjs.com/wileys'
533
+ }
534
+ )
535
+ ```
330
536
 
331
- // Video
332
- await sock.sendMessage(jid, {
333
- video: { url: './video.mp4' },
334
- caption: 'caption',
335
- ptv: false // true = video note (circle)
336
- })
537
+ ### Pesan Media
337
538
 
338
- // Audio
339
- // Convert: ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
340
- await sock.sendMessage(jid, {
341
- audio: { url: './audio.ogg' },
342
- mimetype: 'audio/mp4'
343
- })
539
+ Pengiriman media (video, stiker, gambar) lebih mudah & efisien.
344
540
 
345
- // GIF (must be MP4 + gifPlayback flag)
346
- await sock.sendMessage(jid, {
347
- video: fs.readFileSync('./animation.mp4'),
348
- gifPlayback: true
349
- })
541
+ > [!NOTE] Di pesan media, bisa gunakan `{ stream: Stream }` atau `{ url: Url }` atau Buffer langsung, lihat contoh di bawah.
350
542
 
351
- // View once (works on image, video, audio)
352
- await sock.sendMessage(jid, {
353
- image: { url: './photo.png' },
354
- viewOnce: true
355
- })
543
+ Wileys tidak muat seluruh buffer ke memori; enkripsi sebagai stream.
544
+
545
+ > [!TIP] Gunakan Stream atau Url untuk hemat memori.
546
+
547
+ #### Pesan Gif
548
+
549
+ WA tidak dukung .gif, kirim sebagai .mp4 dengan flag `gifPlayback`.
550
+
551
+ ```javascript
552
+ await sock.sendMessage(
553
+ jid,
554
+ {
555
+ video: fs.readFileSync('Media/ma_gif.mp4'),
556
+ caption: 'halo dunia',
557
+ gifPlayback: true
558
+ }
559
+ )
356
560
  ```
357
561
 
358
- ### Link Preview
562
+ #### Pesan Video
359
563
 
360
- Requires `link-preview-js`:
564
+ ```javascript
565
+ await sock.sendMessage(
566
+ id,
567
+ {
568
+ video: {
569
+ url: './Media/ma_gif.mp4'
570
+ },
571
+ caption: 'halo dunia',
572
+ ptv: false // true untuk video note
573
+ }
574
+ )
575
+ ```
361
576
 
362
- ```bash
363
- npm i link-preview-js
577
+ #### Pesan Audio
578
+
579
+ Konversi dengan ffmpeg: `codec: libopus`, `ac: 1`, `avoid_negative_ts`, `make_zero`.
580
+
581
+ Contoh: `ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg`
582
+
583
+ ```javascript
584
+ await sock.sendMessage(
585
+ jid,
586
+ {
587
+ audio: {
588
+ url: './Media/audio.mp3'
589
+ },
590
+ mimetype: 'audio/mp4'
591
+ }
592
+ )
364
593
  ```
365
594
 
366
- ```js
367
- await sock.sendMessage(jid, {
368
- text: 'check this out: https://npmjs.com/package/@n4tzz/n4lyx'
369
- })
595
+ #### Pesan Gambar
596
+
597
+ ```javascript
598
+ await sock.sendMessage(
599
+ id,
600
+ {
601
+ image: {
602
+ url: './Media/ma_img.png'
603
+ },
604
+ caption: 'halo dunia'
605
+ }
606
+ )
370
607
  ```
371
608
 
372
- ---
609
+ #### Pesan View Once
610
+
611
+ Tambahkan `viewOnce: true` untuk semua pesan di atas.
612
+
613
+ ```javascript
614
+ await sock.sendMessage(
615
+ id,
616
+ {
617
+ image: {
618
+ url: './Media/ma_img.png'
619
+ },
620
+ viewOnce: true, // bekerja dengan video, audio juga
621
+ caption: 'halo dunia'
622
+ }
623
+ )
624
+ ```
373
625
 
374
- ## Edit & Delete
626
+ ## ✏️ Ubah Pesan
375
627
 
376
- ```js
377
- // Delete for everyone
378
- const sent = await sock.sendMessage(jid, { text: 'oops' })
379
- await sock.sendMessage(jid, { delete: sent.key })
628
+ ### Hapus Pesan (untuk semua)
380
629
 
381
- // Edit message
630
+ ```javascript
631
+ const msg = await sock.sendMessage(jid, { text: 'halo dunia' })
632
+ await sock.sendMessage(jid, { delete: msg.key })
633
+ ```
634
+
635
+ Catatan: Hapus untuk diri sendiri dukung via `chatModify`, lihat [Ubah Obrolan](#ubah-obrolan).
636
+
637
+ ### Edit Pesan
638
+
639
+ Gunakan konten editable.
640
+
641
+ ```javascript
382
642
  await sock.sendMessage(jid, {
383
- text: 'corrected text',
384
- edit: sent.key
385
- })
643
+ text: 'teks terupdate di sini',
644
+ edit: response.key,
645
+ });
386
646
  ```
387
647
 
388
- ---
648
+ ## 🖼️ Manipulasi Pesan Media
389
649
 
390
- ## Downloading Media
650
+ ### Thumbnail di Pesan Media
391
651
 
392
- ```js
393
- import { downloadMediaMessage, getContentType } from '@n4tzz/n4lyx'
394
- import { createWriteStream } from 'fs'
652
+ Thumbnail otomatis untuk gambar & stiker jika tambah `jimp` atau `sharp` (`npm i jimp` atau `npm i sharp`).
395
653
 
396
- sock.ev.on('messages.upsert', async ({ messages: [m] }) => {
397
- if (!m.message) return
398
- if (getContentType(m) !== 'imageMessage') return
654
+ Untuk video, butuh `ffmpeg` terinstal.
399
655
 
400
- const stream = await downloadMediaMessage(m, 'stream', {}, {
401
- logger,
402
- reuploadRequest: sock.updateMediaMessage
403
- })
656
+ ### Unduh Pesan Media
404
657
 
405
- stream.pipe(createWriteStream('./download.jpeg'))
658
+ Untuk simpan media yang diterima:
659
+
660
+ ```javascript
661
+ import { createWriteStream } from 'fs'
662
+ import { downloadMediaMessage, getContentType } from 'wileys'
663
+
664
+ sock.ev.on('messages.upsert', async ({ messages: [m] }) => {
665
+ if (!m.message) return
666
+ const messageType = getContentType(m)
667
+
668
+ if (messageType === 'imageMessage') {
669
+ const stream = await downloadMediaMessage(
670
+ m,
671
+ 'stream', // atau 'buffer'
672
+ { },
673
+ {
674
+ logger,
675
+ reuploadRequest: sock.updateMediaMessage
676
+ }
677
+ )
678
+ const writeStream = createWriteStream('./my-download.jpeg')
679
+ stream.pipe(writeStream)
680
+ }
406
681
  })
407
682
  ```
408
683
 
409
- Re-upload expired media:
684
+ ### Unggah Ulang Pesan Media ke WhatsApp
410
685
 
411
- ```js
686
+ WA hapus media lama dari server. Unggah ulang dengan:
687
+
688
+ ```javascript
412
689
  await sock.updateMediaMessage(msg)
413
690
  ```
414
691
 
415
- ---
692
+ ## 📞 Tolak Panggilan
416
693
 
417
- ## Chat Modifications
694
+ Ambil `callId` dan `callFrom` dari event `call`.
418
695
 
419
- > Wrong updates can log you out of all devices. Handle with care.
696
+ ```javascript
697
+ await sock.rejectCall(callId, callFrom)
698
+ ```
699
+
700
+ ## 💬 Status Kirim di Obrolan
701
+
702
+ ### Baca Pesan
420
703
 
421
- ```js
422
- const last = await getLastMessage(jid) // your implementation
704
+ Kumpulan kunci pesan harus ditandai dibaca secara eksplisit.
705
+
706
+ ```javascript
707
+ const key: WAMessageKey
708
+ await sock.readMessages([key]) // bisa multiple kunci
709
+ ```
423
710
 
424
- // Archive
425
- await sock.chatModify({ archive: true, lastMessages: [last] }, jid)
711
+ ID pesan adalah pengenal unik. Akses dengan `message.key.id`.
426
712
 
427
- // Mute (ms) / unmute
428
- await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid) // 8h
713
+ ### Update Kehadiran
714
+
715
+ `presence` bisa: available, composing, recording, paused, unavailable.
716
+
717
+ Berlaku 10 detik. Beri tahu jid apakah Anda online, offline, mengetik, dll.
718
+
719
+ ```javascript
720
+ await sock.sendPresenceUpdate('available', jid)
721
+ ```
722
+
723
+ > [!NOTE] Jika klien desktop aktif, WA tidak kirim notifikasi push. Untuk terima notifikasi, setel offline dengan `sock.sendPresenceUpdate('unavailable')`.
724
+
725
+ ## 📁 Ubah Obrolan
726
+
727
+ WA gunakan komunikasi terenkripsi untuk update obrolan/aplikasi.
728
+
729
+ > [!IMPORTANT] Jika salah update, WA bisa logout dari semua perangkat.
730
+
731
+ ### Arsipkan Obrolan
732
+
733
+ ```javascript
734
+ const lastMsgInChat = await getLastMessageInChat(jid) // implementasikan sendiri
735
+ await sock.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, jid)
736
+ ```
737
+
738
+ ### Bisukan/Buka Bisukan Obrolan
739
+
740
+ Waktu dukung:
741
+
742
+ | Waktu | Milidetik |
743
+ |-------|-------------|
744
+ | Hapus | null |
745
+ | 8j | 86.400.000 |
746
+ | 7h | 604.800.000 |
747
+
748
+ ```javascript
749
+ // Bisukan 8 jam
750
+ await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
751
+ // Buka bisukan
429
752
  await sock.chatModify({ mute: null }, jid)
753
+ ```
754
+
755
+ ### Tandai Obrolan Dibaca/Tidak Dibaca
430
756
 
431
- // Mark unread
432
- await sock.chatModify({ markRead: false, lastMessages: [last] }, jid)
757
+ ```javascript
758
+ const lastMsgInChat = await getLastMessageInChat(jid)
759
+ // tandai tidak dibaca
760
+ await sock.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, jid)
761
+ ```
762
+
763
+ ### Hapus Pesan untuk Saya
764
+
765
+ ```javascript
766
+ await sock.chatModify(
767
+ {
768
+ clear: {
769
+ messages: [
770
+ {
771
+ id: 'ATWYHDNNWU81732J',
772
+ fromMe: true,
773
+ timestamp: '1654823909'
774
+ }
775
+ ]
776
+ }
777
+ },
778
+ jid
779
+ )
780
+ ```
433
781
 
434
- // Pin / unpin
435
- await sock.chatModify({ pin: true }, jid)
436
- await sock.chatModify({ pin: false }, jid)
782
+ ### Hapus Obrolan
437
783
 
438
- // Delete chat
784
+ ```javascript
785
+ const lastMsgInChat = await getLastMessageInChat(jid)
439
786
  await sock.chatModify({
440
- delete: true,
441
- lastMessages: [{ key: last.key, messageTimestamp: last.messageTimestamp }]
442
- }, jid)
787
+ delete: true,
788
+ lastMessages: [
789
+ {
790
+ key: lastMsgInChat.key,
791
+ messageTimestamp: lastMsgInChat.messageTimestamp
792
+ }
793
+ ]
794
+ },
795
+ jid
796
+ )
797
+ ```
443
798
 
444
- // Delete message (self only)
799
+ ### Pin/Hapus Pin Obrolan
800
+
801
+ ```javascript
445
802
  await sock.chatModify({
446
- clear: { messages: [{ id: 'MESSAGE_ID', fromMe: true, timestamp: '...' }] }
447
- }, jid)
803
+ pin: true // atau false untuk hapus pin
804
+ },
805
+ jid
806
+ )
807
+ ```
448
808
 
449
- // Star / unstar
809
+ ### Bintangi/Hapus Bintang Pesan
810
+
811
+ ```javascript
450
812
  await sock.chatModify({
451
- star: {
452
- messages: [{ id: 'MESSAGE_ID', fromMe: true }],
453
- star: true // false = unstar
454
- }
455
- }, jid)
813
+ star: {
814
+ messages: [
815
+ {
816
+ id: 'messageID',
817
+ fromMe: true // atau false
818
+ }
819
+ ],
820
+ star: true // true: Bintangi; false: Hapus Bintang
821
+ }
822
+ },
823
+ jid
824
+ )
456
825
  ```
457
826
 
458
- ### Disappearing Messages
827
+ ### Pesan Menghilang
828
+
829
+ Ephemeral:
459
830
 
460
- ```js
461
- // Enable (86400 = 24h | 604800 = 7d | 7776000 = 90d)
462
- await sock.sendMessage(jid, { disappearingMessagesInChat: WA_DEFAULT_EPHEMERAL })
831
+ | Waktu | Detik |
832
+ |-------|-------------|
833
+ | Hapus | 0 |
834
+ | 24j | 86.400 |
835
+ | 7h | 604.800 |
836
+ | 90h | 7.776.000 |
463
837
 
464
- // Send as ephemeral
465
- await sock.sendMessage(jid, { text: 'poof' }, { ephemeralExpiration: WA_DEFAULT_EPHEMERAL })
838
+ Gunakan detik, default 7 hari.
466
839
 
467
- // Disable
468
- await sock.sendMessage(jid, { disappearingMessagesInChat: false })
840
+ ```javascript
841
+ // Nyalakan pesan menghilang
842
+ await sock.sendMessage(
843
+ jid,
844
+ { disappearingMessagesInChat: WA_DEFAULT_EPHEMERAL }
845
+ )
846
+
847
+ // Kirim sebagai pesan menghilang
848
+ await sock.sendMessage(jid, { text: 'halo' }, { ephemeralExpiration: WA_DEFAULT_EPHEMERAL })
849
+
850
+ // Matikan
851
+ await sock.sendMessage(
852
+ jid,
853
+ { disappearingMessagesInChat: false }
854
+ )
469
855
  ```
470
856
 
471
- ---
857
+ ## 👤 Query Pengguna
472
858
 
473
- ## Groups
859
+ ### Periksa ID Ada di WhatsApp
474
860
 
475
- ```js
476
- // Create
477
- const group = await sock.groupCreate('Group Name', ['jid@s.whatsapp.net'])
478
- console.log('Created:', group.gid)
861
+ ```javascript
862
+ const [result] = await sock.onWhatsApp(jid)
863
+ if (result.exists) console.log(`${jid} ada di WhatsApp, sebagai jid: ${result.jid}`)
864
+ ```
479
865
 
480
- // Add / remove / promote / demote
481
- await sock.groupParticipantsUpdate(jid, ['jid@s.whatsapp.net'], 'add')
482
- // 'add' | 'remove' | 'promote' | 'demote'
866
+ ### Query Riwayat Obrolan (grup juga)
483
867
 
484
- // Update name
485
- await sock.groupUpdateSubject(jid, 'New Name')
868
+ Butuh pesan tertua di obrolan.
486
869
 
487
- // Update description
488
- await sock.groupUpdateDescription(jid, 'New description')
870
+ ```javascript
871
+ const msg = await getOldestMessageInChat(jid) // implementasikan sendiri
872
+ await sock.fetchMessageHistory(
873
+ 50, // jumlah (max: 50 per query)
874
+ msg.key,
875
+ msg.messageTimestamp
876
+ )
877
+ ```
489
878
 
490
- // Settings
491
- await sock.groupSettingUpdate(jid, 'announcement') // admin-only send
492
- await sock.groupSettingUpdate(jid, 'not_announcement') // everyone can send
493
- await sock.groupSettingUpdate(jid, 'locked') // admin-only settings
494
- await sock.groupSettingUpdate(jid, 'unlocked') // everyone can edit
879
+ Pesan diterima di event `messaging.history-set`.
495
880
 
496
- // Leave
497
- await sock.groupLeave(jid)
881
+ ### Ambil Status
498
882
 
499
- // Invite link
500
- const code = await sock.groupInviteCode(jid)
501
- // link: https://chat.whatsapp.com/${code}
883
+ ```javascript
884
+ const status = await sock.fetchStatus(jid)
885
+ console.log('status: ' + status)
886
+ ```
502
887
 
503
- // Revoke invite
504
- await sock.groupRevokeInvite(jid)
888
+ ### Ambil Foto Profil (grup juga)
505
889
 
506
- // Join via code (without https://chat.whatsapp.com/)
507
- await sock.groupAcceptInvite(code)
890
+ ```javascript
891
+ // resolusi rendah
892
+ const ppUrl = await sock.profilePictureUrl(jid)
893
+ console.log(ppUrl)
508
894
 
509
- // Metadata (participants, name, desc...)
510
- const meta = await sock.groupMetadata(jid)
895
+ // resolusi tinggi
896
+ const ppUrl = await sock.profilePictureUrl(jid, 'image')
897
+ ```
511
898
 
512
- // Ephemeral
513
- await sock.groupToggleEphemeral(jid, 86400)
899
+ ### Ambil Profil Bisnis (deskripsi atau kategori)
514
900
 
515
- // Add mode
516
- await sock.groupMemberAddMode(jid, 'all_member_add') // or 'admin_add'
901
+ ```javascript
902
+ const profile = await sock.getBusinessProfile(jid)
903
+ console.log('deskripsi bisnis: ' + profile.description + ', kategori: ' + profile.category)
904
+ ```
517
905
 
518
- // Join approval mode
519
- await sock.groupJoinApprovalMode(jid, 'on') // or 'off'
906
+ ### Ambil Kehadiran Seseorang (mengetik atau online)
520
907
 
521
- // Join requests
522
- const requests = await sock.groupRequestParticipantsList(jid)
523
- await sock.groupRequestParticipantsUpdate(jid, ['jid@s.whatsapp.net'], 'approve') // or 'reject'
908
+ ```javascript
909
+ sock.ev.on('presence.update', console.log)
524
910
 
525
- // All joined group metadata
526
- const all = await sock.groupFetchAllParticipating()
911
+ await sock.presenceSubscribe(jid)
527
912
  ```
528
913
 
529
- ### Group Status V2 — n4lyx exclusive
914
+ ## 🔄 Ubah Profil
530
915
 
531
- Extended group status with full metadata control.
916
+ ### Ubah Status Profil
532
917
 
533
- ```js
534
- // Set group status v2
535
- await sock.groupSetStatusV2(jid, {
536
- duration: 86400, // seconds (default: 86400 = 24h)
537
- allowReply: true, // allow members to reply (default: true)
538
- allowReaction: true, // allow reactions (default: true)
539
- visibility: 'all' // 'all' | 'admin' (default: 'all')
540
- })
918
+ ```javascript
919
+ await sock.updateProfileStatus('Halo Dunia!')
920
+ ```
541
921
 
542
- // Get current group status v2 settings
543
- const settings = await sock.groupGetStatusV2(jid)
544
- console.log(settings)
545
- // { duration: 86400, allowReply: true, allowReaction: true, visibility: 'all' }
922
+ ### Ubah Nama Profil
546
923
 
547
- // Send message as group status v2
548
- await sock.sendMessage(jid, {
549
- text: 'group announcement',
550
- groupStatusV2: {
551
- duration: 604800, // 7 days
552
- allowReply: false,
553
- allowReaction: true,
554
- visibility: 'all'
555
- }
556
- })
924
+ ```javascript
925
+ await sock.updateProfileName('Nama Saya')
557
926
  ```
558
927
 
559
- ---
928
+ ### Ubah Foto Tampilan (grup juga)
560
929
 
561
- ## Presence
930
+ > [!NOTE] Seperti pesan media, gunakan `{ stream: Stream }` atau `{ url: Url }` atau Buffer, lihat [Pesan Media](#pesan-media).
562
931
 
563
- ```js
564
- // Mark messages as read
565
- await sock.readMessages([key])
932
+ ```javascript
933
+ await sock.updateProfilePicture(jid, { url: './new-profile-picture.jpeg' })
934
+ ```
566
935
 
567
- // Send presence
568
- // 'available' | 'unavailable' | 'composing' | 'recording' | 'paused'
569
- await sock.sendPresenceUpdate('composing', jid)
936
+ ### Hapus Foto Tampilan (grup juga)
570
937
 
571
- // Subscribe to contact presence
572
- sock.ev.on('presence.update', console.log)
573
- await sock.presenceSubscribe(jid)
938
+ ```javascript
939
+ await sock.removeProfilePicture(jid)
574
940
  ```
575
941
 
576
- ---
942
+ ## 👥 Grup
577
943
 
578
- ## Querying
944
+ Untuk ubah properti grup, harus admin.
579
945
 
580
- ```js
581
- // Check if number is on WhatsApp
582
- const [result] = await sock.onWhatsApp(jid)
583
- if (result.exists) console.log(result.jid)
946
+ ### Buat Grup
584
947
 
585
- // Status text
586
- const status = await sock.fetchStatus(jid)
948
+ ```javascript
949
+ const group = await sock.groupCreate('Grup Saya', ['1234@s.whatsapp.net', '4564@s.whatsapp.net'])
950
+ console.log('grup dibuat dengan id: ' + group.gid)
951
+ await sock.sendMessage(group.id, { text: 'halo semuanya' })
952
+ ```
953
+
954
+ ### Tambah/Hapus atau Turunkan/Naikkan
587
955
 
588
- // Profile picture
589
- const url = await sock.profilePictureUrl(jid) // low res
590
- const urlHD = await sock.profilePictureUrl(jid, 'image') // high res
956
+ ```javascript
957
+ await sock.groupParticipantsUpdate(
958
+ jid,
959
+ ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
960
+ 'add' // ganti dengan 'remove', 'demote', atau 'promote'
961
+ )
962
+ ```
591
963
 
592
- // Business profile
593
- const biz = await sock.getBusinessProfile(jid)
594
- console.log(biz.description, biz.category)
964
+ ### Ubah Subjek (nama)
595
965
 
596
- // Message history (max 50 per call)
597
- const oldest = await getOldestMessage(jid) // your implementation
598
- await sock.fetchMessageHistory(50, oldest.key, oldest.messageTimestamp)
599
- // messages arrive via messaging.history-set
966
+ ```javascript
967
+ await sock.groupUpdateSubject(jid, 'Subjek Baru!')
600
968
  ```
601
969
 
602
- ---
970
+ ### Ubah Deskripsi
603
971
 
604
- ## Privacy
972
+ ```javascript
973
+ await sock.groupUpdateDescription(jid, 'Deskripsi Baru!')
974
+ ```
605
975
 
606
- ```js
607
- // Block / unblock
608
- await sock.updateBlockStatus(jid, 'block')
609
- await sock.updateBlockStatus(jid, 'unblock')
976
+ ### Ubah Pengaturan
977
+
978
+ ```javascript
979
+ // Hanya admin kirim pesan
980
+ await sock.groupSettingUpdate(jid, 'announcement')
981
+ // Semua bisa kirim
982
+ await sock.groupSettingUpdate(jid, 'not_announcement')
983
+ // Semua bisa ubah pengaturan grup
984
+ await sock.groupSettingUpdate(jid, 'unlocked')
985
+ // Hanya admin ubah pengaturan
986
+ await sock.groupSettingUpdate(jid, 'locked')
987
+ ```
610
988
 
611
- // Get settings
612
- await sock.fetchPrivacySettings(true)
989
+ ### Keluar Grup
613
990
 
614
- // Get blocklist
615
- await sock.fetchBlocklist()
991
+ ```javascript
992
+ await sock.groupLeave(jid)
993
+ ```
994
+
995
+ ### Ambil Kode Undangan
616
996
 
617
- // Update settings
618
- // 'all' | 'contacts' | 'contact_blacklist' | 'none'
619
- await sock.updateLastSeenPrivacy('contacts')
620
- await sock.updateProfilePicturePrivacy('contacts')
621
- await sock.updateStatusPrivacy('contacts')
622
- await sock.updateReadReceiptsPrivacy('all')
623
- await sock.updateGroupsAddPrivacy('contacts')
624
- await sock.updateOnlinePrivacy('all') // or 'match_last_seen'
997
+ Buat tautan: `'https://chat.whatsapp.com/' + code`.
625
998
 
626
- // Default disappearing mode
627
- await sock.updateDefaultDisappearingMode(86400)
999
+ ```javascript
1000
+ const code = await sock.groupInviteCode(jid)
1001
+ console.log('kode grup: ' + code)
628
1002
  ```
629
1003
 
630
- ---
1004
+ ### Cabut Kode Undangan
631
1005
 
632
- ## Profile
1006
+ ```javascript
1007
+ const code = await sock.groupRevokeInvite(jid)
1008
+ console.log('Kode grup baru: ' + code)
1009
+ ```
633
1010
 
634
- ```js
635
- await sock.updateProfileStatus('available')
636
- await sock.updateProfileName('My Name')
637
- await sock.updateProfilePicture(jid, { url: './avatar.jpeg' })
638
- await sock.removeProfilePicture(jid)
1011
+ ### Gabung Menggunakan Kode Undangan
1012
+
1013
+ Kode tanpa `https://chat.whatsapp.com/`.
1014
+
1015
+ ```javascript
1016
+ const response = await sock.groupAcceptInvite(code)
1017
+ console.log('bergabung ke: ' + response)
639
1018
  ```
640
1019
 
641
- ---
1020
+ ### Ambil Info Grup dari Kode Undangan
1021
+
1022
+ ```javascript
1023
+ const response = await sock.groupGetInviteInfo(code)
1024
+ console.log('info grup: ' + response)
1025
+ ```
642
1026
 
643
- ## Broadcast & Stories
1027
+ ### Query Metadata (peserta, nama, deskripsi...)
644
1028
 
645
- ```js
646
- await sock.sendMessage(
647
- 'status@broadcast',
648
- { image: { url: url }, caption: 'caption' },
649
- {
650
- backgroundColor: '#000',
651
- font: 0,
652
- statusJidList: ['jid@s.whatsapp.net'],
653
- broadcast: true
654
- }
1029
+ ```javascript
1030
+ const metadata = await sock.groupMetadata(jid)
1031
+ console.log(metadata.id + ', judul: ' + metadata.subject + ', deskripsi: ' + metadata.desc)
1032
+ ```
1033
+
1034
+ ### Gabung Menggunakan groupInviteMessage
1035
+
1036
+ ```javascript
1037
+ const response = await sock.groupAcceptInviteV4(jid, groupInviteMessage)
1038
+ console.log('bergabung ke: ' + response)
1039
+ ```
1040
+
1041
+ ### Ambil Daftar Permintaan Gabung
1042
+
1043
+ ```javascript
1044
+ const response = await sock.groupRequestParticipantsList(jid)
1045
+ console.log(response)
1046
+ ```
1047
+
1048
+ ### Setujui/Tolak Permintaan Gabung
1049
+
1050
+ ```javascript
1051
+ const response = await sock.groupRequestParticipantsUpdate(
1052
+ jid,
1053
+ ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
1054
+ 'approve' // atau 'reject'
655
1055
  )
1056
+ console.log(response)
1057
+ ```
1058
+
1059
+ ### Ambil Semua Metadata Grup yang Diikuti
656
1060
 
657
- // Broadcast list info
658
- const info = await sock.getBroadcastListInfo('1234@broadcast')
659
- console.log(info.name, info.recipients)
1061
+ ```javascript
1062
+ const response = await sock.groupFetchAllParticipating()
1063
+ console.log(response)
660
1064
  ```
661
1065
 
662
- ---
1066
+ ### Toggle Ephemeral
663
1067
 
664
- ## Calls
1068
+ Ephemeral:
665
1069
 
666
- ```js
667
- sock.ev.on('call', async ([call]) => {
668
- await sock.rejectCall(call.id, call.from)
669
- })
1070
+ | Waktu | Detik |
1071
+ |-------|-------------|
1072
+ | Hapus | 0 |
1073
+ | 24j | 86.400 |
1074
+ | 7h | 604.800 |
1075
+ | 90h | 7.776.000 |
1076
+
1077
+ ```javascript
1078
+ await sock.groupToggleEphemeral(jid, 86400)
670
1079
  ```
671
1080
 
672
- ---
1081
+ ### Ubah Mode Tambah
1082
+
1083
+ ```javascript
1084
+ await sock.groupMemberAddMode(
1085
+ jid,
1086
+ 'all_member_add' // atau 'admin_add'
1087
+ )
1088
+ ```
673
1089
 
674
- ## Poll Decryption
1090
+ ## 🔒 Privasi
675
1091
 
676
- Polls are encrypted by default. Decryption happens in `messages.update`.
1092
+ ### Blokir/Buka Blokir Pengguna
677
1093
 
678
- ```js
679
- sock.ev.on('messages.update', async (events) => {
680
- for (const { key, update } of events) {
681
- if (!update.pollUpdates) continue
1094
+ ```javascript
1095
+ await sock.updateBlockStatus(jid, 'block') // Blokir
1096
+ await sock.updateBlockStatus(jid, 'unblock') // Buka blokir
1097
+ ```
682
1098
 
683
- const creation = await getMessage(key) // your implementation
684
- if (!creation) continue
1099
+ ### Ambil Pengaturan Privasi
685
1100
 
686
- console.log(
687
- getAggregateVotesInPollMessage({
688
- message: creation,
689
- pollUpdates: update.pollUpdates
690
- })
691
- )
692
- }
693
- })
1101
+ ```javascript
1102
+ const privacySettings = await sock.fetchPrivacySettings(true)
1103
+ console.log('pengaturan privasi: ' + privacySettings)
694
1104
  ```
695
1105
 
696
- ---
1106
+ ### Ambil Daftar Blokir
1107
+
1108
+ ```javascript
1109
+ const response = await sock.fetchBlocklist()
1110
+ console.log(response)
1111
+ ```
697
1112
 
698
- ## Low-Level: WebSocket Callbacks
1113
+ ### Update Privasi Terakhir Dilihat
699
1114
 
700
- ```js
701
- sock.ws.on('CB:edge_routing', (node) => { })
702
- sock.ws.on('CB:edge_routing,id:abcd', (node) => { })
703
- sock.ws.on('CB:edge_routing,id:abcd,routing_info', (node) => { })
1115
+ ```javascript
1116
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1117
+ await sock.updateLastSeenPrivacy(value)
704
1118
  ```
705
1119
 
706
- Debug mode logs every WA protocol frame:
1120
+ ### Update Privasi Online
707
1121
 
708
- ```js
709
- const sock = makeWASocket({ logger: P({ level: 'debug' }) })
1122
+ ```javascript
1123
+ const value = 'all' // 'match_last_seen'
1124
+ await sock.updateOnlinePrivacy(value)
710
1125
  ```
711
1126
 
712
- ---
1127
+ ### Update Privasi Foto Profil
713
1128
 
714
- ## JID Format
1129
+ ```javascript
1130
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1131
+ await sock.updateProfilePicturePrivacy(value)
1132
+ ```
715
1133
 
716
- | Type | Format |
717
- |-----------|-------------------------------|
718
- | User | `628XXXXXXXXX@s.whatsapp.net` |
719
- | Group | `123456789-123456@g.us` |
720
- | Broadcast | `[timestamp]@broadcast` |
721
- | Story | `status@broadcast` |
1134
+ ### Update Privasi Status
722
1135
 
723
- ---
1136
+ ```javascript
1137
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1138
+ await sock.updateStatusPrivacy(value)
1139
+ ```
724
1140
 
725
- ## Utilities
1141
+ ### Update Privasi Tanda Terima Baca
726
1142
 
727
- | Function | Description |
728
- |-------------------------------|--------------------------------------|
729
- | `getContentType(msg)` | Returns content type of a message |
730
- | `getDevice(msg)` | Returns sender's device info |
731
- | `makeCacheableSignalKeyStore` | Speeds up auth key store operations |
732
- | `downloadContentFromMessage` | Downloads raw content from a message |
733
- | `fetchLatestN4lyxVersion` | Fetches latest n4lyx version from npm |
734
- | `fetchLatestWaWebVersion` | Fetches latest WA Web version |
1143
+ ```javascript
1144
+ const value = 'all' // 'none'
1145
+ await sock.updateReadReceiptsPrivacy(value)
1146
+ ```
735
1147
 
736
- ---
1148
+ ### Update Privasi Tambah Grup
737
1149
 
738
- ## n4lyx Exclusive Features
1150
+ ```javascript
1151
+ const value = 'all' // 'contacts' | 'contact_blacklist'
1152
+ await sock.updateGroupsAddPrivacy(value)
1153
+ ```
739
1154
 
740
- | Feature | Description |
741
- |---|---|
742
- | `tagAll` in `sendMessage` | Auto-mention all/admins/non-admins in a group |
743
- | `groupTagAll(jid, scope)` | Get list of participant jids by scope |
744
- | `groupSetStatusV2(jid, opts)` | Set group status v2 with full metadata |
745
- | `groupGetStatusV2(jid)` | Get current group status v2 settings |
746
- | `N4lyxMeta` in proto | Internal message metadata (version, session, timestamp) |
747
- | `GroupStatusV2Message` in proto | Extended group status message type |
748
- | `TagAllMessage` in proto | Tag-all message type with scope support |
1155
+ ### Update Mode Menghilang Default
749
1156
 
750
- ---
1157
+ Ephemeral:
751
1158
 
752
- ## Optional Dependencies
1159
+ | Waktu | Detik |
1160
+ |-------|-------------|
1161
+ | Hapus | 0 |
1162
+ | 24j | 86.400 |
1163
+ | 7h | 604.800 |
1164
+ | 90h | 7.776.000 |
753
1165
 
754
- ```bash
755
- npm i jimp # or sharp — thumbnail generation
756
- npm i link-preview-js # link previews in text messages
757
- npm i qrcode-terminal # QR rendering in terminal
1166
+ ```javascript
1167
+ const ephemeral = 86400
1168
+ await sock.updateDefaultDisappearingMode(ephemeral)
758
1169
  ```
759
1170
 
760
- Video thumbnails require `ffmpeg` on your system.
1171
+ ## 📢 Daftar Siaran & Cerita
761
1172
 
762
- Audio conversion:
1173
+ ### Kirim Siaran & Cerita
763
1174
 
764
- ```bash
765
- ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
1175
+ Pesan bisa dikirim ke siaran & cerita. Tambahkan opsi pesan:
1176
+
1177
+ ```javascript
1178
+ await sock.sendMessage(
1179
+ jid,
1180
+ {
1181
+ image: {
1182
+ url: url
1183
+ },
1184
+ caption: caption
1185
+ },
1186
+ {
1187
+ backgroundColor: backgroundColor,
1188
+ font: font,
1189
+ statusJidList: statusJidList,
1190
+ broadcast: true
1191
+ }
1192
+ )
766
1193
  ```
767
1194
 
768
- ---
1195
+ Body pesan bisa `extendedTextMessage`, `imageMessage`, dll., lihat [Pesan Media](#pesan-media).
1196
+
1197
+ `broadcast: true` aktifkan mode siaran.
1198
+
1199
+ `statusJidList`: daftar penerima.
1200
+
1201
+ ID siaran: `12345678@broadcast`.
1202
+
1203
+ ### Query Penerima & Nama Daftar Siaran
1204
+
1205
+ ```javascript
1206
+ const bList = await sock.getBroadcastListInfo('1234@broadcast')
1207
+ console.log(`nama daftar: ${bList.name}, penerima: ${bList.recipients}`)
1208
+ ```
1209
+
1210
+ ## 🛠️ Fungsi Kustom
1211
+
1212
+ Wileys dirancang untuk fungsi kustom. Tambahkan ekstensi sendiri tanpa fork.
1213
+
1214
+ ### Aktifkan Level Debug di Log Wileys
1215
+
1216
+ ```javascript
1217
+ const sock = makeWASocket({
1218
+ logger: P({ level: 'debug' }),
1219
+ })
1220
+ ```
1221
+
1222
+ Ini tampilkan pesan WhatsApp di konsol.
1223
+
1224
+ ### Cara WhatsApp Berkomunikasi
1225
+
1226
+ > [!TIP] Pelajari protokol WhatsApp dengan Libsignal Protocol dan Noise Protocol.
1227
+
1228
+ Contoh: Lacak persentase baterai ponsel. Aktifkan log, pesan baterai muncul:
1229
+
1230
+ ```json
1231
+ {
1232
+ "level": 10,
1233
+ "fromMe": false,
1234
+ "frame": {
1235
+ "tag": "ib",
1236
+ "attrs": {
1237
+ "from": "@s.whatsapp.net"
1238
+ },
1239
+ "content": [
1240
+ {
1241
+ "tag": "edge_routing",
1242
+ "attrs": {},
1243
+ "content": [
1244
+ {
1245
+ "tag": "routing_info",
1246
+ "attrs": {},
1247
+ "content": {
1248
+ "type": "Buffer",
1249
+ "data": [8,2,8,5]
1250
+ }
1251
+ }
1252
+ ]
1253
+ }
1254
+ ]
1255
+ },
1256
+ "msg":"communication"
1257
+ }
1258
+ ```
1259
+
1260
+ `'frame'` punya: `tag` (jenis frame), `attrs` (metadata), `content` (data).
1261
+
1262
+ ### Daftarkan Callback untuk Event Websocket
1263
+
1264
+ > [!TIP] Lihat fungsi `onMessageReceived` di `socket.ts`.
1265
+
1266
+ ```javascript
1267
+ // Untuk tag 'edge_routing'
1268
+ sock.ws.on('CB:edge_routing', (node: BinaryNode) => { })
1269
+
1270
+ // Dengan id 'abcd'
1271
+ sock.ws.on('CB:edge_routing,id:abcd', (node: BinaryNode) => { })
1272
+
1273
+ // Dengan node routing_info
1274
+ sock.ws.on('CB:edge_routing,id:abcd,routing_info', (node: BinaryNode) => { })
1275
+ ```
1276
+
1277
+ ## 💡 Tips & Praktik Terbaik
1278
+
1279
+ - **Gunakan Caching**: Cache metadata grup untuk performa lebih baik.
1280
+ - **Tangani Rekoneksi**: Implementasikan auto-reconnect untuk kestabilan.
1281
+ - **Kelola Store**: Gunakan database (MongoDB, PostgreSQL) untuk produksi.
1282
+ - **Penanganan Error**: Bungkus panggilan socket dengan try-catch.
1283
+ - **Batas Rate**: Hormati batas WhatsApp untuk hindari ban—jangan spam.
1284
+ - **Keamanan**: Jangan bagikan kredensial auth; gunakan variabel lingkungan.
769
1285
 
770
- ## License
1286
+ ## 📄 Lisensi
771
1287
 
772
- MIT see [LICENSE](LICENSE).
1288
+ Didistribusikan di bawah Lisensi GPL-3.0. Lihat [LICENSE](LICENSE) untuk info lebih lanjut.
773
1289
 
774
1290
  ---
775
1291
 
776
- <sub>n4lyx — built by N4tzz.</sub>
1292
+ <div align="center">
1293
+ Fork dan dimodifikasi oleh Tim Wileys.
1294
+ Wileys - API WhatsApp Web Modern dengan Perbaikan @lid Ke @pn
1295
+ </div>