baileys-joss
v1.0.3
Published
WhatsApp Web API with Interactive Buttons, List Messages, Albums, AI Messages, Polls, LID/SenderPn Plotting, Mini Games, Content Detection, Anti-Spam - 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
})Kirim gambar dan video tanpa kompresi dalam kualitas HD:
// Kirim gambar HD (kualitas tinggi, tidak dikompres)
await sock.sendMessage(jid, {
image: { url: './photo-hd.jpg' },
caption: 'Foto HD 📸',
hd: true // Kirim tanpa kompresi
})
// Kirim video HD
await sock.sendMessage(jid, {
video: { url: './video-4k.mp4' },
caption: 'Video 4K 🎬',
hd: true // Kualitas asli
})
// HD dengan media dari URL
await sock.sendMessage(jid, {
image: { url: 'https://example.com/high-res-photo.jpg' },
hd: true,
caption: 'High Resolution Photo'
})Set foto profil panorama (wide) tanpa cropping:
// Set panorama profile picture (tidak di-crop square)
await sock.updatePanoramaProfilePicture(myJid, { url: './panorama.jpg' })
// Dengan opsi kustom
await sock.updatePanoramaProfilePicture(myJid, { url: './wide-photo.jpg' }, {
maxWidth: 1080, // Maximum width
quality: 90 // JPEG quality (1-100)
})
// Set panorama untuk grup
await sock.updatePanoramaProfilePicture(groupJid, { url: './group-banner.jpg' })
// Atau gunakan profile picture biasa (square crop)
await sock.updateProfilePicture(myJid, { url: './square-photo.jpg' })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')🆕 Baileys-Joss v1.0.3 New Features
Jadwalkan pesan untuk dikirim otomatis di waktu tertentu:
import { createMessageScheduler } from 'baileys-joss'
// Buat scheduler
const scheduler = createMessageScheduler(
(jid, content) => sock.sendMessage(jid, content),
{
onSent: (scheduled, message) => {
console.log(`Pesan terkirim ke ${scheduled.jid}`)
},
onFailed: (scheduled, error) => {
console.log(`Gagal kirim: ${error.message}`)
}
}
)
// Jadwalkan pesan untuk waktu tertentu
const scheduled = scheduler.schedule(
'[email protected]',
{ text: 'Selamat Ulang Tahun! 🎂' },
new Date('2024-12-25 09:00:00')
)
// Jadwalkan dengan delay (30 menit dari sekarang)
scheduler.scheduleDelay(jid, { text: 'Reminder!' }, 30 * 60 * 1000)
// Cancel scheduled message
scheduler.cancel(scheduled.id)
// Get all pending messages
const pending = scheduler.getPending()
// Stop scheduler
scheduler.stop()Kirim pesan massal ke banyak kontak dengan rate limiting:
import { createBulkSender, sendBulkMessages } from 'baileys-joss'
// Method 1: Create bulk sender instance
const bulkSender = createBulkSender(
(jid, content) => sock.sendMessage(jid, content),
{
delayBetweenMessages: 2000, // 2 detik delay
randomDelay: 1000, // Random 0-1 detik tambahan
maxRetries: 2,
onProgress: (progress) => {
console.log(`Progress: ${progress.sent}/${progress.total} (${progress.percentage}%)`)
},
onComplete: (results) => {
const success = results.filter(r => r.success).length
console.log(`Selesai: ${success}/${results.length} berhasil`)
}
}
)
// Kirim pesan yang sama ke banyak JID
const jids = [
'[email protected]',
'[email protected]',
'[email protected]'
]
const results = await bulkSender.sendToMany(jids, { text: 'Hello everyone!' })
// Kirim pesan berbeda ke JID berbeda
const messages = [
{ jid: '[email protected]', content: { text: 'Hi John!' } },
{ jid: '[email protected]', content: { text: 'Hi Jane!' } }
]
await bulkSender.send(messages)
// Method 2: Quick helper
await sendBulkMessages(
(jid, content) => sock.sendMessage(jid, content),
jids,
{ text: 'Broadcast message' }
)Sistem balasan otomatis berdasarkan keyword/pattern:
import { createAutoReply } from 'baileys-joss'
// Buat auto-reply handler
const autoReply = createAutoReply(
(jid, content, options) => sock.sendMessage(jid, content, options),
(jid, presence) => sock.sendPresenceUpdate(presence, jid),
{
simulateTyping: true,
typingDuration: 1500,
globalCooldown: 1000
}
)
// Tambah rule berdasarkan keywords
autoReply.addRule({
keywords: ['harga', 'price', 'biaya'],
response: { text: 'Silakan cek katalog kami di example.com' },
cooldown: 60000, // 1 menit cooldown per user
quoted: true // Reply dengan quote
})
// Rule dengan regex pattern
autoReply.addRule({
pattern: /^(hi|hello|halo|hay)/i,
response: { text: 'Hai! Ada yang bisa dibantu? 😊' },
privateOnly: true // Hanya di private chat
})
// Rule dengan dynamic response
autoReply.addRule({
keywords: ['order'],
response: async (message, match) => {
const sender = message.key.remoteJid
return { text: `Terima kasih sudah order! ID: ${Date.now()}` }
}
})
// Rule untuk grup saja
autoReply.addRule({
exactMatch: '/menu',
response: { text: 'Menu:\n1. Help\n2. Info\n3. Contact' },
groupsOnly: true
})
// Proses pesan masuk
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const msg of messages) {
if (!msg.key.fromMe) {
await autoReply.processMessage(msg)
}
}
})Kirim kartu kontak lengkap dengan detail:
import {
createContactCard,
createContactCards,
quickContact,
generateVCard
} from 'baileys-joss'
// Quick contact (simple)
const simple = quickContact('John Doe', '+628123456789', {
organization: 'PT Example',
email: '[email protected]'
})
await sock.sendMessage(jid, createContactCard(simple))
// Full vCard with all details
const fullContact = {
fullName: 'Dr. John Doe',
displayName: 'John D.',
organization: 'Hospital ABC',
title: 'Senior Doctor',
phones: [
{ number: '+628123456789', type: 'CELL' },
{ number: '+622112345678', type: 'WORK' }
],
emails: [
{ email: '[email protected]', type: 'WORK' },
{ email: '[email protected]', type: 'HOME' }
],
urls: [
{ url: 'https://linkedin.com/in/johndoe', type: 'WORK' }
],
addresses: [{
street: 'Jl. Sudirman No. 123',
city: 'Jakarta',
state: 'DKI Jakarta',
postalCode: '12345',
country: 'Indonesia',
type: 'WORK'
}],
birthday: '1990-05-15',
note: 'Met at conference 2024'
}
await sock.sendMessage(jid, createContactCard(fullContact))
// Send multiple contacts
const contacts = [
quickContact('Alice', '+628111111111'),
quickContact('Bob', '+628222222222'),
quickContact('Charlie', '+628333333333')
]
await sock.sendMessage(jid, createContactCards(contacts))
// Generate raw vCard string
const vcardString = generateVCard(fullContact)
console.log(vcardString)Posting status WhatsApp (foto, video, text):
import {
StatusHelper,
STATUS_BROADCAST_JID,
STATUS_BACKGROUNDS,
STATUS_FONTS
} from 'baileys-joss'
const statusJid = STATUS_BROADCAST_JID // 'status@broadcast'
// Post text status
await sock.sendMessage(statusJid, StatusHelper.text(
'Hello World! 🌍',
STATUS_BACKGROUNDS.solid.green
))
// Post image status
const imageBuffer = fs.readFileSync('./my-photo.jpg')
await sock.sendMessage(statusJid, StatusHelper.image(
imageBuffer,
'Beautiful day! ☀️'
))
// Post video status
const videoBuffer = fs.readFileSync('./my-video.mp4')
await sock.sendMessage(statusJid, StatusHelper.video(
videoBuffer,
'Check this out! 🎬'
))
// Post GIF status
await sock.sendMessage(statusJid, StatusHelper.gif(
gifBuffer,
'Animated! 🎭'
))
// Custom text status with font
import { createTextStatus } from 'baileys-joss'
await sock.sendMessage(statusJid, createTextStatus({
text: 'Custom styled status!',
backgroundColor: STATUS_BACKGROUNDS.solid.purple,
font: STATUS_FONTS.DANCING,
textColor: '#FFFFFF'
}))Template pesan siap pakai untuk berbagai keperluan:
import { createTemplateManager, renderTemplate, PRESET_TEMPLATES } from 'baileys-joss'
// Create manager with preset templates
const templates = createTemplateManager(true)
// Render preset template
const orderConfirmation = templates.render('order_confirmation', {
orderId: 'ORD-12345',
customerName: 'John Doe',
orderDate: '2024-01-15',
items: '1x Product A\n2x Product B',
total: '150,000'
})
await sock.sendMessage(jid, { text: orderConfirmation })
// Create custom template
templates.create({
name: 'Welcome Message',
content: `Halo {{name}}! 👋
Selamat datang di {{company}}!
Berikut layanan kami:
{{services}}
Contact: {{phone:021-12345678}}`,
category: 'greeting'
})
// Render custom template
const welcome = templates.render('welcome_message', {
name: 'Budi',
company: 'PT Example',
services: '- Layanan A\n- Layanan B\n- Layanan C'
})
// Quick template rendering (tanpa manager)
const quick = renderTemplate(
'Hi {{name}}, your order #{{orderId}} is {{status:processing}}',
{ name: 'Alice', orderId: '123' }
)
// List available templates
const allTemplates = templates.getAll()
const invoiceTemplates = templates.getByCategory('invoice')
// Export/Import templates
const exportJson = templates.export()
templates.import(exportJson, true) // true = overwrite existingKelola dan kirim ke broadcast list:
import { createBroadcastManager } from 'baileys-joss'
const broadcast = createBroadcastManager(
(jid, content) => sock.sendMessage(jid, content)
)
// Create broadcast list
const customerList = broadcast.create({
name: 'VIP Customers',
description: 'Premium customers for promo',
recipients: [
'[email protected]',
'[email protected]'
]
})
// Add more recipients
broadcast.addRecipients(customerList.id, [
'[email protected]'
])
// Send to broadcast list
const result = await broadcast.broadcast(
customerList.id,
{ text: '🎉 Special promo for VIP customers!' },
{
delay: 2000,
onProgress: (sent, total, jid) => {
console.log(`Sending ${sent}/${total}: ${jid}`)
}
}
)
console.log(`Sent: ${result.sent}, Failed: ${result.failed}`)
// Get statistics
const stats = broadcast.getStats()
console.log(`Total lists: ${stats.totalLists}, Recipients: ${stats.totalRecipients}`)
// Export/Import lists
const json = broadcast.export()
broadcast.import(json)Simulasi sedang mengetik:
import { createTypingIndicator } from 'baileys-joss'
const typing = createTypingIndicator(
(jid, presence) => sock.sendPresenceUpdate(presence, jid)
)
// Start typing
await typing.startTyping(jid, {
duration: 5000, // Auto pause after 5 seconds
autoPause: true
})
// Start recording (for voice notes)
await typing.startRecording(jid, { duration: 3000 })
// Stop typing
await typing.stopTyping(jid)
// Simulate typing then send
await typing.simulateTyping(jid, 2000, async () => {
return sock.sendMessage(jid, { text: 'Hello!' })
})
// Stop all typing indicators
await typing.stopAll()Kontrol centang biru:
import { createReadReceiptController } from 'baileys-joss'
const readReceipts = createReadReceiptController(
(jid, participant, messageIds) => sock.readMessages([{ remoteJid: jid, id: messageIds[0] }]),
{
enabled: true,
readDelay: 1000, // 1 second delay
excludeJids: ['[email protected]']
}
)
// Toggle read receipts
readReceipts.disable() // Stop sending read receipts
readReceipts.enable() // Resume
// Check status
console.log(readReceipts.isEnabled())
// Manual read (respects config)
await readReceipts.markRead(jid, participant, ['messageId123'])
// Force read (ignores config)
await readReceipts.forceMarkRead(jid, participant, ['messageId123'])
// Update config
readReceipts.setConfig({
enabled: true,
readDelay: 2000
})Cari pesan dalam chat:
import { createMessageSearch, searchMessages } from 'baileys-joss'
// Create search manager
const search = createMessageSearch()
// Add messages to index
search.addMessages(chatMessages)
// Search by text
const results = search.search('harga produk', {
caseSensitive: false,
limit: 20,
messageTypes: ['text', 'image'], // Include captions
fromDate: new Date('2024-01-01')
})
for (const result of results) {
console.log(`Found: "${result.matchedText}"`)
console.log(`Score: ${result.relevanceScore}`)
console.log(`Message ID: ${result.message.key.id}`)
}
// Search with regex
const regexResults = search.searchRegex(/order\s*#?\d+/i)
// Get messages by type
const images = search.getByType('image')
const videos = search.getByType('video')
// Get messages by sender
const fromSender = search.getBySender('[email protected]')
// Quick search (without manager)
const quickResults = searchMessages(messages, 'keyword', {
jid: specificChatJid,
fromMe: false
})Statistik dan analitik chat:
import { createChatAnalytics } from 'baileys-joss'
const analytics = createChatAnalytics()
// Add messages for analysis
analytics.addMessages(allMessages)
// Get stats for specific chat
const chatStats = analytics.getChatStats('[email protected]')
console.log(`Total messages: ${chatStats.totalMessages}`)
console.log(`From me: ${chatStats.messagesFromMe}`)
console.log(`Media count: ${chatStats.mediaCount}`)
console.log(`Links shared: ${chatStats.linkCount}`)
console.log(`Emojis used: ${chatStats.emojiCount}`)
console.log(`Most active hour: ${chatStats.mostActiveHour}:00`)
console.log(`Most active day: ${chatStats.mostActiveDay}`)
console.log(`Avg messages/day: ${chatStats.averageMessagesPerDay}`)
// Message breakdown by type
console.log('Messages by type:', chatStats.messagesByType)
// { text: 150, image: 45, video: 12, audio: 8, ... }
// Global stats across all chats
const globalStats = analytics.getGlobalStats()
console.log(`Total chats: ${globalStats.totalChats}`)
console.log(`Total messages: ${globalStats.totalMessages}`)
console.log(`Most active chat: ${globalStats.mostActiveChat?.jid}`)
// Activity analysis
const hourlyActivity = analytics.getActivityByHour(jid) // Array[24]
const dailyActivity = analytics.getActivityByDay(jid) // { Sunday: 10, Monday: 25, ... }
// Top participants in group
const topParticipants = analytics.getTopParticipants(groupJid, 5)
for (const p of topParticipants) {
console.log(`${p.participant}: ${p.count} messages`)
}Export chat ke JSON, HTML, TXT, atau CSV:
import { createChatExporter, exportChat } from 'baileys-joss'
const exporter = createChatExporter()
// Add messages
exporter.addMessages(jid, chatMessages)
// Export to JSON
const jsonExport = exporter.export(jid, {
format: 'json',
includeMediaInfo: true,
includeMetadata: true
})
fs.writeFileSync(jsonExport.filename, jsonExport.content)
// Export to HTML (readable format)
const htmlExport = exporter.export(jid, {
format: 'html',
title: 'Chat dengan John',
dateFormat: 'YYYY-MM-DD HH:mm'
})
fs.writeFileSync(htmlExport.filename, htmlExport.content)
// Export to TXT (simple text)
const txtExport = exporter.export(jid, {
format: 'txt',
dateRange: {
start: new Date('2024-01-01'),
end: new Date('2024-12-31')
}
})
// Export to CSV (for spreadsheet)
const csvExport = exporter.export(jid, {
format: 'csv',
includeMetadata: true
})
// Quick export (without manager)
const result = exportChat(messages, jid, { format: 'json' })
console.log(`Exported ${result.messageCount} messages`)
// Export all chats
const allExports = exporter.exportAll({ format: 'json' })Game sederhana untuk chat interaktif:
import {
MiniGamesManager,
createTicTacToeGame,
createQuiz
} from 'baileys-joss'
// Create games manager
const games = new MiniGamesManager()
// 🎯 Guess Number Game
const guessSession = games.startGuessNumber('[email protected]', {
minNumber: 1,
maxNumber: 100,
maxAttempts: 7
})
// Handle guess
const result = games.handleGuess(guessSession.id, 50)
if (result.correct) {
await sock.sendMessage(jid, { text: `🎉 Correct! The number was ${result.answer}` })
} else {
await sock.sendMessage(jid, { text: `${result.hint} (${result.remaining} attempts left)` })
}
// 🧠 Quiz Game
const quizSession = games.startQuiz(jid, {
questions: [
{
question: 'Apa ibukota Indonesia?',
options: ['Jakarta', 'Bandung', 'Surabaya', 'Medan'],
correctIndex: 0,
explanation: 'Jakarta adalah ibukota Indonesia sejak 1945'
}
],
category: 'geography'
})
await sock.sendMessage(jid, {
text: `📝 Quiz:\n${quizSession.data.currentQuestion}\n\n${quizSession.data.options.map((o, i) => `${i+1}. ${o}`).join('\n')}`
})
// ❌⭕ TicTacToe Game
const tttSession = games.startTicTacToe(jid, player1Jid, player2Jid)
const moveResult = games.handleMove(tttSession.id, player1Jid, 4) // Center position
await sock.sendMessage(jid, {
text: `${games.renderBoard(tttSession)}\n\n${moveResult.message}`
})
// 🎲 Quick Games
const dice = games.rollDice() // { value: 1-6, emoji: '🎲' }
const coin = games.flipCoin() // { result: 'heads'|'tails', emoji: '🪙' }
const rps = games.playRockPaperScissors('rock', 'scissors') // { winner: 'player1', ... }
// 🏆 Leaderboard
const leaderboard = games.getLeaderboard(10)Deteksi otomatis berbagai jenis konten dalam pesan:
import {
ContentDetector,
ContentFilter,
hasLinks,
hasPhoneNumbers,
hasEmails,
hasMediaContent
} from 'baileys-joss'
// Create detector
const detector = new ContentDetector()
// Full analysis
const result = detector.analyze(message)
console.log('Has media:', result.hasMedia)
console.log('Media type:', result.mediaType)
console.log('Links found:', result.links)
console.log('Phone numbers:', result.phoneNumbers)
console.log('Emails:', result.emails)
console.log('Mentions:', result.mentions)
console.log('Hashtags:', result.hashtags)
console.log('Word count:', result.wordCount)
// Quick checks
if (hasLinks(message)) {
console.log('Message contains links!')
}
if (hasPhoneNumbers(message)) {
console.log('Message contains phone numbers!')
}
if (hasMediaContent(message)) {
console.log('Message has media attachment!')
}
// Content filtering
const filter = new ContentFilter({
blockLinks: true,
blockedDomains: ['spam.com', 'malware.xyz'],
blockPhoneNumbers: false,
sensitiveKeywords: ['spam', 'promo', 'click here'],
maxMessageLength: 1000
})
const filterResult = filter.check(message)
if (!filterResult.allowed) {
await sock.sendMessage(jid, {
text: `⚠️ Message blocked: ${filterResult.blockedReason}`
})
}Sistem untuk mendeteksi dan mencegah spam:
import { AntiSpamManager } from 'baileys-joss'
// Create anti-spam manager
const antispam = new AntiSpamManager({
maxMessagesPerMinute: 15,
maxDuplicates: 3,
duplicateWindow: 60000, // 1 minute
minMessageDelay: 500,
whitelist: ['[email protected]'],
onSpamDetected: async (jid, message, result) => {
console.log(`Spam detected from ${jid}: ${result.reason}`)
if (result.action === 'mute') {
await sock.sendMessage(jid, { text: '⚠️ You are muted for spamming!' })
}
}
})
// Add custom spam pattern
antispam.addRule({
id: 'promo_spam',
name: 'Promotional Spam',
type: 'pattern',
enabled: true,
config: { patterns: [/FREE\s+\d+\s+TOKEN/i, /CLICK\s+HERE.*WIN/i] },
action: 'delete'
})
// Check incoming messages
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const msg of messages) {
const result = await antispam.checkMessage(msg)
if (result.isSpam) {
console.log(`🛡️ Spam blocked! Score: ${result.score}, Reason: ${result.reason}`)
// Handle based on action
if (result.action === 'delete') {
await sock.sendMessage(msg.key.remoteJid, { delete: msg.key })
} else if (result.action === 'warn') {
await sock.sendMessage(msg.key.remoteJid, {
text: `⚠️ Warning: ${result.reason}`
})
}
continue
}
// Process non-spam message...
}
})
// Whitelist trusted users
antispam.whitelist('[email protected]')
// Mute spammer temporarily
antispam.muteUser('[email protected]', 3600) // 1 hour
// Ban repeat offender
antispam.banUser('[email protected]')
// Get spam statistics
const stats = antispam.getStats()
console.log('Total spam blocked:', stats.totalBlocked)Scan dan validasi URL untuk keamanan:
import { LinkScanner, scanUrls, isUrlSafe } from 'baileys-joss'
// Create scanner
const scanner = new LinkScanner({
followRedirects: true,
maxRedirects: 5,
timeout: 5000,
enablePhishingDetection: true
})
// Scan single URL
const result = await scanner.scanUrl('https://suspicious-link.xyz/login')
console.log('Safe:', result.safe)
console.log('Risk level:', result.riskLevel) // 'safe' | 'low' | 'medium' | 'high' | 'critical'
console.log('Threats:', result.threats)
console.log('Details:', result.details)
// Scan all URLs in a message
const messageResults = await scanner.scanMessage(message)
for (const urlResult of messageResults) {
if (!urlResult.safe) {
await sock.sendMessage(jid, {
text: `⚠️ Warning! Suspicious link detected:\n${urlResult.url}\n\nRisk: ${urlResult.riskLevel}\nThreats: ${urlResult.threats.join(', ')}`
})
}
}
// Quick safety check
const isSafe = await scanner.isUrlSafe('https://example.com')
// Add custom patterns
scanner.addPhishingPattern(/banking.*verify.*account/i)
scanner.addTrustedDomain('mytrusted.com')
scanner.addMaliciousDomain('known-scam.xyz')
// Auto-scan in message handler
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const msg of messages) {
const scanResults = await scanner.scanMessage(msg)
const dangerous = scanResults.filter(r => r.riskLevel === 'high' || r.riskLevel === 'critical')
if (dangerous.length > 0) {
await sock.sendMessage(msg.key.remoteJid, {
text: `🚨 Dangerous link(s) detected! ${dangerous.length} threat(s) found.`
}, { quoted: msg })
}
}
})Logging aktivitas untuk audit trail:
import { ActivityLogger } from 'baileys-joss'
// Create logger
const logger = new ActivityLogger({
fileLogging: true,
logFilePath: './logs/bot-activity.log',
maxMemoryEntries: 1000,
maxFileSize: 10 * 1024 * 1024, // 10MB
minLevel: 'info',
categories: ['message', 'user', 'group', 'bot'],
onLog: (entry) => {
if (entry.level === 'error') {
// Send alert to admin
console.error(`[ALERT] ${entry.action}: ${entry.details.message}`)
}
}
})
// Log message activity
logger.logMessage(message, 'received', {
processed: true,
responseTime: 150
})
// Log user action
logger.logUserAction('[email protected]', 'command_executed', {
command: '/help',
success: true
})
// Log group action
logger.logGroupAction('[email protected]', 'member_added', {
addedBy: '[email protected]',
newMember: '[email protected]'
})
// Log custom activity
logger.log({
level: 'info',
category: 'bot',
action: 'scheduled_task',
actor: 'system',
details: { task: 'daily_backup', status: 'completed' }
})
// Query logs
const recentErrors = logger.query({
level: 'error',
fromDate: new Date(Date.now() - 24 * 60 * 60 * 1000), // Last 24 hours
limit: 50
})
// Get statistics
const stats = logger.getStats()
console.log('Total entries:', stats.totalEntries)
console.log('By level:', stats.byLevel)
console.log('Top actors:', stats.topActors)
// Export logs
const jsonLogs = logger.export('json')
const csvLogs = logger.export('csv')Generate meme sederhana dengan text overlay:
import {
MemeGenerator,
MEME_TEMPLATES,
drakeMeme,
expandingBrainMeme,
thisIsFineMeme
} from 'baileys-joss'
// Create generator
const meme = new MemeGenerator()
// List available templates
const templates = meme.getTemplates()
console.log('Available templates:', templates.map(t => t.name))
// Generate Drake meme (quick helper)
const drake = drakeMeme(
'Debugging code manually', // Rejected
'Using console.log everywhere' // Approved
)
await sock.sendMessage(jid, { text: drake.htmlContent })
// Generate Expanding Brain meme
const brain = expandingBrainMeme([
'Using var',
'Using let',
'Using const',
'Using TypeScript'
])
await sock.sendMessage(jid, { text: brain.htmlContent })
// Generate "This is Fine" meme
const fine = thisIsFineMeme('Production is on fire but it\'s fine')
await sock.sendMessage(jid, { text: fine.htmlContent })
// Custom meme with template
const custom = meme.generateTextMeme({
template: 'distracted',
texts: {
boyfriend: 'Me',
girlfriend: 'My deadlines',
other: 'New side project'
},
fontSize: 24,
fontColor: '#ffffff'
})
// Generate SVG meme (for advanced use)
const svgMeme = meme.generateSvgMeme({
template: 'two_buttons',
texts: {
button1: 'Sleep early',
button2: 'One more episode'
}
})
// Send as formatted text meme
await sock.sendMessage(jid, {
text: `🎭 *MEME*\n\n${custom.htmlContent}`
})Timer produktivitas dengan teknik Pomodoro:
import { PomodoroManager, DEFAULT_POMODORO_CONFIG } from 'baileys-joss'
// Create pomodoro manager
const pomodoro = new PomodoroManager()
// Register event handler
pomodoro.onEvent(async (event) => {
const jid = event.session.jid
switch (event.type) {
case 'work_start':
await sock.sendMessage(jid, {
text: `🍅 *WORK SESSION STARTED*\n\n⏱️ Duration: 25 minutes\n🎯 Session: ${event.session.currentSession}/${event.session.totalSessions}\n\n💪 Stay focused!`
})
break
case 'work_end':
await sock.sendMessage(jid, {
text: `✅ *WORK SESSION COMPLETE!*\n\n🎉 Great job! Time for a break.\n\nType /break to start break timer.`
})
break
case 'break_start':
await sock.sendMessage(jid, {
text: `☕ *BREAK TIME*\n\n⏱️ Duration: 5 minutes\n\n🧘 Relax and recharge!`
})
break
case 'break_end':
await sock.sendMessage(jid, {
text: `⏰ *BREAK OVER!*\n\nReady for next session?\nType /work to continue.`
})
break
}
})
// Start work session
const session = pomodoro.start('[email protected]', {
workDuration: 25, // 25 minutes
shortBreakDuration: 5, // 5 minutes
longBreakDuration: 15, // 15 minutes
sessionsBeforeLongBreak: 4,
autoStartBreaks: true
})
// Pause/Resume
pomodoro.pause(jid)
pomodoro.resume(jid)
// Start break manually
pomodoro.startBreak(jid)
// Get current status
const status = pomodoro.status(jid)
console.log('Status:', status.status) // 'work' | 'short_break' | 'long_break' | 'paused'
console.log('Time remaining:', status.remainingTime)
console.log('Current session:', status.currentSession)
// Stop and reset
pomodoro.stop(jid)
// Get statistics
const stats = pomodoro.stats(jid)
console.log('Total work sessions:', stats.totalWorkSessions)
console.log('Total work minutes:', stats.totalWorkMinutes)
console.log('Current streak:', stats.currentStreak)Random quotes dan quotes harian:
import {
QuoteManager,
getRandomQuote,
getQuoteOfTheDay,
getMotivationalQuote,
getIslamicQuote,
getFunnyQuote,
quoteCommand,
QUOTES
} from 'baileys-joss'
// Quick helpers
const random = getRandomQuote()
await sock.sendMessage(jid, {
text: `💬 *Quote*\n\n"${random.text}"\n\n— ${random.author}`
})
// Quote of the day (same quote all day)
const qotd = getQuoteOfTheDay()
await sock.sendMessage(jid, {
text: `📅 *Quote of the Day*\n\n"${qotd.quote.text}"\n\n— ${qotd.quote.author}`
})
// Category-specific quotes
const motivational = getMotivationalQuote()
const islamic = getIslamicQuote()
const funny = getFunnyQuote()
// Using QuoteManager for more control
const quoteManager = new QuoteManager()
// Get quote by category
const loveQuote = quoteManager.getByCategory('love')
const wisdomQuote = quoteManager.getByCategory('wisdom')
// Get quote by language
const indonesianQuote = quoteManager.getByLanguage('id')
const englishQuote = quoteManager.getByLanguage('en')
// Search quotes
const searchResults = quoteManager.search('success')
// Add custom quote
quoteManager.addQuote({
id: 'custom1',
text: 'My custom inspirational quote',
author: 'Me',
category: 'inspirational',
language: 'en'
})
// Parse command (for bot integration)
// Supported: /quote, /quote motivational, /quote islamic, /quote funny
const commandResult = quoteCommand('/quote motivational')
await sock.sendMessage(jid, { text: commandResult })
// Send random quote with formatting
const formatted = quoteManager.format(getRandomQuote(), {
style: 'fancy', // 'simple' | 'fancy' | 'minimal'
includeCategory: true
})
await sock.sendMessage(jid, { text: formatted })Informasi cuaca dengan integrasi OpenWeatherMap:
import {
WeatherBot,
getWeather,
getSimpleWeather,
weatherCommand
} from 'baileys-joss'
// Create weather bot (with API key for full features)
const weather = new WeatherBot({
apiKey: 'YOUR_OPENWEATHERMAP_API_KEY', // Optional: enables API mode
units: 'metric', // 'metric' | 'imperial'
language: 'id',
defaultCity: 'Jakarta'
})
// Get weather for a city
const data = await weather.getWeather('Jakarta')
await sock.sendMessage(jid, {
text: `🌤️ *Weather in ${data.city}, ${data.country}*\n\n🌡️ Temperature: ${data.temperature}°C\n🤒 Feels like: ${data.feelsLike}°C\n💧 Humidity: ${data.humidity}%\n💨 Wind: ${data.windSpeed} m/s\n☁️ Condition: ${data.description}\n\n🌅 Sunrise: ${new Date(data.sunrise * 1000).toLocaleTimeString()}\n🌇 Sunset: ${new Date(data.sunset * 1000).toLocaleTimeString()}`
})
// Quick helper (uses sample data if no API key)
const simpleWeather = await getSimpleWeather('Tokyo')
await sock.sendMessage(jid, { text: simpleWeather })
// Get 5-day forecast
const forecast = await weather.getForecast('Singapore')
let forecastText = `📅 *5-Day Forecast for ${forecast.city}*\n\n`
for (const day of forecast.forecasts.slice(0, 5)) {
forecastText += `${day.date}: ${day.temperature}°C, ${day.description}\n`
}
await sock.sendMessage(jid, { text: forecastText })
// Weather alerts
const alerts = await weather.getAlerts('Miami')
if (alerts.length > 0) {
for (const alert of alerts) {
await sock.sendMessage(jid, {
text: `⚠️ *Weather Alert*\n\n${alert.event}\n\nSeverity: ${alert.severity}\n${alert.description}`
})
}
}
// Parse weather command (for bot integration)
// Supported: /weather Jakarta, /cuaca Bandung
const result = await weatherCommand('/weather Singapore', weather)
await sock.sendMessage(jid, { text: result })
// Format with emoji
const formatted = weather.formatWeather(data, {
includeEmoji: true,
includeDetails: true,
language: 'id'
})
await sock.sendMessage(jid, { text: formatted })Generate QR code custom untuk pairing:
import {
createQRGenerator,
QRHelper,
createQRHandler,
createWhatsAppQR
} from 'baileys-joss'
// Quick QR generation
const terminalQR = await QRHelper.terminal(pairingCode)
console.log(terminalQR)
// Generate SVG QR
const svgQR = await QRHelper.svg(pairingCode, {
size: 300,
foregroundColor: '#128C7E', // WhatsApp green
backgroundColor: '#FFFFFF'
})
// Generate base64 QR (for web)
const base64QR = await QRHelper.base64(pairingCode)
// Generate PNG buffer
const pngBuffer = await QRHelper.buffer(pairingCode)
fs.writeFileSync('qr.png', pngBuffer)
// Custom generator
const generator = createQRGenerator({
size: 256,
errorCorrectionLevel: 'H',
foregroundColor: '#000000',
margin: 4
})
const qr = await generator.generate(data)
// WhatsApp-styled QR
const waQR = await createWhatsAppQR(pairingCode)
// Use as QR event handler
const sock = makeWASocket({
// ...
printQRInTerminal: false
})
sock.ev.on('connection.update', async ({ qr }) => {
if (qr) {
const qrHandler = createQRHandler({
maxAttempts: 5,
onQR: (rendered, raw, attempt) => {
console.log(`\nScan QR (${attempt}/5):\n`)
console.log(rendered)
}
})
await qrHandler(qr)
}
})Download semua media dari chat:
import { createMediaDownloader, downloadAllMedia } from 'baileys-joss'
const downloader = createMediaDownloader(
async (key) => store.loadMessage(key.remoteJid, key.id)
)
// Download all media from chat
const summary = await downloader.downloadFromChat(
'[email protected]',
chatMessages,
{
outputDir: './downloads/john-doe',
types: ['image', 'video', 'document'], // or ['all']
createSubfolders: true, // images/, videos/, etc.
skipExisting: true,
maxFileSize: 50 * 1024 * 1024, // 50MB limit
delay: 500, // Delay between downloads
onProgress: (current, total, filename) => {
console.log(`Downloading ${current}/${total}: ${filename}`)
},
onError: (msg, error) => {
console.log(`Failed: ${error.message}`)
}
}
)
console.log(`Downloaded: ${summary.successful}/${summary.total}`)
console.log(`Total size: ${(summary.totalSize / 1024 / 1024).toFixed(2)} MB`)
console.log(`Failed: ${summary.failed}`)
// Download single media
const singleResult = await downloader.downloadSingle(
mediaMessage,
'./downloads',
{ filenameTemplate: '{type}_{date}_{id}{ext}' }
)
// Quick download all (without manager)
await downloadAllMedia(messages, './downloads/all-media', {
types: ['image'],
onProgress: (curr, total) => console.log(`${curr}/${total}`)
})📋 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 (dengan opsi hd: true untuk kualitas HD) |
| video | Kirim video (dengan opsi hd: true untuk kualitas HD) |
| 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 |
| Function | Description |
|----------|-------------|
| updateProfilePicture() | Update foto profil (square crop) |
| updatePanoramaProfilePicture() | Update foto profil panorama (wide, tidak di-crop) |
| removeProfilePicture() | Hapus foto profil |
| profilePictureUrl() | Get URL foto profil |
| Function | Description |
|----------|-------------|
| MiniGamesManager | Main class untuk manage semua games |
| games.startGuessNumber() | Start guess number game |
| games.startQuiz() | Start quiz game |
| games.startTicTacToe() | Start TicTacToe (vs bot/player) |
| games.playRockPaperScissors() | Play RPS game |
| games.rollDice() | Roll dice (1-6) |
| games.flipCoin() | Flip a coin |
| `games.handleGues
