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