npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

zans-xbails

v0.0.2

Published

WhatsApp API

Readme

🍃 Apa Itu Baileys?

Baileys itu library TypeScript berbasis Webconnet buat ngoprek WhatsApp Web API.

Cara Pake

Panduan paling baru ada di https://baileys.wiki.

Disclaimer

Proyek ini gak ada hubungan, gak berafiliasi, gak diizinin, gak didukung, dan gak punya koneksi resmi sama WhatsApp atau anak perusahaannya. Situs resmi WhatsApp bisa dicek di whatsapp.com. "WhatsApp" dan semua nama, merek dagang, logo, serta gambar terkait itu hak milik terdaftar dari pemiliknya masing-masing.

Para pengelola Baileys gak nyaranin pake aplikasi ini buat hal-hal yang ngelanggar Ketentuan Layanan WhatsApp. Kita minta banget buat semua user pake aplikasi ini secara bertanggung jawab dan sesuai tujuan awal dibikinnya. Pake aja sesuai kebutuhan pribadi. Jangan buat spam. Kita gak dukung buat stalkerware, kirim pesan massal, atau otomatisasi pesan yang ganggu.

Lisensi

Proyek ini pake lisensi MIT License, dan ini hasil modifikasi dari Baileys punya Rajeh Taher/Whiskeyconnets.

Kalo lu pake proyek ini, berarti lu setuju sama ketentuan lisensinya.

Tentang Modifikasi

Proyek ini hasil rombakan gede dari Baileys, library open-source WhatsApp Web API yang awalnya ditulis pake TypeScript dan pake format ECMAScript Module (ESM).

Modifikasi ini fokus buat bikin versi yang full JavaScript murni dengan dukungan CommonJS (CJS). Dengan cara ini, library jadi lebih fleksibel dan gampang diintegrasiin ke berbagai jenis runtime Node.js tanpa perlu transpilasi atau setting tambahan kayak "type": "module".

Instalasi

Pake salah satu manajer paket ini buat install versi stabil:

npm install zans-xbaileys
yarn add zans-xbaileys
pnpm add zans-xbaileys

Info Penting

Paket ini butuh Node.js versi 20 ke atas buat jalan.

Proyek ini emang khusus buat lingkungan modern dan gak support Node versi lama. Dukungan bakal selalu ngikutin versi LTS terbaru dari Node.js biar performa dan kompatibilitasnya tetep oke.

Copyright © 2025 zansxart

Admin Contact

🔗 Nyambungin Akun

Baileys support koneksi ke WhatsApp lewat API multi-perangkat. Lu bisa nyambungin akun pake dua cara utama: Kode QR atau Kode Pairing.

📷 Nyambungin Pake Kode QR (ESM)

💡 Tips: Lu bisa atur nama browser yang muncul di perangkat WhatsApp pake konstanta Browsers. Cek daftar nama browser yang tersedia di 📘 dokumentasi

import makeWAconnet, { Browsers } from 'zans-xbaileys'

const conn = makeWAconnet({
  browser: Browsers.ubuntu('Safari'),
  printQRInTerminal: true
})

📱 Kalo koneksi berhasil, kode QR bakal muncul di terminal. Scan aja pake WhatsApp buat login~ 🩵

📦 Nyambungin Pake Kode QR (CommonJS)

Kalo lu pake CommonJS (Node.js versi require), pake ini ya:

const { default: makeWAconnet, Browsers } = require('zans-xbaileys')

const conn = makeWAconnet({
  browser: Browsers.ubuntu('Safari'),
  printQRInTerminal: true
})

📌 Pastikan file lu gak pake "type": "module" di package.json biar mode CJS bisa jalan 💻

💫 Nyambungin Pake Kode Pairing (Multi-Device)

Mau tanpa QR? Bisa pake Pairing Code juga~ 🌸 Cuma bisa dipake di WhatsApp Web ya (bukan Android/iOS) 💻

🌈 ESM (ECMAScript Module)

import makeWAconnet, { Browsers } from 'zans-xbaileys'

const conn = makeWAconnet({
  browser: Browsers.ubuntu('Safari'),
  usePairingCode: true,
  phoneNumber: '628xxxxxxx'
})

🎀 CommonJS

const { default: makeWAconnet, Browsers } = require('zans-xbaileys')

const conn = makeWAconnet({
  browser: Browsers.ubuntu('Safari'),
  usePairingCode: true,
  phoneNumber: '628xxxxxxx'
})

🪄 Pairing code bakal muncul di terminal~ Ketik di WhatsApp Web dan lu langsung nyambung! 🌐✨

🛠️ Mulai connet pake Kode Pairing

⚠️ Penting! Pairing Code bukan API Mobile. Ini cara buat nyambung ke WhatsApp Web tanpa scan kode QR. Cara ini cuma bisa buat koneksi dari satu perangkat aja.

📌 Nomor telepon gak boleh ada karakter kayak +, (), atau - Pake angka murni aja, dan pastiin udah ada kode negaranya 🌐

import makeWAconnet from 'zans-xbaileys'

const conn = makeWAconnet({
  // Setting tambahan bisa disesuaikan di sini
  printQRInTerminal: false // Harus diset false buat pairing
})

if (!conn.authState.creds.registered) {
  const number = '628XXXXXXXXX'
  const code = await conn.requestPairingCode(number)
  // atau pake pairing code custom:
  // const code = await conn.requestPairingCode(number, 'CODEZUMI')
  console.log(code)
}

🪄 Setelah pairing code berhasil dibikin, masukin kode itu lewat WhatsApp Web kayak biasa buat nyelesaiin proses autentikasi 🖥️🩵

🕓 Nerima Riwayat Pesan Lengkap

  1. Set opsi syncFullHistory jadi true
  2. WhatsApp bakal ngirim lebih banyak riwayat kalo lu niru koneksi desktop resmi (WhatsApp Web) dengan setting browser tertentu 👩‍💻
import makeWAconnet, { Browsers } from 'zans-xbaileys'

const conn = makeWAconnet({
  ...otherOpts,
  // Lu bisa pake Windows, Ubuntu, dll.
  browser: Browsers.ubuntu('Safari'),
  syncFullHistory: true
})

📝 Catatan: WhatsApp cuma ngirim riwayat pesan lengkap kalo koneksinya keliatan kayak WhatsApp Web Desktop. Setting browser ngaruh banget seberapa banyak pesan lama yang dikirim 📦

🧠 Catatan Penting Soal Konfigurasi connet

🗂️ Caching Metadata Grup (Disaranin Banget)

  • Kalo bot lu aktif di grup, disaranin banget aktifin cachedGroupMetadata
  • Ini ngehindarin spam permintaan metadata dan bikin bot lebih responsif 🌟

Contoh implementasi cache pake node-cache:

import makeWAconnet from 'zans-xbaileys'
import NodeCache from 'node-cache'

const groupCache = new NodeCache({ stdTTL: 5 * 60, useClones: false })

const conn = makeWAconnet({
  cachedGroupMetadata: async (jid) => groupCache.get(jid)
})

conn.ev.on('groups.update', async ([event]) => {
  const metadata = await conn.groupMetadata(event.id)
  groupCache.set(event.id, metadata)
})

conn.ev.on('group-participants.update', async (event) => {
  const metadata = await conn.groupMetadata(event.id)
  groupCache.set(event.id, metadata)
})

🪄 Dengan cache kayak gini, lu bisa ngurangin beban request dan ngebutin interaksi bot ke grup secara signifikan 🚀

💬 Tips Lanjut: Lu bisa ganti NodeCache pake Redis, SQLite, atau in-memory DB lain sesuai arsitektur bot lu 🧩

⚙️ Konfigurasi Lengkap connetConfig

Baileys bisa lu atur full lewat objek konfigurasi connetConfig. Ini daftar properti penting yang bisa lu set:

🔌 Koneksi & Timeout

  • waWebSocketUrl: URL WebSocket WhatsApp Web (wss://web.whatsapp.com/ws/chat)
  • connectTimeoutMs: Batas waktu koneksi (default: 20000)
  • defaultQueryTimeoutMs: Timeout default query (default: 60000)
  • keepAliveIntervalMs: Interval ping koneksi (default: 30000)
  • qrTimeout: Timeout QR sebelum kadaluarsa (opsional)

🖥️ Browser & Agent

  • browser: Tiruan browser, misal Browsers.ubuntu('Chrome')
  • version: Versi WhatsApp Web (fetchLatestBaileysVersion() buat versi terbaru)
  • printQRInTerminal: Tunjukin QR di terminal? (true/false)
  • agent: Proxy agent buat koneksi custom (opsional)
  • fetchAgent: Custom agent buat media fetch (opsional)

💬 Event & Logging

  • emitOwnEvents: Emit event dari aksi sendiri? (true/false)
  • logger: Logger kayak pino, bisa dikustom
  • fireInitQueries: Kirim query inisialisasi otomatis (true/false)
  • markOnlineOnConnect: Tunjukin status online setelah connect

💾 Media & Caching

  • mediaCache: Cache media upload (opsional)
  • customUploadHosts: Host alternatif upload media
  • linkPreviewImageThumbnailWidth: Ukuran thumbnail link preview
  • generateHighQualityLinkPreview: Upload thumbnail link preview kualitas tinggi

🔐 Autentikasi & History

  • auth: Objek autentikasi dan state sesi WhatsApp
  • shouldSyncHistoryMessage: Kontrol sinkronisasi riwayat pesan
  • syncFullHistory: Sinkron semua pesan dari awal
  • getMessage: Fungsi async buat ambil ulang pesan lokal
  • transactionOpts: Opsi transaksi key Signal
  • userDevicesCache: Cache perangkat pengguna

📦 Grup & Metadata

  • cachedGroupMetadata: Fungsi buat cache metadata grup
  • msgRetryCounterMap: Nyimpen jumlah retry kirim pesan

🌐 HTTP & Request

  • options: Opsi tambahan buat axios request
  • retryRequestDelayMs: Delay antar retry request (default: 250)

📝 Tips dari zansxart: Lu bisa cuma pake sebagian properti aja. Sisanya otomatis fallback ke default bawaan Baileys 😘

📡 Nanganin Event

Baileys pake EventEmitter buat dengerin semua interaksi WhatsApp secara real-time 🧠 Event-nya udah diketik sempurna (TypeScript friendly), jadi dukungan Intellisense-nya mantap banget kalo pake VS Code ✨

⚠️ Daftar lengkap event bisa dicek di sini

📥 Contoh: Nerima Pesan Masuk

import makeWAconnet from 'zans-xbaileys'

const conn = makeWAconnet()

conn.ev.on('messages.upsert', ({ messages }) => {
  console.log('Pesan masuk nih:', messages)
})
  • type bisa notify, append, replace, atau remove.
  • Lu biasanya cuma perlu proses type === 'notify' buat pesan baru yang masuk.

🌐 Contoh: Nanganin Update Koneksi 📶

conn.ev.on('connection.update', ({ connection, lastDisconnect }) => {
  if (connection === 'close') {
    console.log('❌ Koneksi putus.')
  } else if (connection === 'open') {
    console.log('✅ Nyambung ke WhatsApp!')
  }
})
  • ⚠️ Event ini penting banget buat mantau status koneksi connet.
  • 🔁 Kalo connection === 'close', lu bisa coba reconnect otomatis.

🎉 Contoh: Deteksi Peserta Masuk/Keluar Grup

conn.ev.on('group-participants.update', async ({ id, participants, action }) => {
  if (action === 'add') {
    console.log('👋 Ada 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: Update Metadata Grup

conn.ev.on('groups.update', async (updates) => {
  for (let group of updates) {
    console.log('📝 Grup diupdate:', group)
  }
})
  • 💡 Bisa dipake buat deteksi perubahan nama grup, gambar, deskripsi, dll.

🌈 Tips

  • 📩 Event messages.update dipake buat deteksi status pesan kayak dibaca, diterima, atau gagal.
  • 😊 Event messages.reaction dipake buat nangkap reaksi (emoji) di pesan lu.

💬 TIP Baileys gak nyimpen cache pesan secara default. Buat nanganin event dengan akurat (kayak retry atau polling), pake getMessage() bareng store.

🔍 Kalo lu butuh event tambahan kayak reaction, presence, atau call offer, tinggal tambahin listener-nya sesuai struktur BaileysEventMap.

💾 Nyimpen & Balikin Sesi

Pastinya lu gak mau terus-terusan scan QR code tiap kali mau nyambung.

Lu bisa nyimpen kredensial dan pake lagi pas login berikutnya:

import makeWAconnet, { useMultiFileAuthState } from 'zans-xbaileys'

const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')

// Bakal pake kredensial yang ada buat koneksi ulang
// Kalo kredensial valid ketemu, langsung login tanpa QR
const conn = makeWAconnet({ auth: state })

// Fungsi ini bakal dipanggil tiap kali kredensial diupdate
conn.ev.on('creds.update', saveCreds)

⚠️ PENTING useMultiFileAuthState itu fungsi utilitas buat nyimpen state autentikasi di satu folder. Fungsi ini juga bisa jadi dasar buat bikin sistem autentikasi dan penyimpanan kunci di database SQL atau NoSQL — disaranin banget buat sistem skala produksi.

📂 Apa Isi Folder auth_info_baileys?

Folder itu bakal berisi beberapa file .json kayak:

  • creds.json — info kredensial utama
  • keys/ — berisi subfile kunci Signal: pre-keys, session, senderKey, dll.

⚠️ Folder ini jangan pernah dimodifikasi atau dihapus manual. Anggap aja kayak file token yang sensitif banget.

❌ Apa yang Terjadi Kalo Folder Hilang?

Kalo folder auth_info_baileys dihapus:

  • 🔒 Lu gak bisa login ulang tanpa scan QR lagi
  • 🔃 Semua sesi yang aktif bakal invalid
  • 🔐 Signal bakal bikin ulang semua sesi enkripsi end-to-end

💡 Backup disaranin banget kalo lu ngelola sesi penting.

💡 Tips Backup & Restore

  • 🗂️ Salin seluruh folder auth_info_baileys secara utuh.
  • 🔁 Buat restore, tinggal salin folder balik ke path yang sama sebelum mulai bot.
  • 🛡️ Pake .gitignore biar folder ini gak ikut di-push ke GitHub:
auth_info_baileys/

👥 Nyimpen Berdasarkan ID Pengguna (Multi-Akun)

Kalo lu ngelola banyak sesi pengguna (multi-client), bikin direktori penyimpanan berdasarkan ID pengguna:

const { state, saveCreds } = await useMultiFileAuthState(`./sessions/${userId}`)

Dengan cara ini, lu bisa misahin sesi tiap user tanpa bentrok 🔄

🎯 Rekomendasi: gabungin sama database kayak MongoDB/Redis buat nyatet mapping antara userId dan path session-nya.

🚀 Contoh Buat Mulai

💡 CATATAN Contoh ini juga udah termasuk penyimpanan kredensial otomatis

import makeWAconnet, { DisconnectReason, useMultiFileAuthState } from 'zans-xbaileys'
import { Boom } from '@hapi/boom'

async function connectToWhatsApp () {
  const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys')

  const conn = makeWAconnet({
    auth: state,
    printQRInTerminal: true
  })

  conn.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 putus karena', lastDisconnect.error, ', coba sambung lagi:', shouldReconnect)

      if (shouldReconnect) {
        connectToWhatsApp()
      }
    } else if (connection === 'open') {
      console.log('✅ Koneksi berhasil dibuka')
    }
  })

  conn.ev.on('messages.upsert', async (event) => {
    for (const m of event.messages) {
      console.log(JSON.stringify(m, undefined, 2))

      console.log('📨 Balas ke', m.key.remoteJid)
      await conn.sendMessage(m.key.remoteJid!, { text: 'Halo Dunia 🌍' })
    }
  })

  // 💾 Nyimpen kredensial tiap kali diupdate
  conn.ev.on('creds.update', saveCreds)
}

connectToWhatsApp()

🔐 Contoh Pake useSingleFileAuthState dan useMongoFileAuthState

🗂️ Autentikasi pake file tunggal (Single File Auth)

import makeWAconnet, {
  useSingleFileAuthState
} from 'zans-xbaileys'

const { state, saveState } = await useSingleFileAuthState('./auth_info_baileys.json')

const conn = makeWAconnet({
  auth: state,
  printQRInTerminal: true
})

conn.ev.on('creds.update', saveState)

🍃 Autentikasi pake MongoDB

import makeWAconnet, {
  useMongoFileAuthState
} from 'zans-xbaileys'
import { MongoClient } from 'mongodb'

const connectAuth = async () => {
  const client = new MongoClient('mongodb://localhost:27017')
  await client.connect()

  console.log('✅ Berhasil nyambung ke MongoDB')

  const collection = client.db('zans-xbaileys').collection('sessions')
  const { state, saveCreds } = await useMongoFileAuthState(collection)

  const conn = makeWAconnet({
    auth: state,
    printQRInTerminal: true
  })

  conn.ev.on('creds.update', saveCreds)
}

connectAuth()

⚠️ PENTING Di event messages.upsert, disaranin banget pake perulangan for (const message of event.messages) buat nanganin semua pesan di array secara individual. Ini ngehindarin pesan kelewat dan gampangin logging/debugging.

💡 TIP Lu bisa gabungin cara nyimpen sesi (MultiFile, SingleFile, atau MongoDB) sama sistem login berbasis ID pengguna, jadi support banyak akun secara paralel ✨

🔊 Dekripsi Suara Polling

Secara default, suara polling di WhatsApp dienkripsi dan diproses lewat event messages.update.

import pino from 'pino'
import {
  makeInMemoryStore,
  getAggregateVotesInPollMessage
} from 'zans-xbaileys'

const logger = pino({ timestamp: () => `,"time":"${new Date().toJSON()}"` }).child({ class: 'zans-xbaileys' })
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 Gak Ketemu'
  }
}

conn.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)
        // ✨ Tambahin aksi lanjutan di sini
      }
    }
  }
})

📘 Penjelasan

  • 📩 store.loadMessage(jid, id) dipake buat ambil ulang isi pesan polling (karena hasil polling cuma berisi update, bukan isi awal).
  • 🧠 getAggregateVotesInPollMessage() ngegabungin seluruh pollUpdates dan ngasilin daftar suara lengkap.
  • 🧷 Penting banget pake getMessage() yang valid. Kalo lu gak nyimpen store, dekripsi suara gak bakal berhasil.

💡 TIP: Buat polling publik, lu gak perlu key khusus. Tapi buat polling private (atau kalo polling dari orang lain), pastiin lu nyimpen pesan awalnya pake store atau log pesan masuk.

✨ Ringkasan Event Pas Koneksi Pertama 🛜

  1. Pas connet pertama kali nyambung, event connection.update bakal dipicu. Biasanya status koneksi bakal jadi 'open' atau 'close'.
  2. Setelah itu, WhatsApp bakal ngirim riwayat pesan (history chat) lewat event: messaging-history.set 📬
  3. Riwayat itu berisi pesan-pesan dari sesi sebelumnya, termasuk polling yang belum kejawab 🗳️

[!IMPORTANT] 🧠 Buat nanganin polling, lu wajib atur getMessage() di konfigurasi makeWAconnet() yaa~ Ini mastiin Baileys bisa dekripsi hasil polling dengan bener 💌

const conn = makeWAconnet({
  auth: state,
  getMessage: async (key) => await getMessage(key)
})

🧸 Implementasi Data Store

Baileys gak nyediain sistem penyimpanan (storage) bawaan buat chat, kontak, atau pesan. Tapi, ada implementasi sederhana pake in-memory store 🌼 Store ini bakal mantau update chat, pesan baru, dan perubahan lainnya biar data lu tetep up-to-date 💬

[!IMPORTANT] 🌟 Disaranin banget buat bikin sistem penyimpanan sendiri. 💣 Nyimpen seluruh riwayat chat di RAM bakal makan memori gede dan gak efisien buat jangka panjang.

🧪 Contoh Pake Store

import makeWAconnet, { makeInMemoryStore } from 'zans-xbaileys'

// 🧠 Store bakal nyimpen data koneksi WhatsApp di memori
const store = makeInMemoryStore({})

// 📖 Baca data dari file (kalo ada)
store.readFromFile('./baileys_store.json')

// 💾 Nyimpen state ke file tiap 10 detik
setInterval(() => {
  store.writeToFile('./baileys_store.json')
}, 10_000)

const conn = makeWAconnet({})

// 🔌 Store bakal mulai dengerin event dari connet ini
// ♻️ Kalo connet diganti, store masih bisa dipake ulang
store.bind(conn.ev)

conn.ev.on('chats.upsert', () => {
  // 📥 Akses semua chat yang kesimpen
  console.log('Data chat masuk:', store.chats.all())
})

conn.ev.on('contacts.upsert', () => {
  // 📇 Akses semua kontak yang keupdate
  console.log('Kontak diupdate:', Object.values(store.contacts))
})

🎀 Fitur Store

  • 🧠 Nyimpen chat, pesan, dan kontak sementara di memori.
  • 📁 Support baca dan tulis dari/ke file JSON.
  • 🔁 Bisa dipake bareng beberapa koneksi (connet) sekaligus.
  • 💌 Ada fungsi loadMessages, loadMessage, dan loadMessageFromContent.

✨ Kelebihan

  • ⚡ Cepet dan ringan buat penggunaan kecil-menengah.
  • 👩‍💻 Cocok buat penggunaan lokal, testing, atau bot personal.

⚠️ Kekurangan

  • ❌ Data ilang pas proses berhenti kalo gak ditulis ke file.
  • 🚫 Gak cocok buat data skala gede (ribuan pesan atau kontak).
  • 🔍 Gak support query kompleks (karena berbasis object literal di RAM).

💡 Rekomendasi Produksi

Buat sistem gede atau multi-user:

  • 🗃️ Pake database kayak:
    • 🧬 MongoDB (buat struktur fleksibel dan load gede)
    • 🔥 Redis (buat cache cepet)
    • 🧱 PostgreSQL (buat struktur relasional)
  • 🔄 Sinkronin event kayak messages.upsert, chats.upsert, dan contacts.upsert ke penyimpanan permanen.
  • 🧩 Pake store cuma sebagai cache atau layer middleware sementara.

[!TIP] Store ini berguna banget buat keperluan kayak:

  • ✅ Nyimpen polling
  • 🔁 Retry pesan
  • 👥 Ngelacak status kontak dan grup
  • 🧾 Nyediain command .listchat, .listgroup, dll. dengan data real-time

Kalo lu pake custom getMessage(), store ini juga bisa jadi referensi lokal buat dekripsi polling dan kirim ulang pesan 💕

🪪 Penjelasan Soal WhatsApp ID

  • id atau biasa disebut jid itu identitas WhatsApp dari seseorang atau grup yang jadi tujuan kirim pesan.
  • Format ID harus sesuai sama jenis akun tujuan 🌐

🌟 Jenis Format ID WhatsApp

1. 🧍‍♀️ Pengguna Pribadi (User)

Format:

[kode negara][nomor telepon]@s.whatsapp.net

Contoh:

[email protected]

2. 👥 Grup WhatsApp

Format:

[timestamp grup dibuat]-[random id]@g.us

Contoh:

[email protected]

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: Lu bisa dapet jid dari:

  • m.key.remoteJid
  • groupParticipantsUpdate
  • messages.upsert, dll

⚠️ PERHATIAN: Jangan pernah ngubah format jid manual tanpa validasi ya~ Salah format bisa bikin error bad jid atau pesan gak kekirim 😵‍💫

Fungsi Utilitas (Utility Functions) 🛠️✨

Baileys nyediain beberapa fungsi utilitas penting yang ngebantu banget pas ngembangin bot:

  • getContentType(message) 🎯 Ngembaliin jenis konten dari pesan (misalnya: imageMessage, conversation, buttonsMessage, dll).

  • getDevice(jid) 📱 Ngembaliin jenis perangkat yang dipake pengirim (kalo ada), contoh: Android, iPhone, Web.

  • makeCacheableSignalKeyStore(authState) ⚡ Ngebungkus SignalKeyStore jadi versi yang lebih efisien dan bisa di-cache, buat performa autentikasi yang lebih cepet.

  • downloadContentFromMessage(message, type) 📥 Ngunduh media dari pesan (kayak gambar, video, dokumen). type bisa 'image', 'video', 'audio', 'document', dll.

    Contoh penggunaan:

    const stream = await downloadContentFromMessage(msg.imageMessage, 'image')
    const buffer = []
    for await (const chunk of stream) buffer.push(chunk)
    const hasil = Buffer.concat(buffer)

> [💡 CATATAN!]
Sebagian besar fungsi utilitas gak dipanggil otomatis — Lu harus pake sesuai kebutuhan, terutama pas nanganin pesan media, format jid, atau decrypt konten.

## Kirim Pesan 💬📤
- Semua jenis pesan bisa dikirim pake **satu fungsi aja**, yaitu `sendMessage()` 🍓
- Cek daftar jenis pesan yang disupport [di sini](https://baileys.whiskeyconnets.io/types/AnyMessageContent.html) 🌐
- Dan semua opsi kirim pesan [di sini](https://baileys.whiskeyconnets.io/types/MiscMessageGenerationOptions.html) 🧩
Contoh:
```javascript
const jid = '[email protected]' // 🎯 tujuan
const content = { text: 'Halo, ini pesan dari bot!' } // 💌 isi pesan
const options = { quoted: null } // ⚙️ opsi tambahan (misalnya: balasan)
await conn.sendMessage(jid, content, options)

✉️ Pesan Non-Media

📝 Pesan Teks

await conn.sendMessage(jid, { text: 'Halo dunia' })

🔁 Pesan Balasan (Quote)

await conn.sendMessage(jid, { text: 'Ini balasan pesan kamu' }, { quoted: m })

🏷️ Mention Pengguna (Tag)

Pake @nomor di teks dan sertakan mentions di payload.

await conn.sendMessage(
  jid,
  {
    text: '@628XXXXXXXXX Hai zansxart!',
    mentions: ['[email protected]']
  }
)

📤 Nerusin Pesan (Forward)

Butuh objek pesan (WAMessage). Bisa didapet dari store atau pesan sebelumnya.

const msg = getMessageFromStore() // Lu bikin sendiri sesuai struktur
await conn.sendMessage(jid, { forward: msg, force: true })

📍 Lokasi Biasa

await conn.sendMessage(
  jid,
  {
    location: {
      degreesLatitude: -6.200000,
      degreesLongitude: 106.816666
    }
  }
)

📡 Lokasi Langsung (Live Location)

await conn.sendMessage(
  jid,
  {
    location: {
      degreesLatitude: -6.200000,
      degreesLongitude: 106.816666
    },
    live: true
  }
)

👤 Kirim Kontak (vCard)

const vcard =
  'BEGIN:VCARD\n' +
  'VERSION:3.0\n' +
  'FN:zansxart\n' +
  'ORG:zans-xbaileys;\n' +
  'TEL;type=CELL;type=VOICE;waid=628XXXXXXXXX:+62 831-4366-3697\n' +
  'END:VCARD'

await conn.sendMessage(
  jid,
  {
    contacts: {
      displayName: 'zansxart',
      contacts: [{ vcard }]
    }
  }
)

❤️‍🔥 Pesan Reaksi (Reaction Message)

  • Lu perlu ngirim key dari pesan yang mau dikasih reaksi. key bisa diambil dari store atau pake WAMessageKey.
await conn.sendMessage(
  jid,
  {
    react: {
      text: '🔥', // pake string kosong '' buat ngehapus reaksi
      key: message.key
    }
  }
)

📌 Pin Pesan (Pin Message)

  • Lu juga perlu ngasih key dari pesan yang mau di-pin. Lu bisa atur durasi pin berdasarkan waktu dalam detik.

| Durasi | Detik | |--------|--------------| | 24 jam | 86.400 | | 7 hari | 604.800 | | 30 hari| 2.592.000 |

await conn.sendMessage(
  jid,
  {
    pin: {
      type: 1, // 1 buat pin, 2 buat unpin
      time: 86400,
      key: message.key
    }
  }
)

💾 Nandain Pesan (Keep Message)

  • Buat nyimpen pesan tertentu biar gak kehapus otomatis.
await conn.sendMessage(
  jid,
  {
    keep: {
      key: message.key,
      type: 1 // 1 = simpan, 2 = batal simpan
    }
  }
)

🗳️ Pesan Polling (Poll Message)

  • Kirim polling ke grup atau kontak pribadi. Bisa nentuin apakah polling bersifat publik (announcement group).
await conn.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 manual kalo dibutuhin. Cocok buat sistem polling terintegrasi.
await conn.sendMessage(
  jid,
  {
    pollResult: {
      name: 'Hasil Polling',
      values: [
        ['Opsi A', 120],
        ['Opsi B', 350],
        ['Opsi C', 75]
      ]
    }
  }
)

📞 Pesan Panggilan (Call Message)

  • Dipake buat ngirim notifikasi panggilan, bisa suara atau video.
await conn.sendMessage(
  jid,
  {
    call: {
      name: 'Hay',
      type: 1 // 1 = suara, 2 = video
    }
  }
)

🎉 Pesan Event (Event Message)

  • Cocok buat ngumumin acara atau undangan dengan detail lokasi dan waktu.
await conn.sendMessage(
  jid,
  {
    event: {
      isCanceled: false, // true kalo dibatalin
      name: 'Liburan Bareng!',
      description: 'Siapa yang mau ikut?',
      location: {
        degreesLatitude: 24.121231,
        degreesLongitude: 55.1121221,
        name: 'Pantai Selatan'
      },
      startTime: 1715000000,
      endTime: 1715086400,
      extraGuestsAllowed: true // boleh bawa tamu gak
    }
  }
)

📦 Pesan Pemesanan (Order Message)

  • Dipake buat nampilin detail pemesanan dari katalog bisnis WhatsApp.
await conn.sendMessage(
  jid,
  {
    order: {
      orderId: '574XXX',
      thumbnail: 'your_thumbnail',
      itemCount: 3,
      status: 'INQUIRY', // atau ACCEPTED / DECLINED
      surface: 'CATALOG',
      message: 'Deskripsi pesanan',
      orderTitle: 'Judul Pesanan',
      sellerJid: '[email protected]',
      token: 'your_token',
      totalAmount1000: '150000',
      totalCurrencyCode: 'IDR'
    }
  }
)

🛒 Pesan Produk (Product Message)

  • Nampilin detail produk dari katalog bisnis.
await conn.sendMessage(
  jid,
  {
    product: {
      productImage: {
        url: 'https://your-image.url/image.jpg'
      },
      productId: 'PRD-001',
      title: 'Produk',
      description: 'Deskripsi',
      currencyCode: 'IDR',
      priceAmount1000: '50000',
      retailerId: 'store-zansxart', // opsional
      url: 'https://linkproduk.com', // opsional
      productImageCount: 1,
      firstImageId: 'img-001', // opsional
      salePriceAmount1000: '45000',
      signedUrl: 'https://your.signed.url' // opsional
    },
    businessOwnerJid: '[email protected]'
  }
)

🧾 Pesan Pembayaran (Payment Message)

  • Dipake buat ngirim info pembayaran, cocok buat chatbot belanja.
await conn.sendMessage(
  jid,
  {
    payment: {
      note: 'Hi!',
      currency: 'IDR',
      offset: 0,
      amount: '10000',
      expiry: 0,
      from: '[email protected]',
      image: {
        placeholderArgb: '#222222',
        textArgb: '#FFFFFF',
        subtextArgb: '#AAAAAA'
      }
    }
  }
)

💰 Pesan Undangan Pembayaran (Payment Invite Message)

  • Dipake buat ngundang pengguna lain ngelakuin pembayaran.
await conn.sendMessage(
  jid,
  {
    paymentInvite: {
      type: 1, // 1 = request, 2 = accept, 3 = decline (sesuaiin konteks)
      expiry: 0
    }
  }
)

🧑‍💼 Pesan Undangan Admin Channel (Admin Invite Message)

  • Minta pengguna buat jadi admin di saluran (newsletter) lu.
await conn.sendMessage(
  jid,
  {
    adminInvite: {
      jid: '123xxx@newsletter',
      name: 'Channel zansxart',
      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)

  • Ngirim undangan ke grup tertentu pake kode undangan.
await conn.sendMessage(
  jid,
  {
    groupInvite: {
      jid: '[email protected]',
      name: 'Grup Dev zans-xbaileys',
      caption: 'Ayo gabung ke grup WhatsApp kami!',
      code: 'ABCD1234', // kode undangan grup
      expiration: 86400,
      jpegThumbnail: Buffer // opsional
    }
  }
)

📲 Pesan Bagikan Nomor Telepon (Share Phone Number)

  • Ngirim permintaan eksplisit buat ngebagiin nomor telepon pengguna.
await conn.sendMessage(
  jid,
  {
    sharePhoneNumber: {}
  }
)

☎️ Pesan Permintaan Nomor Telepon (Request Phone Number)

  • Minta pengguna buat ngebagiin nomor telepon mereka secara langsung.
await conn.sendMessage(
  jid,
  {
    requestPhoneNumber: {}
  }
)

💬 Pesan Balasan Tombol

Fitur ini dipake buat ngerespons interaksi dari tombol yang ditekan pengguna. Tipe pesan ditentuin berdasarkan jenis tombol yang dipake — baik tombol klasik (buttons) maupun tombol native WhatsApp (interactive).

🔘 Tombol Teks (Buttons)

await conn.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'
})

🌐 Tombol Tipe Interactive (Native Flow)

await conn.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, tergantung skema flow
      }
    },
    type: 'interactive'
  }
)

🔘 Pesan dengan Tombol (Buttons Message)

Fitur ini ngizinin kirim pesan teks (atau media) dengan hingga 3 tombol balasan cepet. Cocok banget buat perintah menu, navigasi bot, atau respons otomatis dari pengguna.

Ini contoh implementasinya:

await conn.sendMessage(
  jid,
  {
    text: '📨 Ini pesan tombol!',
    caption: '🖼️ Pake kalo ada gambar/video',
    footer: '📩 Salam dari zansxart!',
    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)

Fitur ini ngizinin kirim pesan daftar (list) dengan beberapa bagian dan opsi di dalamnya. Ideal buat nampilin menu, layanan, atau kategori dalam format elegan.

⚠️ Cuma bisa dipake di chat pribadi, gak bakal jalan di grup WhatsApp.

Ini contoh implementasinya:

await conn.sendMessage(
  jid,
  {
    text: '📑 Ini daftar pilihan!',
    footer: '📩 Dipersembahkan oleh zansxart',
    title: '📌 Judul Daftar Pilihan',
    buttonText: '🔽 Klik buat liat 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)

Fitur ini dipake buat nampilin daftar produk dari katalog WhatsApp Business dalam bentuk tombol interaktif. Cuma bisa dipake di chat pribadi, bukan di grup.

Contoh implementasinya:

await conn.sendMessage(
  jid,
  {
    text: '🛒 Ini daftar produk!',
    footer: '📩 Dikirim oleh zansxart',
    title: '🌟 Pilih Produk Unggulan',
    buttonText: '📦 Liat Daftar Produk',
    productList: [
      {
        title: '🧁 Kategori Produk Utama',
        products: [
          { productId: '1234' },
          { productId: '5678' }
        ]
      }
    ],
    businessOwnerJid: '[email protected]',
    thumbnail: 'https://example.jpg' // bisa juga Buffer gambar
  }
)

🃏 Pesan Kartu dengan Tombol (Buttons Cards Message)

Fitur ini ngizinin kirim beberapa kartu (cards) interaktif dalam satu pesan. Tiap kartu bisa berisi gambar atau video, disertai judul, deskripsi, dan tombol-tombol aksi kayak balasan cepet atau tautan.

Contoh implementasi lengkap:

await conn.sendMessage(
  jid,
  {
    text: '📢 Isi Utama Pesan',
    title: '🗂️ Judul Utama',
    subtile: '📌 Subjudul Opsional',
    footer: '📩 Footer Pesan',

    cards: [
      {
        image: { url: 'https://example.jpg' }, // Bisa juga Buffer gambar
        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: '🔎 Liat Selengkapnya',
              url: 'https://www.example.com'
            })
          }
        ]
      }
    ]
  }
)

🔘 Pesan Tombol Template (Buttons Template Message)

Fitur ini ngizinin lu kirim pesan dengan tombol-tombol cepet kayak URL, panggilan, dan balasan cepet (quick reply). Cocok banget buat navigasi channel, kontak admin, atau aksi otomatis.

Ini contoh implementasinya:

await conn.sendMessage(
  jid,
  {
    text: '✨ Ini pesan template tombol!',
    footer: '📩 Dikirim oleh zansxart',
    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)

  • Support berbagai jenis tombol dan bisa dipake bareng media kayak teks, gambar, dan lainnya.
await conn.sendMessage(
  jid,
  {
    text: '✨ Ini pesan interaktif!',
    title: '👋 Hai!',
    subtitle: '🌼 Subjudul di sini',
    footer: '📩 Dikirim oleh zansxart',
    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

Kirim pesan interaktif juga bisa digabungin sama media kayak teks, gambar, dokumen, lokasi, dan produk katalog. Ini contoh lengkap penggunaannya dalam satu format:

#### 📸 Gambar
await conn.sendMessage(
  jid,
  {
    image: { url: 'https://example.jpg' },
    caption: '✨ Isi Pesan',
    title: '🖼️ Judul',
    subtitle: '📌 Subjudul',
    footer: '📩 Footer',
    interactiveButtons: [ /* tombol kayak di atas */ ],
    hasMediaAttachment: false
  }
)

🎥 Video

await conn.sendMessage(
  jid,
  {
    video: { url: 'https://example.mp4' },
    caption: '🎬 Isi Video',
    title: '📺 Judul',
    subtitle: '📌 Subjudul',
    footer: '📩 Footer',
    interactiveButtons: [ /* tombol kayak di atas */ ],
    hasMediaAttachment: false
  }
)

📄 Dokumen

await conn.sendMessage(
  jid,
  {
    document: { url: 'https://example.jpg' },
    mimetype: 'image/jpeg',
    jpegThumbnail: await conn.resize('https://example.jpg', 320, 320),
    caption: '📝 Isi Dokumen',
    title: '📄 Judul',
    subtitle: '📌 Subjudul',
    footer: '📩 Footer',
    interactiveButtons: [ /* tombol kayak di atas */ ],
    hasMediaAttachment: false
  }
)

📍 Lokasi

await conn.sendMessage(
  jid,
  {
    location: {
      degreesLatitude: -6.2,
      degreesLongitude: 106.8,
      name: 'zans-xbaileys HQ'
    },
    caption: '📍 Ayo ke sini!',
    title: '🗺️ Lokasi Tujuan',
    subtitle: '📌 Subjudul Lokasi',
    footer: '🧭 Peta lokasi',
    interactiveButtons: [ /* tombol kayak di atas */ ],
    hasMediaAttachment: false
  }
)

🛍️ Produk (Katalog WhatsApp)

await conn.sendMessage(
  jid,
  {
    product: {
      productImage: { url: 'https://example.jpg' },
      productId: '836xxx',
      title: '🎁 Produk Pilihan',
      description: '🛒 Deskripsi produk terbaik',
      currencyCode: 'IDR',
      priceAmount1000: '283000',
      retailerId: 'zansxartStore',
      url: 'https://example.com',
      productImageCount: 1
    },
    businessOwnerJid: '[email protected]',
    caption: '🛍️ Produk baru tersedia!',
    title: '📦 Nama Produk',
    subtitle: '📌 Subjudul Produk',
    footer: '📋 Info Produk',
    interactiveButtons: [ /* tombol kayak di atas */ ],
    hasMediaAttachment: false
  }
)

💳 Kirim Tombol "Salin Kunci Pix"

Fitur ini ngizinin bot buat ngirim tombol interaktif ke pengguna WhatsApp berupa info pembayaran pake metode Pix Static Code. Cocok dipake buat transaksi cepet, donasi, atau beli produk digital.

📌 Contoh Penggunaan:

await conn.sendMessage(
  jid,
  {
    text: '', // Ini wajib diisi, meskipun kosong
    interactiveButtons: [
      {
        name: 'payment_info',
        buttonParamsJson: JSON.stringify({
          payment_settings: [{
            type: "pix_static_code",
            pix_static_code: {
              merchant_name: 'zans-xbaileys',
              key: '[email protected]',
              key_type: 'EMAIL' // Bisa juga: PHONE, EMAIL, CPF, atau EVP
            }
          }]
        })
      }
    ],
  }
)

🏷️ Mention Status (Status Mentions Message)

Fitur ini dipake buat bikin status WhatsApp yang nyebut seseorang secara langsung pake format status dengan media atau caption.

Ini contoh implementasinya:

await conn.sendStatusMentions(
  jid,
  {
    image: {
      url: 'https://example.com.jpg'
    },
    caption: '✨ Halo dari zansxart!'
  }
)

📚 Pesan Album (Send Album Message)

  • Kirim beberapa gambar atau video sebagai album (sekuens media). Bisa pake Buffer atau URL.
await conn.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, buat balas pesan
    delay: 2000 // jeda antar media (ms)
  }
)

🛍️ Pesan Toko (Shop Message)

  • Dipake buat ngarahin pengguna ke katalog atau produk di fitur bisnis WhatsApp.

📝 Teks Aja

await conn.sendMessage(
  jid,
  {
    text: 'Body pesan',
    title: 'Judul Toko',
    subtitle: 'Subjudul',
    footer: 'Powered by zans-xbaileys',
    shop: {
      surface: 1,
      id: 'https://example.com'
    },
    viewOnce: true
  }
)

🖼️ Gambar

await conn.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

await conn.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

await conn.sendMessage(
  jid,
  {
    document: { url: 'https://example.jpg' },
    mimetype: 'image/jpeg',
    jpegThumbnail: await conn.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

await conn.sendMessage(
  jid,
  {
    location: {
      degreesLatitude: -6.2000,
      degreesLongitude: 106.8166,
      name: 'Lokasi Toko'
    },
    caption: 'Liat lokasi kami!',
    title: 'Judul Lokasi',
    subtitle: 'Subjudul',
    footer: 'Peta lokasi',
    shop: {
      surface: 1,
      id: 'https://example.com'
    },
    hasMediaAttachment: false,
    viewOnce: true
  }
)

🛒 Produk

await conn.sendMessage(
  jid,
  {
    product: {
      productImage: { url: 'https://example.jpg' },
      productId: '836xxx',
      title: 'Nama Produk',
      description: 'Deskripsi produk menarik',
      currencyCode: 'IDR',
      priceAmount1000: '283000',
      retailerId: 'zansxartStore',
      url: 'https://example.com',
      productImageCount: 1
    },
    businessOwnerJid: '[email protected]',
    caption: 'Liat 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 dipake buat nampilin koleksi katalog dari bisnis tertentu di WhatsApp.

📝 Teks Aja

await conn.sendMessage(
  jid,
  {
    text: 'Isi pesan',
    title: 'Judul Koleksi',
    subtitle: 'Subjudul',
    footer: 'Dari zansxart',
    collection: {
      bizJid: '[email protected]',
      id: 'https://example.com',
      version: 1
    },
    viewOnce: true
  }
)

🖼️ Gambar

await conn.sendMessage(
  jid,
  {
    image: { url: 'https://example.jpg' },
    caption: 'Koleksi Gambar',
    title: 'Judul Koleksi',
    subtitle: 'Subjudul',
    footer: 'Katalog zansxart',
    collection: {
      bizJid: '[email protected]',
      id: 'https://example.com',
      version: 1
    },
    hasMediaAttachment: false,
    viewOnce: true
  }
)

🎥 Video

await conn.sendMessage(
  jid,
  {
    video: { url: 'https://example.mp4' },
    caption: 'Koleksi Video',
    title: 'Judul Video',
    subtitle: 'Subjudul',
    footer: 'Video Katalog',
    collection: {
      bizJid: '[email protected]',
      id: 'https://example.com',
      version: 1
    },
    hasMediaAttachment: false,
    viewOnce: true
  }
)

📎 Dokumen

await conn.sendMessage(
  jid,
  {
    document: { url: 'https://example.jpg' },
    mimetype: 'image/jpeg',
    jpegThumbnail: await conn.resize('https://example.jpg', 320, 320),
    caption: 'Dokumen Katalog',
    title: 'Judul Dokumen',
    subtitle: 'Subjudul',
    footer: 'Lampiran Koleksi',
    collection: {
      bizJid: '[email protected]',
      id: 'https://example.com',
      version: 1
    },
    hasMediaAttachment: false,
    viewOnce: true
  }
)

📍 Lokasi

await conn.sendMessage(
  jid,
  {
    location: {
      degreesLatitude: -6.2,
      degreesLongitude: 106.8,
      name: 'Lokasi Bisnis'
    },
    caption: 'Liat lokasi koleksi',
    title: 'Judul Lokasi',
    subtitle: 'Subjudul',
    footer: 'Lokasi Katalog',
    collection: {
      bizJid: '[email protected]',
      id: 'https://example.com',
      version: 1
    },
    hasMediaAttachment: false,
    viewOnce: true
  }
)

🛍️ Produk

await conn.sendMessage(
  jid,
  {
    product: {
      productImage: { url: 'https://example.jpg' },
      productId: '836xxx',
      title: 'Nama Produk',
      description: 'Deskripsi produk',
      currencyCode: 'IDR',
      priceAmount1000: '283000',
      retailerId: 'zansxartStore',
      url: 'https://example.com',
      productImageCount: 1
    },
    businessOwnerJid: '[email protected]',
    caption: 'Koleksi Produk',
    title: 'Judul',
    subtitle: 'Subjudul',
    footer: 'Produk Katalog',
    collection: {
      bizJid: '[email protected]',
      id: 'https://example.com',
      version: 1
    },
    hasMediaAttachment: false,
    viewOnce: true
  }
)

🌐 Kirim Pesan dengan Pratinjau Link (Link Preview)

  1. Secara default, WhatsApp Web gak nampilin pratinjau link.
  2. Tapi, Baileys nyediain fungsi pembangkit preview link otomatis.
  3. Buat ngaktifinnya, install dulu dependensinya dengan:
    npm install link-preview-js
  4. Contoh kirim pesan dengan pratinjau link:
await conn.sendMessage(
  jid,
  {
    text: 'Hai! Ini dikirim dari https://github.com/whiskeyconnets/baileys'
  }
)

🎞️ Pesan Media (Media Messages)

Kirim media (gambar, video, audio, stiker) jauh lebih efisien pake Baileys.

[!CATATAN] Lu bisa pake Buffer, { stream }, atau { url }. Liat lebih lengkap di dokumentasi media

[!TIP] Pake stream atau url langsung biar lebih hemat memori.

🌀 Pesan GIF (video pendek)

WhatsApp gak support file .gif, jadi harus dikirim dalam bentuk .mp4 dengan flag gifPlayback: true

await conn.sendMessage(
  jid,
  {
    video: fs.readFileSync('Media/ma_gif.mp4'),
    caption: 'Halo dari GIF!',
    gifPlayback: true
  }
)

🎥 Pesan Video

await conn.sendMessage(
  jid,
  {
    video: { url: './Media/ma_video.mp4' },
    caption: 'Ini videonya'
  }
)

🔵 Pesan Video PTV (Picture to Video / video bulat WA)

await conn.sendMessage(
  jid,
  {
    video: { url: './Media/ma_video.mp4' },
    ptv: true
  }
)

🔊 Pesan Audio

Biar audio kompatibel di semua perangkat, sebaiknya pake ffmpeg dengan setting berikut:

ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
await conn.sendMessage(
  jid,
  {
    audio: { url: './Media/audio.ogg' },
    mimetype: 'audio/ogg; codecs=opus'
  }
)

🖼️ Pesan Gambar

await conn.sendMessage(
  jid,
  {
    image: { url: './Media/ma_img.png' },
    caption: 'Halo dari gambar!'
  }
)

👁️ Pesan View Once

Fitur View Once ngizinin media cuma bisa diliat satu kali.

await conn.sendMessage(
  jid,
  {
    image: { url: './Media/ma_img.png' },
    viewOnce: true,
    caption: 'Media cuma bisa diliat sekali'
  }
)

✏️ Modifikasi Pesan

🗑️ Hapus Pesan (Buat Semua Orang)

  • Dipake buat narik pesan yang udah dikirim (delete for everyone).
const msg = await conn.sendMessage(jid, { text: 'Halo dunia' })
await conn.sendMessage(jid, { delete: msg.key })

📝 Catatan: Buat ngehapus pesan cuma buat diri sendiri, pake chatModify (cek bagian Modifikasi Chat).

📝 Edit Pesan

  • Lu bisa ngedit isi pesan yang udah dikirim sebelumnya, selama masih dalam konteks yang diizinin sama WhatsApp.
await conn.sendMessage(jid, {
  text: 'Teks yang udah diupdate di sini',
  edit: response.key
})

🎨 Manipulasi Pesan Media

🖼️ Tambah Thumbnail di Media

  • Thumbnail (gambar pratinjau) buat gambar dan stiker bisa diasilin otomatis kalo lu nambahin salah satu dari dependency berikut:
npm install jimp
# atau
npm install sharp
  • Buat video, lu juga bisa ngasilin thumbnail otomatis, tapi pastiin lu udah install ffmpeg di sistem lu.

✅ Contoh penggunaan otomatis biasanya gak perlu lu atur manual — Baileys bakal nge-generate thumbnail kalo dependensi udah ada.

💾 Ngunduh Media dari Pesan (Downloading Media Messages)

Kalo lu mau nyimpen media yang diterima dari pengguna:

import { createWriteStream } from 'fs'
import { downloadMediaMessage, getContentType } from 'zans-xbaileys'

conn.ev.on('messages.upsert', async ({ messages }) => {
let m = messages[0]
if (!m.message) return // kalo gak ada media atau isi pesan

let messageType = getContentType(m.message) // deteksi tipe pesan (image, video, audio, dll)

if (messageType === 'imageMessage') {
let stream = await downloadMediaMessage(
m,
'stream', // bisa juga 'buffer' kalo mau langsung di-handle tanpa file
{},
{
logger,
reuploadRequest: conn.updateMediaMessage // biar bisa reupload kalo file udah gak ada
}
)

let file = createWriteStream('./downloaded-image.jpeg')
stream.pipe(file)
}
})

🔄 Re-upload Media ke WhatsApp

Kalo media udah dihapus dari server WhatsApp, lu bisa minta perangkat pengirim buat ngelakuin reupload:

await conn.updateMediaMessage(msg)

⚠️ Fitur ini penting pas media gagal diunduh karena udah gak tersedia di server WhatsApp.

🚫 Nolak Panggilan (Reject Call)

  • Lu bisa dapet callId dan callFrom dari event call.
await conn.rejectCall(callId, callFrom)

📨 Kirim Status ke Chat (Send States in Chat)

✅ Nandain Pesan Dibaca (Reading Messages)

  • Lu harus nandain pesan satu per satu pake key dari WAMessage.
  • Gak bisa nandain seluruh chat sebagai terbaca secara langsung kayak di WhatsApp Web.
const key = {
  remoteJid: '[email protected]',
  fromMe: false,
  id: 'ABCDEF123456'
}

// bisa juga array buat banyak pesan sekaligus
await conn.readMessages([key])

🍓 Lu bisa dapet messageID dari:

let messageID = message.key.id

✨ Update Status Kehadiran (Update Presence)

await conn.sendPresenceUpdate('available', jid) // online
await conn.sendPresenceUpdate('composing', jid) // ngetik
await conn.sendPresenceUpdate('unavailable', jid) // offline

💡 Catatan: Kalo lu pake WhatsApp Desktop barengan, WA gak bakal ngirim notifikasi ke perangkat lain. Kalo lu mau tetep terima notifikasi di HP, lu bisa set status bot jadi offline:

await conn.sendPresenceUpdate('unavailable')

🛠️ Modifikasi Chat (Modifying Chats)

WhatsApp pake komunikasi terenkripsi buat ngupdate status chat atau aplikasi. Beberapa fitur modifikasi udah disupport sama Baileys, dan bisa lu kirim kayak di bawah ini.

⚠️ PERINGATAN: Kalo lu salah pake modifikasi ini (misal kirim data invalid), WhatsApp bisa logout semua perangkat dan lu harus scan ulang QR.

📥 Ngarsipin Chat (Archive)

let lastMsgInChat = await getLastMessageInChat(jid) // lu bikin fungsi ini sendiri
await conn.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, jid)

🔕 Bisukan / Aktifin Notifikasi (Mute / Unmute)

| Durasi | Milidetik | |-----------|------------------| | Hapus | null | | 8 Jam | 86400000 | | 7 Hari | 604800000 |

await conn.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid) // bisukan 8 jam
await conn.chatModify({ mute: null }, jid) // aktifin lagi notifikasi

📩 Tandain Sebagai Terbaca / Belum Dibaca

let lastMsgInChat = await getLastMessageInChat(jid)
await conn.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, jid)

🧹 Hapus Pesan Cuma Buat Saya

await conn.chatModify(
  {
    clear: {
      messages: [
        {
          id: 'ATWYHDNNWU81732J',
          fromMe: true,
          timestamp: '1654823909'
        }
      ]
    }
  },
  jid
)

🗑️ Hapus Chat Secara Keseluruhan

let lastMsgInChat = await getLastMessageInChat(jid)
await conn.chatModify({
  delete: true,
  lastMessages: [
    {
      key: lastMsgInChat.key,
      messageTimestamp: lastMsgInChat.messageTimestamp
    }
  ]
}, jid)

📌 Pin / Unpin Chat

await conn.chatModify({
  pin: true // false buat unpin
}, jid)

⭐ Tandain / Hapus Bintang dari Pesan

await conn.chatModify({
  star: {
    messages: [
      {
        id: 'messageID',
        fromMe: true
      }
    ],
    star: true // true: kasih bintang, false: hapus bintang
  }
}, jid)

🕒 Pesan Menghilang Otomatis (Disappearing Messages)

| Durasi | Detik (Seconds) | |-----------|------------------| | Nonaktif | 0 | | 24 Jam | 86400 | | 7 Hari | 604800 | | 90 Hari | 7776000 |

✅ Aktifin

await conn.sendMessage(jid, {
  disappearingMessagesInChat: 604800 // 7 hari
})

✉️ Kirim Pesan dengan Mode Menghilang

await conn.sendMessage(
  jid,
  { text: 'halo' },
  { ephemeralExpiration: 604800 }
)

❌ Nonaktifin

await conn.sendMessage(jid, {
  disappearingMessagesInChat: false
})

🧽 Hapus Pesan Tertentu (Clear Messages)

await conn.clearMessage(jid, key, timestamps)

🔍 Query Pengguna (User Queries)

📞 Cek Apakah Nomor Terdaftar di WhatsApp

let [result] = await conn.onWhatsApp(jid)
if (result.exists) console.log(`${jid} terdaftar di WhatsApp sebagai ${result.jid}`)

📜 Ambil Riwayat Chat (termasuk grup)

Lu perlu ambil pesan paling lama dari chat itu

let msg = await getOldestMessageInChat(jid)
await conn.fetchMessageHistory(
  50, // maksimal 50 per query
  msg.key,
  msg.messageTimestamp
)

📥 Hasilnya bakal dikirim lewat event messaging.history-set

📝 Ambil Status WhatsApp (Bio)

let status = await conn.fetchStatus(jid)
console.log('Status: ' + status)

🖼️ Ambil Foto Profil (Profil, Grup, Channel)

let ppUrl = await conn.profilePictureUrl(jid)
console.log('Foto profil: ' + ppUrl)

🧾 Ambil Profil Bisnis (Business Profile)

Cocok buat akun bisnis WhatsApp, kayak deskripsi & kategori bisnis

let profile = await conn.getBusinessProfile(jid)
console.log('Deskripsi bisnis: ' + profile.description + ', Kategori: ' + profile.category)

🟢 Cek Kehadiran Seseorang (Presence: Online / Typing)

conn.ev.on('presence.update', console.log)
await conn.presenceSubscribe(jid)

✏️ Ubah Profil

✨ Ubah Status Profil (Bio)

await conn.updateProfileStatus('Halo Dunia!')

🪪 Ubah Nama Profil

await conn.updateProfileName('zansxart')

📷 Ubah Foto Profil (termasuk grup)

Sama kayak pesan media, lu bisa pake: { url }, Buffer, atau { stream }

await conn.updateProfilePicture(jid, { url: './foto-baru.jpeg' })

❌ Hapus Foto Profil (termasuk grup)

await conn.removeProfilePicture(jid)

👥 Grup WhatsApp (Groups)

Buat ngubah setting grup, lu harus jadi admin grup itu.

📌 Bikin Grup

let group = await conn.groupCreate('Grup Keren zans-xbaileys', ['[email protected]', '[email protected]'])
console.log('Grup berhasil dibikin dengan ID: ' + group.gid)

await conn.sendMessage(group.id, { text: 'Halo semuanya!' })

➕➖ Tambah / Hapus / Jadiin Admin / Turunin Admin

await conn.groupParticipantsUpdate(
  jid,
  ['[email protected]', '[email protected]'],
  'add' // bisa diganti: 'remove', 'promote', 'demote'
)

✏️ Ubah Nama Grup

await conn.groupUpdateSubject(jid, 'Nama Baru Grup!')

📃 Ubah Deskripsi Grup

await conn.groupUpdateDescription(jid, 'Deskripsi baru buat grup ini')

🛠️ Ubah Setting Grup

// cuma admin yang bisa kirim pesan
await conn.groupSettingUpdate(jid, 'announcement')

// semua anggota bisa kirim pesan
await conn.groupSettingUpdate(jid, 'not_announcement')

// semua anggota bisa ubah info grup (foto, nama, dll.)
await conn.groupSettingUpdate(jid, 'unlocked')

// cuma admin yang bisa ubah info grup
await conn.groupSettingUpdate(jid, 'locked')

🚪 Keluar dari Grup

await conn.groupLeave(jid)

🔗 Dapet Kode Undangan Grup

let code = await conn.groupInviteCode(jid)
console.log('Kode undangan grup: ' + code)
// gabung pake: https://chat.whatsapp.com/ + code

♻️ Reset / Ganti Kode Undangan Grup

let newCode = await conn.groupRevokeInvite(jid)
console.log('Kode undangan baru: ' + newCode)

🤝 Gabung Grup dengan Kode Undangan

let response = await conn.groupAcceptInvite('ABC123DEF456')
console.log('Berhasil gabung ke grup: ' + response)

🔍 Liat Info Grup dari Kode Undangan

let response = await conn.groupGetInviteInfo('ABC123DEF456')
console.log('Info grup: ', response)

📑 Liat Metadata Grup

let metadata = await conn.groupMetadata(jid)
console.log(metadata.id + ', Nama: ' + metadata.subject + ', Deskripsi: ' + metadata.desc)

📨 Gabung Grup dari groupInviteMessage

let response = await conn.groupAcceptInviteV4(jid, groupInviteMessage)
consol