@kangwifi-pro/waliwa
v4.0.0
Published
WhatsApp library based on Baileys 7 + zaileys + baileys-mbuilder. Super lightweight with MessageBuilder, CommandSystem, Automation, Plugin system, Media/Sticker helpers.
Maintainers
Readme
Waliwa
WhatsApp library based on Baileys 7 + zaileys + baileys-mbuilder
Super ringan, fluent API, dengan MessageBuilder, CommandSystem, Automation, dan Plugin system.
Instalasi
npm install @kangwifi-pro/waliwaQuick Start (3 baris)
import { quickStart, MessageHelper } from '@kangwifi-pro/waliwa';
const sock = await quickStart({ authFolder: './auth' });
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const msg of messages) {
if (MessageHelper.isFromMe(msg)) continue;
const text = MessageHelper.getText(msg);
if (text === '!ping') await MessageHelper.reply(sock, msg, 'pong! 🏓');
}
});QR otomatis muncul di terminal. Scan dengan WhatsApp → Settings → Linked Devices.
Auto-reconnect, auto-save credentials, auto-keepalive — semua sudah aktif default.
Fitur Utama
| Modul | Asal | Deskripsi |
|-------|------|-----------|
| Core | Baileys 7 | Koneksi WA Web multi-device, Noise XX, protobuf |
| quickStart() | Waliwa | One-liner setup dengan auto QR, reconnect, save creds |
| MessageBuilder | zaileys | Fluent chaining: .to().text().image().reply().send() |
| ButtonBuilder | baileys-mbuilder | Button interactive messages |
| CarouselBuilder | baileys-mbuilder | Carousel card messages |
| AIRichBuilder | baileys-mbuilder | AI rich response (hyperlink, citation, LaTeX) |
| CommandSystem | zaileys | Command registry + middleware + guards (cooldown, adminOnly) |
| AutoRejectCall | zaileys | Auto-reject incoming calls |
| AutoRead | zaileys | Auto-mark messages as read |
| AutoPresence | zaileys | Auto typing indicator |
| Broadcast | zaileys | Send to multiple recipients dengan delay |
| Scheduler | zaileys | Schedule messages untuk future delivery |
| RateLimiter | zaileys | Per-recipient rate limiting |
| PluginRegistry | zaileys | Modular plugin system dengan definePlugin() |
| MediaHelper | Waliwa | Download, convert, resize (sharp) |
| StickerHelper | Waliwa | Create stickers dari image/video/text (sharp + ffmpeg) |
| MessageHelper | Waliwa | Parse, format, reply utilities |
API
quickStart()
const sock = await quickStart({
authFolder: './auth',
browser: ['Waliwa Bot', 'Chrome', '1.0.0'],
printQRInTerminal: true, // default: true
autoReconnect: true, // default: true
reconnectDelayMs: 5000, // default: 5000
markOnlineOnConnect: true,
syncFullHistory: false
});MessageBuilder
import { MessageBuilder } from '@kangwifi-pro/waliwa';
const builder = new MessageBuilder(sock);
// Text + reply + mentions
await builder.to(jid).text('Hello!').reply(message).mentions(['[email protected]']).send();
// Image
await builder.to(jid).image(buffer, { caption: 'Check this!' }).send();
// Audio (voice note)
await builder.to(jid).audio(buffer, { ptt: true }).send();
// Document
await builder.to(jid).document(buffer, { fileName: 'report.pdf' }).send();
// Sticker
await builder.to(jid).sticker(webpBuffer).send();
// Location
await builder.to(jid).location(-6.2088, 106.8456, { name: 'Jakarta' }).send();
// Contact
await builder.to(jid).contact(vcardString, 'John Doe').send();
// Poll
await builder.to(jid).poll('Pilih makan?', ['Nasi', 'Mie', 'Sate']).send();
// Buttons
await builder.to(jid).text('Choose:').buttons([
{ label: 'Yes', id: 'yes' },
{ label: 'No', id: 'no' }
]).send();
// Carousel
await builder.to(jid).carousel([
{ title: 'Product A', text: '$10', buttons: [{ label: 'Buy', id: 'buy_a' }] },
{ title: 'Product B', text: '$20', buttons: [{ label: 'Buy', id: 'buy_b' }] }
]).send();
// Broadcast ke multiple recipients
await builder.to('dummy').text('Announcement!').broadcast([jid1, jid2, jid3], 2000);
// View once
await builder.to(jid).image(buffer).viewOnce().send();ButtonBuilder
import { ButtonBuilder } from '@kangwifi-pro/waliwa';
const msg = new ButtonBuilder()
.text('Choose an option:')
.button('Yes', 'yes_id')
.button('No', 'no_id')
.footer('Powered by Waliwa')
.build();
await sock.sendMessage(jid, msg);CarouselBuilder
import { CarouselBuilder } from '@kangwifi-pro/waliwa';
const msg = new CarouselBuilder()
.card(c => c.title('Product A').text('$10').button('Buy', 'buy_a'))
.card(c => c.title('Product B').text('$20').button('Buy', 'buy_b'))
.build();
await sock.sendMessage(jid, msg);AIRichBuilder
import { AIRichBuilder } from '@kangwifi-pro/waliwa';
const msg = new AIRichBuilder()
.text('Visit [Google](https://google.com) for details')
.build();
await sock.sendMessage(jid, msg);CommandSystem
import { CommandSystem } from '@kangwifi-pro/waliwa';
const cmd = new CommandSystem(sock, {
prefix: '!',
ownerIds: ['[email protected]']
});
// Simple command
cmd.command('ping', async (ctx) => {
await ctx.reply('pong! 🏓');
});
// With guards
cmd.command('kick', {
adminOnly: true,
cooldown: 5000,
description: 'Kick member dari grup',
aliases: ['remove']
}, async (ctx) => {
// ctx.sender, ctx.jid, ctx.args, ctx.isGroup, ctx.isOwner, ctx.quoted
const target = ctx.mentions[0] || ctx.quoted?.participant;
if (!target) return ctx.reply('Tag atau reply user yang mau di-kick');
await sock.groupParticipantsUpdate(ctx.jid, [target], 'remove');
await ctx.reply(`✅ Kicked ${target}`);
});
// Middleware
cmd.use(async (ctx, next) => {
console.log(`[${ctx.senderName}] ${ctx.fullText}`);
await next();
});
cmd.attach();CommandContext Properties
| Property | Type | Description |
|----------|------|-------------|
| sock | any | Socket instance |
| message | any | Raw WA message |
| jid | string | Chat JID |
| sender | string | Sender JID |
| text | string | Full message text |
| command | string | Command name (tanpa prefix) |
| args | string[] | Arguments |
| isGroup | boolean | Apakah dari grup |
| isFromMe | boolean | Apakah dari bot sendiri |
| isOwner | boolean | Apakah sender adalah owner |
| senderName | string | Nama sender (pushName) |
| quoted | any | Quoted message context |
| mentions | string[] | Mentioned JIDs |
CommandContext Methods
| Method | Description |
|--------|-------------|
| reply(text) | Reply ke message |
| replyWithMedia(buffer) | Reply dengan image |
| react(emoji) | React ke message |
| sendTyping() | Kirim typing indicator |
| sendRecording() | Kirim recording indicator |
| stopTyping() | Stop typing indicator |
CommandOptions
| Option | Type | Description |
|--------|------|-------------|
| adminOnly | boolean | Hanya admin grup |
| ownerOnly | boolean | Hanya owner bot |
| groupOnly | boolean | Hanya bisa di grup |
| privateOnly | boolean | Hanya bisa di DM |
| cooldown | number | Cooldown dalam ms |
| rateLimit | { max, windowMs } | Rate limit per user |
| aliases | string[] | Command aliases |
| description | string | Deskripsi untuk help |
Automation
import { AutoRejectCall, AutoRead, AutoPresence, Broadcast, Scheduler, RateLimiter } from '@kangwifi-pro/waliwa';
// Auto-reject incoming calls
const autoReject = new AutoRejectCall(sock);
autoReject.start();
// Allow specific users
autoReject.allow('[email protected]');
// Auto-read messages (exclude groups)
const autoRead = new AutoRead(sock, { excludeGroups: true });
autoRead.start();
// Auto typing indicator
const autoPresence = new AutoPresence(sock);
autoPresence.start();
// Broadcast
const broadcast = new Broadcast(sock, 2000); // 2s delay
await broadcast.sendText([jid1, jid2, jid3], 'Announcement!');
// Scheduler
const scheduler = new Scheduler(sock);
scheduler.schedule('reminder1', jid, { text: 'Waktunya meeting!' }, 60 * 60 * 1000); // 1 hour
scheduler.cancel('reminder1');
scheduler.list(); // [{ id, jid }]
// Rate limiter
const limiter = new RateLimiter();
limiter.setLimit(jid, 10, 60000); // 10 messages per minute
if (limiter.canSend(jid)) {
await sock.sendMessage(jid, { text: 'Hi!' });
}Plugin System
import { definePlugin, PluginLoader } from '@kangwifi-pro/waliwa';
// plugins/echo.ts
export default definePlugin({
name: 'echo',
version: '1.0.0',
description: 'Echo plugin',
onLoad: (ctx) => console.log('Echo plugin loaded!'),
onMessage: async (msg, ctx) => {
const text = msg.message?.conversation || '';
if (text === '!echo') {
await ctx.sock.sendMessage(msg.key.remoteJid, { text: 'Echo!' });
}
}
});
// Load plugins
const loader = new PluginLoader(sock);
await loader.loadFromDir('./plugins');
loader.getRegistry().list(); // [{ name, version, description }]MediaHelper
import { MediaHelper } from '@kangwifi-pro/waliwa';
// Download dari message
const buffer = await MediaHelper.downloadFromMessage(sock, msg);
// Download dari URL
const buffer = await MediaHelper.downloadFromUrl('https://...');
// Resize (untuk profile picture 640x640)
const resized = await MediaHelper.resizeImage(buffer, 640, 640);
// Convert format
const webp = await MediaHelper.toWebP(buffer);
const jpeg = await MediaHelper.toJPEG(buffer, 80);
// Compress
const compressed = await MediaHelper.compress(buffer, 60);
// Thumbnail
const thumb = await MediaHelper.createThumbnail(buffer, 200);
// Watermark
const watermarked = await MediaHelper.addWatermark(buffer, '© Waliwa');
// Grayscale / blur
const gray = await MediaHelper.grayscale(buffer);
const blurred = await MediaHelper.blur(buffer, 5);StickerHelper
import { StickerHelper } from '@kangwifi-pro/waliwa';
// Dari image
const sticker = await StickerHelper.fromImage(imageBuffer, {
pack: 'My Pack',
author: 'Me',
categories: ['😀']
});
// Dari video (animated)
const animated = await StickerHelper.fromVideo(videoBuffer);
// Dari text
const textSticker = await StickerHelper.fromText('Hello!', {
color: '#ffffff',
backgroundColor: '#000000'
});
// Dari URL
const urlSticker = await StickerHelper.fromUrl('https://...');
// Dari file
const fileSticker = await StickerHelper.fromFile('./image.jpg');
// Send
await sock.sendMessage(jid, { sticker });MessageHelper
import { MessageHelper } from '@kangwifi-pro/waliwa';
// Extract text
const text = MessageHelper.getText(msg);
// Info
MessageHelper.isFromMe(msg);
MessageHelper.isGroupMessage(msg);
MessageHelper.getSender(msg);
MessageHelper.getChat(msg);
MessageHelper.hasMedia(msg);
MessageHelper.getMediaType(msg);
MessageHelper.getMentions(msg);
MessageHelper.getQuoted(msg);
// Parse command
const cmd = MessageHelper.parseCommand(msg, '!');
// { command: 'ping', args: [], fullText: '!ping' }
// Actions
await MessageHelper.reply(sock, msg, 'Hello!');
await MessageHelper.sendText(sock, jid, 'Hi!', { mentions: [...] });
await MessageHelper.mentionAll(sock, groupJid);
await MessageHelper.react(sock, msg, '👍');
await MessageHelper.markAsRead(sock, msg.key);
await MessageHelper.sendTyping(sock, jid);
await MessageHelper.stopTyping(sock, jid);
await MessageHelper.delete(sock, msg);
await MessageHelper.forward(sock, toJid, msg);Events
sock.ev.on('connection.update', (update) => {
// update.connection: 'connecting' | 'open' | 'close'
// update.qr: string (QR code)
// update.lastDisconnect: { error, output }
});
sock.ev.on('messages.upsert', ({ messages, type }) => {
// type: 'notify' (new) | 'append' (history)
});
sock.ev.on('messages.update', (updates) => {
// Status updates: sent, delivered, read
});
sock.ev.on('message-receipt.update', (updates) => {
// Delivery/read receipts
});
sock.ev.on('presence.update', ({ id, presences }) => {
// Presence: available, unavailable, composing, recording
});
sock.ev.on('chats.upsert', (chats) => {});
sock.ev.on('chats.update', (chats) => {});
sock.ev.on('contacts.upsert', (contacts) => {});
sock.ev.on('groups.upsert', (groups) => {});
sock.ev.on('groups.update', (groups) => {});
sock.ev.on('group-participants.update', (update) => {
// update.action: 'add' | 'remove' | 'promote' | 'demote'
});
sock.ev.on('call', (calls) => {});
sock.ev.on('creds.update', () => saveCreds());Reconnect Behavior
| Status Code | Reason | Reconnect? | |-------------|--------|------------| | 515 | Restart required | ✅ Ya | | 428 | Connection closed | ✅ Ya | | 440 | Connection replaced | ✅ Ya | | 500 | Server error | ✅ Ya | | 401 | Logged out | ❌ Tidak (clear auth folder) |
Auto-reconnect default aktif dengan delay 5 detik.
Dependencies
| Package | Purpose |
|---------|---------|
| @whiskeysockets/baileys | Core WA protocol |
| @hapi/boom | Error handling |
| pino + pino-pretty | Logging |
| qrcode-terminal | QR display |
| axios | HTTP requests |
| mime-types | MIME detection |
| sharp | Image processing |
| fluent-ffmpeg + @ffmpeg-installer/ffmpeg | Video/sticker processing |
License
MIT
