ayoubwa 1.0.0

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