Elynn Baileys adalah library WhatsApp Web API yang kuat, stabil, dan ditingkatkan jauh dari basis aslinya — kini menyatu dengan engine Telegram Bot (
ElynnTelegraf) dan Discord Client (ElynnDiscord) dalam satu package. Mendukung penuh protokol WhatsApp 2026 — View-Once Text, View-Once Voice Note, Community Events, Group Message History, Channel Polling, dan lainnya — dilengkapi plugin Brat/Bratvid bawaan serta fungsi eksklusiftestMessageuntuk menguji seluruh jenis pesan dalam satu panggilan. Dibangun khusus untuk Node.js dengan format ECMAScript Modules (ESM).
◈ PETA NAVIGASI ◈
Engine inti, enhanced dari Baileys dengan dukungan protokol 2026 penuh — pesan interaktif, media, event komunitas, hingga sistem keamanan session.
|
⟡ Telegram
|
⟡ Discord
|
| ◆ | Satu dependency untuk tiga platform messaging sekaligus — tidak perlu lagi merangkai tiga library berbeda dengan API yang tidak konsisten |
| ◆ | Dukungan penuh protokol WhatsApp 2026 — fitur-fitur terbaru yang belum tersedia di kebanyakan fork Baileys lain |
| ◆ | testMessage bawaan — uji 16 jenis pesan dalam satu panggilan fungsi, tanpa setup tambahan |
| ◆ | sessionGuard — kunci session ke IP server pertama, proteksi nyata dari pencurian session |
| ◆ | Plugin Brat/Bratvid bawaan, tidak perlu API key eksternal tambahan |
| ◆ | Tiga jenis Auth State (multiFile, singleFile, sqlite) — fleksibel untuk semua skala deployment |
01 — Installation
Anda dapat menginstal package ini menggunakan manajer paket Node.js favorit Anda. Package ini membutuhkan Node.js versi 20 ke atas.
npm install elynn-baileys
yarn add elynn-baileys
pnpm add elynn-baileys
Untuk memaksimalkan semua fitur yang ada, terutama fitur manipulasi media, integrasi database, dan sistem preview, Anda disarankan untuk menginstal peer dependencies opsional berikut ini secara bersamaan.
npm install sharp jimp @napi-rs/image audio-decode better-sqlite3 link-preview-js
02 — Quick Start
Berikut adalah contoh lengkap cara melakukan inisialisasi koneksi ke WhatsApp. Kode ini menangani pembuatan socket, integrasi kredensial login, dan logika rekoneksi otomatis. Terdapat dua metode login: menggunakan Pairing Code atau QR Code.
import pino from 'pino'
import { makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, Browsers } from 'elynn-baileys'
async function connectToWhatsApp() {
const logger = pino({ level: 'silent' })
const { state, saveCreds } = await useMultiFileAuthState('./session-auth')
const { version, isLatest } = await fetchLatestBaileysVersion()
const usePairingCode = true
const phoneNumber = '6281234567890'
const sock = makeWASocket({
version: version,
logger: logger,
printQRInTerminal: !usePairingCode,
auth: state,
browser: Browsers.ubuntu('Chrome'), // bisa juga Browsers.kiwi(), Browsers.ucBrowser(), dll — lihat Bab 15
markOnlineOnConnect: true,
generateHighQualityLinkPreview: true,
syncFullHistory: false
})
if (usePairingCode && !sock.authState.creds.registered) {
const code = await sock.requestPairingCode(phoneNumber)
console.log(`Pairing Code Anda: ${code}`)
}
sock.ev.on('creds.update', saveCreds)
sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect } = update
if (connection === 'close') {
const shouldReconnect = lastDisconnect.error?.output?.statusCode !== DisconnectReason.loggedOut
if (shouldReconnect) {
connectToWhatsApp()
} else {
console.log('Koneksi terputus dan sesi telah dihapus.')
}
} else if (connection === 'open') {
console.log('Koneksi berhasil dibuka dan WhatsApp siap digunakan.')
}
})
return sock
}
connectToWhatsApp()
03 — Auth State
elynn-baileys menyediakan tiga jenis mekanisme penyimpanan status autentikasi yang dapat Anda pilih sesuai dengan infrastruktur aplikasi Anda.
◈ 3.1 · Multi File Auth State
Menyimpan data kredensial dan keys dalam sebuah direktori yang berisi banyak file JSON. Sangat stabil dan direkomendasikan untuk penggunaan standar.
import { useMultiFileAuthState } from 'elynn-baileys'
async function setupAuth() {
const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys')
return { state, saveCreds }
}
◈ 3.2 · Single File Auth State
Menyimpan seluruh data kredensial ke dalam satu file JSON tunggal. Mudah dipindahkan namun bisa menjadi sangat besar seiring waktu.
import { useSingleFileAuthState } from 'elynn-baileys'
async function setupAuth() {
const { state, saveCreds } = await useSingleFileAuthState('./creds.json')
return { state, saveCreds }
}
◈ 3.3 · SQLite Auth State
Menyimpan data autentikasi ke dalam database SQLite. Sangat cepat, hemat memori, dan sangat disarankan untuk produksi berskala besar.
import { useSqliteAuthState } from 'elynn-baileys'
async function setupAuth() {
// Membutuhkan peer dependency: npm install better-sqlite3
const { state, saveCreds } = await useSqliteAuthState({ dbPath: './auth_database.db' })
return { state, saveCreds }
}
04 — makeInMemoryStore
makeInMemoryStore adalah sistem penyimpanan data sesi dalam memori yang ditingkatkan. Menyediakan caching cerdas untuk pesan, kontak, dan metadata grup. Konfigurasi dan implementasi lengkap:
import { makeInMemoryStore } from 'elynn-baileys'
import pino from 'pino'
const logger = pino({ level: 'silent' })
const store = makeInMemoryStore({
logger: logger,
maxMessages: Infinity,
presenceTTL: 300000
})
function setupStore(sock) {
store.bind(sock.ev)
store.on('onMessage', (message) => {
console.log(message)
})
store.on('onPresence', (presence) => {
console.log(presence)
})
store.on('onChat', (chat) => {
console.log(chat)
})
setInterval(() => {
store.writeToFile('./store_backup.json')
}, 10000)
}
async function useStoreFeatures(sock, jid, messageId) {
const stats = store.getStats()
const searchResults = await store.searchMessages('halo dunia', jid)
const allMessages = await store.loadAllMessages(jid)
const lastMessages = await store.loadLastMessages(jid, 20)
const allGroupMetadata = await store.fetchAllGroupMetadata(sock)
const isRead = store.isMessageRead(jid, messageId)
store.readFromFile('./store_backup.json')
store.clear()
}
05 — Sending Messages
Seksi ini memuat seluruh metode dan struktur pengiriman pesan menggunakan library ini.
◈ 5.1 · Text Biasa
async function sendText(sock, jid) {
await sock.sendMessage(jid, {
text: 'Halo, ini adalah pesan teks biasa.'
})
}
◈ 5.2 · Text dengan Mention User
async function sendMention(sock, jid) {
await sock.sendMessage(jid, {
text: 'Halo @6281234567890, selamat datang di grup!',
mentions: ['6281234567890@s.whatsapp.net']
})
}
◈ 5.3 · Mention All
async function sendMentionAll(sock, jid) {
const meta = await sock.groupMetadata(jid)
await sock.sendMessage(jid, {
text: 'Pengumuman untuk seluruh anggota grup!',
mentionAll: true,
groupMetadata: meta
})
}
◈ 5.4 · Reply / Quote Message
async function sendReply(sock, jid, quotedMessage) {
await sock.sendMessage(jid, {
text: 'Ini adalah balasan dari pesan sebelumnya.',
quote: quotedMessage
})
}
◈ 5.5 · Reaction
async function sendReaction(sock, jid, messageKey) {
await sock.sendMessage(jid, {
react: {
text: '🔥',
key: messageKey
}
})
}
◈ 5.6 · Image
import fs from 'fs'
async function sendImages(sock, jid) {
await sock.sendMessage(jid, {
image: { url: 'https://domain.com/gambar-bagus.jpg' },
caption: 'Ini adalah gambar yang dikirim dari URL'
})
const bufferImage = fs.readFileSync('./lokal_foto.jpg')
await sock.sendMessage(jid, {
image: bufferImage,
caption: 'Ini adalah gambar yang dikirim dari buffer lokal'
})
}
◈ 5.7 · Video
async function sendVideo(sock, jid) {
await sock.sendMessage(jid, {
video: { url: 'https://domain.com/video-keren.mp4' },
caption: 'Deskripsi untuk video ini',
gifPlayback: false
})
}
◈ 5.8 · Audio
async function sendAudio(sock, jid) {
await sock.sendMessage(jid, {
audio: { url: 'https://domain.com/voice-note.ogg' },
mimetype: 'audio/ogg; codecs=opus',
ptt: true
})
await sock.sendMessage(jid, {
audio: { url: 'https://domain.com/musik.mp3' },
mimetype: 'audio/mp4'
})
}
◈ 5.9 · Document
async function sendDocument(sock, jid) {
await sock.sendMessage(jid, {
document: { url: 'https://domain.com/laporan-tahunan.pdf' },
mimetype: 'application/pdf',
fileName: 'laporan-tahunan-2026.pdf',
caption: 'Berikut adalah file dokumen yang diminta'
})
}
◈ 5.10 · Sticker
import fs from 'fs'
async function sendSticker(sock, jid) {
const stickerBuffer = fs.readFileSync('./animasi_sticker.webp')
await sock.sendMessage(jid, {
sticker: stickerBuffer
})
}
◈ 5.11 · Sticker Pack
import fs from 'fs'
async function sendStickerPack(sock, jid) {
const localSticker = fs.readFileSync('./sticker_dua.webp')
await sock.sendMessage(jid, {
stickerPack: {
name: 'Koleksi Sticker Eksklusif',
publisher: 'Elynn',
cover: { url: 'https://domain.com/cover-pack.png' },
stickers: [
{ data: { url: 'https://domain.com/sticker_satu.webp' }, emojis: ['😂', '🤣'] },
{ data: localSticker, emojis: ['🔥', '✨'] }
]
}
})
}
◈ 5.12 · Contact / vCard
async function sendContact(sock, jid) {
const vcardString = 'BEGIN:VCARD\nVERSION:3.0\nFN:Elynn\nTEL;type=CELL;waid=6281234567890:+62 812 3456 7890\nEND:VCARD'
await sock.sendMessage(jid, {
contacts: {
displayName: 'Elynn Contact',
contacts: [{
vcard: vcardString
}]
}
})
}
◈ 5.13 · Location
async function sendLocation(sock, jid) {
await sock.sendMessage(jid, {
location: {
degreesLatitude: -6.2087634,
degreesLongitude: 106.845599,
name: 'Monumen Nasional',
address: 'Gambir, Jakarta Pusat, DKI Jakarta, Indonesia'
}
})
}
◈ 5.14 · Live Location
import { generateWAMessageFromContent } from 'elynn-baileys'
async function sendLiveLocation(sock, jid) {
const messageContent = {
locationMessage: {
degreesLatitude: -6.2087634,
degreesLongitude: 106.845599,
name: 'Lokasi Terkini',
address: 'Berbagi Lokasi Langsung',
liveLocation: {
degreesLatitude: -6.2087634,
degreesLongitude: 106.845599,
accuracyInMeters: 10,
speedInMps: 0,
degreesClockwiseFromMagneticNorth: 0,
caption: 'Saya sedang membagikan lokasi langsung',
sequenceNumber: 1,
timeOffset: 3600
},
contextInfo: {
forwardingScore: 1,
isForwarded: false
}
}
}
const generatedMessage = await generateWAMessageFromContent(
jid,
messageContent,
{ userJid: sock.user.id }
)
await sock.relayMessage(jid, generatedMessage.message, {
messageId: generatedMessage.key.id
})
}
◈ 5.15 · Poll
async function sendPoll(sock, jid) {
await sock.sendMessage(jid, {
poll: {
name: 'Apa bahasa pemrograman favorit Anda untuk backend?',
values: ['Node.js', 'Python', 'Go', 'Rust'],
selectableCount: 1
}
})
}
◈ 5.16 · Album
import fs from 'fs'
async function sendAlbum(sock, jid) {
const localImage = fs.readFileSync('./foto_galeri.jpg')
await sock.sendMessage(jid, {
album: [
{ image: { url: 'https://domain.com/foto_satu.jpg' }, caption: 'Dokumentasi Bagian 1' },
{ image: localImage, caption: 'Dokumentasi Bagian 2' },
{ video: { url: 'https://domain.com/video_dokumentasi.mp4' }, caption: 'Video Rekaman' }
]
})
}
◈ 5.17 · Interactive — Buttons (Native Flow)
import { generateWAMessageFromContent } from 'elynn-baileys'
async function sendInteractiveButtons(sock, jid) {
const messageContent = {
viewOnceMessage: {
message: {
interactiveMessage: {
header: {
hasMediaAttachment: false
},
body: {
text: 'Silakan pilih salah satu opsi di bawah ini untuk melanjutkan:'
},
footer: {
text: 'elynn-baileys'
},
nativeFlowMessage: {
buttons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: '✅ Konfirmasi Pesanan',
id: 'btn_confirm_order'
})
},
{
name: 'cta_url',
buttonParamsJson: JSON.stringify({
display_text: '🌐 Kunjungi Website Resmi',
url: 'https://example.com',
merchant_url: 'https://example.com'
})
},
{
name: 'cta_copy',
buttonParamsJson: JSON.stringify({
display_text: '📋 Salin Kode Promo',
copy_code: 'ELYNN2026PROMO'
})
},
{
name: 'cta_call',
buttonParamsJson: JSON.stringify({
display_text: '📞 Hubungi Customer Service',
phone_number: '+6281234567890'
})
}
],
messageVersion: 1
}
}
}
}
}
const generatedMessage = await generateWAMessageFromContent(
jid,
messageContent,
{ userJid: sock.user.id }
)
await sock.relayMessage(jid, generatedMessage.message, {
messageId: generatedMessage.key.id
})
}
◈ 5.18 · Interactive — List
import { generateWAMessageFromContent } from 'elynn-baileys'
async function sendInteractiveList(sock, jid) {
const messageContent = {
viewOnceMessage: {
message: {
interactiveMessage: {
body: {
text: 'Berikut adalah katalog produk kami. Silakan pilih kategori yang Anda inginkan:'
},
footer: {
text: 'elynn-baileys'
},
nativeFlowMessage: {
buttons: [
{
name: 'single_select',
buttonParamsJson: JSON.stringify({
title: '📋 Buka Katalog Menu',
sections: [
{
title: '🍔 Makanan Utama',
rows: [
{
id: 'menu_nasi_goreng',
title: 'Nasi Goreng Spesial',
description: 'Rp 25.000 - Ekstra Telur'
},
{
id: 'menu_mie_goreng',
title: 'Mie Goreng Seafood',
description: 'Rp 30.000 - Udang & Cumi'
}
]
},
{
title: '🥤 Minuman Segar',
rows: [
{
id: 'menu_es_teh',
title: 'Es Teh Manis',
description: 'Rp 5.000 - Gula Asli'
},
{
id: 'menu_jus_jeruk',
title: 'Jus Jeruk Peras',
description: 'Rp 12.000 - Jeruk Murni'
}
]
}
]
})
}
],
messageVersion: 1
}
}
}
}
}
const generatedMessage = await generateWAMessageFromContent(
jid,
messageContent,
{ userJid: sock.user.id }
)
await sock.relayMessage(jid, generatedMessage.message, {
messageId: generatedMessage.key.id
})
}
◈ 5.19 · Interactive — Image Header
async function sendInteractiveImageHeader(sock, jid) {
const imagePreparation = await sock.prepareMessage(jid, {
image: { url: 'https://domain.com/banner-promo.jpg' }
})
await sock.sendMessage(jid, {
interactive: {
type: 'native_flow',
header: {
hasMediaAttachment: true,
imageMessage: imagePreparation.message.imageMessage
},
body: { text: 'Dapatkan diskon 50% untuk pembelian pertama Anda hari ini!' },
footer: { text: 'elynn-baileys' },
nativeFlowMessage: {
buttons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: '🛒 Klaim Diskon & Beli Sekarang',
id: 'claim_discount_buy'
})
}
]
}
}
})
}
◈ 5.20 · Interactive sebagai Template
Opsi
interactiveAsTemplatemembungkus pesan jaditemplateMessage, format legacy yang tidak tampil di akun WhatsApp personal (lihat catatan di 5.21). Hanya gunakan ini jika tujuan target adalah WhatsApp Business Cloud API resmi dengan template approved. Untuk bot/personal account biasa, kirim langsung tanpa flaginteractiveAsTemplate(lihat 5.17).
async function sendInteractiveAsTemplate(sock, jid) {
await sock.sendMessage(jid, {
interactive: {
type: 'native_flow',
body: { text: 'Pesan interaktif ini dikirim menggunakan format bungkus template.' },
footer: { text: 'elynn-baileys' },
nativeFlowMessage: {
buttons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: 'Tampilkan Detail',
id: 'show_details'
})
}
]
}
},
interactiveAsTemplate: true
})
}
◈ 5.21 · Hydrated Template Button
PENTING —
templateMessage/buttonsMessage(legacy) SUDAH TIDAK WORK di akun WhatsApp personal. Berdasarkan dokumentasi resmi WhatsApp (developers.facebook.com), button & template format lama ini hanya didukung lewat WhatsApp Business Cloud API dengan template yang sudah di-approve Meta — bukan lewat koneksi personal/MD seperti Baileys. MengirimtemplateMessagementah dari akun biasa akan terkirim tapi buttonnya tidak muncul / pesan tidak tampil di sisi penerima (silent fail). Gunakan 5.17 Native Flow sebagai gantinya — itu yang dipakai WA app resmi sekarang untuk personal account.
Helper templateButtons di bawah ini tetap disediakan untuk kompatibilitas kode lama, tapi secara internal otomatis di-convert memakai struktur yang sama dengan native flow agar tetap bisa tampil:
import { generateWAMessageFromContent, proto } from 'elynn-baileys'
// ✅ CARA YANG BENAR-BENAR WORK — pakai nativeFlow (lihat juga 5.17)
async function sendWorkingButtons(sock, jid) {
await sock.sendMessage(jid, {
text: 'Pilih salah satu opsi di bawah ini:',
footer: 'elynn-baileys',
nativeFlow: {
buttons: [
{ url: 'https://example.com', text: '🌐 Buka Situs Web' },
{ call: '+6281234567890', text: '📞 Hubungi Kami' },
{ id: 'btn_agree_terms', text: '✅ Setuju' }
]
}
})
}
// ⚠️ Legacy hydratedTemplate — disediakan untuk backward-compat, TIDAK direkomendasikan untuk fitur baru
async function sendHydratedTemplate(sock, jid) {
await sock.sendMessage(jid, {
templateButtons: [
{ url: 'https://example.com', text: '🌐 Buka Situs Web' },
{ call: '+6281234567890', text: '📞 Hubungi Kami' },
{ id: 'btn_agree_terms', text: '✅ Setuju' }
],
text: 'Ini adalah teks konten utama untuk pesan jenis hydrated template.',
footer: 'Informasi Footer Tambahan'
})
}
◈ 5.22 · View Once
async function sendViewOnce(sock, jid) {
await sock.sendMessage(jid, {
image: { url: 'https://domain.com/rahasia.jpg' },
caption: 'Dokumen ini hanya dapat dilihat satu kali.',
viewOnce: true
})
await sock.sendMessage(jid, {
video: { url: 'https://domain.com/video-rahasia.mp4' },
viewOnceV2: true
})
}
◈ 5.23 · Ephemeral
async function sendEphemeral(sock, jid) {
await sock.sendMessage(jid, {
text: 'Pesan ini bersifat rahasia dan akan terhapus otomatis secara permanen dalam waktu 24 jam.',
ephemeral: true
}, {
ephemeralExpiration: 86400
})
}
◈ 5.24 · Spoiler
async function sendSpoiler(sock, jid) {
await sock.sendMessage(jid, {
image: { url: 'https://domain.com/kejutan.jpg' },
caption: 'Ini adalah gambar kejutan yang disembunyikan di balik spoiler!',
spoiler: true
})
}
◈ 5.25 · Group Status
async function sendGroupStatus(sock, jid) {
await sock.sendMessage(jid, {
text: 'Pengumuman penting telah ditambahkan ke status grup.',
groupStatus: true
})
}
◈ 5.26 · External Ad Reply
Catatan penting:
externalAdReplydi shorthandsock.sendMessage()butuh fieldurl(string, dipakai untukmediaUrl/sourceUrl/thumbnailUrlsekaligus) danthumbnail(Buffer JPEG, bukanthumbnailUrlstring) — bukanthumbnailUrl/sourceUrlterpisah. Tanpathumbnail(Buffer), preview card sering tidak muncul karena WA app butuh gambar sudah ter-embed, tidak bisa fetch dari URL eksternal saat render. Sertakan jugaforwardingScore+isForwarded: true— pola ini paling konsisten membuat card-nya muncul.[!WARNING] Limitasi yang tidak bisa diperbaiki dari sisi kode:
externalAdReplymurni metadata dekorasi dicontextInfo, bukan tipe pesan sendiri — apakah card-nya dirender atau tidak itu keputusan WhatsApp app di sisi penerima, tergantung platform (Android/iOS) dan versi app. Ini dikonfirmasi sebagai known issue di banyak fork Baileys (lihat issue #51 dan #75 di repo WhiskeySockets/Baileys). Gejala umum: pengirim/linked-device sendiri melihat card lengkap (karena disinkron via WA Web/Desktop yang versinya lebih baru), tapi penerima dengan WA app versi/platform berbeda hanya melihat teks biasa tanpa card. Tidak ada konfigurasi proto yang menjamin tampil 100% di semua device — anggap fitur ini sebagai progressive enhancement, bukan sesuatu yang reliable untuk dipakai sebagai fitur utama bot.
import fs from 'fs'
async function sendExternalAdReply(sock, jid) {
await sock.sendMessage(jid, {
text: 'Silakan periksa tautan referensi berikut ini untuk informasi lebih lanjut!',
contextInfo: {
forwardingScore: 100,
isForwarded: true
},
externalAdReply: {
title: 'Artikel Referensi Lengkap',
body: 'Membahas teknologi terbaru dan perkembangannya di masa depan',
thumbnail: fs.readFileSync('./thumbnail-artikel.jpg'), // wajib Buffer, bukan URL
url: 'https://example.com/artikel-lengkap', // dipakai untuk mediaUrl & sourceUrl
mediaType: 1, // 1 = tanpa media spesifik, 2 = image, 3 = video
renderLargerThumbnail: true,
showAdAttribution: true // default sudah true di lib, eksplisit di sini untuk kejelasan
}
})
}
// Alternatif: raw style sesuai proto asli, kalau butuh kontrol penuh tanpa shorthand
async function sendExternalAdReplyRaw(sock, jid) {
await sock.sendMessage(jid, {
text: 'Versi raw, langsung isi contextInfo.externalAdReply.',
contextInfo: {
forwardingScore: 100,
isForwarded: true,
externalAdReply: {
title: 'Artikel Referensi Lengkap',
body: 'Membahas teknologi terbaru',
thumbnail: fs.readFileSync('./thumbnail-artikel.jpg'),
thumbnailUrl: 'https://example.com/thumbnail-artikel.jpg',
sourceUrl: 'https://example.com/artikel-lengkap',
mediaType: 1,
showAdAttribution: true
}
}
})
}
◈ 5.27 · Forward Pesan
async function sendForwardMessage(sock, jid, messageToForward) {
await sock.sendMessage(jid, {
forward: messageToForward
})
}
◈ 5.28 · Pin Pesan
async function pinMessageInChat(sock, jid, messageKey) {
await sock.sendMessage(jid, {
pin: {
messageKey: messageKey,
type: 1
}
})
}
◈ 5.29 · Raw Message
async function sendRawProtoMessage(sock, jid) {
await sock.sendMessage(jid, {
text: 'Pengujian pengiriman struktur raw protocol buffer langsung.',
raw: true
})
}
◈ 5.30 · Group Invite Link
async function sendGroupInvite(sock, jid) {
const currentTime = Math.round(new Date().getTime() / 1000)
const expirationTime = currentTime + 86400
await sock.sendMessage(jid, {
groupInviteMessage: {
inviteCode: 'AbCdEfGhIjKlMnOp',
inviteExpiration: expirationTime,
groupJid: '1234567890-0987654321@g.us',
groupName: 'Komunitas Pengembang Nusantara',
caption: 'Mari bergabung dengan grup diskusi kami untuk bertukar wawasan dan pengalaman!'
}
})
}
◈ 5.31 · Event dengan Reminder (fitur WA Januari 2026)
WhatsApp resmi menambahkan "Event Reminders" pada update grup chat 7 Januari 2026 — pembuat event kini bisa menyetel pengingat otomatis untuk semua undangan sebelum acara dimulai. Cukup tambahkan reminderOffsetSec (dalam detik) ke object event yang sudah ada di elynn-baileys.
async function sendEventWithReminder(sock, jid) {
await sock.sendMessage(jid, {
event: {
name: 'Nonton Bareng Final Liga',
description: 'Kumpul bareng nonton final di basecamp ya, jangan telat!',
startDate: new Date('2026-08-01T20:00:00+07:00'),
endDate: new Date('2026-08-01T23:00:00+07:00'),
location: {
degreesLatitude: -7.983908,
degreesLongitude: 112.621391,
name: 'Basecamp Komunitas, Jl. Mawar No. 5'
},
extraGuestsAllowed: true,
reminderOffsetSec: 3600
}
})
}
Catatan: jika
reminderOffsetSecdiisi, elynn-baileys otomatis menyetelhasReminder: truepadaeventMessage. Tanpa parameter ini, event tetap terkirim normal tanpa pengingat — perilaku ini sepenuhnya backward-compatible dengan kode event lama Anda.
◈ 5.32 · Text Sticker (fitur WA Januari 2026)
WhatsApp juga merilis "Text Stickers" pada update yang sama — mengubah kata apa pun menjadi stiker hanya dengan mengetik di Sticker Search. Karena fitur aslinya murni rendering sisi klien (tanpa endpoint protokol khusus), elynn-baileys menyediakan generator renderTextSticker() bawaan yang merender teks menjadi stiker WebP secara lokal (memakai canvas + sharp/@napi-rs/image, tanpa API pihak ketiga) lalu langsung bisa dikirim seperti stiker biasa.
import { renderTextSticker } from 'elynn-baileys'
async function sendTextSticker(sock, jid) {
const stickerBuffer = await renderTextSticker('MANTAP', {
backgroundColor: '#FFD60A',
textColor: '#1A1A1A',
fontWeight: 'bold'
})
await sock.sendMessage(jid, {
sticker: stickerBuffer
})
}
Beda dengan plugin
attp/ttp(Bab 11) yang memanggil API eksternal untuk efek teks bergerak/glow,renderTextStickermurni lokal — tidak butuh koneksi internet maupun API key, cocok untuk stiker teks polos yang cepat dan privat.
◈ 5.33 · View-Once Text — Teks Sekali Lihat (WA 2026)
Pertengahan 2026, WhatsApp merilis kemampuan mengirim teks murni sebagai view-once: pesan hanya bisa dibaca satu kali, setelah itu otomatis dihapus. Penerima tidak bisa menyalin, meneruskan, atau merekam layarnya. Di Baileys, ini bekerja dengan membungkus extendedTextMessage ke dalam viewOnceMessageV2 via generateWAMessageFromContent.
import { generateWAMessageFromContent, proto } from 'elynn-baileys'
async function sendViewOnceText(sock, jid) {
// Cara 1 — shorthand flag (dicoba dulu, support tergantung versi WA penerima)
await sock.sendMessage(jid, {
text: 'Pesan rahasia ini hanya bisa dibaca satu kali. 🔒',
viewOnce: true,
})
// Cara 2 — raw proto wrap (lebih kompatibel dengan WA build terbaru)
const innerMsg = generateWAMessageFromContent(jid, {
extendedTextMessage: {
text: 'Isi pesan rahasia yang hanya bisa dilihat sekali.',
},
}, {})
const viewOnceMsg = generateWAMessageFromContent(jid, {
viewOnceMessageV2: {
message: innerMsg.message,
},
}, { userJid: sock.user.id })
await sock.relayMessage(jid, viewOnceMsg.message, { messageId: viewOnceMsg.key.id })
}Catatan: Pastikan WA penerima sudah versi yang mendukung view-once teks (2025.8+). Pada versi lebih lama pesan akan tampil sebagai teks biasa.
◈ 5.34 · View-Once Voice Note — Audio Sekali Dengar (WA 2026)
Voice note (PTT) kini resmi bisa dikirim sebagai view-once: audio hanya bisa diputar satu kali lalu hilang. Cocok untuk kirim kode OTP audio atau pesan suara rahasia.
async function sendViewOnceVoice(sock, jid) {
// View-Once Voice Note (PTT sekali dengar)
await sock.sendMessage(jid, {
audio: { url: './voice-rahasia.ogg' },
mimetype: 'audio/ogg; codecs=opus',
ptt: true, // wajib true agar muncul sebagai voice note
viewOnce: true, // sekali dengar, lalu terhapus otomatis
})
// Dengan waveform custom (opsional, memperindah tampilan)
await sock.sendMessage(jid, {
audio: { url: './voice-rahasia.ogg' },
mimetype: 'audio/ogg; codecs=opus',
ptt: true,
viewOnce: true,
waveform: [0, 15, 42, 80, 110, 95, 70, 50, 30, 10], // array amplitudo 0-100
})
}Catatan:
ptt: truewajib ada — tanpa itu audio dikirim sebagai musik biasa dan flagviewOncetidak akan aktif dengan benar.
◈ 5.35 · Community Event — RSVP & Virtual Meeting Call (WA 2026)
WhatsApp 2026 memperluas fitur event di Community dengan dukungan RSVP tracking dan link virtual meeting langsung di dalam pesan event. Berbeda dari 5.31 (event grup biasa dengan reminder), fitur ini spesifik untuk:
| Kapabilitas | Penjelasan |
|---|---|
| Virtual call | Audio/video link tertanam langsung di pesan event |
| RSVP | Bot mendeteksi siapa yang menerima/menolak via messages.upsert bertipe eventResponseMessage |
| extraGuestsAllowed | Anggota grup bisa mengajak tamu di luar grup ke event |
// Kirim event virtual meeting di community/grup
async function sendVirtualMeetingEvent(sock, groupJid) {
await sock.sendMessage(groupJid, {
event: {
isCancelled: false,
name: 'Elynn Dev — Sprint Review Q4',
description: 'Review sprint bulanan + demo fitur baru. Join via WA Call.',
location: {
// Untuk virtual meeting: isi name dengan link meeting, lat/long bisa 0
degreesLatitude: 0,
degreesLongitude: 0,
name: 'Google Meet — meet.google.com/abc-defg-hij',
},
call: 'video', // 'audio' = voice call, 'video' = video call -- butuh options.getCallLink saat dipanggil dari generateWAMessageFromContent agar joinLink terisi
startDate: new Date('2026-10-10T15:00:00+07:00'), // wajib objek Date, bukan unix timestamp
endDate: new Date('2026-10-10T16:30:00+07:00'),
extraGuestsAllowed: false, // false = hanya member grup yang bisa join
},
})
}
// Handle respons RSVP dari peserta
sock.ev.on('messages.upsert', ({ messages }) => {
for (const msg of messages) {
const rsvp = msg.message?.eventResponseMessage
if (!rsvp) continue
// rsvp.response: 1 = GOING, 2 = NOT GOING
const status = rsvp.response === 1 ? 'HADIR ✅' : 'TIDAK HADIR ❌'
const eventId = rsvp.eventCreationMessageKey?.id
const voter = msg.key.participant || msg.key.remoteJid
console.log(`RSVP dari ${voter}: ${status} (event ID: ${eventId})`)
}
})Perbedaan dari 5.31: Section 5.31 fokus pada event grup biasa dengan
reminderOffsetSec(pengingat waktu). Section ini fokus pada virtual meeting + RSVP response handling — dua kemampuan berbeda yang hadir bersamaan di WA 2026.
◈ 5.36 · Group Message History Share (WA 2026)
WhatsApp merilis fitur ini Februari 2026: saat member baru ditambahkan, admin/member bisa membagikan 25–100 pesan terakhir ke member tersebut lewat prompt di UI client resmi. Fitur ini murni client-side (ditangani oleh aplikasi WA, bukan dikirim sebagai pesan protokol terpisah) dan field internalnya (GroupHistoryBundleInfo) ditandai deprecated di proto WA sendiri — sehingga belum ada endpoint resmi untuk men-trigger ini lewat Baileys/elynn-baileys.
Yang sudah bisa dilakukan lewat lib ini sekarang:
// Cek setting grup yang berkaitan (member add mode, announce, dst)
async function checkGroupSettings(sock, groupJid) {
const meta = await sock.groupMetadata(groupJid)
console.log('Group metadata:', {
name: meta.subject,
memberAddMode: meta.memberAddMode, // 'all_member_add' | 'admin_add'
announce: meta.announce, // true = hanya admin bisa kirim pesan
participants: meta.participants.length,
})
return meta
}
// Alternatif manual: forward N pesan terakhir ke member baru via DM/bot logic sendiri
async function shareRecentMessagesManually(sock, groupJid, newMemberJid, messages) {
for (const msg of messages.slice(-25)) { // ambil 25 pesan terakhir
await sock.relayMessage(newMemberJid, msg.message, { messageId: msg.key.id })
}
}Catatan: Belum ada method native (
groupToggleMessageHistorydkk tidak exist) karena WA belum membuka protokol publik untuk fitur ini. Jangan gunakan nama method yang belum ada di lib — cek dulu denganconsole.log(Object.keys(sock))untuk daftar method yang benar-benar tersedia.
◈ 5.37 · Channel Poll — Polling di Saluran/Channel (WA 2026)
WhatsApp Channels kini mendukung pembuatan polling — fitur interaksi satu arah berskala besar langsung di saluran. Gunakan toAnnouncementGroup: true agar poll terkirim ke channel/saluran (newsletter JID).
async function sendChannelPoll(sock, channelJid) {
// Kirim poll ke Channel / Saluran WhatsApp
// channelJid format: 'xxxxxxxxxxxxxxxxxx@newsletter'
await sock.sendMessage(channelJid, {
poll: {
name: 'Bahasa pemrograman favorit kamu?',
values: ['JavaScript', 'Python', 'Go', 'Rust', 'TypeScript'],
selectableCount: 1, // 1 = single choice, >1 = multi choice
toAnnouncementGroup: true, // WAJIB true untuk Channel/saluran
},
})
}
// Poll biasa di grup (bukan channel)
async function sendGroupPoll(sock, groupJid) {
await sock.sendMessage(groupJid, {
poll: {
name: 'Kapan kita meet offline?',
values: ['Minggu ini', 'Minggu depan', 'Bulan depan', 'Belum bisa'],
selectableCount: 1,
toAnnouncementGroup: false,
},
})
}
// Handling respons poll di event handler
sock.ev.on('messages.upsert', ({ messages }) => {
for (const msg of messages) {
if (msg.message?.pollUpdateMessage) {
const update = msg.message.pollUpdateMessage
console.log('Vote masuk:', {
voter: msg.key.participant,
pollMsgId: update.pollCreationMessageKey?.id,
selectedOpt: update.vote?.selectedOptions,
})
}
}
})◈ 5.38 · Channel Voice Note (WA 2026)
WhatsApp Channels kini mendukung pengiriman voice note — memungkinkan kreator saluran berinteraksi lebih personal dengan subscriber via audio langsung di channel.
async function sendChannelVoiceNote(sock, channelJid) {
// channelJid format: 'xxxxxxxxxxxxxxxxxx@newsletter'
await sock.sendMessage(channelJid, {
audio: { url: './pengumuman.ogg' },
mimetype: 'audio/ogg; codecs=opus',
ptt: true, // wajib true agar tampil sebagai voice note di channel
})
// Dengan caption/deskripsi (support tergantung WA build)
await sock.sendMessage(channelJid, {
audio: { url: './rekaman-siaran.mp3' },
mimetype: 'audio/mp4',
ptt: false, // false = audio biasa (musik/rekaman), bukan PTT
caption: 'Rekaman siaran terbaru — dengarkan sekarang! 🎙️',
})
}Catatan: Newsletter JID bisa didapat dari
sock.newsletterSubscribers(channelJid),sock.newsletterFetchMessages(...), atau dari metadata channel yang sudah kamu follow saat eventmessaging-history.set.
06 — Rich Response Messages
Fitur ini secara eksklusif memungkinkan Anda mengirim struktur data yang lebih kompleks menyerupai antarmuka dari bot AI resmi WhatsApp.
◈ 6.1 · Text Rich
import { prepareRichResponseMessage } from 'elynn-baileys'
async function sendRichText(sock, jid) {
const messageData = prepareRichResponseMessage({
contentText: 'Ini adalah paragraf teks biasa yang dirender dalam kontainer rich response yang memiliki margin dan padding khusus.'
})
await sock.sendMessage(jid, messageData)
}
◈ 6.2 · Code Block
import { prepareRichResponseMessage } from 'elynn-baileys'
async function sendRichCode(sock, jid) {
const kodeProgram = 'const status = "success";\nconsole.log(`Operasi selesai dengan status: ${status}`);'
const messageData = prepareRichResponseMessage({
headerText: 'Berikut adalah implementasi kode dalam JavaScript:',
code: kodeProgram,
language: 'javascript'
})
await sock.sendMessage(jid, messageData)
}
◈ 6.3 · Table
import { prepareRichResponseMessage } from 'elynn-baileys'
async function sendRichTable(sock, jid) {
const tabelData = [
['Nama Menu', 'Harga', 'Ketersediaan'],
['Nasi Goreng Spesial', 'Rp 25.000', '✅ Tersedia'],
['Mie Goreng Seafood', 'Rp 30.000', '✅ Tersedia'],
['Es Teh Manis', 'Rp 5.000', '✅ Tersedia'],
['Ayam Bakar Madu', 'Rp 35.000', '❌ Habis']
]
const messageData = prepareRichResponseMessage({
headerText: 'Daftar Harga Lengkap:',
title: 'Katalog Menu Restoran',
table: tabelData,
noHeading: false
})
await sock.sendMessage(jid, messageData)
}
◈ 6.4 · Inline Image
import { prepareRichResponseMessage } from 'elynn-baileys'
async function sendRichInlineImage(sock, jid) {
const messageData = prepareRichResponseMessage({
contentText: 'Gambar di bawah ini disisipkan langsung di dalam kotak pesan:',
inlineImage: 'https://domain.com/gambar-inline.jpg',
imageText: 'Ilustrasi pemandangan alam',
tapLinkUrl: 'https://example.com/galeri'
})
await sock.sendMessage(jid, messageData)
}
◈ 6.5 · Inline Link / Citation
import { prepareRichResponseMessage } from 'elynn-baileys'
async function sendRichCitation(sock, jid) {
const messageData = prepareRichResponseMessage({
links: [{
text: 'Silakan merujuk ke dokumentasi resmi untuk rincian lebih lanjut',
title: 'Dokumentasi API',
url: 'https://example.com/docs',
displayName: 'Portal Edukasi',
sources: [{
displayName: 'Portal Edukasi',
subtitle: 'Situs Referensi',
url: 'https://example.com/docs'
}]
}]
})
await sock.sendMessage(jid, messageData)
}
◈ 6.6 · Rich Response Kombinasi
import { prepareRichResponseMessage } from 'elynn-baileys'
async function sendComplexRichResponse(sock, jid) {
const tabelKombinasi = [
{ isHeading: true, items: ['Kolom Identitas', 'Kolom Status'] },
{ isHeading: false, items: ['Server Utama', 'Online'] },
{ isHeading: false, items: ['Server Cadangan', 'Maintenance'] }
]
const messageData = prepareRichResponseMessage({
richResponse: [
{ text: 'Sistem telah menyelesaikan analisis keseluruhan. Berikut adalah laporan terperinci:' },
{ code: [{ codeContent: 'function checkStatus() { return true; }', highlightType: 0 }], language: 'javascript' },
{ text: 'Kode di atas memvalidasi integritas data. Status server saat ini adalah:' },
{ table: tabelKombinasi, title: 'Status Infrastruktur Jaringan' },
{ inlineImage: 'https://domain.com/grafik-server.png', imageText: 'Grafik Beban Server' }
]
})
await sock.sendMessage(jid, messageData)
}
07 — Group Management
API yang ekstensif untuk memanipulasi dan mengelola data serta operasional grup secara menyeluruh.
async function manageGroup(sock, jid) {
const daftarAnggotaAwal = ['6281234567890@s.whatsapp.net', '6289876543210@s.whatsapp.net']
const grupBaru = await sock.groupCreate('Grup Diskusi Internal', daftarAnggotaAwal)
const idGrup = grupBaru.id
const metadataGrup = await sock.groupMetadata(idGrup)
const targetUser = ['628111222333@s.whatsapp.net']
await sock.groupParticipantsUpdate(idGrup, targetUser, 'add')
await sock.groupParticipantsUpdate(idGrup, targetUser, 'promote')
await sock.groupParticipantsUpdate(idGrup, targetUser, 'demote')
await sock.groupParticipantsUpdate(idGrup, targetUser, 'remove')
await sock.groupUpdateSubject(idGrup, 'Grup Diskusi Internal v2')
await sock.groupUpdateDescription(idGrup, 'Ini adalah deskripsi grup yang baru saja diperbarui melalui sistem bot otomatis.')
await sock.updateProfilePicture(idGrup, { url: 'https://domain.com/ikon-grup.png' })
const kodeUndangan = await sock.groupInviteCode(idGrup)
await sock.groupRevokeInvite(idGrup)
const infoUndangan = await sock.groupGetInviteInfo(kodeUndangan)
await sock.groupAcceptInvite(kodeUndangan)
await sock.groupSettingUpdate(idGrup, 'announcement')
await sock.groupSettingUpdate(idGrup, 'not_announcement')
await sock.groupSettingUpdate(idGrup, 'locked')
await sock.groupSettingUpdate(idGrup, 'unlocked')
await sock.groupToggleEphemeral(idGrup, 86400)
await sock.groupJoinApprovalMode(idGrup, 'on')
await sock.groupMemberAddMode(idGrup, 'admin_add')
await sock.groupLeave(idGrup)
const daftarGrupAktif = await sock.groupFetchAllParticipating()
}
08 — Newsletter / Channel
Fungsionalitas penuh untuk memoderasi saluran informasi siaran satu arah (Channel WhatsApp).
async function manageNewsletter(sock) {
const metadataChannelBaru = await sock.newsletterCreate('Saluran Berita Utama', 'Pusat informasi dan pembaruan sistem secara langsung dan cepat.')
const idChannel = metadataChannelBaru.id
await sock.newsletterFollow(idChannel)
await sock.newsletterUnfollow(idChannel)
await sock.newsletterMute(idChannel)
await sock.newsletterUnmute(idChannel)
await sock.newsletterUpdateName(idChannel, 'Berita Utama Revisi')
await sock.newsletterUpdateDescription(idChannel, 'Pembaruan deskripsi untuk memperjelas tujuan dari saluran komunikasi ini.')
await sock.newsletterUpdatePicture(idChannel, { url: 'https://domain.com/logo-channel.jpg' })
await sock.newsletterRemovePicture(idChannel)
const kodeInviteChannel = 'KODE_INVITE_YANG_VALID'
const detailMetadataChannel = await sock.newsletterMetadata('invite', kodeInviteChannel)
const idPesanServer = '1234567890'
await sock.newsletterReactMessage(idChannel, idPesanServer, '🔥')
const daftarSaluranDiikuti = await sock.newsletterSubscribed()
const batasPesan = 10
const daftarPesanChannel = await sock.newsletterFetchMessages('invite', kodeInviteChannel, batasPesan, null, null)
await sock.newsletterDelete(idChannel)
}
09 — Privacy & Profile
Pengaturan terkait profil pribadi pengguna dan konfigurasi privasi keamanan akun.
async function updateProfileAndPrivacy(sock) {
const targetJid = '6281234567890@s.whatsapp.net'
await sock.updateProfileName('Elynn Bot System')
await sock.updateProfileStatus('Sistem berjalan dengan optimal dan sedang memonitor antrean tugas.')
await sock.updateProfilePicture(targetJid, { url: 'https://domain.com/foto-profil-baru.jpg' })
await sock.removeProfilePicture(targetJid)
const tautanFotoProfil = await sock.profilePictureUrl(targetJid, 'image')
const informasiBio = await sock.fetchStatus(targetJid)
await sock.updateLastSeenPrivacy('all')
await sock.updateOnlinePrivacy('all')
await sock.updateProfilePicturePrivacy('all')
await sock.updateStatusPrivacy('all')
await sock.updateReadReceiptsPrivacy('all')
await sock.updateGroupsAddPrivacy('all')
await sock.updateCallPrivacy('all')
await sock.updateMessagesPrivacy('all')
await sock.updateDefaultDisappearingMode(86400)
await sock.updateBlockStatus(targetJid, 'block')
await sock.updateBlockStatus(targetJid, 'unblock')
const daftarBlokir = await sock.fetchBlocklist()
const nomorTelepon = '6281234567890'
const hasilPengecekanWA = await sock.onWhatsApp(nomorTelepon)
await sock.sendPresenceUpdate('composing', targetJid)
await sock.sendPresenceUpdate('recording', targetJid)
await sock.sendPresenceUpdate('paused', targetJid)
await sock.presenceSubscribe(targetJid)
}
10 — Handling Events
Cara komprehensif untuk mendaftarkan pendengar acara ke seluruh aktivitas yang terjadi di jaringan.
function setupEventHandlers(sock, saveCreds) {
sock.ev.on('connection.update', (updatePayload) => {
const koneksi = updatePayload.connection
const pemutusanTerakhir = updatePayload.lastDisconnect
const kodeQr = updatePayload.qr
const loginBaru = updatePayload.isNewLogin
})
sock.ev.on('messages.upsert', (dataUpsert) => {
const daftarPesan = dataUpsert.messages
const tipeData = dataUpsert.type
for (const dataPesan of daftarPesan) {
const pengirimJid = dataPesan.key.remoteJid
const dikirimOlehSaya = dataPesan.key.fromMe
const apakahGrup = pengirimJid.endsWith('@g.us')
const teksPesan = dataPesan.message?.conversation
|| dataPesan.message?.extendedTextMessage?.text
|| dataPesan.message?.imageMessage?.caption
|| ''
console.log({ pengirimJid, dikirimOlehSaya, apakahGrup, teksPesan })
}
})
sock.ev.on('messages.update', (dataPembaruanPesan) => {
})
sock.ev.on('messages.reaction', (dataReaksi) => {
})
sock.ev.on('message-receipt.update', (dataTandaTerima) => {
})
sock.ev.on('presence.update', (dataKehadiran) => {
const identitasUser = dataKehadiran.id
const statusKehadiran = dataKehadiran.presences
})
sock.ev.on('chats.update', (dataPembaruanChat) => {
})
sock.ev.on('chats.upsert', (dataChatBaru) => {
})
sock.ev.on('chats.delete', (dataPenghapusanChat) => {
})
sock.ev.on('contacts.upsert', (dataKontakBaru) => {
})
sock.ev.on('contacts.update', (dataPembaruanKontak) => {
})
sock.ev.on('groups.update', (dataPembaruanGrup) => {
})
sock.ev.on('group-participants.update', (dataAksiPesertaGrup) => {
const idGrup = dataAksiPesertaGrup.id
const daftarPeserta = dataAksiPesertaGrup.participants
const jenisTindakan = dataAksiPesertaGrup.action
})
sock.ev.on('call', (dataPanggilanMasuk) => {
for (const panggilan of dataPanggilanMasuk) {
const idPanggilan = panggilan.id
const pemanggil = panggilan.from
sock.rejectCall(idPanggilan, pemanggil)
}
})
sock.ev.on('labels.edit', (dataLabelDiedit) => {
})
sock.ev.on('labels.association', (dataAsosiasiLabel) => {
const tipeAsosiasi = dataAsosiasiLabel.type
const detailAsosiasi = dataAsosiasiLabel.association
})
sock.ev.on('creds.update', saveCreds)
}
11 — Elynn Plugins : Brat & Bratvid
elynn-baileys menyertakan 30+ plugin bawaan siap pakai mencakup AI, berita, downloader, search, stalk, info, dan maker. Plugin dapat diimport langsung atau diakses via objek plugins. Output tiap plugin mengikuti format { ok, type, result } — langsung bisa dipakai di sendMessage.
| Key | Method | Endpoint | Output | Parameter |
|---|---|---|---|---|
brat |
GET |
/api/maker/brat |
Sticker · img | text string |
bratvid |
GET |
/api/maker/bratvid |
Sticker · vid | text string |
import { plugins, listPlugins } from 'elynn-baileys'
// Cek plugin yang tersedia
console.log(listPlugins()) // ['ai', 'deepseek', 'qwq', 'glm', 'gpt', 'gita', 'cnbc', 'cnn', ..., 'brat', 'bratvid'] (30+ plugins)
// Kirim Brat image sebagai stiker
async function kirimBrat(sock, jid) {
const hasil = await plugins.brat({ text: 'gabut nih' })
if (!hasil.ok) return console.error(hasil.message)
// hasil.type === 'sticker' — kirim langsung sebagai stiker
await sock.sendMessage(jid, {
sticker: { url: hasil.result },
})
}
// Kirim Bratvid (video) sebagai stiker animasi
async function kirimBratvid(sock, jid) {
const hasil = await plugins.bratvid({ text: 'literally me every monday' })
if (!hasil.ok) return console.error(hasil.message)
await sock.sendMessage(jid, {
sticker: { url: hasil.result },
isAnimated: true, // opsional — indikator untuk stiker bergerak
})
}
// Contoh di dalam handler pesan bot
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const msg of messages) {
const text = msg.message?.conversation || msg.message?.extendedTextMessage?.text || ''
const jid = msg.key.remoteJid
const isBot = msg.key.fromMe
if (isBot || !text) continue
if (text.startsWith('.brat ')) {
const input = text.slice(6).trim()
const res = await plugins.brat({ text: input })
if (res.ok) {
await sock.sendMessage(jid, { sticker: { url: res.result } }, { quoted: msg })
}
}
if (text.startsWith('.bratvid ')) {
const input = text.slice(9).trim()
const res = await plugins.bratvid({ text: input })
if (res.ok) {
await sock.sendMessage(jid, { sticker: { url: res.result } }, { quoted: msg })
}
}
}
})Plugin Brat & Bratvid selalu mengembalikan
{ ok: boolean, type: 'sticker', result: string }di manaresultadalah URL gambar/video yang bisa langsung dipakai disendMessage. Tidak ada API key tambahan yang diperlukan — sudah ter-bundle di dalam library.
12 — Read Messages & Presence
Kendali mutlak atas indikator pesan dibaca dan pelaporan presensi sesi secara waktu nyata.
async function markMessagesAsRead(sock, kunciPesanTunggal, arrayKunciPesan) {
await sock.readMessages([kunciPesanTunggal])
const kunciPesanSatu = arrayKunciPesan[0]
const kunciPesanDua = arrayKunciPesan[1]
const kunciPesanTiga = arrayKunciPesan[2]
await sock.readMessages([kunciPesanSatu, kunciPesanDua, kunciPesanTiga])
}
13 — Delete / Edit Pesan
Mekanisme pasca-pengiriman yang memungkinkan Anda menarik kembali atau merevisi pesan yang telah telanjur terkirim ke server tujuan.
async function modifySentMessages(sock, jid, kunciPesanTerkirim) {
await sock.sendMessage(jid, {
delete: kunciPesanTerkirim
})
await sock.sendMessage(jid, {
edit: kunciPesanTerkirim,
text: 'Ini adalah teks yang telah direvisi dan menggantikan konten pesan sebelumnya yang salah.'
})
}
14 — Message Options Tambahan
Modifikasi perilaku tambahan untuk pesan agar sesuai dengan spesifikasi kasus penggunaan tingkat lanjut.
import { p