n4lyx 3.0.3 → 3.0.5

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
@@ -3,8 +3,8 @@
3
3
  ```
4
4
  ███╗ ██╗ ██╗ ██╗ ██╗ ██╗ ██╗ ██╗ ██╗
5
5
  ████╗ ██║ ██║ ██║ ██║ ╚██╗ ██╔╝ ╚██╗██╔╝
6
- ██╔██╗ ██║ ███████║ ██║ ╚████╔╝ ╚███╔╝
7
- ██║╚██╗██║ ╚════██║ ██║ ╚██╔╝ ██╔██╗
6
+ ██╔██╗ ██║ ███████║ ██║ ╚████╔╝ ╚███╔╝
7
+ ██║╚██╗██║ ╚════██║ ██║ ╚██╔╝ ██╔██╗
8
8
  ██║ ╚████║ ██║ ███████╗ ██║ ██╔╝ ██╗
9
9
  ╚═╝ ╚═══╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝
10
10
  ```
@@ -22,12 +22,43 @@
22
22
 
23
23
  ## Apa ini?
24
24
 
25
- **n4lyx** adalah WhatsApp Web API library untuk Node.js multi-device, proper `@lid → @pn` resolution, dan punya fitur-fitur eksklusif yang nggak ada di library lain.
25
+ **n4lyx** adalah WhatsApp Web API library untuk Node.js yang fokus pada **stabilitas, efisiensi, dan kemudahan penggunaan**.
26
26
 
27
- - **Tag all** mention semua member/admin/non-admin otomatis
28
- - 📸 **Group Status V2** — post story langsung ke group
29
- - 🎯 **Shorthand methods** — nggak perlu susun object manual
30
- - 🔧 **Bug-fixed** — semua edge case umum udah dipatch
27
+ Dirancang untuk **production-ready**: minim crash, tahan edge-case, dan tetap ringan tanpa bloat.
28
+
29
+ ---
30
+
31
+ ## ✨ Fitur Utama
32
+
33
+ - ⚡ **Tag All System** — mention semua / admin / non-admin otomatis
34
+ - 📸 **Group Status V2** — kirim story langsung ke group
35
+ - 🎯 **Shorthand Methods** — kirim pesan tanpa ribet object manual
36
+ - 🔄 **Auto-safe Handling** — banyak method sudah null-safe & anti crash
37
+ - 🧠 **Smart Internal Handling** — cache, retry, dan sync lebih stabil
38
+ - 📡 **Channel Tracker** — cek semua channel & group yang diikuti
39
+ - 👥 **Contact Fetcher** — ambil semua kontak tersimpan
40
+ - 🖼️ **Media Converter** — resize, compress, dan convert ke sticker otomatis
41
+ - 📦 **Sticker Pack Batch** — kirim sticker pack sekaligus (bukan 1-by-1)
42
+ - 📄 **Document Pack** — kirim banyak dokumen sekaligus dengan delay & parallel mode
43
+
44
+ ---
45
+
46
+ ## ⚠️ Stability & Fixes (Latest)
47
+
48
+ - ✅ **Profile Picture Safe Fetch** — tidak crash jika 404 / not-authorized, return `null`
49
+ - ✅ **Message Handling Stabil** — dedup cache dibungkus try/catch
50
+ - ✅ **Sync State Robust** — transisi state lebih aman, timeout tetap berjalan
51
+ - ✅ **Group Metadata Safe Guard** — tidak error jika data kosong
52
+ - ✅ **Newsletter Parsing Aman** — selalu dilindungi, tidak crash
53
+ - ✅ **Interactive & Button Normalization** — support berbagai format tombol
54
+ - ✅ **isOnWhatsApp Konsisten** — selalu return object (tidak undefined)
55
+ - ✅ **chalk Optional** — fallback otomatis jika tidak terinstall
56
+ - ✅ **Broadcast & Group Fix** — method internal lebih akurat
57
+ - ✅ **sendDocument Auto Mime** — deteksi mimetype otomatis dari extension
58
+ - ✅ **sendStickerPack Batch** — kirim paralel per batch, bukan 1-by-1
59
+ - ✅ **Auto Join Channel** — client otomatis join channel saat connect
60
+
61
+ ---
31
62
 
32
63
  > **Disclaimer:** Bukan afiliasi dengan WhatsApp Inc. Jangan spam. Jangan abuse. Konsekuensi akun banned adalah tanggung jawab kamu sendiri.
33
64
 
@@ -39,49 +70,44 @@
39
70
  npm i n4lyx
40
71
  ```
41
72
 
42
- ```js
43
- // CommonJS
44
- const { default: makeWASocket } = require('n4lyx')
73
+ ```bash
74
+ # Optional tapi direkomendasikan untuk fitur convert/sticker
75
+ npm i sharp # lebih cepat (recommended)
76
+ npm i jimp # fallback jika sharp tidak bisa
77
+ npm i link-preview-js
78
+ npm i qrcode-terminal
79
+ ```
45
80
 
46
- // ESM
47
- import makeWASocket from 'n4lyx'
81
+ ```js
82
+ const { default: makeWASocket } = require("n4lyx")
48
83
  ```
49
84
 
50
85
  ---
51
86
 
52
87
  ## Quick Start
53
88
 
54
- Ini contoh bot paling minimal yang bisa jalan — terima pesan, balas "pong", auto-reconnect kalau putus.
55
-
56
89
  ```js
57
- const { default: makeWASocket, DisconnectReason, useMultiFileAuthState } = require('n4lyx')
58
- const { Boom } = require('@hapi/boom')
90
+ const { default: makeWASocket, DisconnectReason, useMultiFileAuthState } = require("n4lyx")
91
+ const { Boom } = require("@hapi/boom")
59
92
 
60
93
  async function start() {
61
- const { state, saveCreds } = await useMultiFileAuthState('auth')
94
+ const { state, saveCreds } = await useMultiFileAuthState("auth")
62
95
 
63
- const sock = makeWASocket({
64
- auth: state,
65
- printQRInTerminal: true
66
- })
96
+ const sock = makeWASocket({ auth: state, printQRInTerminal: true })
67
97
 
68
- // Handle koneksi
69
- sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
70
- if (connection === 'close') {
71
- const shouldReconnect =
72
- new Boom(lastDisconnect?.error)?.output?.statusCode !== DisconnectReason.loggedOut
98
+ sock.ev.on("connection.update", ({ connection, lastDisconnect }) => {
99
+ if (connection === "close") {
100
+ const shouldReconnect = new Boom(lastDisconnect?.error)?.output?.statusCode !== DisconnectReason.loggedOut
73
101
  if (shouldReconnect) start()
74
102
  }
75
103
  })
76
104
 
77
- // Simpan credentials
78
- sock.ev.on('creds.update', saveCreds)
105
+ sock.ev.on("creds.update", saveCreds)
79
106
 
80
- // Terima pesan
81
- sock.ev.on('messages.upsert', async ({ messages }) => {
107
+ sock.ev.on("messages.upsert", async ({ messages }) => {
82
108
  const msg = messages[0]
83
109
  if (!msg.message) return
84
- await sock.sendMessage(msg.key.remoteJid, { text: 'pong' })
110
+ await sock.sendMessage(msg.key.remoteJid, { text: "pong" })
85
111
  })
86
112
  }
87
113
 
@@ -93,458 +119,358 @@ start()
93
119
  ## Login
94
120
 
95
121
  ### QR Code
96
-
97
- Scan QR dari terminal — paling cepat untuk testing.
98
-
99
122
  ```js
100
123
  const sock = makeWASocket({ printQRInTerminal: true })
101
124
  ```
102
125
 
103
126
  ### Pairing Code
104
-
105
- Cocok kalau nggak bisa scan QR (server headless, dll).
106
-
107
127
  ```js
108
128
  const sock = makeWASocket({ printQRInTerminal: false })
109
-
110
129
  if (!sock.authState.creds.registered) {
111
- const code = await sock.requestPairingCode('628XXXXXXXXX')
112
- console.log('Kode pairing:', code) // → misalnya: N4LX-1234
130
+ const code = await sock.requestPairingCode("628XXXXXXXXX")
131
+ console.log("Kode pairing:", code)
113
132
  }
114
133
  ```
115
134
 
116
- Custom kode (tepat 8 karakter):
117
-
118
- ```js
119
- const code = await sock.requestPairingCode('628XXXXXXXXX', 'N4LYX001')
120
- ```
121
-
122
135
  ### Simpan Session
123
-
124
- Session disimpan ke folder `auth/`. Kalau file-nya ada, next run langsung connect tanpa QR lagi.
125
-
126
136
  ```js
127
- const { state, saveCreds } = await useMultiFileAuthState('auth')
137
+ const { state, saveCreds } = await useMultiFileAuthState("auth")
128
138
  const sock = makeWASocket({ auth: state })
129
- sock.ev.on('creds.update', saveCreds)
139
+ sock.ev.on("creds.update", saveCreds)
130
140
  ```
131
141
 
132
- > **Untuk production:** simpan credentials ke database (PostgreSQL / MongoDB / Redis), bukan ke disk. Disk bisa corrupt, database tidak.
133
-
134
142
  ---
135
143
 
136
144
  ## Config Penting
137
145
 
138
146
  ### Cache Group Metadata
139
-
140
- Wajib kalau bot kamu aktif di banyak group. Ini ngurangin request ke WA API secara signifikan.
141
-
142
147
  ```js
143
- const NodeCache = require('node-cache')
148
+ const NodeCache = require("node-cache")
144
149
  const groupCache = new NodeCache({ stdTTL: 300, useClones: false })
145
150
 
146
151
  const sock = makeWASocket({
147
152
  cachedGroupMetadata: async (jid) => groupCache.get(jid)
148
153
  })
149
154
 
150
- // Update cache kalau ada perubahan di group
151
- sock.ev.on('groups.update', async ([e]) => {
152
- groupCache.set(e.id, await sock.groupMetadata(e.id))
153
- })
154
- sock.ev.on('group-participants.update', async (e) => {
155
- groupCache.set(e.id, await sock.groupMetadata(e.id))
156
- })
155
+ sock.ev.on("groups.update", async ([e]) => { groupCache.set(e.id, await sock.groupMetadata(e.id)) })
156
+ sock.ev.on("group-participants.update", async (e) => { groupCache.set(e.id, await sock.groupMetadata(e.id)) })
157
157
  ```
158
158
 
159
159
  ### Background Mode
160
-
161
- Bot nggak kelihatan online tapi tetap terima pesan.
162
-
163
160
  ```js
164
161
  const sock = makeWASocket({ markOnlineOnConnect: false })
165
162
  ```
166
163
 
167
- ### Message Store (untuk Poll & Retry)
164
+ ---
168
165
 
169
- Diperlukan untuk dekripsi poll vote dan message retry.
166
+ ## NEW: Channel, Group & Contact Tracker
170
167
 
168
+ ### Cek Semua Channel yang Diikuti
171
169
  ```js
172
- const sock = makeWASocket({
173
- getMessage: async (key) => await getMessageFromDB(key)
174
- // implementasi getMessageFromDB sesuai DB kamu
175
- })
176
- ```
177
-
178
- ---
170
+ const channels = await sock.getFollowedChannels()
171
+ // [{ jid, name, description, subscribers, role, state, invite }, ...]
179
172
 
180
- ## Kirim Pesan
173
+ for (const ch of channels) {
174
+ console.log(`📡 ${ch.name} — ${ch.subscribers} subscribers`)
175
+ }
176
+ ```
181
177
 
182
- Semua pengiriman pesan lewat satu method: `sock.sendMessage(jid, content, options?)`.
178
+ ### Cek Semua Group yang Diikuti
179
+ ```js
180
+ // Cepat (tanpa profile pic)
181
+ const groups = await sock.getJoinedGroups()
182
+ // → [{ id, subject, participants, ... }, ...]
183
183
 
184
- ### Teks biasa
184
+ // Lengkap dengan foto profil
185
+ const groupsFull = await sock.getJoinedGroups(true)
186
+ // → [{ id, subject, participants, profilePic, ... }, ...]
185
187
 
186
- ```js
187
- await sock.sendMessage(jid, { text: 'Halo!' })
188
+ for (const g of groups) {
189
+ console.log(`👥 ${g.subject} ${g.participants?.length} member`)
190
+ }
188
191
  ```
189
192
 
190
- ### Reply / Quote
191
-
193
+ ### Cek Semua Kontak
192
194
  ```js
193
- await sock.sendMessage(jid, { text: 'Oke siap' }, { quoted: message })
195
+ const contacts = await sock.getAllContacts()
196
+ // → [{ jid, lid, exists, name }, ...]
197
+
198
+ const saved = contacts.filter(c => c.exists)
199
+ console.log(`📒 Total kontak tersimpan: ${saved.length}`)
194
200
  ```
195
201
 
196
- ### Mention user
202
+ ---
197
203
 
204
+ ## NEW: Convert, Resize & Compress ⚡
205
+
206
+ ### Convert Image → Sticker WebP
198
207
  ```js
199
- await sock.sendMessage(jid, {
200
- text: 'Hei @628XXXXXXXXX, cek ini',
201
- mentions: ['628XXXXXXXXX@s.whatsapp.net']
208
+ // Dari buffer gambar biasa
209
+ const { buffer, metadata } = await sock.convertToSticker(imageBuffer, {
210
+ packName: "Pack Gue",
211
+ packPublisher: "N4tzz",
212
+ quality: 80, // 1-100
213
+ maxSize: 512, // max px (default 512)
202
214
  })
203
- ```
204
-
205
- ### Tag All ⚡
215
+ await sock.sendMessage(jid, { sticker: buffer, ...metadata })
206
216
 
207
- Fitur eksklusif n4lyx. Auto-fetch participant list lalu mention semua sekaligus.
217
+ // Atau langsung kirim setelah convert
218
+ const result = await sock.convertToSticker(imageBuffer, { packName: "Sticker", packPublisher: "Bot" })
219
+ await sock.sendStickerWithMetadata(jid, result.buffer, result.metadata)
220
+ ```
208
221
 
222
+ ### Resize & Compress Image
209
223
  ```js
210
- // Tag semua member
211
- await sock.sendMessage(jid, {
212
- text: '📢 Pengumuman penting buat semua!',
213
- tagAll: true
224
+ // Resize ke max 800px, format JPEG, quality 75%
225
+ const compressed = await sock.convertMedia(imageBuffer, {
226
+ maxSize: 800,
227
+ format: "jpeg",
228
+ quality: 75,
214
229
  })
215
-
216
- // Tag admin aja
217
- await sock.sendMessage(jid, {
218
- text: '🔔 Info untuk para admin',
219
- tagAll: true,
220
- tagAllScope: 'admins'
230
+ await sock.sendImage(jid, compressed, "Foto sudah dikompress")
231
+
232
+ // Resize ke dimensi spesifik
233
+ const resized = await sock.convertMedia(imageBuffer, {
234
+ width: 1280,
235
+ height: 720,
236
+ format: "webp",
237
+ quality: 85,
221
238
  })
222
239
 
223
- // Tag non-admin aja
224
- await sock.sendMessage(jid, {
225
- text: '👋 Hei member!',
226
- tagAll: true,
227
- tagAllScope: 'non_admins'
228
- })
240
+ // Convert ke PNG
241
+ const png = await sock.convertMedia(imageBuffer, { format: "png", quality: 90 })
229
242
  ```
230
243
 
231
- Atau ambil list JID-nya dulu kalau mau diproses manual:
244
+ > **Catatan:** Butuh `sharp` (recommended) atau `jimp` terinstall.
245
+ > ```bash
246
+ > npm i sharp # atau: npm i jimp
247
+ > ```
232
248
 
233
- ```js
234
- const jids = await sock.groupTagAll(groupJid, 'all')
235
- // → ['628xxx@s.whatsapp.net', '628yyy@s.whatsapp.net', ...]
236
- ```
237
-
238
- ### Media
249
+ ---
239
250
 
240
- Semua media support: `Buffer`, `{ url: '...' }`, atau `{ stream: Stream }`.
251
+ ## NEW: Sticker Pack Batch
241
252
 
253
+ ### Kirim Sticker Pack Sekaligus (Batch Parallel)
242
254
  ```js
243
- // Gambar
244
- await sock.sendMessage(jid, {
245
- image: { url: './foto.jpg' },
246
- caption: 'Caption foto'
255
+ // sendStickerPack — sekarang batch paralel per 5, bukan 1-by-1
256
+ await sock.sendStickerPack(jid, [buf1, buf2, buf3, buf4, buf5], "Pack Gue", "N4tzz", {
257
+ batchSize: 5, // kirim 5 sekaligus per batch
258
+ delayBatch: 500, // delay 500ms antar batch
247
259
  })
248
260
 
249
- // Video
250
- await sock.sendMessage(jid, {
251
- video: { url: './video.mp4' },
252
- caption: 'Caption video'
261
+ // sendStickerPackAlbum — batch lebih besar (max 10 per batch)
262
+ const results = await sock.sendStickerPackAlbum(jid, [buf1, buf2, buf3], "Pack Gue", "N4tzz", {
263
+ batchSize: 10,
264
+ delayBatch: 800,
253
265
  })
266
+ console.log(results) // [{ success, msg? }, ...]
267
+ ```
254
268
 
255
- // Audio biasa
256
- await sock.sendMessage(jid, {
257
- audio: { url: './audio.mp3' },
258
- mimetype: 'audio/mp4'
259
- })
269
+ ---
260
270
 
261
- // Voice note (PTT)
262
- await sock.sendMessage(jid, {
263
- audio: fs.readFileSync('./voice.ogg'),
264
- mimetype: 'audio/ogg; codecs=opus',
265
- ptt: true
266
- })
271
+ ## NEW: Document Pack ⚡
267
272
 
268
- // Sticker
269
- await sock.sendMessage(jid, {
270
- sticker: fs.readFileSync('./sticker.webp')
273
+ ### Kirim Banyak Dokumen Sekaligus
274
+ ```js
275
+ // Sequential dengan delay (default)
276
+ const results = await sock.sendDocumentPack(jid, [
277
+ { buffer: pdfBuffer, fileName: "laporan.pdf", caption: "Ini laporannya" },
278
+ { buffer: excelBuf, fileName: "data.xlsx", caption: "Data excel" },
279
+ { url: "https://...", fileName: "manual.pdf" },
280
+ ], {
281
+ delayMs: 600, // delay 600ms antar dokumen
271
282
  })
272
283
 
273
- // Dokumen
274
- await sock.sendMessage(jid, {
275
- document: { url: './laporan.pdf' },
276
- mimetype: 'application/pdf',
277
- fileName: 'laporan.pdf'
278
- })
284
+ // Kirim semua sekaligus (paralel)
285
+ const results = await sock.sendDocumentPack(jid, documents, { parallel: true })
286
+
287
+ console.log(results) // [{ success, msg? }, ...]
279
288
  ```
280
289
 
281
- ### Link Preview
290
+ > **Auto Mime Detection** — tidak perlu set `mimetype` manual. Deteksi otomatis dari extension:
291
+ > `.pdf` → `application/pdf`, `.xlsx` → spreadsheet, `.apk` → android package, dll.
282
292
 
283
- Install `link-preview-js` dulu, lalu kirim teks dengan URL biasa — preview auto-generate.
293
+ ---
284
294
 
285
- ```bash
286
- npm i link-preview-js
295
+ ## Kirim Pesan
296
+
297
+ ### Teks biasa
298
+ ```js
299
+ await sock.sendMessage(jid, { text: "Halo!" })
300
+ ```
301
+
302
+ ### Reply / Quote
303
+ ```js
304
+ await sock.sendMessage(jid, { text: "Oke siap" }, { quoted: message })
287
305
  ```
288
306
 
307
+ ### Mention user
289
308
  ```js
290
309
  await sock.sendMessage(jid, {
291
- text: 'Cek library ini: https://npmjs.com/package/n4lyx'
310
+ text: "Hei @628XXXXXXXXX, cek ini",
311
+ mentions: ["628XXXXXXXXX@s.whatsapp.net"]
292
312
  })
293
313
  ```
294
314
 
315
+ ### Tag All ⚡
316
+ ```js
317
+ // Tag semua member
318
+ await sock.sendMessage(jid, { text: "📢 Pengumuman!", tagAll: true })
319
+ // Tag admin saja
320
+ await sock.sendMessage(jid, { text: "🔔 Info admin", tagAll: true, tagAllScope: "admins" })
321
+ // Tag non-admin saja
322
+ await sock.sendMessage(jid, { text: "👋 Hei member!", tagAll: true, tagAllScope: "non_admins" })
323
+
324
+ // Ambil list JID manual
325
+ const jids = await sock.groupTagAll(groupJid, "all")
326
+ ```
327
+
295
328
  ---
296
329
 
297
330
  ## Shorthand Methods ⚡
298
331
 
299
- Biar nggak perlu susun object setiap kali, n4lyx punya shorthand methods langsung di `sock`.
300
-
301
332
  ### Gambar & Video
302
-
303
333
  ```js
304
- // Gambar
305
- await sock.sendImage(jid, buffer, 'Caption opsional')
306
- await sock.sendImage(jid, { url: './foto.jpg' })
307
-
308
- // Video
309
- await sock.sendVideo(jid, buffer, 'Caption opsional')
334
+ await sock.sendImage(jid, buffer, "Caption opsional")
335
+ await sock.sendImage(jid, { url: "./foto.jpg" })
336
+ await sock.sendVideo(jid, buffer, "Caption opsional")
310
337
  ```
311
338
 
312
339
  ### Audio
313
-
314
340
  ```js
315
- await sock.sendAudio(jid, buffer) // audio biasa
316
- await sock.sendAudio(jid, buffer, true) // voice note / PTT
317
- await sock.sendAudioPTT(jid, buffer) // alias PTT
318
- await sock.sendVoiceNote(jid, buffer) // alias voice note
341
+ await sock.sendAudio(jid, buffer) // audio biasa
342
+ await sock.sendAudio(jid, buffer, true) // voice note / PTT
343
+ await sock.sendAudioPTT(jid, buffer) // alias PTT
344
+ await sock.sendVoiceNote(jid, buffer) // alias voice note
319
345
  ```
320
346
 
321
- ### Dokumen
322
-
347
+ ### Dokumen (Auto Mime Detection)
323
348
  ```js
324
- await sock.sendDocument(jid, buffer, 'laporan.pdf', 'application/pdf', 'Ini file-nya')
349
+ // Mimetype auto-detect dari extension tidak perlu set manual
350
+ await sock.sendDocument(jid, buffer, "laporan.pdf", null, "Ini file-nya")
351
+ await sock.sendDocument(jid, buffer, "data.xlsx")
352
+ await sock.sendDocument(jid, buffer, "app.apk", null, "Update terbaru")
353
+
354
+ // Atau set manual jika perlu
355
+ await sock.sendDocument(jid, buffer, "file.bin", "application/octet-stream")
325
356
  ```
326
357
 
327
358
  ### GIF & Video Note
328
-
329
359
  ```js
330
- // GIF animasi
331
- await sock.sendGIF(jid, gifBuffer, 'wkwk')
332
-
333
- // Circular video note (kayak voice note tapi video)
360
+ await sock.sendGIF(jid, gifBuffer, "wkwk")
334
361
  await sock.sendPTV(jid, videoBuffer)
335
- await sock.sendPTV(jid, videoBuffer, { quoted: m }) // dengan quote
362
+ await sock.sendPTV(jid, videoBuffer, { quoted: m })
336
363
  ```
337
364
 
338
365
  ### View Once
339
-
340
- Media otomatis hilang setelah dilihat sekali.
341
-
342
366
  ```js
343
367
  await sock.sendViewOnce(jid, { image: buffer })
344
368
  await sock.sendViewOnce(jid, { video: buffer }, { quoted: m })
345
- await sock.sendViewOnce(jid, { audio: buffer, mimetype: 'audio/mp4' })
369
+ await sock.sendViewOnce(jid, { audio: buffer, mimetype: "audio/mp4" })
346
370
  ```
347
371
 
348
372
  ### Sticker
349
-
350
373
  ```js
351
- // Dari Buffer
352
374
  await sock.sendStickerFromBuffer(jid, buffer)
353
-
354
- // Dari URL langsung
355
- await sock.sendStickerFromUrl(jid, 'https://example.com/sticker.webp')
356
-
357
- // Dengan metadata pack
375
+ await sock.sendStickerFromUrl(jid, "https://example.com/sticker.webp")
358
376
  await sock.sendStickerWithMetadata(jid, buffer, {
359
- packName: 'Pack Gue',
360
- packPublisher: 'N4tzz',
361
- categories: ['😂']
377
+ packName: "Pack Gue", packPublisher: "N4tzz", categories: ["😂"]
362
378
  })
363
-
364
- // Kirim banyak sticker sekaligus (max 30, ada auto-delay)
365
- await sock.sendStickerPack(jid, [buf1, buf2, buf3], 'Pack Gue', 'N4tzz')
379
+ // Kirim banyak sticker (batch paralel, bukan 1-by-1)
380
+ await sock.sendStickerPack(jid, [buf1, buf2, buf3], "Pack Gue", "N4tzz")
366
381
  ```
367
382
 
368
383
  ### Album
369
-
370
- Kumpulan foto/video yang bisa di-swipe (max 10 item, bisa mix image + video).
371
-
372
384
  ```js
373
385
  await sock.sendAlbum(jid, [
374
- { image: buf1, caption: 'Foto 1' },
375
- { image: buf2, caption: 'Foto 2' },
376
- { video: buf3, caption: 'Video' }
386
+ { image: buf1, caption: "Foto 1" },
387
+ { image: buf2, caption: "Foto 2" },
388
+ { video: buf3, caption: "Video" }
377
389
  ])
378
390
  ```
379
391
 
380
392
  ### Poll
381
-
382
393
  ```js
383
- // Pilih lebih dari satu
384
- await sock.sendPoll(jid, 'Bahasa favorit?', ['JavaScript', 'Python', 'Go'])
385
-
386
- // Pilih satu saja
387
- await sock.sendPoll(jid, 'Setuju?', ['Ya', 'Tidak'], { selectableCount: 1 })
394
+ await sock.sendPoll(jid, "Bahasa favorit?", ["JavaScript", "Python", "Go"])
395
+ await sock.sendPoll(jid, "Setuju?", ["Ya", "Tidak"], { selectableCount: 1 })
388
396
  ```
389
397
 
390
398
  ### Lokasi
391
-
392
399
  ```js
393
- // Lokasi statis
394
- await sock.sendLocation(jid, -7.797068, 110.370529, 'Yogyakarta')
395
-
396
- // Live location
400
+ await sock.sendLocation(jid, -7.797068, 110.370529, "Yogyakarta")
397
401
  await sock.sendLiveLocation(jid, -7.79, 110.37, 10, 300)
398
- // parameter: lat, lng, accuracy (meter), duration (detik)
399
402
  ```
400
403
 
401
404
  ### Kontak
402
-
403
405
  ```js
404
- // Single
405
- await sock.sendContact(jid, {
406
- fullName: 'Budi Santoso',
407
- phoneNumber: '+62812xxxxxxx',
408
- org: 'Acme Corp' // opsional
409
- })
410
-
411
- // Multiple sekaligus
406
+ await sock.sendContact(jid, { fullName: "Budi Santoso", phoneNumber: "+62812xxxxxxx", org: "Acme" })
412
407
  await sock.sendContact(jid, [
413
- { fullName: 'Budi', phoneNumber: '+62812xxxxxxx' },
414
- { fullName: 'Sari', phoneNumber: '+62813xxxxxxx' }
408
+ { fullName: "Budi", phoneNumber: "+62812xxxxxxx" },
409
+ { fullName: "Sari", phoneNumber: "+62813xxxxxxx" }
415
410
  ])
416
411
  ```
417
412
 
418
413
  ### Event & Jadwal Call
419
-
420
414
  ```js
421
- // WhatsApp Event
422
415
  await sock.sendEvent(jid, {
423
- name: 'Rapat Mingguan',
424
- description: 'Sync tim setiap Senin',
425
- startTime: Date.now() + 3_600_000, // 1 jam dari sekarang
426
- endTime: Date.now() + 7_200_000, // 2 jam dari sekarang
427
- location: 'Google Meet',
428
- joinLink: 'https://meet.google.com/xxx'
416
+ name: "Rapat Mingguan", description: "Sync tim",
417
+ startTime: Date.now() + 3_600_000, endTime: Date.now() + 7_200_000,
418
+ location: "Google Meet", joinLink: "https://meet.google.com/xxx"
429
419
  })
430
-
431
- // Jadwalkan panggilan
432
- await sock.sendScheduledCall(jid, 'Catch-up session', Date.now() + 86_400_000) // video call (default)
433
- await sock.sendScheduledCall(jid, 'Voice call', Date.now() + 3_600_000, 2) // voice call
420
+ await sock.sendScheduledCall(jid, "Catch-up", Date.now() + 86_400_000) // video
421
+ await sock.sendScheduledCall(jid, "Voice call", Date.now() + 3_600_000, 2) // voice
434
422
  ```
435
423
 
436
424
  ### Reply & Mention
437
-
438
425
  ```js
439
- // Reply cepat
440
- await sock.sendReply(jid, 'Oke siap!', m)
441
-
442
- // Reply dengan media
443
- await sock.sendMediaReply(jid, { image: buffer, caption: 'ini' }, m)
444
-
445
- // Reply + mention sekaligus
446
- await sock.sendQuotedText(jid, 'Hayo @kamu', m, ['628xxx@s.whatsapp.net'])
447
-
448
- // Teks + mention
449
- await sock.sendTextWithMentions(jid, 'Halo @A dan @B', [jidA, jidB])
450
-
451
- // Tag all shorthand
452
- await sock.sendTagAll(jid, '📢 Pengumuman untuk semua')
453
- await sock.sendTagAll(jid, '🔔 Khusus admin', 'admins')
454
- await sock.sendTagAll(jid, '👋 Hei member', 'non_admins')
455
-
456
- // Tag all + mention
457
- await sock.sendMentionAll(jid, 'Hei semua!')
426
+ await sock.sendReply(jid, "Oke siap!", m)
427
+ await sock.sendMediaReply(jid, { image: buffer, caption: "ini" }, m)
428
+ await sock.sendQuotedText(jid, "Hayo @kamu", m, ["628xxx@s.whatsapp.net"])
429
+ await sock.sendTextWithMentions(jid, "Halo @A dan @B", [jidA, jidB])
430
+ await sock.sendTagAll(jid, "📢 Pengumuman untuk semua")
431
+ await sock.sendTagAll(jid, "🔔 Khusus admin", "admins")
432
+ await sock.sendMentionAll(jid, "Hei semua!")
458
433
  ```
459
434
 
460
435
  ### Invite Group
461
-
462
- Kirim invite sebagai card (bukan plain link).
463
-
464
436
  ```js
465
- await sock.sendGroupInvite(jid, '120363xxx@g.us')
437
+ await sock.sendGroupInvite(jid, "120363xxx@g.us")
466
438
  ```
467
439
 
468
440
  ### Typing Indicator
469
-
470
441
  ```js
471
- // Typing 3 detik lalu berhenti
472
- await sock.sendTyping(jid)
473
-
474
- // Recording 2 detik
475
- await sock.sendTyping(jid, 2000, 'recording')
476
-
477
- // Kirim pesan dengan typing dulu
478
- await sock.sendWithTyping(jid, { text: 'Halo!' })
479
- await sock.sendWithTyping(jid, { text: 'Halo!' }, {}, 2000) // typing 2 detik
442
+ await sock.sendTyping(jid) // typing 3 detik
443
+ await sock.sendTyping(jid, 2000, "recording") // recording 2 detik
444
+ await sock.sendWithTyping(jid, { text: "Halo!" })
445
+ await sock.sendWithTyping(jid, { text: "Halo!" }, {}, 2000)
480
446
  ```
481
447
 
482
448
  ### Broadcast & Multi-Message
483
-
484
449
  ```js
485
- // Kirim ke banyak JID (auto deduplicate, ada delay antar kirim)
486
450
  const results = await sock.broadcastMessage(
487
- ['628xxx@s.whatsapp.net', '628yyy@s.whatsapp.net'],
488
- { text: 'Pengumuman penting!' },
489
- { delayMs: 1000 }
451
+ ["628xxx@s.whatsapp.net", "628yyy@s.whatsapp.net"],
452
+ { text: "Pengumuman penting!" }, { delayMs: 1000 }
490
453
  )
491
- // results: [{ jid, success, msg? }, ...]
492
-
493
- // Broadcast ke semua group yang diikuti
494
- await sock.broadcastToGroups([groupJid1, groupJid2], { text: 'Halo semua group!' })
495
-
496
- // Kirim array pesan berurutan ke satu JID
454
+ await sock.broadcastToGroups({ text: "Halo semua group!" })
497
455
  await sock.sendMultipleMessages(jid, [
498
- { text: 'Pesan 1' },
499
- { text: 'Pesan 2' },
500
- { image: buffer, caption: 'Foto' }
501
- ], 800) // delay 800ms antar pesan
456
+ { text: "Pesan 1" }, { text: "Pesan 2" }, { image: buffer, caption: "Foto" }
457
+ ], 800)
502
458
  ```
503
459
 
504
460
  ### Status / Story
505
-
506
461
  ```js
507
- // Status pribadi
508
- await sock.sendStatus({ text: 'Pagi semua! ☀️', backgroundColor: '#128C7E' })
509
- await sock.sendStatus({ image: buffer, caption: 'Foto hari ini' })
510
- await sock.sendStatus({ video: buffer })
511
-
512
- // Batasi siapa yang bisa lihat
513
- await sock.sendStatus({ text: 'Khusus kamu' }, ['628xxx@s.whatsapp.net'])
462
+ await sock.sendStatus({ text: "Pagi semua! ☀️", backgroundColor: "#128C7E" })
463
+ await sock.sendStatus({ image: buffer, caption: "Foto hari ini" })
464
+ await sock.sendStatus({ text: "Khusus kamu" }, ["628xxx@s.whatsapp.net"])
514
465
  ```
515
466
 
516
467
  ### Group Status V2 ⚡
517
-
518
- Post story langsung di dalam group — muncul kayak story WhatsApp tapi di group.
519
-
520
468
  ```js
521
- // Teks
522
- await sock.groupStatusV2('120363xxx@g.us', {
523
- text: 'GM semua! 🌅',
524
- backgroundColor: '#25D366'
525
- })
526
-
527
- // Teks dengan font custom
528
- await sock.groupStatusV2('120363xxx@g.us', {
529
- text: 'Selamat ulang tahun! 🎉',
530
- backgroundColor: '#FF6B6B',
531
- font: 1
532
- })
533
-
534
- // Gambar
535
- await sock.groupStatusV2('120363xxx@g.us', {
536
- image: buffer,
537
- caption: 'Foto kegiatan hari ini'
538
- })
539
-
540
- // Video
541
- await sock.groupStatusV2('120363xxx@g.us', {
542
- video: buffer,
543
- caption: 'Tonton ini!'
544
- })
545
-
546
- // Sticker
547
- await sock.groupStatusV2('120363xxx@g.us', { sticker: buffer })
469
+ await sock.groupStatusV2("120363xxx@g.us", { text: "GM semua! 🌅", backgroundColor: "#25D366" })
470
+ await sock.groupStatusV2("120363xxx@g.us", { text: "HBD! 🎉", backgroundColor: "#FF6B6B", font: 1 })
471
+ await sock.groupStatusV2("120363xxx@g.us", { image: buffer, caption: "Foto kegiatan" })
472
+ await sock.groupStatusV2("120363xxx@g.us", { video: buffer, caption: "Tonton!" })
473
+ await sock.groupStatusV2("120363xxx@g.us", { sticker: buffer })
548
474
  ```
549
475
 
550
476
  ---
@@ -552,34 +478,20 @@ await sock.groupStatusV2('120363xxx@g.us', { sticker: buffer })
552
478
  ## Edit, Delete, React
553
479
 
554
480
  ```js
555
- const sent = await sock.sendMessage(jid, { text: 'Ada typo nih' })
556
-
557
- // Edit pesan
558
- await sock.editMessage(jid, sent.key, 'Sudah diperbaiki')
559
-
560
- // Hapus untuk semua
481
+ const sent = await sock.sendMessage(jid, { text: "Ada typo" })
482
+ await sock.editMessage(jid, sent.key, "Sudah diperbaiki")
561
483
  await sock.deleteMessage(jid, sent.key)
562
-
563
- // Pin pesan
564
484
  await sock.pinMessage(jid, m.key) // 24 jam
565
485
  await sock.pinMessage(jid, m.key, 604800) // 7 hari
566
486
  await sock.pinMessage(jid, m.key, 0) // unpin
567
-
568
- // Bookmark / keep
569
- await sock.keepMessage(jid, m.key) // keep
570
- await sock.keepMessage(jid, m.key, false) // unkeep
571
-
572
- // Bintang / star
573
- await sock.starMessage(jid, m.key, true) // bintangin
574
- await sock.unstarMessage(jid, m.key) // hapus bintang
575
-
576
- // React
577
- await sock.reactMessage(jid, m.key, '❤️')
578
- await sock.reactMessage(jid, m.key, '') // hapus reaksi
579
-
580
- // Forward
487
+ await sock.keepMessage(jid, m.key)
488
+ await sock.keepMessage(jid, m.key, false)
489
+ await sock.starMessage(jid, m.key, true)
490
+ await sock.unstarMessage(jid, m.key)
491
+ await sock.reactMessage(jid, m.key, "❤️")
492
+ await sock.reactMessage(jid, m.key, "") // hapus reaksi
581
493
  await sock.forwardMessage(jid, m)
582
- await sock.forwardWithComment(jid, m, 'Check ini!') // forward + komentar
494
+ await sock.forwardWithComment(jid, m, "Check ini!")
583
495
  ```
584
496
 
585
497
  ---
@@ -587,32 +499,21 @@ await sock.forwardWithComment(jid, m, 'Check ini!') // forward + komentar
587
499
  ## Chat Management
588
500
 
589
501
  ```js
590
- // Archive / unarchive
591
502
  await sock.archiveChat(jid, lastMsg)
592
503
  await sock.unarchiveChat(jid, lastMsg)
593
-
594
- // Pin / unpin chat
595
504
  await sock.pinChat(jid)
596
505
  await sock.unpinChat(jid)
597
-
598
- // Mute / unmute
599
- await sock.muteJid(jid) // mute 8 jam
600
- await sock.muteJid(jid, 24 * 60 * 60 * 1000) // mute 24 jam
506
+ await sock.muteJid(jid)
507
+ await sock.muteJid(jid, 24 * 60 * 60 * 1000)
601
508
  await sock.unmuteJid(jid)
602
-
603
- // Tandai baca / belum baca
604
509
  await sock.markAsRead([m.key])
605
- await sock.sendSeen(jid) // alias markAsRead
510
+ await sock.sendSeen(jid)
606
511
  await sock.markAsUnread(jid, lastMsg)
607
-
608
- // Hapus & bersihkan
609
512
  await sock.deleteChat(jid)
610
513
  await sock.clearChat(jid)
611
-
612
- // Block / unblock
613
514
  await sock.blockUser(jid)
614
515
  await sock.unblockUser(jid)
615
- await sock.fetchBlocklist() // ambil daftar yang diblokir
516
+ await sock.fetchBlocklist()
616
517
  ```
617
518
 
618
519
  ---
@@ -620,15 +521,10 @@ await sock.fetchBlocklist() // ambil daftar yang diblokir
620
521
  ## Disappearing Messages
621
522
 
622
523
  ```js
623
- // Aktifkan di chat
624
- await sock.sendDisappearingToggle(jid, 86400) // 24 jam
625
- await sock.setGroupDisappearing(jid, 604800) // 7 hari di group
626
- await sock.setGroupDisappearing(jid, 0) // matikan
627
-
628
- // Kirim satu pesan sebagai ephemeral
629
- await sock.sendDisappearingMessage(jid, { text: 'Pesan ini akan hilang' }, 86400)
630
-
631
- // Set default disappearing mode
524
+ await sock.sendDisappearingToggle(jid, 86400)
525
+ await sock.setGroupDisappearing(jid, 604800)
526
+ await sock.setGroupDisappearing(jid, 0)
527
+ await sock.sendDisappearingMessage(jid, { text: "Pesan ini akan hilang" }, 86400)
632
528
  await sock.setDefaultDisappearing(86400)
633
529
  ```
634
530
 
@@ -637,61 +533,37 @@ await sock.setDefaultDisappearing(86400)
637
533
  ## Groups
638
534
 
639
535
  ```js
640
- // Buat group baru
641
- const group = await sock.groupCreate('Nama Group', ['628xxx@s.whatsapp.net'])
642
- console.log('Group ID:', group.gid)
643
-
644
- // Tambah / hapus / promote / demote member
645
- await sock.groupParticipantsUpdate(jid, ['628xxx@s.whatsapp.net'], 'add')
646
- await sock.groupParticipantsUpdate(jid, ['628xxx@s.whatsapp.net'], 'remove')
647
- await sock.groupParticipantsUpdate(jid, ['628xxx@s.whatsapp.net'], 'promote')
648
- await sock.groupParticipantsUpdate(jid, ['628xxx@s.whatsapp.net'], 'demote')
649
-
650
- // Bulk action (auto chunk per 5 + delay)
651
- await sock.bulkGroupAction(jid, [jid1, jid2, jid3], 'remove')
652
-
653
- // Update info group
654
- await sock.groupUpdateSubject(jid, 'Nama Group Baru')
655
- await sock.groupUpdateDescription(jid, 'Deskripsi baru')
656
- await sock.updateGroupName(jid, 'Nama Group Baru') // alias
657
- await sock.updateGroupDescription(jid, 'Deskripsi baru') // alias
658
- await sock.updateGroupProfilePicture(jid, buffer) // ganti foto group
659
-
660
- // Setting group
661
- await sock.groupSettingUpdate(jid, 'announcement') // hanya admin yang bisa kirim
662
- await sock.groupSettingUpdate(jid, 'not_announcement') // semua bisa kirim
663
- await sock.updateGroupSetting(jid, 'locked') // alias
664
- await sock.updateGroupSetting(jid, 'unlocked')
665
-
666
- // Invite link
536
+ const group = await sock.groupCreate("Nama Group", ["628xxx@s.whatsapp.net"])
537
+ await sock.groupParticipantsUpdate(jid, ["628xxx@s.whatsapp.net"], "add")
538
+ await sock.groupParticipantsUpdate(jid, ["628xxx@s.whatsapp.net"], "remove")
539
+ await sock.groupParticipantsUpdate(jid, ["628xxx@s.whatsapp.net"], "promote")
540
+ await sock.groupParticipantsUpdate(jid, ["628xxx@s.whatsapp.net"], "demote")
541
+ await sock.bulkGroupAction(jid, [jid1, jid2, jid3], "remove")
542
+ await sock.updateGroupName(jid, "Nama Baru")
543
+ await sock.updateGroupDescription(jid, "Deskripsi baru")
544
+ await sock.updateGroupProfilePicture(jid, buffer)
545
+ await sock.updateGroupSetting(jid, "announcement")
546
+ await sock.updateGroupSetting(jid, "not_announcement")
547
+ await sock.updateGroupSetting(jid, "locked")
548
+ await sock.updateGroupSetting(jid, "unlocked")
667
549
  const code = await sock.groupInviteCode(jid)
668
- const link = await sock.getGroupInviteLink(jid) // return URL lengkap
669
- await sock.groupRevokeInvite(jid) // atau: revokeGroupInvite(jid)
670
- await sock.groupAcceptInvite(code) // join (tanpa URL prefix)
671
- await sock.joinGroupViaLink('https://chat.whatsapp.com/...') // join via URL
672
-
673
- // Info & metadata
674
- const meta = await sock.groupMetadata(jid)
675
- const all = await sock.fetchAllGroups() // semua group yang diikuti
676
-
677
- // Admin utilities
550
+ const link = await sock.getGroupInviteLink(jid)
551
+ await sock.groupRevokeInvite(jid)
552
+ await sock.groupAcceptInvite(code)
553
+ await sock.joinGroupViaLink("https://chat.whatsapp.com/...")
554
+ const meta = await sock.groupMetadata(jid)
555
+ const all = await sock.fetchAllGroups()
678
556
  const admins = await sock.getGroupAdmins(jid)
679
- const isAdmin = await sock.isGroupAdmin(jid, '628xxx@s.whatsapp.net')
557
+ const isAdmin = await sock.isGroupAdmin(jid, "628xxx@s.whatsapp.net")
680
558
  const members = await sock.getGroupParticipants(jid)
681
- await sock.sendToAdminsOnly(jid, 'Pesan khusus admin')
682
- await sock.sendAdminInvite(jid, targetJid) // undang jadi admin
683
-
684
- // Join approval
685
- await sock.setGroupJoinApproval(jid, true) // nyalakan approval
559
+ await sock.sendToAdminsOnly(jid, "Pesan khusus admin")
560
+ await sock.sendAdminInvite(jid, targetJid)
561
+ await sock.setGroupJoinApproval(jid, true)
686
562
  const requests = await sock.getGroupJoinRequests(jid)
687
- await sock.approveGroupJoinRequest(jid, ['628xxx@s.whatsapp.net'])
688
- await sock.rejectGroupJoinRequest(jid, ['628xxx@s.whatsapp.net'])
689
-
690
- // Member add mode
691
- await sock.setGroupMemberAddMode(jid, 'all_member_add') // semua bisa add
692
- await sock.setGroupMemberAddMode(jid, 'admin_add') // hanya admin
693
-
694
- // Leave
563
+ await sock.approveGroupJoinRequest(jid, ["628xxx@s.whatsapp.net"])
564
+ await sock.rejectGroupJoinRequest(jid, ["628xxx@s.whatsapp.net"])
565
+ await sock.setGroupMemberAddMode(jid, "all_member_add")
566
+ await sock.setGroupMemberAddMode(jid, "admin_add")
695
567
  await sock.leaveGroup(jid)
696
568
  ```
697
569
 
@@ -700,57 +572,39 @@ await sock.leaveGroup(jid)
700
572
  ## Interaktif: Buttons, List, Template ⚡
701
573
 
702
574
  ```js
703
- // Pesan dengan tombol
704
- await sock.sendButtonsMessage(jid, {
705
- text: 'Pilih salah satu:',
706
- buttons: [
707
- { buttonId: 'id1', buttonText: { displayText: 'Opsi A' }, type: 1 },
708
- { buttonId: 'id2', buttonText: { displayText: 'Opsi B' }, type: 1 }
709
- ],
710
- headerType: 1
711
- })
575
+ await sock.sendButtonsMessage(jid, "Pilih salah satu:", [
576
+ { buttonId: "id1", buttonText: { displayText: "Opsi A" }, type: 1 },
577
+ { buttonId: "id2", buttonText: { displayText: "Opsi B" }, type: 1 }
578
+ ], "Footer")
712
579
 
713
- // Gambar + tombol
714
- await sock.sendImageWithButtons(jid, buffer, 'Caption', [
715
- { buttonId: 'confirm', buttonText: { displayText: '✅ Konfirmasi' }, type: 1 },
716
- { buttonId: 'cancel', buttonText: { displayText: '❌ Batal' }, type: 1 }
580
+ await sock.sendImageWithButtons(jid, buffer, "Caption", [
581
+ { buttonId: "confirm", buttonText: { displayText: "✅ Konfirmasi" }, type: 1 },
582
+ { buttonId: "cancel", buttonText: { displayText: "❌ Batal" }, type: 1 }
717
583
  ])
718
-
719
- // Video + tombol
720
- await sock.sendVideoWithButtons(jid, videoBuffer, 'Tonton dulu', [
721
- { buttonId: 'share', buttonText: { displayText: '📤 Share' }, type: 1 }
584
+ await sock.sendVideoWithButtons(jid, videoBuffer, "Tonton dulu", [
585
+ { buttonId: "share", buttonText: { displayText: "📤 Share" }, type: 1 }
722
586
  ])
723
-
724
- // Dokumen + tombol
725
- await sock.sendDocumentWithButtons(jid, pdfBuffer, 'laporan.pdf', 'application/pdf', 'Ini laporan nya', [
726
- { buttonId: 'download', buttonText: { displayText: '⬇️ Download' }, type: 1 }
587
+ await sock.sendDocumentWithButtons(jid, pdfBuffer, "laporan.pdf", "Laporan ini", [
588
+ { buttonId: "download", buttonText: { displayText: "⬇️ Download" }, type: 1 }
727
589
  ])
728
590
 
729
- // List / menu
730
591
  await sock.sendListMessage(jid, {
731
- text: 'Pilih menu:',
732
- footer: 'n4lyx bot',
733
- title: 'Main Menu',
734
- buttonText: 'Buka Menu',
735
- sections: [
736
- {
737
- title: 'Kategori 1',
738
- rows: [
739
- { title: 'Info', rowId: 'info', description: 'Lihat informasi' },
740
- { title: 'Help', rowId: 'help', description: 'Bantuan' }
741
- ]
742
- }
743
- ]
592
+ text: "Pilih menu:", footer: "n4lyx bot", title: "Main Menu", buttonText: "Buka Menu",
593
+ sections: [{
594
+ title: "Kategori 1",
595
+ rows: [
596
+ { title: "Info", rowId: "info", description: "Lihat informasi" },
597
+ { title: "Help", rowId: "help", description: "Bantuan" }
598
+ ]
599
+ }]
744
600
  })
745
601
 
746
- // Template message
747
602
  await sock.sendTemplateMessage(jid, {
748
- text: 'Hai! Ada yang bisa dibantu?',
749
- footer: 'n4lyx',
603
+ text: "Hai! Ada yang bisa dibantu?", footer: "n4lyx",
750
604
  templateButtons: [
751
- { index: 1, urlButton: { displayText: '🌐 Website', url: 'https://example.com' } },
752
- { index: 2, callButton: { displayText: '📞 Telepon', phoneNumber: '+62812xxxxxxx' } },
753
- { index: 3, quickReplyButton: { displayText: '💬 Chat', id: 'chat' } }
605
+ { index: 1, urlButton: { displayText: "🌐 Website", url: "https://example.com" } },
606
+ { index: 2, callButton: { displayText: "📞 Telepon", phoneNumber: "+62812xxxxxxx" } },
607
+ { index: 3, quickReplyButton: { displayText: "💬 Chat", id: "chat" } }
754
608
  ]
755
609
  })
756
610
  ```
@@ -760,15 +614,10 @@ await sock.sendTemplateMessage(jid, {
760
614
  ## Newsletter ⚡
761
615
 
762
616
  ```js
763
- // Info channel / newsletter
764
617
  const info = await sock.getNewsletterInfo(newsletterJid)
765
-
766
- // Kirim pesan ke newsletter
767
- await sock.sendNewsletterMessage(newsletterJid, { text: 'Update terbaru!' })
768
- await sock.sendNewsletterMessage(newsletterJid, { image: buffer, caption: 'Foto' })
769
-
770
- // Reaksi di newsletter
771
- await sock.sendNewsletterReaction(newsletterJid, messageId, '🔥')
618
+ await sock.sendNewsletterMessage(newsletterJid, { text: "Update terbaru!" })
619
+ await sock.sendNewsletterMessage(newsletterJid, { image: buffer, caption: "Foto" })
620
+ await sock.sendNewsletterReaction(newsletterJid, messageId, "🔥")
772
621
  ```
773
622
 
774
623
  ---
@@ -776,52 +625,35 @@ await sock.sendNewsletterReaction(newsletterJid, messageId, '🔥')
776
625
  ## Download Media
777
626
 
778
627
  ```js
779
- const { downloadMediaMessage, getContentType } = require('n4lyx')
780
- const { createWriteStream } = require('fs')
628
+ const { downloadMediaMessage, getContentType } = require("n4lyx")
629
+ const { createWriteStream } = require("fs")
781
630
 
782
- sock.ev.on('messages.upsert', async ({ messages: [m] }) => {
631
+ sock.ev.on("messages.upsert", async ({ messages: [m] }) => {
783
632
  if (!m.message) return
784
633
  const type = getContentType(m)
785
-
786
- if (type === 'imageMessage') {
787
- const stream = await downloadMediaMessage(m, 'stream', {}, {
788
- logger,
789
- reuploadRequest: sock.updateMediaMessage
634
+ if (type === "imageMessage") {
635
+ const stream = await downloadMediaMessage(m, "stream", {}, {
636
+ logger, reuploadRequest: sock.updateMediaMessage
790
637
  })
791
- stream.pipe(createWriteStream('./download.jpg'))
638
+ stream.pipe(createWriteStream("./download.jpg"))
792
639
  }
793
640
  })
794
641
  ```
795
642
 
796
- Re-upload media yang expired (link kedaluwarsa):
797
-
798
- ```js
799
- const refreshed = await sock.updateMediaMessage(msg)
800
- ```
801
-
802
643
  ---
803
644
 
804
645
  ## Poll — Dekripsi Vote
805
646
 
806
- Poll dienkripsi by default. Dekripsi harus dilakukan di event `messages.update`.
807
-
808
647
  ```js
809
- const { getAggregateVotesInPollMessage } = require('n4lyx')
648
+ const { getAggregateVotesInPollMessage } = require("n4lyx")
810
649
 
811
- sock.ev.on('messages.update', async (events) => {
650
+ sock.ev.on("messages.update", async (events) => {
812
651
  for (const { key, update } of events) {
813
652
  if (!update.pollUpdates) continue
814
-
815
- const creation = await getMessage(key) // ambil dari DB/store kamu
653
+ const creation = await getMessage(key)
816
654
  if (!creation) continue
817
-
818
- const result = getAggregateVotesInPollMessage({
819
- message: creation,
820
- pollUpdates: update.pollUpdates
821
- })
822
-
823
- console.log('Hasil vote:', result)
824
- // result: [{ name: 'JavaScript', voters: ['628xxx@s.whatsapp.net', ...] }, ...]
655
+ const result = getAggregateVotesInPollMessage({ message: creation, pollUpdates: update.pollUpdates })
656
+ console.log("Hasil vote:", result)
825
657
  }
826
658
  })
827
659
  ```
@@ -831,18 +663,13 @@ sock.ev.on('messages.update', async (events) => {
831
663
  ## Presence
832
664
 
833
665
  ```js
834
- // Kirim indikator presence
835
- await sock.sendPresenceUpdate('composing', jid) // lagi ngetik
836
- await sock.sendPresenceUpdate('recording', jid) // lagi rekam audio
837
- await sock.sendPresenceUpdate('paused', jid) // berhenti ngetik
838
- await sock.sendPresenceUpdate('available', jid) // online
839
- await sock.sendPresenceUpdate('unavailable', jid) // offline
840
-
841
- // Subscribe presence orang lain
666
+ await sock.sendPresenceUpdate("composing", jid)
667
+ await sock.sendPresenceUpdate("recording", jid)
668
+ await sock.sendPresenceUpdate("paused", jid)
669
+ await sock.sendPresenceUpdate("available", jid)
670
+ await sock.sendPresenceUpdate("unavailable", jid)
842
671
  await sock.presenceSubscribe(jid)
843
- sock.ev.on('presence.update', ({ id, presences }) => {
844
- console.log(id, presences) // lihat siapa yang lagi online
845
- })
672
+ sock.ev.on("presence.update", ({ id, presences }) => { console.log(id, presences) })
846
673
  ```
847
674
 
848
675
  ---
@@ -850,26 +677,13 @@ sock.ev.on('presence.update', ({ id, presences }) => {
850
677
  ## Query & Info
851
678
 
852
679
  ```js
853
- // Cek apakah nomor terdaftar di WA
854
- const info = await sock.isOnWhatsApp('628xxxxxxxxx')
855
- // → { exists: true, jid: '628xxx@s.whatsapp.net' }
856
-
857
- // Info lengkap kontak
680
+ const info = await sock.isOnWhatsApp("628xxxxxxxxx")
858
681
  const contact = await sock.getContactInfo(jid)
859
-
860
- // Status teks (safe — return null kalau gagal)
861
- const status = await sock.getUserStatus(jid)
862
-
863
- // Foto profil (safe — return null kalau gagal)
864
- const pic = await sock.getProfilePicture(jid) // low res
865
- const picHD = await sock.getProfilePicture(jid, true) // high res
866
-
867
- // Business profile
868
- const biz = await sock.getBusinessProfile(jid)
869
-
870
- // Riwayat pesan (max 50 per call)
682
+ const status = await sock.getUserStatus(jid)
683
+ const pic = await sock.getProfilePicture(jid)
684
+ const picHD = await sock.getProfilePicture(jid, true)
685
+ const biz = await sock.getBusinessProfile(jid)
871
686
  await sock.fetchMessageHistory(50, oldest.key, oldest.messageTimestamp)
872
- // masuk via event: messaging.history-set
873
687
  ```
874
688
 
875
689
  ---
@@ -877,16 +691,12 @@ await sock.fetchMessageHistory(50, oldest.key, oldest.messageTimestamp)
877
691
  ## Privacy
878
692
 
879
693
  ```js
880
- // Update semua privacy settings
881
- // nilai: 'all' | 'contacts' | 'contact_blacklist' | 'none'
882
- await sock.updateLastSeenPrivacy('contacts')
883
- await sock.updateProfilePicturePrivacy('contacts')
884
- await sock.updateStatusPrivacy('contacts')
885
- await sock.updateReadReceiptsPrivacy('all')
886
- await sock.updateGroupsAddPrivacy('contacts')
887
- await sock.updateOnlinePrivacy('all') // atau 'match_last_seen'
888
-
889
- // Default disappearing mode
694
+ await sock.updateLastSeenPrivacy("contacts")
695
+ await sock.updateProfilePicturePrivacy("contacts")
696
+ await sock.updateStatusPrivacy("contacts")
697
+ await sock.updateReadReceiptsPrivacy("all")
698
+ await sock.updateGroupsAddPrivacy("contacts")
699
+ await sock.updateOnlinePrivacy("all")
890
700
  await sock.updateDefaultDisappearingMode(86400)
891
701
  ```
892
702
 
@@ -895,9 +705,9 @@ await sock.updateDefaultDisappearingMode(86400)
895
705
  ## Profile
896
706
 
897
707
  ```js
898
- await sock.updateProfileStatus('Sedang coding...')
899
- await sock.updateProfileName('Nama Baru')
900
- await sock.updateProfilePicture(jid, { url: './foto.jpg' })
708
+ await sock.updateProfileStatus("Sedang coding...")
709
+ await sock.updateProfileName("Nama Baru")
710
+ await sock.updateProfilePicture(jid, { url: "./foto.jpg" })
901
711
  await sock.removeProfilePicture(jid)
902
712
  ```
903
713
 
@@ -906,12 +716,7 @@ await sock.removeProfilePicture(jid)
906
716
  ## Calls
907
717
 
908
718
  ```js
909
- // Tolak incoming call
910
- sock.ev.on('call', async ([call]) => {
911
- await sock.rejectCall(call.id, call.from)
912
- })
913
-
914
- // Auto-reject semua call (aktifkan sekali saat startup)
719
+ sock.ev.on("call", async ([call]) => { await sock.rejectCall(call.id, call.from) })
915
720
  sock.rejectAllCalls()
916
721
  ```
917
722
 
@@ -919,76 +724,35 @@ sock.rejectAllCalls()
919
724
 
920
725
  ## In-Memory Store
921
726
 
922
- Untuk development / testing. **Jangan dipakai di production.**
923
-
924
727
  ```js
925
- const { makeInMemoryStore } = require('n4lyx')
926
-
728
+ const { makeInMemoryStore } = require("n4lyx")
927
729
  const store = makeInMemoryStore({})
928
- store.readFromFile('./store.json')
929
- setInterval(() => store.writeToFile('./store.json'), 10_000)
930
-
931
- const sock = makeWASocket({})
730
+ store.readFromFile("./store.json")
731
+ setInterval(() => store.writeToFile("./store.json"), 10_000)
932
732
  store.bind(sock.ev)
933
733
  ```
934
734
 
935
735
  ---
936
736
 
937
- ## WebSocket Low-Level
938
-
939
- ```js
940
- // Listen ke protokol WA secara langsung
941
- sock.ws.on('CB:edge_routing', (node) => { })
942
- sock.ws.on('CB:edge_routing,id:abcd', (node) => { })
943
- ```
944
-
945
- Debug mode — log semua WA protocol frame:
946
-
947
- ```js
948
- const P = require('pino')
949
- const sock = makeWASocket({ logger: P({ level: 'debug' }) })
950
- ```
951
-
952
- ---
953
-
954
737
  ## JID Format
955
738
 
956
739
  | Tipe | Format |
957
740
  |---|---|
958
741
  | User | `628XXXXXXXXX@s.whatsapp.net` |
959
742
  | Group | `123456789-123456@g.us` |
743
+ | Newsletter/Channel | `xxxxxxxxxx@newsletter` |
960
744
  | Broadcast list | `[timestamp]@broadcast` |
961
745
  | Story / Status | `status@broadcast` |
962
746
 
963
747
  ---
964
748
 
965
- ## Utilities
966
-
967
- | Fungsi | Kegunaan |
968
- |---|---|
969
- | `getContentType(msg)` | Ambil tipe konten dari sebuah pesan |
970
- | `getDevice(msg)` | Info device pengirim pesan |
971
- | `makeCacheableSignalKeyStore` | Percepat operasi auth key store |
972
- | `downloadContentFromMessage` | Download raw content dari pesan |
973
- | `fetchLatestN4lyxVersion` | Ambil versi terbaru n4lyx dari npm |
974
- | `fetchLatestWaWebVersion` | Ambil versi terbaru WA Web |
975
-
976
- ---
977
-
978
749
  ## Optional Dependencies
979
750
 
980
- Install sesuai kebutuhan — nggak wajib semua.
981
-
982
751
  ```bash
983
- npm i jimp # thumbnail generator (bisa juga pakai sharp)
984
- npm i link-preview-js # link preview otomatis di pesan teks
985
- npm i qrcode-terminal # render QR code di terminal
986
- ```
987
-
988
- Konversi audio ke format yang kompatibel (butuh `ffmpeg` di sistem):
989
-
990
- ```bash
991
- ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
752
+ npm i sharp # resize, compress, convert (RECOMMENDED)
753
+ npm i jimp # fallback resize/convert jika sharp tidak bisa
754
+ npm i link-preview-js # link preview otomatis
755
+ npm i qrcode-terminal # QR di terminal
992
756
  ```
993
757
 
994
758
  ---
@@ -998,6 +762,18 @@ ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
998
762
  <details>
999
763
  <summary><strong>Lihat semua method (klik untuk expand)</strong></summary>
1000
764
 
765
+ ### NEW ⚡
766
+
767
+ | Method | Keterangan |
768
+ |---|---|
769
+ | `getFollowedChannels()` | Semua channel/newsletter yang diikuti |
770
+ | `getJoinedGroups(withMeta?)` | Semua group yang diikuti, optional dengan foto profil |
771
+ | `getAllContacts()` | Semua kontak tersimpan |
772
+ | `convertToSticker(buf, opts)` | Convert image → WebP sticker (resize+compress) |
773
+ | `convertMedia(buf, opts)` | Resize + compress image (JPEG/PNG/WebP) |
774
+ | `sendStickerPackAlbum(jid, stickers, pack, pub, opts)` | Kirim sticker pack batch besar paralel |
775
+ | `sendDocumentPack(jid, docs, opts)` | Kirim banyak dokumen sekaligus |
776
+
1001
777
  ### Pesan
1002
778
 
1003
779
  | Method | Keterangan |
@@ -1007,15 +783,17 @@ ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
1007
783
  | `sendAudio` | Kirim audio / PTT |
1008
784
  | `sendAudioPTT` | Alias PTT |
1009
785
  | `sendVoiceNote` | Alias voice note |
1010
- | `sendDocument` | Kirim dokumen |
786
+ | `sendDocument` | Kirim dokumen (auto mime detection) |
1011
787
  | `sendGIF` | Kirim GIF animasi |
1012
788
  | `sendPTV` | Circular video note |
1013
789
  | `sendViewOnce` | View-once media |
1014
- | `sendSticker` / `sendStickerMessage` | Kirim sticker |
790
+ | `sendStickerMessage` | Kirim sticker |
1015
791
  | `sendStickerFromBuffer` | Sticker dari Buffer |
1016
792
  | `sendStickerFromUrl` | Sticker dari URL |
1017
793
  | `sendStickerWithMetadata` | Sticker + pack info |
1018
- | `sendStickerPack` | Kirim banyak sticker |
794
+ | `sendStickerPack` | Kirim banyak sticker (batch paralel) |
795
+ | `sendStickerPackAlbum` | Kirim sticker pack album mode |
796
+ | `sendDocumentPack` | Kirim banyak dokumen sekaligus |
1019
797
  | `sendAlbum` | Album swipeable |
1020
798
  | `sendPoll` | Buat poll |
1021
799
  | `sendEvent` | WhatsApp Event |
@@ -1040,7 +818,6 @@ ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
1040
818
  | `sendWithQuotedFake` | Kirim dengan fake quote |
1041
819
  | `forwardWithComment` | Forward + komentar |
1042
820
  | `sendWithMentionAndReply` | Reply + mention sekaligus |
1043
- | `tagAll` di `sendMessage` | Auto-mention all/admin/non-admin |
1044
821
  | `groupTagAll` | Ambil list JID by scope |
1045
822
 
1046
823
  ### Interaktif
@@ -1056,10 +833,11 @@ ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
1056
833
  | `sendVideoWithButtons` | Video + tombol |
1057
834
  | `sendDocumentWithButtons` | Dokumen + tombol |
1058
835
 
1059
- ### Newsletter
836
+ ### Newsletter / Channel
1060
837
 
1061
838
  | Method | Keterangan |
1062
839
  |---|---|
840
+ | `getFollowedChannels` | Semua channel yang diikuti |
1063
841
  | `sendNewsletterMessage` | Kirim ke newsletter |
1064
842
  | `sendNewsletterReaction` | Reaksi di newsletter |
1065
843
  | `getNewsletterInfo` | Info channel |
@@ -1108,16 +886,17 @@ ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
1108
886
 
1109
887
  | Method | Keterangan |
1110
888
  |---|---|
889
+ | `getJoinedGroups` | Semua group yang diikuti |
1111
890
  | `groupCreate` | Buat group |
1112
891
  | `groupParticipantsUpdate` | add/remove/promote/demote |
1113
892
  | `bulkGroupAction` | Bulk action member |
1114
- | `groupUpdateSubject` / `updateGroupName` | Ganti nama |
1115
- | `groupUpdateDescription` / `updateGroupDescription` | Ganti deskripsi |
893
+ | `updateGroupName` | Ganti nama |
894
+ | `updateGroupDescription` | Ganti deskripsi |
1116
895
  | `updateGroupProfilePicture` | Ganti foto group |
1117
- | `updateGroupSetting` / `groupSettingUpdate` | Setting group |
1118
- | `getGroupInviteLink` / `groupInviteCode` | Invite link |
1119
- | `revokeGroupInvite` / `groupRevokeInvite` | Revoke link |
1120
- | `joinGroupViaLink` / `groupAcceptInvite` | Join group |
896
+ | `updateGroupSetting` | Setting group |
897
+ | `getGroupInviteLink` | Invite link URL |
898
+ | `revokeGroupInvite` | Revoke link |
899
+ | `joinGroupViaLink` | Join via URL |
1121
900
  | `groupMetadata` | Metadata group |
1122
901
  | `fetchAllGroups` | Semua group |
1123
902
  | `getGroupAdmins` | Daftar admin |
@@ -1130,7 +909,7 @@ ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
1130
909
  | `approveGroupJoinRequest` | Approve request |
1131
910
  | `rejectGroupJoinRequest` | Reject request |
1132
911
  | `setGroupMemberAddMode` | Siapa yang bisa add member |
1133
- | `groupLeave` / `leaveGroup` | Leave group |
912
+ | `leaveGroup` | Leave group |
1134
913
  | `setGroupDisappearing` | Disappearing messages di group |
1135
914
 
1136
915
  ### Disappearing
@@ -1148,10 +927,18 @@ ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
1148
927
  | `sendStatus` | Post story pribadi |
1149
928
  | `groupStatusV2` | Post story di group ⚡ |
1150
929
 
930
+ ### Convert & Media Utils ⚡
931
+
932
+ | Method | Keterangan |
933
+ |---|---|
934
+ | `convertToSticker(buf, opts)` | Convert image → WebP sticker |
935
+ | `convertMedia(buf, opts)` | Resize + compress image |
936
+
1151
937
  ### Query & Info
1152
938
 
1153
939
  | Method | Keterangan |
1154
940
  |---|---|
941
+ | `getAllContacts` | Semua kontak tersimpan |
1155
942
  | `isOnWhatsApp` | Cek nomor (input fleksibel) |
1156
943
  | `getContactInfo` | Info kontak |
1157
944
  | `getUserStatus` | Status teks (safe) |
@@ -1182,5 +969,5 @@ MIT — lihat [LICENSE](LICENSE).
1182
969
  ---
1183
970
 
1184
971
  <div align="center">
1185
- <sub>built by N4tzzOfficial · <a href="https://whatsapp.com/channel/0029VbAVYIx5PO0z9LqImz3U">Channel WhatsApp</a> · <a href="https://npmjs.com/package/n4lyx">npm</a></sub>
972
+ <sub>Built with stability in mind · N4tzzOfficial</sub>
1186
973
  </div>