neroxbailx
Version:
baileys whatsapp-api
2,052 lines (1,683 loc) ⢠73 kB
Markdown
# š¬ Baileys ā API WhatsApp Indonesia
<div align="center">
<img src="https://i.pinimg.com/736x/b1/7b/b0/b17bb0c5e75398ae8108d3688340b9fe.jpg" alt="WhatsApp Baileys" width="500" style="border-radius: 15px;">
> **ā ļø SECURITY WARNING ā ļø**
>
> This is a **private version** of Baileys with enhanced security features.
> This repository is NOT for public use and contains proprietary security measures.
> Unauthorized access or distribution is strictly prohibited.
[](https://github.com/neroxkira)
[](https://www.npmjs.com/package/neroxbails)
[](https://www.npmjs.com/package/neroxbails)
[](https://nodejs.org/)
</div>
---
## š Support
Jika project ini membantu Anda, berikan ā di GitHub!
<div align="center">
**Made with ā¤ļø by [@neroxkira](https://github.com/neroxkira)**
[](https://github.com/neroxkira)
[](https://instagram.com/nerox)
</div>
## š Deskripsi
**Baileys** adalah pustaka JavaScript yang ringan dan powerful untuk terhubung dengan **WhatsApp Web API** melalui WebSocket. Memungkinkan Anda membuat bot WhatsApp, automasi, dan integrasi dengan mudah tanpa perlu WhatsApp Business API yang berbayar!
### ⨠Fitur Unggulan
- š **Ringan & Cepat** - Tanpa overhead TypeScript
- š **Auto Reconnect** - Koneksi stabil dengan auto-reconnect
- š± **Multi Device** - Mendukung WhatsApp Multi Device
- š¼ļø **Media Support** - Kirim gambar, video, audio, dokumen
- šÆ **Interactive Buttons** - Tombol interaktif dan katalog produk
- š **Group Management** - Kelola grup dengan mudah
- š **Session Management** - Simpan sesi untuk login otomatis
- š **Gratis Selamanya** - Open source dan gratis digunakan
---
## š Links
<div align="center">
[](https://github.com/neroxkira)
[](https://instagram.com/nerox)
[](https://baileys.wiki)
</div>
---
## ā ļø Disclaimer
> **PENTING:** Proyek ini **TIDAK berafiliasi** dengan WhatsApp Inc. atau Meta Platforms Inc.
>
> š« **Dilarang untuk:**
> - Spam massal
> - Stalking atau harassment
> - Melanggar Terms of Service WhatsApp
> - Aktivitas ilegal lainnya
>
> āļø **Segala bentuk penyalahgunaan adalah tanggung jawab pengguna sepenuhnya.**
---
## š¦ Instalasi
### š Requirements
-  **Node.js versi 18 atau lebih tinggi**
-  **NPM, Yarn, atau PNPM**
### š§ Install Package
```bash
# NPM
npm install neroxbails
# Yarn
yarn add neroxbails
# PNPM
pnpm add neroxbails
```
---
## š Quick Start
### 1ļøā£ Koneksi dengan QR Code (ESM)
```javascript
import makeWASocket, { Browsers } from 'neroxbails'
const socket = makeWASocket({
browser: Browsers.ubuntu('Safari'),
printQRInTerminal: true
})
console.log('š Scan QR code di terminal untuk login!')
```
### 2ļøā£ Koneksi dengan QR Code (CommonJS)
```javascript
const { default: makeWASocket, Browsers } = require('neroxbails')
const socket = makeWASocket({
browser: Browsers.ubuntu('Safari'),
printQRInTerminal: true
})
console.log('š Scan QR code di terminal untuk login!')
```
> ā ļø **Catatan:** Pastikan `package.json` **TIDAK** mengandung `"type": "module"` untuk CommonJS
### 3ļøā£ Koneksi dengan Pairing Code (Tanpa QR)
```javascript
import makeWASocket from 'neroxbails'
const socket = makeWASocket({
printQRInTerminal: false
})
// Login tanpa scan QR code
if (!socket.authState.creds.registered) {
const phoneNumber = '628123456789' // Nomor tanpa + atau -
const pairingCode = await socket.requestPairingCode(phoneNumber)
console.log('š¢ Kode Pairing:', pairingCode)
console.log('š± Masukkan kode di WhatsApp > Linked Devices > Link a Device')
}
```
---
## šÆ Event Handling
### šØ Menangani Pesan Masuk
```javascript
socket.ev.on('messages.upsert', ({ messages }) => {
const message = messages[0]
if (!message.message) return
console.log('šØ Pesan baru:', message.message)
// Balas pesan otomatis
if (message.message.conversation === 'ping') {
socket.sendMessage(message.key.remoteJid, { text: 'š pong!' })
}
})
```
### š Status Koneksi
```javascript
socket.ev.on('connection.update', ({ connection, lastDisconnect }) => {
if (connection === 'close') {
console.log('ā Koneksi terputus. Reconnecting...')
// Logic untuk reconnect otomatis
} else if (connection === 'open') {
console.log('ā
Berhasil terhubung ke WhatsApp!')
} else if (connection === 'connecting') {
console.log('š Sedang menghubungkan...')
}
})
```
---
## š¾ Session Management
### š Simpan Session untuk Auto Login
```javascript
import makeWASocket, { useMultiFileAuthState } from 'neroxbails'
// Load session dari folder
const { state, saveCreds } = await useMultiFileAuthState('./auth_session')
const socket = makeWASocket({
auth: state,
printQRInTerminal: true
})
// Auto save credentials
socket.ev.on('creds.update', saveCreds)
console.log('š¾ Session akan tersimpan otomatis')
```
---
## šØ Contoh Penggunaan Lanjutan
### šø Kirim Media
```javascript
import fs from 'fs'
// Kirim gambar
await socket.sendMessage(chatId, {
image: fs.readFileSync('./gambar.jpg'),
caption: 'š¼ļø Ini adalah gambar'
})
// Kirim video
await socket.sendMessage(chatId, {
video: fs.readFileSync('./video.mp4'),
caption: 'š¬ Video keren!'
})
// Kirim dokumen
await socket.sendMessage(chatId, {
document: fs.readFileSync('./dokumen.pdf'),
mimetype: 'application/pdf',
fileName: 'Document.pdf'
})
```
### š Kirim Pesan dengan Format
```javascript
// Pesan dengan format
await socket.sendMessage(chatId, {
text: `*Halo!* š
_Ini adalah pesan dengan format:_
⢠Poin 1
⢠Poin 2
⢠Poin 3
~Text tercoret~
\`\`\`javascript
console.log("Code block")
\`\`\`
Kunjungi: https://github.com/neroxkira`
})
```
### š„ Manajemen Grup
```javascript
// Buat grup baru
const group = await socket.groupCreate('Nama Grup š', ['628xxx', '629xxx'])
console.log('š± Grup dibuat:', group.id)
// Tambah anggota
await socket.groupParticipantsUpdate(groupId, ['628xxx'], 'add')
// Hapus anggota
await socket.groupParticipantsUpdate(groupId, ['628xxx'], 'remove')
// Jadikan admin
await socket.groupParticipantsUpdate(groupId, ['628xxx'], 'promote')
// Update info grup
await socket.groupUpdateDescription(groupId, 'Deskripsi grup baru š')
```
---
## ā” Optimasi Performance
### šļø Group Metadata Caching
```javascript
import NodeCache from 'node-cache'
const groupCache = new NodeCache({
stdTTL: 5 * 60, // 5 menit
useClones: false
})
const socket = makeWASocket({
cachedGroupMetadata: async (jid) => groupCache.get(jid)
})
// Auto update cache
socket.ev.on('groups.update', async ([event]) => {
const metadata = await socket.groupMetadata(event.id)
groupCache.set(event.id, metadata)
})
socket.ev.on('group-participants.update', async (event) => {
const metadata = await socket.groupMetadata(event.id)
groupCache.set(event.id, metadata)
})
```
### š Sync Full History
```javascript
const socket = makeWASocket({
browser: Browsers.ubuntu('Safari'), // Penting untuk full history
syncFullHistory: true, // Download semua riwayat chat
fireInitQueries: true,
})
```
---
## š ļø Konfigurasi Lengkap
```javascript
import makeWASocket, {
Browsers,
useMultiFileAuthState,
fetchLatestBaileysVersion
} from 'neroxbails'
const { version } = await fetchLatestBaileysVersion()
const { state, saveCreds } = await useMultiFileAuthState('./auth')
const socket = makeWASocket({
version,
auth: state,
browser: Browsers.ubuntu('Safari'),
// Koneksi
connectTimeoutMs: 20000,
defaultQueryTimeoutMs: 20000,
keepAliveIntervalMs: 10000,
// QR & Pairing
printQRInTerminal: true,
qrTimeout: 40000,
// Performance
syncFullHistory: true,
markOnlineOnConnect: false,
emitOwnEvents: false,
// Media
generateHighQualityLinkPreview: true,
linkPreviewImageThumbnailWidth: 120,
// Custom functions
getMessage: async (key) => {
// Return message dari database Anda
return await getMessageFromDB(key)
}
})
socket.ev.on('creds.update', saveCreds)
```
---
## š” Tips & Best Practices
### ā
Do's
- ā
**Selalu handle event `connection.update`** untuk auto reconnect
- ā
**Simpan session** agar tidak perlu login berulang
- ā
**Gunakan cache** untuk metadata grup yang sering diakses
- ā
**Handle error** dengan try-catch pada setiap operasi
- ā
**Respect rate limits** WhatsApp untuk avoid banned
- ā
**Update Baileys secara berkala** untuk fix bug terbaru
### ā Don'ts
- ā **Jangan spam** pesan dalam jumlah besar
- ā **Jangan expose credentials** di public repository
- ā **Jangan abaikan event handling** yang penting
- ā **Jangan lupa backup** file session Anda
- ā **Jangan gunakan untuk aktivitas ilegal**
---
## š Troubleshooting
### š Masalah Umum
| Masalah | Solusi |
|---------|--------|
| QR Code tidak muncul | Cek koneksi internet & pastikan `printQRInTerminal: true` |
| Koneksi sering putus | Gunakan `keepAliveIntervalMs` dan implement auto-reconnect |
| Session hilang | Backup folder `auth_session` secara berkala |
| Pesan tidak terkirim | Cek format `remoteJid` dan pastikan nomor valid |
| Error "Cannot find module" | Install ulang dependencies dengan `npm install` |
### š Debug Mode
```javascript
import pino from 'pino'
const socket = makeWASocket({
logger: pino({ level: 'debug' }),
printQRInTerminal: true
})
```
---
## š¤ Contributing
Kontribusi sangat diterima! Silakan:
1. š“ Fork repository ini
2. šæ Buat branch feature (`git checkout -b feature/AmazingFeature`)
3. š¾ Commit changes (`git commit -m 'Add some AmazingFeature'`)
4. š¤ Push ke branch (`git push origin feature/AmazingFeature`)
5. š Buat Pull Request
---
## š License
Distributed unter der **MIT License**. Lihat `LICENSE` file untuk informasi lebih lanjut.
---
## š Stats
<div align="center">
<img src="https://github-readme-stats.vercel.app/api?username=neroxkira&show_icons=true&theme=radical" alt="GitHub Stats">
</div>
> [!IMPORTANT]
> **Daftar lengkap event tersedia [di sini](https://baileys.whiskeysockets.io/types/BaileysEventMap.html)**.
> Sangat penting untuk memahami setiap event yang bisa digunakan.
Contoh penggunaan listener untuk menangani pesan masuk:
```javascript
import makeWASocket from 'neroxbails'
const sock = makeWASocket()
sock.ev.on('messages.upsert', ({ messages }) => {
console.log('Pesan diterima:', messages)
})
```
## Menangani Event
Baileys menggunakan sistem **EventEmitter** untuk menangani interaksi WhatsApp secara real-time.
Semua event yang terjadi saat koneksi aktif akan dipancarkan melalui `sock.ev.on(...)`, dan kamu bisa menangkap serta meresponsnya sesuai kebutuhan bot kamu.
> [!IMPORTANT]
> **Daftar lengkap event tersedia [di sini](https://baileys.whiskeysockets.io/types/BaileysEventMap.html)**.
> Disarankan untuk memahami struktur tiap event agar integrasi kamu lebih stabil dan efisien.
### Contoh: Menangani Pesan Masuk
```javascript
sock.ev.on('messages.upsert', async ({ messages, type }) => {
const msg = messages[0]
if (!msg.message) return
console.log('Pesan diterima:', msg.message)
})
```
- `type` bisa bernilai `notify`, `append`, `replace`, atau `remove`.
- Kamu biasanya hanya perlu memproses `type === 'notify'` untuk pesan baru yang masuk.
### Contoh: Menangani Pembaruan Koneksi
```javascript
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
if (connection === 'close') {
console.log('Koneksi terputus.')
} else if (connection === 'open') {
console.log('Terhubung ke WhatsApp!')
}
})
```
- Event ini sangat penting untuk memantau status koneksi socket.
- Jika `connection === 'close'`, Kamu dapat mencoba reconnect otomatis.
### Contoh: Deteksi Peserta Masuk/Keluar Grup
```javascript
sock.ev.on('group-participants.update', async ({ id, participants, action }) => {
if (action === 'add') {
console.log('Anggota baru masuk:', participants)
} else if (action === 'remove') {
console.log('Anggota keluar:', participants)
}
})
```
- `id`: JID grup
- `participants`: array nomor yang terlibat
- `action`: `'add' | 'remove' | 'promote' | 'demote'`
### Contoh: Pembaruan Metadata Grup
```javascript
sock.ev.on('groups.update', async (updates) => {
for (let group of updates) {
console.log('Grup diperbarui:', group)
}
})
```
- Bisa digunakan untuk mendeteksi perubahan nama grup, gambar, deskripsi, dll.
### Tips
- Event `messages.update` digunakan untuk mendeteksi status pesan seperti dibaca, diterima, atau gagal.
- Event `messages.reaction` digunakan untuk menangkap reaksi (emoji) pada pesan kamu.
> [!TIP]
> Baileys tidak menyimpan cache pesan secara default.
> Untuk menangani event dengan akurat (seperti retry atau polling), gunakan `getMessage()` bersama `store`.
Jika kamu butuh event tambahan seperti **reaction**, **presence**, atau **call offer**, tinggal tambahkan listener-nya sesuai struktur [BaileysEventMap](https://baileys.whiskeysockets.io/types/BaileysEventMap.html).
## Menyimpan & Memulihkan Sesi
Tentu kamu tidak ingin terus-menerus memindai QR code setiap kali ingin terkoneksi.
Kamu bisa menyimpan kredensial dan menggunakannya kembali saat login berikutnya:
```javascript
import makeWASocket, { useMultiFileAuthState } from 'neroxbails'
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
// Akan menggunakan kredensial yang tersedia untuk koneksi ulang
// Jika kredensial valid ditemukan, akan langsung login tanpa QR
const sock = makeWASocket({ auth: state })
// Fungsi ini akan dipanggil setiap kali kredensial diperbarui
sock.ev.on('creds.update', saveCreds)
```
> [!IMPORTANT]
> `useMultiFileAuthState` adalah fungsi utilitas untuk menyimpan state autentikasi dalam satu folder.
> Fungsi ini juga dapat dijadikan dasar untuk menulis sistem autentikasi dan penyimpanan kunci pada database SQL atau NoSQL ā sangat direkomendasikan untuk sistem berskala produksi.
### Apa Isi Folder `auth_info_baileys`?
Folder tersebut akan berisi beberapa file `.json` seperti:
- `creds.json` ā informasi kredensial utama
- `keys/` ā berisi subfile kunci Signal: pre-keys, session, senderKey, dll.
> Folder ini **jangan pernah dimodifikasi atau dihapus secara manual**.
> Perlakukan seperti file token yang sangat sensitif.
### Apa yang Terjadi Jika Folder Hilang?
Jika folder `auth_info_baileys` dihapus:
- Kamu **tidak bisa login ulang** tanpa memindai QR lagi
- Semua sesi yang aktif akan invalid
- Signal akan membuat ulang semua sesi enkripsi end-to-end
Backup sangat disarankan jika kamu mengelola sesi penting.
### Tips Backup & Restore
- Salin seluruh folder `auth_info_baileys` secara utuh.
- Untuk restore, cukup salin folder kembali ke path yang sama sebelum memulai bot.
- Gunakan `.gitignore` agar folder ini tidak ikut di-push ke GitHub:
```
auth_info_baileys/
```
### Menyimpan Berdasarkan ID Pengguna (Multi-Akun)
Jika kamu mengelola banyak sesi pengguna (multi-client), buat direktori penyimpanan berdasarkan ID pengguna:
```javascript
const { state, saveCreds } = await useMultiFileAuthState(`./sessions/${userId}`)
```
Dengan cara ini, kamu bisa memisahkan sesi tiap user tanpa saling bentrok.
> Rekomendasi: kombinasikan dengan database seperti MongoDB/Redis untuk mencatat mapping antara userId dan path session-nya.
### Contoh untuk Memulai
> [!NOTE]
> Contoh ini juga sudah mencakup penyimpanan kredensial secara otomatis
```javascript
import makeWASocket, { DisconnectReason, useMultiFileAuthState } from 'neroxbails'
import { Boom } from '@hapi/boom'
async function connectToWhatsApp () {
const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys')
const sock = makeWASocket({
auth: state,
printQRInTerminal: true
})
sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect } = update
if (connection === 'close') {
const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
console.log('Koneksi terputus karena', lastDisconnect.error, ', mencoba sambung ulang:', shouldReconnect)
if (shouldReconnect) {
connectToWhatsApp()
}
} else if (connection === 'open') {
console.log('Koneksi berhasil dibuka')
}
})
sock.ev.on('messages.upsert', async (event) => {
for (const m of event.messages) {
console.log(JSON.stringify(m, undefined, 2))
console.log('Membalas ke', m.key.remoteJid)
await sock.sendMessage(m.key.remoteJid!, { text: 'Hello World' })
}
})
// Menyimpan kredensial setiap kali diperbarui
sock.ev.on('creds.update', saveCreds)
}
connectToWhatsApp()
```
### Contoh Penggunaan `useSingleFileAuthState` dan `useMongoFileAuthState`
```javascript
import makeWASocket, {
useSingleFileAuthState,
useMongoFileAuthState
} from 'neroxbails'
// Autentikasi menggunakan file tunggal (Single File Auth)
const { state, saveState } = await useSingleFileAuthState('./auth_info_baileys.json')
const sock = makeWASocket({
auth: state,
printQRInTerminal: true
})
sock.ev.on('creds.update', saveState)
```
```javascript
// Autentikasi menggunakan MongoDB
import { MongoClient } from 'mongodb'
const connectAuth = async () => {
const client = new MongoClient('mongodb://localhost:27017')
await client.connect()
console.log('Berhasil terhubung ke MongoDB')
const collection = client.db('neroxbails').collection('sessions')
const { state, saveCreds } = await useMongoFileAuthState(collection)
const sock = makeWASocket({
auth: state,
printQRInTerminal: true
})
sock.ev.on('creds.update', saveCreds)
}
connectAuth()
```
> [!IMPORTANT]
> Dalam event `messages.upsert`, sangat disarankan menggunakan perulangan `for (const message of event.messages)` untuk menangani semua pesan dalam array secara individual.
> Hal ini mencegah pesan terlewat dan memudahkan logging/debugging.
> [!TIP]
> Kamu bisa menggabungkan pendekatan penyimpanan sesi (`MultiFile`, `SingleFile`, atau `MongoDB`) dengan sistem login berbasis ID pengguna, sehingga mendukung banyak akun secara paralel.
### Mendekripsi Suara Polling
Secara default, suara polling di WhatsApp dienkripsi dan diproses melalui event `messages.update`.
```javascript
import pino from 'pino'
import {
makeInMemoryStore,
getAggregateVotesInPollMessage
} from 'neroxbails'
const logger = pino({ timestamp: () => `,"time":"${new Date().toJSON()}"` }).child({ class: 'neroxbails' })
logger.level = 'fatal'
const store = makeInMemoryStore({ logger })
async function getMessage(key) {
if (store) {
const msg = await store.loadMessage(key.remoteJid, key.id)
return msg?.message
}
return {
conversation: 'Polling Tidak Ditemukan'
}
}
sock.ev.on('messages.update', async (chatUpdate) => {
for (const { key, update } of chatUpdate) {
if (update.pollUpdates && key.fromMe) {
const pollCreation = await getMessage(key)
if (pollCreation) {
const pollUpdate = await getAggregateVotesInPollMessage({
message: pollCreation,
pollUpdates: update.pollUpdates
})
const toCmd = pollUpdate.filter(v => v.voters.length !== 0)[0]?.name
if (!toCmd) return
console.log('Pilihan terpilih:', toCmd)
// Tambahkan aksi lanjutan di sini
}
}
}
})
```
### Penjelasan
- **`store.loadMessage(jid, id)`** digunakan untuk mengambil ulang isi pesan polling (karena hasil polling hanya berisi update, bukan isi awal).
- **`getAggregateVotesInPollMessage()`** menggabungkan seluruh `pollUpdates` dan menghasilkan daftar suara lengkap.
- Sangat penting menggunakan `getMessage()` yang valid. Jika kamu tidak menyimpan store, dekripsi suara tidak akan berhasil.
> [!TIP]
> Untuk polling publik, kamu tidak perlu key khusus.
> Tapi untuk polling private (atau jika polling berasal dari orang lain), pastikan kamu menyimpan pesan awalnya menggunakan store atau log pesan masuk.
### Ringkasan Event Saat Koneksi Pertama
1. Saat socket pertama kali terkoneksi, event `connection.update` akan dipicu.
Biasanya status koneksi akan masuk ke `'open'` atau `'close'`.
2. Setelah itu, WhatsApp akan mengirimkan riwayat pesan (history chat) melalui event:
**`messaging-history.set`**
3. Riwayat tersebut berisi pesan-pesan dari sesi sebelumnya, termasuk polling yang belum terjawab.
> [!IMPORTANT]
> Untuk menangani polling, kamu **wajib mengatur `getMessage()`** di konfigurasi `makeWASocket()`.
> Ini memastikan Baileys bisa mendekripsi hasil polling dengan benar.
```javascript
const sock = makeWASocket({
auth: state,
getMessage: async (key) => await getMessage(key)
})
```
## Mengimplementasikan Data Store
Baileys tidak menyediakan sistem penyimpanan (*storage*) bawaan untuk chat, kontak, atau pesan.
Namun, tersedia implementasi sederhana menggunakan **in-memory store**. Store ini akan memantau pembaruan chat, pesan baru, dan perubahan lainnya agar data kamu tetap mutakhir.
> [!IMPORTANT]
> Sangat disarankan untuk membangun sistem penyimpanan sendiri.
> Menyimpan seluruh riwayat chat di RAM akan memakan memori yang besar dan tidak efisien untuk jangka panjang.
---
### Contoh Penggunaan Store
```javascript
import makeWASocket, { makeInMemoryStore } from 'neroxbails'
// Store akan menyimpan data koneksi WhatsApp dalam memori
const store = makeInMemoryStore({})
// Membaca data dari file (jika tersedia)
store.readFromFile('./baileys_store.json')
// Menyimpan state ke file setiap 10 detik
setInterval(() => {
store.writeToFile('./baileys_store.json')
}, 10_000)
const sock = makeWASocket({})
// Store akan mulai mendengarkan event dari socket ini
// Jika socket diganti, store masih bisa digunakan ulang
store.bind(sock.ev)
sock.ev.on('chats.upsert', () => {
// Akses semua chat tersimpan
console.log('Data chat diterima:', store.chats.all())
})
sock.ev.on('contacts.upsert', () => {
// Akses semua kontak tersimpan
console.log('Kontak diperbarui:', Object.values(store.contacts))
})
```
### Fitur Store
- Menyimpan chat, pesan, dan kontak sementara di memori.
- Mendukung pembacaan dan penulisan dari/ke file JSON.
- Bisa digunakan bersama beberapa koneksi (socket) sekaligus.
- Tersedia fungsi `loadMessages`, `loadMessage`, dan `loadMessageFromContent`.
### Kelebihan
- Cepat dan ringan untuk penggunaan kecil-menengah.
- Ideal untuk penggunaan lokal, testing, atau bot personal.
### Kekurangan
- Data hilang saat proses dihentikan jika tidak ditulis ke file.
- Tidak cocok untuk data skala besar (ribuan pesan atau kontak).
- Tidak mendukung query kompleks (karena berbasis object literal di RAM).
### Rekomendasi Produksi
Untuk sistem besar atau multi-user:
- Gunakan database seperti:
- MongoDB (untuk struktur fleksibel dan load besar)
- Redis (untuk cache cepat)
- PostgreSQL (untuk struktur relasional)
- Sinkronkan event seperti `messages.upsert`, `chats.upsert`, dan `contacts.upsert` ke penyimpanan permanen.
- Gunakan store hanya sebagai cache atau layer middleware sementara.
> [!TIP]
> Store ini sangat berguna untuk keperluan seperti:
> - Menyimpan polling
> - Retry pesan
> - Melacak status kontak dan grup
> - Menyediakan command `.listchat`, `.listgroup`, dll. dengan data real-time
Jika kamu menggunakan custom `getMessage()`, store ini juga dapat dijadikan referensi lokal untuk mendekripsi polling dan mengirim ulang pesan.
## Penjelasan Tentang WhatsApp ID
- `id` atau biasa disebut juga `jid` adalah **identitas WhatsApp** dari seseorang atau grup yang menjadi tujuan pengiriman pesan.
- Format ID harus sesuai dengan jenis akun tujuan:
### Jenis Format ID WhatsApp
#### 1. Pengguna Pribadi (User)
**Format:**
```
[kode negara][nomor telepon]@s.whatsapp.net
```
**Contoh:**
```
628123456789@s.whatsapp.net
```
#### 2. Grup WhatsApp
**Format:**
```
[timestamp grup dibuat]-[random id]@g.us
```
**Contoh:**
```
1234567890-987654321@g.us
```
#### 3. Broadcast (Daftar Siaran)
**Format:**
```
[timestamp]@broadcast
```
**Contoh:**
```
1685539347@broadcast
```
#### 4. Status (Story)
**Format:**
```
status@broadcast
```
#### 5. Newsletter (Channel WhatsApp)
**Format:**
```
[numeric id]@newsletter
```
**Contoh:**
```
120363025487665599@newsletter
```
> **TIP:**
> Kamu bisa mendapatkan `jid` dari:
> - `m.key.remoteJid`
> - `groupParticipantsUpdate`
> - `messages.upsert`, dll
> **CAUTION:**
> Jangan pernah mengubah format `jid` secara manual tanpa validasi.
> Salah format bisa menyebabkan error `bad jid` atau pesan tidak terkirim.
## Fungsi Utilitas (Utility Functions)
Baileys menyediakan beberapa fungsi utilitas penting yang sangat membantu saat mengembangkan bot:
- **`getContentType(message)`**
Mengembalikan jenis konten dari pesan (misalnya: `imageMessage`, `conversation`, `buttonsMessage`, dll).
- **`getDevice(jid)`**
Mengembalikan jenis perangkat yang digunakan pengirim (jika tersedia), contoh: Android, iPhone, Web.
- **`makeCacheableSignalKeyStore(authState)`**
Membungkus SignalKeyStore menjadi versi yang lebih efisien dan bisa di-cache, untuk performa autentikasi yang lebih cepat.
- **`downloadContentFromMessage(message, type)`**
Mengunduh media dari pesan (seperti gambar, video, dokumen).
`type` bisa berupa `'image'`, `'video'`, `'audio'`, `'document'`, dll.
Contoh penggunaan:
```javascript
const stream = await downloadContentFromMessage(msg.imageMessage, 'image')
const buffer = Buffer.concat([])
for await (const chunk of stream) buffer.push(chunk)
```
> [!NOTE]
> Sebagian besar fungsi utilitas tidak dipanggil otomatis ā Kamu harus menggunakannya sesuai kebutuhan, terutama saat menangani pesan media, format jid, atau decrypt konten.
## Mengirim Pesan
- Semua jenis pesan dapat dikirim menggunakan **satu fungsi saja**, yaitu `sendMessage()`.
- Lihat daftar jenis pesan yang didukung [di sini](https://baileys.whiskeysockets.io/types/AnyMessageContent.html)
- Dan semua opsi pengiriman pesan [di sini](https://baileys.whiskeysockets.io/types/MiscMessageGenerationOptions.html)
Contoh:
```javascript
const jid = '628XXXXXXXXX@s.whatsapp.net' // tujuan
const content = { text: 'Halo, ini pesan dari bot!' } // isi pesan
const options = { quoted: null } // opsi tambahan (misalnya: balasan)
await sock.sendMessage(jid, content, options)
```
### Pesan Non-Media
#### Pesan Teks
```javascript
await sock.sendMessage(jid, { text: 'Halo dunia' })
```
#### Pesan Balasan (Quote)
```javascript
await sock.sendMessage(jid, { text: 'Ini balasan pesan kamu' }, { quoted: message })
```
#### Mention Pengguna (Tag)
Gunakan `@nomor` dalam teks dan sertakan `mentions` di payload.
```javascript
await sock.sendMessage(
jid,
{
text: '@628XXXXXXXXX Hai Nerox!',
mentions: ['628XXXXXXXXX@s.whatsapp.net']
}
)
```
#### Meneruskan Pesan (Forward)
Butuh objek pesan (`WAMessage`). Bisa didapat dari store atau pesan sebelumnya.
```javascript
const msg = getMessageFromStore() // Kamu buat sendiri sesuai struktur
await sock.sendMessage(jid, { forward: msg, force: true })
```
### Pesan Interaktif
#### Tombol Teks (Buttons)
```javascript
await sock.sendMessage(jid, {
text: 'Pilih salah satu:',
buttons: [
{ buttonId: 'btn_1', buttonText: { displayText: 'Tombol 1' }, type: 1 },
{ buttonId: 'btn_2', buttonText: { displayText: 'Tombol 2' }, type: 1 }
],
footer: 'Contoh footer'
})
```
#### Daftar (List Message)
```javascript
await sock.sendMessage(jid, {
text: 'Pilih dari daftar berikut:',
footer: 'Contoh footer',
title: 'Judul Daftar',
buttonText: 'Buka List',
sections: [
{
title: 'Menu 1',
rows: [
{ title: 'Opsi A', rowId: 'pilih_a' },
{ title: 'Opsi B', rowId: 'pilih_b' }
]
},
{
title: 'Menu 2',
rows: [
{ title: 'Opsi C', rowId: 'pilih_c' }
]
}
]
})
```
> [!TIP]
> Kamu bisa menggabungkan semua jenis pesan dengan opsi tambahan seperti `quoted`, `mentions`, `ephemeralExpiration`, dan lainnya untuk membuat interaksi bot yang lebih kaya dan interaktif.
#### Lokasi Biasa
```javascript
await sock.sendMessage(
jid,
{
location: {
degreesLatitude: -6.200000,
degreesLongitude: 106.816666
}
}
)
```
#### Lokasi Langsung (Live Location)
```javascript
await sock.sendMessage(
jid,
{
location: {
degreesLatitude: -6.200000,
degreesLongitude: 106.816666
},
live: true
}
)
```
#### Kirim Kontak (vCard)
```javascript
const vcard =
'BEGIN:VCARD\n' +
'VERSION:3.0\n' +
'FN:Nerox\n' +
'ORG:ZERO DEV;\n' +
'TEL;type=CELL;type=VOICE;waid=628XXXXXXXXX:+62 831-4366-3697\n' +
'END:VCARD'
await sock.sendMessage(
jid,
{
contacts: {
displayName: 'Nerox',
contacts: [{ vcard }]
}
}
)
```
#### Pesan Reaksi (Reaction Message)
- Kamu perlu mengirimkan `key` dari pesan yang ingin diberikan reaksi.
`key` bisa diambil dari [store](#mengimplementasikan-data-store) atau menggunakan [WAMessageKey](https://baileys.whiskeysockets.io/types/WAMessageKey.html).
```javascript
await sock.sendMessage(
jid,
{
react: {
text: 'š„', // gunakan string kosong '' untuk menghapus reaksi
key: message.key
}
}
)
```
#### Pin Pesan (Pin Message)
- Kamu juga perlu memberikan `key` dari pesan yang ingin dipin.
Kamu dapat mengatur durasi pin berdasarkan waktu dalam detik.
| Durasi | Detik |
|--------|--------------|
| 24 jam | 86.400 |
| 7 hari | 604.800 |
| 30 hari| 2.592.000 |
```javascript
await sock.sendMessage(
jid,
{
pin: {
type: 1, // 1 untuk pin, 2 untuk unpin
time: 86400,
key: message.key
}
}
)
```
### Menandai Pesan (Keep Message)
- Untuk menyimpan pesan tertentu agar tidak terhapus otomatis.
```javascript
await sock.sendMessage(
jid,
{
keep: {
key: message.key,
type: 1 // 1 = simpan, 2 = batalkan simpan
}
}
)
```
#### Pesan Polling (Poll Message)
- Kirim polling ke grup atau kontak pribadi. Dapat menentukan apakah polling bersifat publik (announcement group).
```javascript
await sock.sendMessage(
jid,
{
poll: {
name: 'Polling Hari Ini',
values: ['Opsi A', 'Opsi B', 'Opsi C'],
selectableCount: 1,
toAnnouncementGroup: false
}
}
)
```
#### Pesan Hasil Polling (Poll Result)
- Kirim hasil polling secara manual jika dibutuhkan. Cocok untuk sistem polling terintegrasi.
```javascript
await sock.sendMessage(
jid,
{
pollResult: {
name: 'Hasil Polling',
values: [
['Opsi A', 120],
['Opsi B', 350],
['Opsi C', 75]
]
}
}
)
```
### Pesan Panggilan (Call Message)
- Digunakan untuk mengirim notifikasi panggilan, bisa suara atau video.
```javascript
await sock.sendMessage(
jid,
{
call: {
name: 'Hay',
type: 1 // 1 = suara, 2 = video
}
}
)
```
### Pesan Event (Event Message)
- Cocok untuk mengumumkan acara atau undangan dengan detail lokasi dan waktu.
```javascript
await sock.sendMessage(
jid,
{
event: {
isCanceled: false, // true jika dibatalkan
name: 'Liburan Bareng!',
description: 'Siapa yang mau ikut?',
location: {
degreesLatitude: 24.121231,
degreesLongitude: 55.1121221,
name: 'Pantai Sanur'
},
startTime: 1715000000,
endTime: 1715086400,
extraGuestsAllowed: true // apakah boleh bawa tamu
}
}
)
```
### Pesan Pemesanan (Order Message)
- Digunakan untuk menampilkan detail pemesanan dari katalog bisnis WhatsApp.
```javascript
await sock.sendMessage(
jid,
{
order: {
orderId: '574XXX',
thumbnail: 'your_thumbnail',
itemCount: 3,
status: 'INQUIRY', // atau ACCEPTED / DECLINED
surface: 'CATALOG',
message: 'Deskripsi pesanan',
orderTitle: 'Judul Pesanan',
sellerJid: '628xxx@s.whatsapp.net',
token: 'your_token',
totalAmount1000: '150000',
totalCurrencyCode: 'IDR'
}
}
)
```
### Pesan Produk (Product Message)
- Menampilkan detail produk dari katalog bisnis.
```javascript
await sock.sendMessage(
jid,
{
product: {
productImage: {
url: 'https://your-image.url/image.jpg'
},
productId: 'PRD-001',
title: 'Produk Spesial',
description: 'Deskripsi lengkap produk kamu di sini',
currencyCode: 'IDR',
priceAmount1000: '50000',
retailerId: 'nerox', // opsional
url: 'https://linkproduk.com', // opsional
productImageCount: 1,
firstImageId: 'img-001', // opsional
salePriceAmount1000: '45000',
signedUrl: 'https://your.signed.url' // opsional
},
businessOwnerJid: '628xxx@s.whatsapp.net'
}
)
```
### Pesan Pembayaran (Payment Message)
- Digunakan untuk mengirimkan informasi pembayaran, cocok untuk chatbot belanja.
```javascript
await sock.sendMessage(
jid,
{
payment: {
note: 'Hi!',
currency: 'IDR',
offset: 0,
amount: '10000',
expiry: 0,
from: '628xxxx@s.whatsapp.net',
image: {
placeholderArgb: '#222222',
textArgb: '#FFFFFF',
subtextArgb: '#AAAAAA'
}
}
}
)
```
#### Pesan Undangan Pembayaran (Payment Invite Message)
- Digunakan untuk mengundang pengguna lain melakukan pembayaran.
```javascript
await sock.sendMessage(
jid,
{
paymentInvite: {
type: 1, // 1 = request, 2 = accept, 3 = decline (sesuaikan sesuai konteks)
expiry: 0
}
}
)
```
### Pesan Undangan Admin Channel (Admin Invite Message)
- Meminta pengguna untuk menjadi admin di saluran (newsletter) kamu.
```javascript
await sock.sendMessage(
jid,
{
adminInvite: {
jid: '123xxx@newsletter',
name: 'Channel Nerox',
caption: 'Tolong jadi admin channel saya ya!',
expiration: 86400, // dalam detik (24 jam)
jpegThumbnail: Buffer // opsional, bisa berupa buffer gambar
}
}
)
```
### Undangan Grup WhatsApp (Group Invite Message)
- Mengirim undangan ke grup tertentu menggunakan kode undangan.
```javascript
await sock.sendMessage(
jid,
{
groupInvite: {
jid: '123xxx@g.us',
name: 'Grup Dev Nerox',
caption: 'Ayo gabung ke grup WhatsApp kami!',
code: 'ABCD1234', // kode undangan grup
expiration: 86400,
jpegThumbnail: Buffer // opsional
}
}
)
```
### Pesan Bagikan Nomor Telepon (Share Phone Number)
- Mengirim permintaan eksplisit untuk membagikan nomor telepon pengguna.
```javascript
await sock.sendMessage(
jid,
{
sharePhoneNumber: {}
}
)
```
### Pesan Permintaan Nomor Telepon (Request Phone Number)
- Meminta pengguna untuk membagikan nomor telepon mereka secara langsung.
```javascript
await sock.sendMessage(
jid,
{
requestPhoneNumber: {}
}
)
```
### Pesan Balasan Tombol (Button Reply Message)
- Digunakan untuk merespons interaksi tombol yang diklik pengguna. Tipe pesan dibedakan berdasarkan jenis tombol yang digunakan.
#### Tombol Tipe List
```javascript
await sock.sendMessage(
jid,
{
buttonReply: {
name: 'Hai',
description: 'Deskripsi pilihan',
rowId: 'pilihan_1'
},
type: 'list'
}
)
```
#### Tombol Tipe Plain
```javascript
await sock.sendMessage(
jid,
{
buttonReply: {
displayText: 'Halo',
id: 'plain_id'
},
type: 'plain'
}
)
```
#### Tombol Tipe Template
```javascript
await sock.sendMessage(
jid,
{
buttonReply: {
displayText: 'Pilih Saya',
id: 'template_id',
index: 1
},
type: 'template'
}
)
```
#### Tombol Tipe Interactive (Native Flow)
```javascript
await sock.sendMessage(
jid,
{
buttonReply: {
body: 'Mau pilih yang mana?',
nativeFlows: {
name: 'menu_options',
paramsJson: JSON.stringify({ id: 'menu_1', description: 'Deskripsi interaktif' }),
version: 1 // bisa juga 2 atau 3
}
},
type: 'interactive'
}
)
```
### Pesan dengan Tombol (Buttons Message)
- Pesan biasa yang disertai hingga **3 tombol** untuk respon cepat.
```javascript
await sock.sendMessage(
jid,
{
text: 'Ini adalah pesan tombol!',
caption: 'Gunakan jika memakai gambar/video',
footer: 'Salam dari Nerox!',
buttons: [
{
buttonId: 'btn1',
buttonText: { displayText: 'Tombol 1' }
},
{
buttonId: 'btn2',
buttonText: { displayText: 'Tombol 2' }
},
{
buttonId: 'btn3',
buttonText: { displayText: 'Tombol 3' }
}
]
}
)
```
### Pesan List Tombol (Buttons List Message)
- Hanya bisa digunakan di **chat pribadi**, bukan grup.
```javascript
await sock.sendMessage(
jid,
{
text: 'Ini adalah daftar pilihan!',
footer: 'Dipersembahkan oleh Nerox',
title: 'Judul Daftar Pilihan',
buttonText: 'Klik untuk melihat opsi',
sections: [
{
title: 'Bagian 1',
rows: [
{ title: 'Opsi 1', rowId: 'opsi1' },
{ title: 'Opsi 2', rowId: 'opsi2', description: 'Deskripsi Opsi 2' }
]
},
{
title: 'Bagian 2',
rows: [
{ title: 'Opsi 3', rowId: 'opsi3' },
{ title: 'Opsi 4', rowId: 'opsi4', description: 'Deskripsi Opsi 4' }
]
}
]
}
)
```
### Pesan Daftar Produk dengan Tombol (Buttons Product List Message)
- Hanya dapat digunakan di **chat pribadi**, bukan grup.
- Menampilkan daftar produk dari katalog bisnis WhatsApp kamu.
```javascript
await sock.sendMessage(
jid,
{
text: 'Ini adalah daftar produk!',
footer: 'Dikirim oleh Nerox',
title: 'Pilih Produk Unggulan',
buttonText: 'Lihat Daftar Produk',
productList: [
{
title: 'Kategori Produk Utama',
products: [
{ productId: '1234' },
{ productId: '5678' }
]
}
],
businessOwnerJid: '628xxx@s.whatsapp.net',
thumbnail: 'https://example.jpg' // atau buffer gambar
}
)
```
### Pesan Kartu dengan Tombol (Buttons Cards Message)
- Menampilkan beberapa kartu (card) interaktif dengan gambar atau video + tombol.
```javascript
await sock.sendMessage(
jid,
{
text: 'Isi Utama Pesan',
title: 'Judul Utama',
subtile: 'Subjudul Opsional',
footer: 'Footer Pesan',
cards: [
{
image: { url: 'https://example.jpg' }, // bisa juga Buffer
title: 'Judul Kartu',
body: 'Isi Konten Kartu',
footer: 'Footer Kartu',
buttons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: 'Tombol Cepat',
id: 'ID_TOMBOL_1'
})
},
{
name: 'cta_url',
buttonParamsJson: JSON.stringify({
display_text: 'Kunjungi Website',
url: 'https://www.example.com'
})
}
]
},
{
video: { url: 'https://example.mp4' }, // bisa juga Buffer video
title: 'Judul Kartu Video',
body: 'Deskripsi Konten',
footer: 'Footer Kartu',
buttons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: 'Respon Cepat',
id: 'ID_TOMBOL_2'
})
},
{
name: 'cta_url',
buttonParamsJson: JSON.stringify({
display_text: 'Lihat Selengkapnya',
url: 'https://www.example.com'
})
}
]
}
]
}
)
```
### Pesan Tombol Template (Buttons Template Message)
- Menampilkan tombol dengan tipe URL, panggilan, atau tombol balasan cepat.
```javascript
await sock.sendMessage(
jid,
{
text: 'Ini adalah pesan template tombol!',
footer: 'Dikirim oleh Nerox',
templateButtons: [
{
index: 1,
urlButton: {
displayText: 'Ikuti Channel',
url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y'
}
},
{
index: 2,
callButton: {
displayText: 'Hubungi Saya!',
phoneNumber: '628xxxx'
}
},
{
index: 3,
quickReplyButton: {
displayText: 'Balas Cepat',
id: 'id-button-reply'
}
}
]
}
)
```
### Pesan Tombol Interaktif (Interactive Buttons)
- Mendukung berbagai jenis tombol dan dapat digunakan dengan media.
```javascript
await sock.sendMessage(
jid,
{
text: 'Ini pesan interaktif!',
title: 'Hai!',
subtitle: 'Subjudul di sini',
footer: 'Dikirim oleh Nerox',
interactiveButtons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: 'Klik Aku!',
id: 'id_kamu'
})
},
{
name: 'cta_url',
buttonParamsJson: JSON.stringify({
display_text: 'Kunjungi Channel',
url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y',
merchant_url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y'
})
},
{
name: 'cta_copy',
buttonParamsJson: JSON.stringify({
display_text: 'Salin Link',
copy_code: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y'
})
},
{
name: 'cta_call',
buttonParamsJson: JSON.stringify({
display_text: 'Telepon Saya',
phone_number: '628xxxx'
})
},
{
name: 'single_select',
buttonParamsJson: JSON.stringify({
title: 'Pilih Opsi',
sections: [
{
title: 'Pilihan Utama',
highlight_label: 'Rekomendasi',
rows: [
{
header: 'Header 1',
title: 'Opsi 1',
description: 'Deskripsi 1',
id: 'id1'
},
{
header: 'Header 2',
title: 'Opsi 2',
description: 'Deskripsi 2',
id: 'id2'
}
]
}
]
})
}
]
}
)
```
#### Versi dengan Media
##### Gambar
```javascript
await sock.sendMessage(
jid,
{
image: { url: 'https://example.jpg' },
caption: 'Isi Pesan',
title: 'Judul',
subtitle: 'Subjudul',
footer: 'Footer',
interactiveButtons: [ /* tombol seperti di atas */ ],
hasMediaAttachment: false
}
)
```
##### Video
```javascript
await sock.sendMessage(
jid,
{
video: { url: 'https://example.mp4' },
caption: 'Isi Video',
title: 'Judul',
subtitle: 'Subjudul',
footer: 'Footer',
interactiveButtons: [ /* tombol seperti di atas */ ],
hasMediaAttachment: false
}
)
```
##### Dokumen
```javascript
await sock.sendMessage(
jid,
{
document: { url: 'https://example.jpg' },
mimetype: 'image/jpeg',
jpegThumbnail: await sock.resize('https://example.jpg', 320, 320),
caption: 'Isi Dokumen',
title: 'Judul',
subtitle: 'Subjudul',
footer: 'Footer',
interactiveButtons: [ /* tombol seperti di atas */ ],
hasMediaAttachment: false
}
)
```
##### Lokasi
```javascript
await sock.sendMessage(
jid,
{
location: {
degreesLatitude: -6.2,
degreesLongitude: 106.8,
name: 'Nerox'
},
caption: 'Ayo ke sini!',
title: 'Lokasi Tujuan',
subtitle: 'Subjudul Lokasi',
footer: 'Peta lokasi',
interactiveButtons: [ /* tombol seperti di atas */ ],
hasMediaAttachment: false
}
)
```
##### Produk
```javascript
await sock.sendMessage(
jid,
{
product: {
productImage: { url: 'https://example.jpg' },
productId: '836xxx',
title: 'Produk Pilihan',
description: 'Deskripsi produk terbaik',
currencyCode: 'IDR',
priceAmount1000: '283000',
retailerId: 'Nerox',
url: 'https://example.com',
productImageCount: 1
},
businessOwnerJid: '628xxx@s.whatsapp.net',
caption: 'Produk baru tersedia!',
title: 'Nama Produk',
subtitle: 'Subjudul Produk',
footer: 'Info Produk',
interactiveButtons: [ /* tombol seperti di atas */ ],
hasMediaAttachment: false
}
)
```
### Mention Status (Status Mentions Message)
- Digunakan untuk membuat status WhatsApp yang menyebut seseorang secara langsung.
```javascript
await sock.sendStatusMentions(
jid,
{
image: {
url: 'https://example.com.jpg'
},
caption: 'Halo dari Nerox!'
}
)
```
### Pesan Album (Send Album Message)
- Mengirim beberapa gambar atau video sebagai album (sekuens media). Bisa pakai `Buffer` atau URL.
```javascript
await sock.sendAlbumMessage(
jid,
[
{
image: { url: 'https://example.jpg' },
caption: 'Gambar 1'
},
{
image: Buffer,
caption: 'Gambar 2'
},
{
video: { url: 'https://example.mp4' },
caption: 'Video 1'
},
{
video: Buffer,
caption: 'Video 2'
}
],
{
quoted: message, // opsional, untuk membalas pesan
delay: 2000 // jeda antar media (ms)
}
)
```
### Pesan Toko (Shop Message)
- Digunakan untuk mengarahkan pengguna ke katalog atau produk dalam fitur bisnis WhatsApp.
#### Teks Saja
```javascript
await sock.sendMessage(
jid,
{
text: 'Body pesan',
title: 'Judul Toko',
subtitle: 'Subjudul',
footer: 'Powered by Nerox',
shop: {
surface: 1,
id: 'https://example.com'
},
viewOnce: true
}
)
```
#### Gambar
```javascript
await sock.sendMessage(
jid,
{
image: { url: 'https://example.jpg' },
caption: 'Deskripsi produk',
title: 'Judul',
subtitle: 'Subjudul',
footer: 'Footer',
shop: {
surface: 1,
id: 'https://example.com'
},
hasMediaAttachment: false,
viewOnce: true
}
)
```
#### Video
```javascript
await sock.sendMessage(
jid,
{
video: { url: 'https://example.mp4' },
caption: 'Tonton videonya!',
title: 'Judul Video',
subtitle: 'Subjudul',
footer: 'Footer',
shop: {
surface: 1,
id: 'https://example.com'
},
hasMediaAttachment: false,
viewOnce: true
}
)
```
#### Dokumen
```javascript
await sock.sendMessage(
jid,
{
document: { url: 'https://example.jpg' },
mimetype: 'image/jpeg',
jpegThumbnail: await sock.resize('https://example.jpg', 320, 320),
caption: 'Lampiran dokumen',
title: 'Judul',
subtitle: 'Subjudul',
footer: 'Footer',
shop: {
surface: 1,
id: 'https://example.com'
},
hasMediaAttachment: false,
viewOnce: true
}
)
```
#### Lokasi
```javascript
await sock.sendMessage(
jid,
{
location: {
degreesLatitude: -6.2000,
degreesLongitude: 106.8166,
name: 'Lokasi Toko'
},
caption: 'Lihat lokasi kami!',
title: 'Judul Lokasi',
subtitle: 'Subjudul',
footer: 'Peta lokasi',
shop: {
surface: 1,
id: 'https://example.com'
},
hasMediaAttachment: false,
viewOnce: true
}
)
```
#### Produk
```javascript
await sock.sendMessage(
jid,
{
product: {
productImage: { url: 'https://example.jpg' },
productId: '836xxx',
title: 'Nama Produk',
description: 'Deskripsi produk menarik',
currencyCode: 'IDR',
priceAmount1000: '283000',
retailerId: 'Nerox',
url: 'https://example.com',
productImageCount: 1
},
businessOwnerJid: '628xxx@s.whatsapp.net',
caption: 'Lihat produk unggulan kami!',
title: 'Judul Produk',
subtitle: 'Subjudul Produk',
footer: 'Info produk',
shop: {
surface: 1,
id: 'https://example.com'
},
hasMediaAttachment: false,
viewOnce: true
}
)
```
### Pesan Koleksi (Collection Message)
- Fitur ini digunakan untuk menampilkan koleksi katalog dari bisnis tertentu di WhatsApp.
#### Teks Saja
```javascript
await sock.sendMessage(
jid,
{
text: 'Isi pesan',
title: 'Judul Koleksi',
subtitle: 'Subjudul',
footer: 'Dari Nerox',
collection: {
bizJid: '628xxx@s.whatsapp.net',
id: 'https://example.com',
version: 1
},
viewOnce: true
}
)
```
#### Gambar
```javascript
await sock.sendMessage(
jid,
{
image: { url: 'https://example.jpg' },
caption: 'Koleksi Gambar',
title: 'Judul Koleksi',
subtitle: 'Subjudul',
footer: 'Katalog Nerox',
collection: {
bizJid: '628xxx@s.whatsapp.net',
id: 'https://example.com',
version: 1
},
hasMediaAttachment: false,
viewOnce: true
}
)
```
#### Video
```javascript
await sock.sendMessage(
jid,
{
video: { url: 'https://example.mp4' },
caption: 'Koleksi Video',
title: 'Judul Video',
subtitle: 'Subjudul',
footer: 'Video Katalog',
collection: {
bizJid: '628xxx@s.whatsapp.net',
id: 'https://example.com',
version: 1
},
hasMediaAttachment: false,
viewOnce: true
}
)
```
#### Dokumen
```javascript
await sock.sendMessage(
jid,
{
document: { url: 'https://example.jpg' },