baileys-joss
v1.0.1
Published
WhatsApp Web API with Interactive Buttons, List Messages, Albums, AI Messages, Polls, LID/SenderPn Plotting - A feature-rich Baileys fork
Maintainers
Readme
✨ Kenapa Baileys-Joss?
📦 Installation
# Menggunakan npm
npm install baileys-joss
# Menggunakan yarn
yarn add baileys-joss
# Menggunakan pnpm
pnpm add baileys-joss// Untuk mengganti @whiskeysockets/baileys
{
"dependencies": {
"@whiskeysockets/baileys": "npm:baileys-joss"
}
}
// Untuk mengganti @adiwajshing/baileys
{
"dependencies": {
"@adiwajshing/baileys": "npm:baileys-joss"
}
}🎯 Features
Fitur button interactive yang lebih lengkap dan mudah digunakan:
import {
generateInteractiveButtonMessage,
generateInteractiveListMessage,
generateTemplateMessage,
generateCombinedButtons,
generateCopyCodeButton,
generateUrlButtonMessage,
generateQuickReplyButtons
} from 'baileys-joss'
// Quick Reply Buttons
const quickButtons = generateQuickReplyButtons(
'Pilih opsi di bawah ini:',
[
{ id: 'btn-1', displayText: '✅ Setuju' },
{ id: 'btn-2', displayText: '❌ Tolak' },
{ id: 'btn-3', displayText: '📞 Hubungi CS' }
],
{ footer: 'Powered by Baileys-Joss' }
)
await sock.sendMessage(jid, quickButtons)
// URL Button
const urlButton = generateUrlButtonMessage(
'Kunjungi website kami untuk info lebih lanjut',
[{ displayText: '🌐 Buka Website', url: 'https://example.com' }],
{ title: 'Info Produk', footer: 'Click untuk membuka' }
)
await sock.sendMessage(jid, urlButton)
// Copy Code Button (untuk OTP, kode promo, dll)
const copyButton = generateCopyCodeButton(
'Kode OTP Anda adalah:',
'123456',
'📋 Copy Kode'
)
await sock.sendMessage(jid, copyButton)
// Combined Buttons (mix URL, Reply, Copy, Call)
const combinedButtons = generateCombinedButtons(
'Pilih aksi:',
[
{ type: 'reply', displayText: '🛒 Pesan Sekarang', id: 'order' },
{ type: 'url', displayText: '🌐 Website', url: 'https://example.com' },
{ type: 'call', displayText: '📞 Telepon', phoneNumber: '+6281234567890' },
{ type: 'copy', displayText: '📋 Copy Promo', copyCode: 'PROMO2024' }
],
{ title: 'Menu Utama', footer: 'Baileys-Joss' }
)
await sock.sendMessage(jid, combinedButtons)
// List Message
const listMessage = generateInteractiveListMessage({
title: '📋 Menu Produk',
buttonText: 'Lihat Menu',
description: 'Silahkan pilih produk yang diinginkan',
footer: 'Ketik nomor untuk memesan',
sections: [
{
title: 'Makanan',
rows: [
{ rowId: 'nasi-goreng', title: 'Nasi Goreng', description: 'Rp 25.000' },
{ rowId: 'mie-goreng', title: 'Mie Goreng', description: 'Rp 22.000' }
]
},
{
title: 'Minuman',
rows: [
{ rowId: 'es-teh', title: 'Es Teh', description: 'Rp 5.000' },
{ rowId: 'kopi', title: 'Kopi', description: 'Rp 10.000' }
]
}
]
})
await sock.sendMessage(jid, listMessage)Kirim beberapa gambar/video sekaligus dalam format album:
// Send Album (grouped images/videos)
const albumMedia = [
{ image: { url: 'https://example.com/pic1.jpg' }, caption: 'Photo 1' },
{ image: { url: 'https://example.com/pic2.jpg' }, caption: 'Photo 2' },
{ video: { url: 'https://example.com/video.mp4' }, caption: 'Video' }
]
await sock.sendMessage(jid, {
album: albumMedia,
caption: 'My Album 📸'
})
// Album dari file lokal
const localAlbum = [
{ image: fs.readFileSync('./image1.jpg') },
{ image: fs.readFileSync('./image2.jpg') },
{ video: fs.readFileSync('./video.mp4'), gifPlayback: true }
]
await sock.sendMessage(jid, { album: localAlbum })Tambahkan ikon AI stylish pada pesan:
// Kirim pesan dengan AI icon
await sock.sendMessage(jid, {
text: 'Halo! Saya adalah asisten AI Anda 🤖',
ai: true // Menampilkan ikon AI pada pesan
})
// AI dengan media
await sock.sendMessage(jid, {
image: { url: 'https://example.com/ai-generated.jpg' },
caption: 'Generated by AI',
ai: true
})Buat polling dengan mudah:
// Create a Poll
const pollMessage = {
name: '🎨 Warna Favorit?',
values: ['🔴 Merah', '🔵 Biru', '🟢 Hijau', '🟡 Kuning'],
selectableCount: 1 // Jumlah pilihan yang bisa dipilih
}
await sock.sendMessage(jid, { poll: pollMessage })
// Multi-select Poll
const multiPoll = {
name: '🍕 Topping Pizza Favorit?',
values: ['Pepperoni', 'Mushroom', 'Cheese', 'Olive', 'Bacon'],
selectableCount: 3 // Bisa pilih hingga 3 opsi
}
await sock.sendMessage(jid, { poll: multiPoll })Kelola WhatsApp Channel dengan lengkap:
// Create Newsletter/Channel
await sock.newsletterCreate('My Channel', 'Channel description')
// Update channel info
await sock.newsletterUpdateName(channelJid, 'New Channel Name')
await sock.newsletterUpdateDescription(channelJid, 'Updated description')
await sock.newsletterUpdatePicture(channelJid, { url: 'https://example.com/pic.jpg' })
// Follow/Unfollow
await sock.newsletterFollow(channelJid)
await sock.newsletterUnfollow(channelJid)
// Mute/Unmute
await sock.newsletterMute(channelJid)
await sock.newsletterUnmute(channelJid)
// Send reaction to channel message
await sock.newsletterReactMessage(channelJid, 'server_id', '🔥')
// Get channel metadata
const metadata = await sock.newsletterMetadata('jid', channelJid)
console.log('Subscribers:', metadata.subscribers)
// Admin operations
await sock.newsletterChangeOwner(channelJid, newOwnerLid)
await sock.newsletterDemote(channelJid, adminLid)
const adminCount = await sock.newsletterAdminCount(channelJid)Generate custom alphanumeric pairing code:
// Standard pairing code
const code = await sock.requestPairingCode('6281234567890')
console.log('Your Pairing Code:', code)
// Custom alphanumeric pairing code
const customCode = await sock.requestPairingCode('6281234567890', 'MYCODE12')
console.log('Your Custom Code:', customCode)Utilities untuk mengelola JID, LID (Linked ID), dan senderPn:
import {
parseJid,
getSenderPn,
getCurrentSenderInfo,
isSelf,
plotJid,
normalizePhoneToJid,
extractPhoneNumber,
formatJidDisplay,
isSameUser,
getJidVariants,
getRemoteJidFromMessage,
createJidPlotter
} from 'baileys-joss'
// Get info tentang current session (senderPn)
const senderInfo = getCurrentSenderInfo(sock.authState)
console.log('Phone:', senderInfo.phoneNumber)
console.log('Phone JID:', senderInfo.phoneJid)
console.log('LID:', senderInfo.lid)
console.log('Device ID:', senderInfo.deviceId)
console.log('Name:', senderInfo.pushName)
// Parse JID untuk info lengkap
const jidInfo = parseJid('[email protected]')
console.log('User:', jidInfo.user)
console.log('Is LID:', jidInfo.isLid)
console.log('Is PN:', jidInfo.isPn)
console.log('Device:', jidInfo.device)
// Check apakah JID adalah diri sendiri
const isMe = isSelf(someJid, senderInfo)
// Normalize berbagai format nomor
const jid = normalizePhoneToJid('+62 812-3456-7890') // -> [email protected]
// Extract phone number dari JID
const phone = extractPhoneNumber('[email protected]') // -> 6281234567890
// Format untuk display
const display = formatJidDisplay('6281234567890:[email protected]', {
showDevice: true,
showType: true
}) // -> 6281234567890:1 (PN)
// Compare dua JID
const same = isSameUser('[email protected]', '6281234567890:[email protected]') // true
// Get sender dari message
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const msg of messages) {
const { chatJid, senderJid } = getRemoteJidFromMessage(msg)
console.log('Chat:', chatJid)
console.log('Sender:', senderJid)
}
})
// Advanced: Create plotter dengan LID mapping support
const plotter = createJidPlotter(
sock.lidMapping.getLIDForPN.bind(sock.lidMapping),
sock.lidMapping.getPNForLID.bind(sock.lidMapping)
)
const plotted = await plotter.plotBidirectional('[email protected]')
console.log('Phone:', plotted.pn)
console.log('LID:', plotted.lid)Kirim lokasi dengan mudah:
// Send location
await sock.sendMessage(jid, {
location: {
degreesLatitude: -6.2088,
degreesLongitude: 106.8456,
name: 'Jakarta, Indonesia',
address: 'Jl. Sudirman, Jakarta Pusat'
}
})Kelola grup dengan lengkap:
// Create group
const group = await sock.groupCreate('My Group', ['[email protected]'])
// Update group info
await sock.groupUpdateSubject(groupJid, 'New Group Name')
await sock.groupUpdateDescription(groupJid, 'New description')
// Manage participants
await sock.groupParticipantsUpdate(groupJid, ['[email protected]'], 'add')
await sock.groupParticipantsUpdate(groupJid, ['[email protected]'], 'remove')
await sock.groupParticipantsUpdate(groupJid, ['[email protected]'], 'promote')
await sock.groupParticipantsUpdate(groupJid, ['[email protected]'], 'demote')
// Get group metadata
const metadata = await sock.groupMetadata(groupJid)
console.log('Group Name:', metadata.subject)
console.log('Members:', metadata.participants.length)
// Group settings
await sock.groupSettingUpdate(groupJid, 'announcement') // Only admins can send
await sock.groupSettingUpdate(groupJid, 'not_announcement') // Everyone can send
await sock.groupSettingUpdate(groupJid, 'locked') // Only admins can edit info
await sock.groupSettingUpdate(groupJid, 'unlocked') // Everyone can edit info
// Leave group
await sock.groupLeave(groupJid)🚀 Quick Start
import makeWASocket, {
useMultiFileAuthState,
DisconnectReason,
// Interactive Message features
generateQuickReplyButtons,
generateInteractiveListMessage,
generateCombinedButtons,
// JID Plotting features
getCurrentSenderInfo,
parseJid,
isSelf
} from 'baileys-joss'
async function startBot() {
const { state, saveCreds } = await useMultiFileAuthState('auth_session')
const sock = makeWASocket({
auth: state,
printQRInTerminal: true
})
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) {
startBot()
}
} else if (connection === 'open') {
console.log('✅ Connected!')
// Get sender info
const sender = getCurrentSenderInfo(sock.authState)
console.log('📱 Logged in as:', sender?.phoneNumber)
}
})
sock.ev.on('messages.upsert', async ({ messages }) => {
const msg = messages[0]
if (!msg.message || msg.key.fromMe) return
const text = msg.message.conversation ||
msg.message.extendedTextMessage?.text || ''
if (text === '/menu') {
// Kirim interactive buttons
const buttons = generateQuickReplyButtons(
'🤖 Bot Menu\n\nPilih opsi:',
[
{ id: 'help', displayText: '❓ Bantuan' },
{ id: 'info', displayText: 'ℹ️ Info' },
{ id: 'order', displayText: '🛒 Order' }
],
{ footer: 'Baileys-Joss Bot' }
)
await sock.sendMessage(msg.key.remoteJid!, buttons)
}
if (text === '/poll') {
// Kirim poll
await sock.sendMessage(msg.key.remoteJid!, {
poll: {
name: '🗳️ Vote sekarang!',
values: ['Option A', 'Option B', 'Option C'],
selectableCount: 1
}
})
}
if (text === '/ai') {
// Kirim pesan dengan AI style
await sock.sendMessage(msg.key.remoteJid!, {
text: 'Halo! Saya asisten AI Anda 🤖',
ai: true
})
}
})
}
startBot()💡 Use Case Examples
// Create a newsletter
await sock.newsletterCreate('My Updates Channel', 'Stay updated!')
// Update description
await sock.newsletterUpdateDescription(channelJid, 'Fresh updates weekly 🔥')
// Send reaction to channel message
await sock.newsletterReactMessage(channelJid, 'server_id', '❤️')
// Fetch channel messages
const messages = await sock.newsletterFetchMessages('jid', channelJid, 10)// Native Flow Buttons
const buttons = generateCombinedButtons(
'Welcome to our service! 🎉',
[
{ type: 'reply', displayText: '📋 View Menu', id: 'menu' },
{ type: 'url', displayText: '🌐 Visit Website', url: 'https://example.com' },
{ type: 'call', displayText: '📞 Call Us', phoneNumber: '+1234567890' },
{ type: 'copy', displayText: '📋 Copy Promo', copyCode: 'SAVE20' }
],
{ title: 'Welcome!', footer: 'Powered by Baileys-Joss' }
)
await sock.sendMessage(jid, buttons)const media = [
{ image: { url: 'https://example.com/pic1.jpg' }, caption: 'Photo 1 📸' },
{ image: { url: 'https://example.com/pic2.jpg' }, caption: 'Photo 2 📸' },
{ video: { url: 'https://example.com/clip.mp4' }, caption: 'Video 🎬' }
]
await sock.sendMessage(jid, {
album: media,
caption: 'My Vacation Memories 🌴'
})// Request standard pairing code
const code = await sock.requestPairingCode('6281234567890')
console.log('Your Pairing Code:', code)
// Request custom pairing code
const customCode = await sock.requestPairingCode('6281234567890', 'BAILEYS1')
console.log('Your Custom Code:', customCode)const pollMessage = {
name: '🎬 Film Favorit Weekend Ini?',
values: [
'🦸 Superhero Movie',
'😂 Comedy',
'😱 Horror',
'💑 Romance'
],
selectableCount: 1
}
await sock.sendMessage(jid, { poll: pollMessage })await sock.sendMessage(jid, {
location: {
degreesLatitude: -6.2088,
degreesLongitude: 106.8456,
name: 'Monas Jakarta',
address: 'Jalan Medan Merdeka, Jakarta Pusat'
}
})// Create group
const group = await sock.groupCreate('My Awesome Group', [
'[email protected]',
'[email protected]'
])
console.log('Group created:', group.id)
// Update group settings
await sock.groupUpdateSubject(group.id, 'Updated Group Name')
await sock.groupSettingUpdate(group.id, 'announcement')
// Add members
await sock.groupParticipantsUpdate(group.id, [
'[email protected]'
], 'add')📋 API Reference
| Function | Description |
|----------|-------------|
| generateInteractiveButtonMessage() | Buat button message dengan media header |
| generateInteractiveListMessage() | Buat list message dengan sections |
| generateTemplateMessage() | Buat template message (Quick Reply, URL, Call) |
| generateNativeFlowMessage() | Buat native flow message (format terbaru) |
| generateCopyCodeButton() | Button untuk copy code |
| generateUrlButtonMessage() | Button dengan URL |
| generateQuickReplyButtons() | Quick reply buttons |
| generateCombinedButtons() | Gabungan berbagai jenis button |
| Function | Description |
|----------|-------------|
| parseJid() | Parse JID dan extract info lengkap |
| getSenderPn() | Get senderPn dari AuthenticationCreds |
| getCurrentSenderInfo() | Get current sender info dari authState |
| isSelf() | Check apakah JID adalah diri sendiri |
| plotJid() | Plot JID (basic, tanpa LID mapping) |
| normalizePhoneToJid() | Normalize nomor ke JID |
| extractPhoneNumber() | Extract phone number dari JID |
| formatJidDisplay() | Format JID untuk display |
| isSameUser() | Compare dua JID |
| getJidVariants() | Get semua variant JID dari nomor |
| constructJidWithDevice() | Construct JID dengan device ID |
| getRemoteJidFromMessage() | Get remoteJid dari message |
| createJidPlotter() | Create plotter dengan LID mapping support |
| Function | Description |
|----------|-------------|
| newsletterCreate() | Buat channel baru |
| newsletterUpdateName() | Update nama channel |
| newsletterUpdateDescription() | Update deskripsi channel |
| newsletterUpdatePicture() | Update foto channel |
| newsletterFollow() | Follow channel |
| newsletterUnfollow() | Unfollow channel |
| newsletterMute() | Mute notifikasi channel |
| newsletterUnmute() | Unmute notifikasi channel |
| newsletterReactMessage() | React ke pesan channel |
| newsletterMetadata() | Get metadata channel |
| newsletterAdminCount() | Get jumlah admin |
| newsletterChangeOwner() | Ganti owner channel |
| newsletterDemote() | Demote admin channel |
| newsletterDelete() | Hapus channel |
| Function | Description |
|----------|-------------|
| groupCreate() | Buat grup baru |
| groupUpdateSubject() | Update nama grup |
| groupUpdateDescription() | Update deskripsi grup |
| groupParticipantsUpdate() | Add/remove/promote/demote member |
| groupSettingUpdate() | Update pengaturan grup |
| groupMetadata() | Get metadata grup |
| groupLeave() | Keluar dari grup |
| groupInviteCode() | Get kode invite grup |
| groupAcceptInvite() | Join grup via invite code |
| Type | Description |
|------|-------------|
| text | Pesan teks biasa |
| image | Kirim gambar |
| video | Kirim video |
| audio | Kirim audio |
| document | Kirim dokumen |
| sticker | Kirim sticker |
| location | Kirim lokasi |
| contacts | Kirim kontak |
| poll | Buat polling |
| album | Kirim album (multiple media) |
| react | React ke pesan |
| edit | Edit pesan |
| delete | Hapus pesan |
🔄 Changelog
- ✨ Added Album Messages support (carousel format)
- ✨ Added AI Message Style (
ai: true) - shows AI indicator on messages - ✨ Added Custom Pairing Code support
- ✨ Enhanced Newsletter/Channel control
- ✨ Enhanced Poll creation
- 🔧 Fixed Interactive Buttons - Added
biznode for proper button rendering - 🔧 Fixed List Messages delivery
- 🎨 Improved documentation with collapsible sections
- 🐛 Bug fixes and stability improvements
- 🎉 Initial release
- ✨ Interactive Buttons support
- ✨ List Messages support
- ✨ Copy Code Button
- ✨ URL Buttons
- ✨ Combined Button Types
- ✨ Native Flow Messages
- ✨ LID/SenderPn Plotting utilities
🤝 Contributing
Kontribusi sangat diterima! Silahkan:
- 🍴 Fork repository ini
- 🌿 Buat branch fitur (
git checkout -b feature/AmazingFeature) - 💾 Commit changes (
git commit -m 'Add some AmazingFeature') - 📤 Push ke branch (
git push origin feature/AmazingFeature) - 🔃 Buka Pull Request
💖 Support
Jika project ini membantu, berikan ⭐ di GitHub!
⚠️ Disclaimer
Peringatan: Proyek ini tidak berafiliasi dengan WhatsApp atau Meta. Gunakan dengan tanggung jawab dan sesuai dengan Terms of Service WhatsApp.
❌ Jangan spam!
❌ Jangan abuse API!
✅ Gunakan untuk keperluan yang baik!
📄 License
MIT License - Lihat file LICENSE untuk detail.
