aldy-baileys
v1.0.6
Published
WhatsApp Web API Multi-Device Library by ALDY
Downloads
1,184
Maintainers
Readme
aldy-baileys
✨ Fitur Utama
- 🌟 Native Creative Helpers (v1.0.6) – 18 method pengiriman modern langsung pada objek
sock(sock.sendText,sock.sendButton,sock.sendCard,sock.sendAlbum,sock.react, dll.). - 🔘 Interactive Button & List Builders – Class
Button&ButtonV2untuk membuat CTA URL, Salin Kode, Telepon, Quick Reply, dan Single-Select List. - 🛡️ Anti-Delete & Anti-ViewOnce Terintegrasi – Event otomatis
sock.ev.on('message:delete')dansock.ev.on('message:view_once'). - ⚡ Bypass Download Otomatis Meta AI / Canvas – Pesan HTML Canvas dan Game langsung terbuka tanpa perlu menekan tombol "Unduh".
- 🗄️ MessageVault Storage – Caching pesan & riwayat pesan in-memory dengan fitur pencadangan file JSON.
- 🚀 Modern & Cepat – Dibangun dengan TypeScript dan teknologi terkini.
- 🔧 Perbaikan @lid & @jid – Mengatasi masalah ID lokal ke ID ponsel di grup WhatsApp.
- ⚡ Optimasi Cache Canggih – Mendukung
makeCacheableSignalKeyStore,msgRetryCounterCache, dancachedGroupMetadata. - 🛡️ Anti "Waiting for Message" – Dukungan callback
getMessageuntuk retry otomatis dan dekripsi poll. - 📱 Dukungan Multi‑Device – Koneksi penuh ke WhatsApp Multi‑Device.
- 🔐 Enkripsi End‑to‑End – Semua pesan terenkripsi.
- 📨 Semua Jenis Pesan – Teks, media (gambar, video, audio), polling, stiker, lokasi, kontak, dan lainnya.
- 🧩 Ringan & Optimal – Performa stabil dengan dukungan streaming media.
- 📂 Manajemen Autentikasi – Simpan kredensial di file atau database.
⚠️ Peringatan
Proyek ini tidak berafiliasi, didukung, atau terhubung secara resmi dengan WhatsApp atau anak perusahaannya. Situs resmi WhatsApp: whatsapp.com.
Pengguna bertanggung jawab penuh atas penggunaan aplikasi ini. Hindari spam dan otomatisasi berlebihan yang melanggar Ketentuan Layanan WhatsApp.
📦 Instalasi
Versi Stabil (Direkomendasikan)
npm install aldy-baileysVersi Terbaru (Edge)
npm install aldy-baileys@latest
# atau dengan yarn
yarn add aldy-baileys@latestCara Impor
// CommonJS
const { default: makeWASocket } = require("aldy-baileys")
// ES6 Module
import makeWASocket from "aldy-baileys"🚀 Mulai Cepat
Contoh Dasar (dengan QR Code)
const {
default: makeWASocket,
DisconnectReason,
useMultiFileAuthState,
makeCacheableSignalKeyStore,
makeInMemoryStore,
jidNormalizedUser
} = require('aldy-baileys')
const { NodeCache } = require('@cacheable/node-cache')
const pino = require('pino')
async function connectToWhatsApp() {
const logger = pino({ level: 'silent' })
// 1. Simpan kredensial di folder 'auth_info_aldy-baileys'
const { state, saveCreds } = await useMultiFileAuthState('auth_info_aldy-baileys')
// 2. Cache retry counter & in-memory store pesan
const msgRetryCounterCache = new NodeCache({ stdTTL: 3600, useClones: false })
const store = makeInMemoryStore({ logger })
const sock = makeWASocket({
logger,
printQRInTerminal: true,
browser: ['aldy-baileys', 'Desktop', '3.0'],
// Cache Signal keys di RAM untuk performa tinggi
auth: {
creds: state.creds,
keys: makeCacheableSignalKeyStore(state.keys, logger)
},
msgRetryCounterCache,
// Callback getMessage: mengambil pesan dari store untuk retry & decrypt poll
getMessage: async (key) => {
const jid = jidNormalizedUser ? jidNormalizedUser(key.remoteJid) : key.remoteJid
const msg = await store.loadMessage(jid, key.id)
return msg?.message || undefined
}
})
// Hubungkan store dengan event socket
store.bind(sock.ev)
// Event koneksi
sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect } = update
if (connection === 'close') {
const statusCode = lastDisconnect?.error?.output?.statusCode
const shouldReconnect = statusCode !== DisconnectReason.loggedOut
console.log('Koneksi tertutup, reconnecting:', shouldReconnect)
if (shouldReconnect) connectToWhatsApp()
} else if (connection === 'open') {
console.log('✅ Berhasil terhubung ke WhatsApp!')
}
})
// Event pesan masuk
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const m of messages) {
if (!m.message) continue
console.log('📱 Pesan baru dari:', m.key.remoteJid)
// Contoh balas pesan (jika bukan dari bot sendiri)
if (!m.key.fromMe) {
await sock.sendMessage(m.key.remoteJid, {
text: 'Halo! Saya bot WhatsApp menggunakan aldy-baileys 🤖'
}, { quoted: m })
}
}
})
// Simpan kredensial saat diperbarui
sock.ev.on('creds.update', saveCreds)
}
connectToWhatsApp()🔌 Koneksi Akun
WhatsApp menyediakan API multi‑device yang memungkinkan aldy-baileys terautentikasi sebagai klien WhatsApp sekunder melalui QR code atau pairing code.
Hubungkan dengan QR Code
const { default: makeWASocket, Browsers } = require("aldy-baileys")
const sock = makeWASocket({
browser: Browsers.ubuntu('My App'),
printQRInTerminal: true
})Setelah koneksi berhasil, QR code akan muncul di terminal. Pindai dengan WhatsApp di ponsel Anda untuk login.
Hubungkan dengan Pairing Code
Penting: Pairing code memungkinkan koneksi tanpa QR code. Nomor telepon harus tanpa +, (), atau -, dan sertakan kode negara.
const { default: makeWASocket } = require("aldy-baileys")
const sock = makeWASocket({
printQRInTerminal: false
})
// Pairing normal
if (!sock.authState.creds.registered) {
const number = '6283134600805' // ganti dengan nomor Anda
const code = await sock.requestPairingCode(number)
console.log('🔑 Kode Pairing:', code)
}
// Pairing dengan kode kustom (8 karakter)
if (!sock.authState.creds.registered) {
const pair = "aldy-baileys"
const number = '6283134600805'
const code = await sock.requestPairingCode(number, pair)
console.log('🔑 Kode Pairing Kustom:', code)
}Terima Riwayat Lengkap
Untuk menerima riwayat pesan lengkap, setel syncFullHistory ke true.
const { default: makeWASocket, Browsers } = require("aldy-baileys")
const sock = makeWASocket({
browser: Browsers.macOS('Desktop'),
syncFullHistory: true
})⚙️ Catatan Penting Konfigurasi Socket (Optimasi & Anti-Error)
Agar bot WhatsApp Anda stabil, tidak mengalami rate-limit, terhindar dari pesan stuck "Menunggu pesan ini" (Waiting for this message), serta memiliki performa yang ringan, sangat disarankan menerapkan konfigurasi berikut:
1. Caching Metadata Grup (cachedGroupMetadata)
Untuk bot yang berada di banyak grup aktif, implementasikan cache metadata grup agar bot tidak diblokir atau terkena rate limit WhatsApp karena fetch data grup berulang kali:
const { default: makeWASocket } = require("aldy-baileys")
const { NodeCache } = require('@cacheable/node-cache') // atau require('node-cache')
const groupCache = new NodeCache({ stdTTL: 5 * 60, useClones: false })
const sock = makeWASocket({
cachedGroupMetadata: async (jid) => groupCache.get(jid)
})
sock.ev.on('groups.update', async ([event]) => {
const metadata = await sock.groupMetadata(event.id)
groupCache.set(event.id, metadata)
})
sock.ev.on('group-participants.update', async (event) => {
const metadata = await sock.groupMetadata(event.id)
groupCache.set(event.id, metadata)
})2. Penanganan Retry Pesan & Dekripsi Vote Poll (msgRetryCounterCache & getMessage)
Saat perangkat penerima gagal mendekripsi pesan (misal: ponsel penerima baru aktif atau kunci enkripsi berubah), WhatsApp mengirimkan permintaan pengiriman ulang (retry request).
msgRetryCounterCache: Cache untuk menghitung percobaan pengiriman ulang agar tidak terjadi infinite loop saat pengiriman gagal berkali-kali.getMessage: Fungsi wajib untuk memuat kembali pesan dari Store/Database agar Baileys dapat mengenkripsi ulang dan mengirimkannya kembali ke penerima. Selain itu, fungsi ini juga digunakan untuk mendekripsi pilihan suara pada pesan polling (Poll Vote Updates).
const { default: makeWASocket, makeInMemoryStore, jidNormalizedUser } = require("aldy-baileys")
const { NodeCache } = require('@cacheable/node-cache')
const msgRetryCounterCache = new NodeCache({ stdTTL: 3600, useClones: false })
const store = makeInMemoryStore({})
const sock = makeWASocket({
msgRetryCounterCache,
getMessage: async (key) => {
if (!store) return undefined
const jid = jidNormalizedUser ? jidNormalizedUser(key.remoteJid) : key.remoteJid
let msg = await store.loadMessage(jid, key.id)
if (!msg && key.remoteJid !== jid) {
msg = await store.loadMessage(key.remoteJid, key.id)
}
return msg?.message || undefined
}
})
// Hubungkan store dengan event socket
store.bind(sock.ev)3. Caching Kunci Enkripsi Signal di RAM (makeCacheableSignalKeyStore)
Secara default, useMultiFileAuthState membaca dan menulis file sesi ke disk setiap kali pesan dikirim atau diterima. Gunakan makeCacheableSignalKeyStore untuk menyimpan kunci enkripsi di memori RAM, yang secara signifikan mempercepat proses pengiriman dan menghemat beban I/O disk/SSD:
const { default: makeWASocket, useMultiFileAuthState, makeCacheableSignalKeyStore } = require("aldy-baileys")
const pino = require("pino")
async function connect() {
const logger = pino({ level: 'silent' })
const { state, saveCreds } = await useMultiFileAuthState('session_auth')
const sock = makeWASocket({
auth: {
creds: state.creds,
keys: makeCacheableSignalKeyStore(state.keys, logger)
}
})
sock.ev.on('creds.update', saveCreds)
}4. Terima Notifikasi di Aplikasi WhatsApp Ponsel
Secara default, saat bot terhubung, WhatsApp web membuat status bot selalu online sehingga notifikasi di ponsel dibungkam. Nonaktifkan status online untuk tetap menerima notifikasi di ponsel utama Anda:
const sock = makeWASocket({
markOnlineOnConnect: false
})💾 Simpan Info Auth (Manajemen Sesi)
Hindari pemindaian QR code berulang dengan menyimpan kredensial sesi multi-device:
const { default: makeWASocket, useMultiFileAuthState, makeCacheableSignalKeyStore } = require("aldy-baileys")
const pino = require('pino')
async function connect() {
const logger = pino({ level: 'silent' })
const { state, saveCreds } = await useMultiFileAuthState('auth_info_aldy-baileys')
const sock = makeWASocket({
auth: {
creds: state.creds,
keys: makeCacheableSignalKeyStore(state.keys, logger)
}
})
// Simpan kredensial saat diperbarui oleh server WhatsApp
sock.ev.on('creds.update', saveCreds)
}
connect()💡 Tips:
useMultiFileAuthStatemenyimpan file sesi dalam sebuah folder lokal. Untuk server berskala besar atau deployment container multi-instance, Anda juga dapat mengintegrasikannya dengan database (Redis, MongoDB, atau PostgreSQL).
🗄️ Implementasi Data Store (makeInMemoryStore)
aldy-baileys menyediakan implementasi in-memory store yang efisien untuk menyimpan obrolan, kontak, dan pesan ke dalam RAM, serta mendukung persistensi otomatis ke file JSON:
const { default: makeWASocket, makeInMemoryStore, jidNormalizedUser } = require("aldy-baileys")
const fs = require('fs')
const STORE_FILE = './aldy-baileys_store.json'
const store = makeInMemoryStore({})
// 1. Muat riwayat store dari file jika ada
if (fs.existsSync(STORE_FILE)) {
try {
store.readFromFile(STORE_FILE)
console.log('📦 Riwayat store berhasil dimuat dari file')
} catch (e) {
console.error('Gagal membaca file store:', e?.message || e)
}
}
// 2. Simpan data store ke file secara berkala setiap 30 detik
setInterval(() => {
try {
store.writeToFile(STORE_FILE)
} catch (e) {}
}, 30_000)
async function start() {
const sock = makeWASocket({
// Sambungkan getMessage ke store
getMessage: async (key) => {
const jid = jidNormalizedUser ? jidNormalizedUser(key.remoteJid) : key.remoteJid
const msg = await store.loadMessage(jid, key.id)
return msg?.message || undefined
}
})
// 3. Wajib: Sambungkan event socket ke store
store.bind(sock.ev)
// Contoh mengakses data dari store:
sock.ev.on('messages.upsert', async () => {
// Ambil daftar chat aktif
const allChats = store.chats.all()
// Ambil pesan terakhir dari suatu kontak
const recentMsg = await store.mostRecentMessage('[email protected]')
// Ambil pesan spesifik berdasarkan JID dan ID
const specificMsg = await store.loadMessage('[email protected]', 'MESSAGE_ID')
})
}🆔 Penjelasan ID WhatsApp
id adalah ID WhatsApp, disebut juga jid, untuk orang atau grup tujuan pesan.
· Orang: [kode negara][nomor telepon]@s.whatsapp.net Contoh: [email protected] · Grup: [email protected] · Daftar siaran: [timestamp pembuatan]@broadcast · Cerita: status@broadcast
🔧 Fungsi Utilitas
aldy-baileys menyediakan berbagai helper & utilitas siap pakai:
getContentType(message)– Mengembalikan tipe konten utama dari pesan (misal:conversation,imageMessage,extendedTextMessage).getDevice(id)– Mendeteksi jenis perangkat pengirim pesan (android,ios,desktop,web).jidNormalizedUser(jid)– Menormalkan JID dengan membuang nomor perangkat/agent (contoh: mengubah628xxx:[email protected]menjadi[email protected]).jidDecode(jid)– Mengurai string JID menjadi objek komponen{ user, server, device, domainType }.makeCacheableSignalKeyStore(store, logger)– Membungkus Signal Keystore dengan in-memory cache agar proses pembacaan kunci sesi tidak membebani I/O disk.downloadContentFromMessage(message, mediaType)– Mengunduh buffer stream media (gambar, audio, video, dokumen, stiker).
Contoh Mengunduh Media Pesan:
const { downloadContentFromMessage } = require('aldy-baileys')
async function downloadMedia(m) {
const messageType = Object.keys(m.message)[0]
if (messageType === 'imageMessage') {
const stream = await downloadContentFromMessage(m.message.imageMessage, 'image')
let buffer = Buffer.from([])
## 🌟 Fitur Baru v1.0.6: Native Creative Helpers & Interactive Engine (Ported from Merajah Sockets)
Di versi **1.0.6**, `aldy-baileys` secara resmi mengadopsi seluruh fitur canggih dari arsitektur **Merajah Sockets**. Anda tidak perlu lagi menyusun payload Protobuf/JSON yang panjang dan rumit untuk mengirim tombol, kartu tautan, atau media. Seluruh 18 method baru otomatis terinjeksi ke objek `sock` yang dibuat oleh `makeWASocket()`.
### 📊 Tabel Perbandingan: Sintaks Lama vs Sintaks Baru
| Kebutuhan Fitur | Cara Lama (Baileys Standar) | Cara Baru (aldy-baileys v1.0.6) |
| :--- | :--- | :--- |
| **Kirim Teks** | `sock.sendMessage(jid, { text: 'halo' })` | `sock.sendText(jid, 'halo', opts)` |
| **Kirim Gambar** | `sock.sendMessage(jid, { image: { url } })` | `sock.sendImage(jid, './img.png', opts)` |
| **Kirim Video** | `sock.sendMessage(jid, { video: { url } })` | `sock.sendVideo(jid, './vid.mp4', opts)` |
| **Voice Note (VN)** | `sock.sendMessage(jid, { audio: ..., ptt: true })` | `sock.sendAudio(jid, './vn.opus', { ptt: true })` |
| **Kirim Dokumen** | `sock.sendMessage(jid, { document: ... })` | `sock.sendDocument(jid, './doc.pdf', opts)` |
| **Kirim Stiker** | `sock.sendMessage(jid, { sticker: ... })` | `sock.sendSticker(jid, './stiker.webp', opts)` |
| **Kirim Lokasi** | `sock.sendMessage(jid, { location: { ... } })` | `sock.sendLocation(jid, { degreesLatitude, ... })` |
| **Kirim Kontak** | `sock.sendMessage(jid, { contacts: { ... } })` | `sock.sendContact(jid, { displayName, vcard })` |
| **Kirim Polling** | `sock.sendMessage(jid, { poll: { ... } })` | `sock.sendPoll(jid, { name, values: [...] })` |
| **Tombol Interaktif** | Ratusan baris Protobuf `interactiveMessage` | `sock.sendButton(jid, { buttons: [...] })` |
| **Single-Select List** | Protobuf `sections` & `nativeFlowMessage` rumit | `sock.sendList(jid, { sections: [...] })` |
| **Kartu Preview Tautan** | Rangkaian object `contextInfo.externalAdReply` | `sock.sendCard(jid, { title, body, url, thumbnail })` |
| **Album Grid Media** | Pengiriman pesan berantai manual tanpa delay | `sock.sendAlbum(jid, { album: [...] })` |
| **Reaksi Emoji** | `sock.sendMessage(jid, { react: { text, key } })` | `sock.react(jid, key, '🔥')` |
| **Edit Pesan** | `sock.sendMessage(jid, { text, edit: key })` | `sock.edit(jid, key, 'Teks baru')` |
| **Tarik / Hapus Pesan** | `sock.sendMessage(jid, { delete: key })` | `sock.revoke(jid, key)` atau `sock.deleteMessage(jid, key)` |
| **Broadcast Massal** | Looping `sendMessage` berisiko banned | `sock.broadcast(jids, content, { delayMs: 1500 })` |
| **Deteksi Anti-Delete** | Parsing manual ProtocolMessage di messages.upsert | `sock.ev.on('message:delete', ({ chat, sender, ... }))` |
| **Deteksi Anti-ViewOnce** | Unwrapping manual Ephemeral / ViewOnceMessage | `sock.ev.on('message:view_once', ({ payload, ... }))` |
| **Bypass Tombol Unduh** | Kanvas HTML / Meta AI memunculkan tombol "Unduh" | **Otomatis 100%** via Protocol Message Edit (Type 14) |
---
### 1. 18 Method Pengiriman Modern (`sock.send...`)
Semua method di bawah ini menerima parameter `options` di argumen terakhir (opsional) yang mendukung `quoted`, `mentions`, `ephemeralExpiration`, dan opsi pengiriman standar Baileys lainnya.
#### a. Kirim Pesan Teks (`sock.sendText`)
```javascript
// Kirim pesan teks sederhana
await sock.sendText(m.chat, 'Halo dunia! Ini pesan dari aldy-baileys.')
// Kirim teks dengan quote & mention
await sock.sendText(m.chat, 'Halo @628123456789!', {
quoted: m,
mentions: ['[email protected]']
})b. Kirim Gambar (sock.sendImage)
Mendukung path berkas lokal (string) maupun Buffer langsung:
// Menggunakan path file lokal
await sock.sendImage(m.chat, './assets/foto.jpg', {
caption: 'Berikut foto profil bot!',
quoted: m
})
// Menggunakan Buffer langsung
const imageBuffer = fs.readFileSync('./assets/foto.jpg')
await sock.sendImage(m.chat, imageBuffer, {
caption: 'Foto sekali lihat (View Once)',
viewOnce: true
})c. Kirim Video (sock.sendVideo)
Mendukung video biasa, video note (PTV), maupun animasi GIF:
// Kirim video biasa
await sock.sendVideo(m.chat, './assets/video.mp4', {
caption: 'Tutorial video',
quoted: m
})
// Kirim video sebagai animasi GIF berulang
await sock.sendVideo(m.chat, './assets/animasi.mp4', {
gifPlayback: true,
caption: 'GIF lucu'
})
// Kirim sebagai Video Note (lingkaran bulat/PTV)
await sock.sendVideo(m.chat, './assets/note.mp4', {
ptv: true
})d. Kirim Voice Note / Audio (sock.sendAudio)
// Kirim sebagai Voice Note / PTT (Push To Talk dengan gelombang suara)
await sock.sendAudio(m.chat, './assets/rekaman.opus', {
ptt: true,
quoted: m
})
// Kirim sebagai file audio musik biasa (MP3/M4A)
await sock.sendAudio(m.chat, './assets/lagu.mp3', {
ptt: false,
mimetype: 'audio/mp4'
})e. Kirim Dokumen / File (sock.sendDocument)
await sock.sendDocument(m.chat, './dokumen/laporan.pdf', {
fileName: 'Laporan_Keuangan_2026.pdf',
caption: 'Berikut laporan yang diminta',
mimetype: 'application/pdf',
quoted: m
})f. Kirim Stiker (sock.sendSticker)
// Mengirim file WebP sebagai stiker WhatsApp
await sock.sendSticker(m.chat, './assets/stiker.webp', { quoted: m })
// Atau dengan buffer stiker
const stickerBuffer = fs.readFileSync('./assets/stiker.webp')
await sock.sendSticker(m.chat, stickerBuffer)g. Kirim Lokasi (sock.sendLocation)
await sock.sendLocation(m.chat, {
degreesLatitude: -6.2088,
degreesLongitude: 106.8456,
name: 'Monumen Nasional (Monas)',
address: 'Jakarta Pusat, DKI Jakarta'
}, { quoted: m })h. Kirim Kontak vCard (sock.sendContact)
const vcard = 'BEGIN:VCARD\n'
+ 'VERSION:3.0\n'
+ 'FN:Customer Service\n'
+ 'ORG:ALDY Bot Service;\n'
+ 'TEL;type=CELL;type=VOICE;waid=6281233959931:+62 812-3395-9931\n'
+ 'END:VCARD'
// Mengirim satu kontak
await sock.sendContact(m.chat, {
displayName: 'Customer Service',
vcard
}, { quoted: m })i. Kirim Polling / Voting (sock.sendPoll)
await sock.sendPoll(m.chat, {
name: 'Apa fitur favorit Anda di aldy-baileys?',
values: ['Interactive Buttons', 'Anti-Delete', 'Auto Bypass Download', 'RAM Hemat'],
selectableCount: 1 // Jumlah maksimal opsi yang dapat dipilih pengguna
}, { quoted: m })j. Beri Reaksi Emoji (sock.react)
// Memberikan reaksi emoji pada pesan tertentu
await sock.react(m.chat, m.key, '🔥')
// Menghapus reaksi emoji (cukup kosongkan parameter emoji)
await sock.react(m.chat, m.key, '')k. Edit Pesan yang Sudah Terkirim (sock.edit)
// Kirim pesan awal
const sent = await sock.sendText(m.chat, 'Sedang memproses data...')
// Edit pesan tersebut beberapa detik kemudian
await sock.edit(m.chat, sent.key, '✅ Proses selesai! Data berhasil diolah.')l. Tarik / Hapus Pesan untuk Semua Orang (sock.revoke / sock.deleteMessage)
// Menghapus / menarik pesan untuk semua orang (Delete for Everyone)
await sock.revoke(m.chat, targetMessageKey)
// Alias:
await sock.deleteMessage(m.chat, targetMessageKey)m. Broadcast Pesan Massal (sock.broadcast)
Mengirim pesan beruntun ke banyak JID dengan throttling delay otomatis (default 1.5 detik per pesan) untuk menghindari pemblokiran nomor WhatsApp:
const penerima = [
'[email protected]',
'[email protected]',
'[email protected]'
]
const hasil = await sock.broadcast(penerima, 'Pemberitahuan: Server bot sedang maintenance terjadwal.', {
delayMs: 2000, // jeda 2 detik per pengiriman pesan
onProgress: ({ current, total, jid, success, error }) => {
console.log(`[BROADCAST] ${current}/${total} ke ${jid} -> ${success ? 'OK' : 'GAGAL (' + error?.message + ')'}`)
}
})
console.log(`Broadcast selesai! Berhasil: ${hasil.sent.length}, Gagal: ${hasil.failed.length}`)n. Kirim Tombol Interaktif (sock.sendButton)
Mendukung tombol CTA URL, Salin Kode, Panggilan Telepon, dan Quick Reply:
await sock.sendButton(m.chat, {
title: '🎉 PROMO SPESIAL BOT',
body: 'Dapatkan diskon langganan bot premium hari ini!',
footer: 'ALDY Multi-Device Bot',
buttons: [
{ type: 'url', text: '🌐 Kunjungi Website', url: 'https://whatsapp.com' },
{ type: 'copy', text: '📋 Salin Kode Promo', copy: 'DISKON50' },
{ type: 'call', text: '📞 Hubungi CS', phone: '+628123456789' },
{ type: 'reply', text: '⚡ Cek Status Server', id: '/ping' }
],
quoted: m
})o. Kirim Single-Select List Menu (sock.sendList)
await sock.sendList(m.chat, {
title: '📋 DAFTAR MENU BOT',
body: 'Silakan pilih kategori menu yang ingin Anda akses:',
footer: 'Ketik .menu untuk bantuan kapan saja',
buttonText: 'PILIH MENU DISINI',
sections: [
{
title: 'Fitur Utama',
rows: [
{ id: '/ping', title: '⚡ Cek Ping', description: 'Melihat kecepatan respon bot' },
{ id: '/owner', title: '👑 Kontak Owner', description: 'Menghubungi pengembang bot' }
]
},
{
title: 'Game & Hiburan',
rows: [
{ id: '/spacerush', title: '🚀 Space Rush', description: 'Game canvas interaktif tanpa unduh' },
{ id: '/tebakgambar', title: '🧩 Tebak Gambar', description: 'Mini game seru di WhatsApp' }
]
}
],
quoted: m
})p. Kirim Kartu Tautan Preview (sock.sendCard / ExternalAdReply)
Menghasilkan pratinjau tautan WhatsApp dengan gambar thumbnail besar yang modern dan elegan:
await sock.sendCard(m.chat, {
text: 'Halo! Kunjungi saluran resmi kami untuk mendapatkan info pembaruan dan tips bot terbaru.',
title: 'ALDY OFFICIAL COMMUNITY',
body: 'Pusat Komunitas & Pengembangan Bot WhatsApp Indonesia',
url: 'https://whatsapp.com/channel/example',
thumbnail: './lib/media/thumb_aldy.jpg', // Path berkas lokal atau Buffer
renderLargerThumbnail: true, // Menampilkan banner thumbnail besar
showAdAttribution: true, // Label sponsor/iklan resmi
quoted: m
})q. Kirim Album Grid Media (sock.sendAlbum)
Mengirim 2 foto/video atau lebih yang otomatis menyatu menjadi format album foto di WhatsApp penerima:
await sock.sendAlbum(m.chat, {
album: [
{ image: fs.readFileSync('./foto1.jpg'), caption: 'Foto Pemandangan 1' },
{ image: fs.readFileSync('./foto2.jpg'), caption: 'Foto Pemandangan 2' }
],
caption: 'Koleksi album foto terbaru',
delayMs: 500, // Jeda antar file media (ms)
quoted: m
})2. Tombol Interaktif NativeFlow (Button & ButtonV2)
Selain sock.sendButton, aldy-baileys menyediakan dua class builder tombol bertipe fluent (Button & ButtonV2) yang memudahkan penyusunan tombol secara modular:
a. Menggunakan Class Button (Fluent Builder)
Class Button mendukung penyusunan tombol interaktif lengkap dengan media header (gambar, dokumen, atau video):
const { Button } = require('aldy-baileys')
const btn = new Button(sock)
btn.setTitle('Menu Utama Bot')
.setBody('Halo! Silakan pilih layanan atau aksi di bawah:')
.setFooter('aldy-baileys v1.0.6')
.setImage('./assets/banner.jpg') // Opsional: pasang gambar banner header
.addUrl('🌐 Kunjungi Website', 'https://whatsapp.com')
.addCopy('📋 Salin Kode Voucher', 'VOUCHER2026')
.addCall('📞 Hubungi Hotline', '+628123456789')
.addQuickReply('⚡ Cek Ping Server', '/ping')
.addQuickReply('ℹ️ Informasi Bot', '/info')
// Kirim tombol
await btn.send(m.chat, { quoted: m })Daftar Method Chaining Button:
btn.setTitle(text)– Mengatur judul teks pesan.btn.setBody(text)– Mengatur teks badan (body) pesan.btn.setFooter(text)– Mengatur teks kaki (footer) pesan.btn.setImage(bufferOrPath)– Melampirkan gambar pada header kartu.btn.setDocument(bufferOrPath, fileName, mimetype)– Melampirkan dokumen file pada header kartu.btn.setVideo(bufferOrPath)– Melampirkan video pada header kartu.btn.addUrl(display, url)– Menambahkan tombol tautan web (CTA URL).btn.addCopy(display, code)– Menambahkan tombol salin teks/kode (CTA Copy).btn.addCall(display, phone)– Menambahkan tombol dial nomor telepon (CTA Call).btn.addQuickReply(display, id)– Menambahkan tombol balasan cepat (Quick Reply).btn.build()– Menghasilkan payload JSON interaktif mentah.btn.send(jid, options)– Mengirimkan pesan tombol langsung ke WhatsApp tujuan.
b. Menggunakan Class ButtonV2 (Location & Thumbnail Interactive)
Class ButtonV2 menggunakan format pesan berbasis lokasi dengan thumbnail preview:
const { ButtonV2 } = require('aldy-baileys')
const btn2 = new ButtonV2(sock)
btn2.setTitle('Konfirmasi Pesanan')
.setBody('Apakah Anda ingin memproses transaksi ini?')
.setFooter('Sistem Pembayaran Otomatis')
.setThumbnail('./assets/thumb.jpg')
.addButton('✅ Setuju & Bayar', 'btn_accept')
.addButton('❌ Batalkan Transaksi', 'btn_cancel')
// Kirim tombol
await btn2.send(m.chat, { quoted: m })3. Sistem Event Otomatis Anti-Delete & Anti-ViewOnce
aldy-baileys v1.0.6 telah mengintegrasikan engine listener otomatis ke dalam sock.ev. Anda tidak perlu lagi melakukan parsing manual terhadap pesan protocolMessage tipe revoke atau pesan viewOnceMessage:
// 1. Event Anti-Delete: Otomatis terpanggil saat ada yang menarik / menghapus pesan
sock.ev.on('message:delete', async ({ chat, sender, targetKey, originalMessage, revokedAt }) => {
console.log(`[ANTI-DELETE] Pesan dari ${sender} di ${chat} telah ditarik!`)
// Jika pesan yang ditarik ada di cache/store:
if (originalMessage) {
const textContent = originalMessage.message?.conversation
|| originalMessage.message?.extendedTextMessage?.text
|| '[Media atau Objek]'
// Kirim notifikasi peringatan ke chat grup atau admin bot:
await sock.sendText(chat, `⚠️ @${sender.split('@')[0]} baru saja menarik pesan:\n\n"${textContent}"`, {
mentions: [sender]
})
}
})
// 2. Event Anti-ViewOnce: Otomatis terpanggil saat ada pesan sekali lihat (View Once) masuk
sock.ev.on('message:view_once', async ({ msg, payload, chat, sender, id }) => {
console.log(`[ANTI-VIEWONCE] Pesan sekali lihat terdeteksi dari ${sender}`)
// 'payload' berisi objek pesan media (imageMessage/videoMessage) yang sudah otomatis di-unwrap:
if (payload?.imageMessage) {
console.log('Caption foto view-once:', payload.imageMessage.caption)
}
})
// 3. Event Pesan Mentah (Raw Message)
sock.ev.on('message', (rawMsg) => {
// Menangkap pesan masuk tanpa filter untuk kemudahan debugging
})4. MessageVault (Penyimpanan Memori Cepat & Cadangan Disk)
MessageVault adalah class store canggih berkinerja tinggi yang dirancang khusus untuk bot WhatsApp. Menyimpan riwayat pesan di memori RAM dengan pembatasan jumlah pesan per chat (LRU style) serta mendukung pencadangan (backup/restore) ke disk JSON:
const { createMessageVault } = require('aldy-baileys')
// Buat instance vault dengan batasan 500 pesan per chat
const vault = createMessageVault({ maxMessagesPerChat: 500 })
// Hubungkan otomatis ke socket Baileys
vault.bind(sock)
// Cari pesan berdasarkan ID chat dan ID pesan
const pesan = vault.findMessage(m.chat, m.key.id)
// Ambil riwayat chat (misal: 20 pesan terakhir)
const riwayat = vault.getHistory(m.chat, 20)
// Cari pesan yang pernah ditarik (revoked)
const revokedMsg = vault.findRevoked(m.chat, 'TARGET_MESSAGE_ID')
// Ekstrak pesan View-Once yang pernah disimpan
const viewOnceData = vault.decodeViewOnce(m.chat, 'VO_MESSAGE_ID')
// Lihat statistik penyimpanan
console.log(vault.stats()) // Output: { totalChats: 12, totalMessages: 850, revokedMessages: 4, viewOnceMessages: 2 }
// Cadangkan data store ke file JSON di disk
vault.backup('./vault_backup.json')
// Pulihkan data store dari file JSON saat bot baru restart
vault.restore('./vault_backup.json')5. Bypass Download Otomatis untuk Canvas / HTML / Meta AI (Game Space Rush dll.)
Pada versi resmi aplikasi WhatsApp, pesan HTML Canvas interaktif (seperti game Space Rush atau Mini Web Application Meta AI) selalu memunculkan tombol "Unduh" terlebih dahulu sebelum konten kanvas dapat dimainkan oleh pengguna.
Di aldy-baileys v1.0.6, Baileys secara otomatis menyisipkan Protocol Message Edit (Type 14) saat pesan Rich Response dikirimkan:
- ✅ WhatsApp di ponsel penerima otomatis merender kanvas secara instan dan langsung dapat dimainkan tanpa perlu menekan tombol unduh.
- ✅ Menghilangkan teks footer disclaimer seperti "Dihasilkan oleh AI" untuk pengalaman bermain yang bersih dan mulus.
- ⚙️ Opsi Manual: Jika Anda ingin menonaktifkan fitur bypass ini pada pesan tertentu, cukup berikan opsi
{ bypassDownload: false }pada parameter pengiriman.
Contoh Pengiriman Game Canvas:
// Game Space Rush atau Canvas HTML akan langsung terbuka tanpa tombol unduh di ponsel pengguna
await sock.relayMessage(m.chat, canvasMessagePayload, {
messageId: sock.generateMessageTag()
})📤 Kirim Pesan (Sintaks Lama Baileys)
Kirim semua jenis pesan dengan satu fungsi.
sock.sendMessage(jid, content, options)Pesan Non‑Media
Pesan Teks
await sock.sendMessage(jid, { text: 'halo dunia' })Pesan Kutipan (bekerja dengan semua tipe)
await sock.sendMessage(jid, { text: 'halo dunia' }, { quoted: message })Sebut Pengguna
await sock.sendMessage(
jid,
{
text: '@12345678901',
mentions: ['[email protected]']
}
)Teruskan Pesan
const msg = getMessageFromStore() // implementasikan sendiri
await sock.sendMessage(jid, { forward: msg })Pesan Lokasi
await sock.sendMessage(
jid,
{
location: {
degreesLatitude: 24.121231,
degreesLongitude: 55.1121221
}
}
)Pesan Kontak (vCard)
const vcard = 'BEGIN:VCARD\n'
+ 'VERSION:3.0\n'
+ 'FN:Jeff Singh\n'
+ 'ORG:Ashoka Uni;\n'
+ 'TEL;type=CELL;type=VOICE;waid=911234567890:+91 12345 67890\n'
+ 'END:VCARD'
await sock.sendMessage(
id,
{
contacts: {
displayName: 'Jeff',
contacts: [{ vcard }]
}
}
)Pesan Reaksi
await sock.sendMessage(
jid,
{
react: {
text: '💖', // kosongkan untuk hapus reaksi
key: message.key
}
}
)Pin Pesan
await sock.sendMessage(
jid,
{
pin: {
type: 1, // 0 untuk hapus
time: 86400, // 24 jam dalam detik
key: message.key
}
}
)Pesan Poll
await sock.sendMessage(
jid,
{
poll: {
name: 'Poll Saya',
values: ['Opsi 1', 'Opsi 2', 'Opsi 3'],
selectableCount: 1,
toAnnouncementGroup: false
}
}
)Kirim dengan Pratinjau Tautan
Instal link-preview-js:
npm install link-preview-jsawait sock.sendMessage(
jid,
{
text: 'Halo, ini dikirim menggunakan https://npmjs.com/aldy-baileys'
}
)Pesan Media
Catatan: Di pesan media, bisa gunakan { stream: Stream }, { url: Url }, atau Buffer langsung.
Kirim Gambar
await sock.sendMessage(
id,
{
image: {
url: './Media/ma_img.png'
},
caption: 'halo dunia'
}
)Kirim Video
await sock.sendMessage(
id,
{
video: {
url: './Media/ma_video.mp4'
},
caption: 'halo dunia',
ptv: false // true untuk video note
}
)Kirim GIF
await sock.sendMessage(
jid,
{
video: fs.readFileSync('Media/ma_gif.mp4'),
caption: 'halo dunia',
gifPlayback: true
}
)Kirim Audio
await sock.sendMessage(
jid,
{
audio: {
url: './Media/audio.mp3'
},
mimetype: 'audio/mp4'
}
)View Once
await sock.sendMessage(
id,
{
image: {
url: './Media/ma_img.png'
},
viewOnce: true,
caption: 'halo dunia'
}
)✏️ Ubah Pesan
Hapus Pesan (untuk semua)
const msg = await sock.sendMessage(jid, { text: 'halo dunia' })
await sock.sendMessage(jid, { delete: msg.key })Edit Pesan
await sock.sendMessage(jid, {
text: 'teks terupdate di sini',
edit: response.key,
})🖼️ Manipulasi Pesan Media
Unduh Pesan Media
import { createWriteStream } from 'fs'
import { downloadMediaMessage, getContentType } from 'aldy-baileys'
sock.ev.on('messages.upsert', async ({ messages: [m] }) => {
if (!m.message) return
const messageType = getContentType(m)
if (messageType === 'imageMessage') {
const stream = await downloadMediaMessage(
m,
'stream',
{ },
{
logger,
reuploadRequest: sock.updateMediaMessage
}
)
const writeStream = createWriteStream('./my-download.jpeg')
stream.pipe(writeStream)
}
})📞 Tolak Panggilan
await sock.rejectCall(callId, callFrom)💬 Status Kirim di Obrolan
Baca Pesan
await sock.readMessages([key]) // bisa multiple kunciUpdate Kehadiran
await sock.sendPresenceUpdate('available', jid)
await sock.sendPresenceUpdate('composing', jid)📁 Ubah Obrolan
Arsipkan Obrolan
const lastMsgInChat = await getLastMessageInChat(jid) // implementasikan sendiri
await sock.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, jid)Bisukan/Buka Bisukan Obrolan
// Bisukan 8 jam
await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
// Buka bisukan
await sock.chatModify({ mute: null }, jid)Tandai Obrolan Dibaca/Tidak Dibaca
const lastMsgInChat = await getLastMessageInChat(jid)
await sock.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, jid)Hapus Pesan untuk Saya
await sock.chatModify(
{
clear: {
messages: [
{
id: 'ATWYHDNNWU81732J',
fromMe: true,
timestamp: '1654823909'
}
]
}
},
jid
)Hapus Obrolan
const lastMsgInChat = await getLastMessageInChat(jid)
await sock.chatModify({
delete: true,
lastMessages: [
{
key: lastMsgInChat.key,
messageTimestamp: lastMsgInChat.messageTimestamp
}
]
}, jid)Pin/Hapus Pin Obrolan
await sock.chatModify({ pin: true }, jid) // pin
await sock.chatModify({ pin: false }, jid) // hapus pinBintangi/Hapus Bintang Pesan
await sock.chatModify({
star: {
messages: [
{
id: 'messageID',
fromMe: true
}
],
star: true // atau false untuk hapus bintang
}
}, jid)Pesan Menghilang
// Nyalakan pesan menghilang (7 hari default)
await sock.sendMessage(
jid,
{ disappearingMessagesInChat: 604800 } // 7 hari dalam detik
)
// Kirim sebagai pesan menghilang
await sock.sendMessage(jid, { text: 'halo' }, { ephemeralExpiration: 604800 })
// Matikan
await sock.sendMessage(
jid,
{ disappearingMessagesInChat: false }
)👤 Query Pengguna
Periksa ID Ada di WhatsApp
const [result] = await sock.onWhatsApp(jid)
if (result.exists) console.log(`${jid} ada di WhatsApp, sebagai jid: ${result.jid}`)Query Riwayat Obrolan
const msg = await getOldestMessageInChat(jid) // implementasikan sendiri
await sock.fetchMessageHistory(
50, // jumlah (max: 50 per query)
msg.key,
msg.messageTimestamp
)Ambil Status
const status = await sock.fetchStatus(jid)
console.log('status: ' + status)Ambil Foto Profil (grup juga)
// resolusi rendah
const ppUrl = await sock.profilePictureUrl(jid)
console.log(ppUrl)
// resolusi tinggi
const ppUrlHigh = await sock.profilePictureUrl(jid, 'image')Ambil Profil Bisnis
const profile = await sock.getBusinessProfile(jid)
console.log('deskripsi: ' + profile.description + ', kategori: ' + profile.category)Ambil Kehadiran Seseorang
sock.ev.on('presence.update', console.log)
await sock.presenceSubscribe(jid) 🔄 Ubah Profil
Ubah Status Profil
await sock.updateProfileStatus('Halo Dunia!')Ubah Nama Profil
await sock.updateProfileName('Nama Saya')Ubah Foto Tampilan (grup juga)
await sock.updateProfilePicture(jid, { url: './new-profile-picture.jpeg' })Hapus Foto Tampilan (grup juga)
await sock.removeProfilePicture(jid)👥 Grup
Buat Grup
const group = await sock.groupCreate('Grup Saya', ['[email protected]', '[email protected]'])
console.log('grup dibuat dengan id: ' + group.gid)Tambah/Hapus atau Turunkan/Naikkan
await sock.groupParticipantsUpdate(
jid,
['[email protected]', '[email protected]'],
'add' // 'remove', 'demote', atau 'promote'
)Ubah Subjek (nama)
await sock.groupUpdateSubject(jid, 'Subjek Baru!')Ubah Deskripsi
await sock.groupUpdateDescription(jid, 'Deskripsi Baru!')Ubah Pengaturan
// Hanya admin kirim pesan
await sock.groupSettingUpdate(jid, 'announcement')
// Semua bisa kirim
await sock.groupSettingUpdate(jid, 'not_announcement')
// Semua bisa ubah pengaturan grup
await sock.groupSettingUpdate(jid, 'unlocked')
// Hanya admin ubah pengaturan
await sock.groupSettingUpdate(jid, 'locked')Keluar Grup
await sock.groupLeave(jid)Ambil Kode Undangan
const code = await sock.groupInviteCode(jid)
console.log('https://chat.whatsapp.com/' + code)Cabut Kode Undangan
const code = await sock.groupRevokeInvite(jid)
console.log('Kode grup baru: ' + code)Gabung Menggunakan Kode Undangan
const response = await sock.groupAcceptInvite(code)
console.log('bergabung ke: ' + response)Ambil Info Grup dari Kode Undangan
const response = await sock.groupGetInviteInfo(code)
console.log('info grup: ' + response)Query Metadata
const metadata = await sock.groupMetadata(jid)
console.log(metadata.id + ', judul: ' + metadata.subject + ', deskripsi: ' + metadata.desc)Ambil Semua Metadata Grup yang Diikuti
const response = await sock.groupFetchAllParticipating()
console.log(response)Toggle Ephemeral
await sock.groupToggleEphemeral(jid, 86400) // 24 jamUbah Mode Tambah
await sock.groupMemberAddMode(
jid,
'all_member_add' // atau 'admin_add'
)🔒 Privasi
Blokir/Buka Blokir Pengguna
await sock.updateBlockStatus(jid, 'block')
await sock.updateBlockStatus(jid, 'unblock')Ambil Pengaturan Privasi
const privacySettings = await sock.fetchPrivacySettings(true)
console.log(privacySettings)Ambil Daftar Blokir
const blocklist = await sock.fetchBlocklist()
console.log(blocklist)Update Privasi
await sock.updateLastSeenPrivacy('contacts')
await sock.updateOnlinePrivacy('all')
await sock.updateProfilePicturePrivacy('contacts')
await sock.updateStatusPrivacy('none')
await sock.updateReadReceiptsPrivacy('all')
await sock.updateGroupsAddPrivacy('contacts')
await sock.updateDefaultDisappearingMode(86400) // 24 jam📢 Daftar Siaran & Cerita
Kirim Siaran & Cerita
await sock.sendMessage(
jid,
{
image: {
url: url
},
caption: caption
},
{
backgroundColor: backgroundColor,
font: font,
statusJidList: statusJidList,
broadcast: true
}
)Query Penerima & Nama Daftar Siaran
const bList = await sock.getBroadcastListInfo('1234@broadcast')
console.log(`nama daftar: ${bList.name}, penerima: ${bList.recipients}`)🛠️ Fungsi Kustom
Aktifkan Level Debug
const { P } = require('aldy-baileys')
const sock = makeWASocket({
logger: P({ level: 'debug' }),
})Daftarkan Callback untuk Event Websocket
// Untuk tag 'edge_routing'
sock.ws.on('CB:edge_routing', (node) => { })
// Dengan id 'abcd'
sock.ws.on('CB:edge_routing,id:abcd', (node) => { })
// Dengan node routing_info
sock.ws.on('CB:edge_routing,id:abcd,routing_info', (node) => { })💡 Tips & Praktik Terbaik
- ⚡ Gunakan Caching & getMessage – Selalu pasang
msgRetryCounterCache,makeCacheableSignalKeyStore, dangetMessageagar bot bebas dari error dekripsi "Menunggu pesan ini" (Waiting for this message) dan performa I/O tetap ringan. - 📁 Contoh Siap Pakai – Lihat file
example.jsdi repositori ini untuk contoh implementasi bot lengkap dari awal hingga akhir. - 🔄 Tangani Rekoneksi – Gunakan logika reconnecting saat status koneksi terputus kecuali jika akun ter-logout (
DisconnectReason.loggedOut). - 🗄️ Kelola Store dengan Baik – Simpan file store secara berkala atau gunakan database (MongoDB, PostgreSQL, Redis) untuk penggunaan jangka panjang agar RAM tidak cepat penuh.
- 🛡️ Anti-Crash & Penanganan Error – Selalu bungkus event listener pesan dengan
try ... catchdan tangani eventprocess.on('uncaughtException'). - ⏱️ Batas Rate & Anti-Spam – Berikan jeda waktu antar pengiriman pesan untuk mematuhi batas wajar WhatsApp dan mencegah pemblokiran nomor.
- 🔐 Keamanan Kredensial – Masukkan folder sesi (
session_auth,session, atau file.json) ke.gitignoreagar tidak bocor ke publik.
📄 Lisensi
Didistribusikan di bawah Lisensi GPL‑3.0. Lihat file LICENSE untuk informasi lebih lanjut.
