@aldy11/rekber-bot
v1.3.0
Published
Modifikasi @whiskeysockets/baileys untuk bot rekber (escrow) WhatsApp. Fitur: LID Converter otomatis, rate limiter, auto-reconnect, timeout manager, persistent storage, ESM+CJS.
Maintainers
Readme
🏦 @aldy11/rekber-bot
Modifikasi @whiskeysockets/baileys untuk bot rekening bersama (rekber/escrow) WhatsApp dengan LID Converter otomatis.
✨ Fitur Utama
| Fitur | Keterangan |
|---|---|
| 🔗 LID Converter | Konversi LID ↔ JID ↔ Phone dari sumber manapun secara otomatis |
| 🏦 Rekber Engine | Sistem escrow lengkap dengan status PENDING → DONE |
| 🔘 Interactive Msg | Button, List, Carousel, Copy, Call, Location — support WA versi terbaru |
| 💾 Database Support | JSON (default), MongoDB, SQLite, MySQL — pluggable adapter |
| 🤖 Bot Commands | Command !rekber, !bayar, !terima, dll siap pakai |
| 🔄 Auto-patch | LID otomatis diisi dari semua event Baileys |
| 🧪 Unit Tested | 45 test semua lulus |
📦 Instalasi
# Clone atau copy folder ini
npm installAtau jika dipublish ke npm:
npm install @aldy11/rekber-bot🚀 Quick Start
const { createRekberBot } = require('@aldy11/rekber-bot')
;(async () => {
const { sock } = await createRekberBot({
sessionDir: './auth_info',
dataDir: './rekber-data',
adminPhone: '628123456789', // nomor admin/mediator
prefix: '!',
feePercent: 0, // fee 0% = gratis
})
sock.ev.on('connection.update', ({ connection }) => {
if (connection === 'open') console.log('Bot online!')
})
})()Jalankan:
node example/bot.js
# atau
npm start🔑 Custom Pairing Code
Anda bisa menentukan pairing code sendiri (8 karakter) alih-alih mendapatkan kode random:
const { sock } = await createRekberBot({
usePairingCode: true,
phoneNumber: '628123456789',
customPairingCode: 'ABCD1234', // tepat 8 karakter
})Atau via .env:
USE_PAIRING_CODE=true
PHONE_NUMBER=628123456789
CUSTOM_PAIRING_CODE=ABCD1234Catatan: Custom pairing code harus tepat 8 karakter. Jika dikosongkan, Baileys akan generate kode random secara otomatis.
🔗 LID Converter
LID (Linked Device ID) adalah ID baru WhatsApp yang dipakai untuk privasi nomor telepon. Package ini mengkonversi LID secara otomatis dari:
- Event kontak (
contacts.upsert,contacts.update) - Pesan masuk (
messages.upsert,key.participant,key.participantLid) - Update grup (
group-participants.update) - Manual (
register,registerBatch,registerFromContact)
Cara Pakai LidConverter
const { LidConverter } = require('@aldy11/rekber-bot')
const conv = new LidConverter()
// ── Normalisasi input apapun ──────────────────────────────
LidConverter.normalize('081234567890') // → [email protected]
LidConverter.normalize('lid:123456789') // → 123456789:0@lid
LidConverter.normalize('[email protected]') // → [email protected]
// ── Register mapping ──────────────────────────────────────
conv.register('111111:0@lid', '[email protected]')
conv.registerFromContact({ id: '[email protected]', lid: '222:0@lid', name: 'Budi' })
conv.registerBatch(contacts) // array kontak dari Baileys
// ── Konversi ──────────────────────────────────────────────
conv.lidToJid('111111:0@lid') // → [email protected]
conv.jidToLid('[email protected]') // → 111111:0@lid
conv.lidToPhone('111111:0@lid') // → 6281111111111
conv.phoneToLid('6281111111111') // → 111111:0@lid
// ── Resolve dari input APAPUN ─────────────────────────────
conv.resolveToJid('081111111111') // → [email protected]
conv.resolveToJid('111111:0@lid') // → [email protected]
conv.resolveToJid('[email protected]') // → [email protected]
conv.resolveAll('111111:0@lid')
// → { jid, lid, phone, name, isResolved }Patch Manual ke Socket Baileys
const { makeWASocket, patchBaileysSock } = require('@aldy11/rekber-bot')
const sock = makeWASocket({ ... })
patchBaileysSock(sock, { debug: true })
// Setelah patch, socket punya method tambahan:
sock.resolveJid('081234567890') // → JID
sock.resolveSender(msg) // → JID sender (support LID participant)
sock.resolveAll('lid:12345') // → { jid, lid, phone, name }
sock.lidConverter // → instance LidConverter🏦 Sistem Rekber
Flow Status Transaksi
PENDING → AGREED → PAID → CONFIRMED → DONE
↓ ↓
CANCELLED DISPUTED → REFUNDEDCommand Bot
Prefix default: ! — bisa diganti di config, atau dikosongkan untuk mode tanpa prefix.
// Dengan prefix (default)
prefix: '!' // → !rekber, !help, !bayar ...
prefix: '.' // → .rekber, .help, .bayar ...
// Tanpa prefix
prefix: '' // → rekber, help, bayar ...| Command | Keterangan |
|---|---|
| rekber @seller 500000 Beli item | Buat transaksi rekber baru |
| rekber 628xxx 500000 Beli item | Dengan nomor telepon |
| rekber lid:12345 500000 Beli item | Dengan LID |
| setuju RKB-XXXXX | Setujui transaksi |
| bayar RKB-XXXXX bukti-transfer | Konfirmasi pembayaran |
| terima RKB-XXXXX | Konfirmasi barang diterima |
| selesai RKB-XXXXX | Finalisasi (dana dilepas) |
| sengketa RKB-XXXXX alasan | Buka sengketa |
| batal RKB-XXXXX alasan | Batalkan transaksi |
| cektx RKB-XXXXX | Lihat info transaksi |
| txsaya | Daftar transaksi aktif saya |
| ceklid lid:12345 | Resolve LID/JID/nomor |
| help | Tampilkan bantuan |
Catatan: Pada mode tanpa prefix, bot hanya merespon kata-kata yang dikenali sebagai command. Pesan biasa tidak akan diproses.
Contoh Output Bot
╔══ 🏦 REKBER ══╗
║ ID: `RKB-M5X1A2BC-0001`
║ Status: 💸 PAID
╠═══════════════╣
║ 👤 Buyer : @628111xxxxxx
║ 🏪 Seller : @628222xxxxxx
╠═══════════════╣
║ 📦 Item : Akun Mobile Legends
║ 💰 Nominal: Rp 500.000
╠═══════════════╣
║ 🤝 Buyer setuju : ✅
║ 🤝 Seller setuju: ✅
║ 🧾 Bukti: ref-BCA-12345
╚══════════════════╝💻 RekberManager (Programmatic)
const { RekberManager, LidConverter } = require('@aldy11/rekber-bot')
const conv = new LidConverter()
const mgr = new RekberManager(conv, {
feePercent: 1, // 1% fee
feeFixed: 2500, // + Rp 2.500
adminJid: '[email protected]',
})
// Buat transaksi - bisa pakai LID, JID, atau nomor telepon
const tx = mgr.create({
buyer: 'lid:111111', // LID
seller: '[email protected]', // JID
amount: 500000,
desc: 'Akun Mobile Legends',
})
// Event listener
mgr.on('created', tx => console.log('Dibuat:', tx.id))
mgr.on('paid', tx => console.log('Bayar masuk:', tx.id))
mgr.on('completed', tx => console.log('Selesai:', tx.id))
// Flow transaksi
mgr.agree(tx.id, buyerJid)
mgr.agree(tx.id, sellerJid)
mgr.confirmPayment(tx.id, buyerJid, 'bukti-transfer')
mgr.confirmReceived(tx.id, buyerJid)
mgr.complete(tx.id, buyerJid)
// Format output
console.log(mgr.formatTx(tx.id))💾 Storage (Persistent)
const { RekberStorage } = require('@aldy11/rekber-bot')
const storage = new RekberStorage('./rekber-data')
// Attach ke manager (auto save + restore)
storage.attachToManager(rekberBot.rekber)
// Manual backup
storage.backup()
// Hapus TX lama > 30 hari
storage.cleanup(30)
// Statistik
console.log(await storage.getStats())
// { adapter: 'json', totalTransactions: 42, lidMappings: 150, dataDir: '/path/...' }🗄️ Database Adapter
Secara default, data disimpan di file JSON lokal. Tapi kamu bisa pakai database lain dengan adapter yang sudah disediakan:
| Adapter | Package | Install |
|---|---|---|
| JsonAdapter | — (built-in) | Tidak perlu install |
| MongoAdapter | mongodb | npm install mongodb |
| SqliteAdapter | better-sqlite3 | npm install better-sqlite3 |
| MysqlAdapter | mysql2 | npm install mysql2 |
MongoDB
const { createRekberBot, MongoAdapter } = require('@aldy11/rekber-bot')
const storage = new MongoAdapter('mongodb://localhost:27017', 'rekber-bot')
const { sock } = await createRekberBot({
storage,
// ... opsi lain
})SQLite
const { createRekberBot, SqliteAdapter } = require('@aldy11/rekber-bot')
const storage = new SqliteAdapter('./rekber.db')
const { sock } = await createRekberBot({
storage,
// ... opsi lain
})MySQL / MariaDB
const { createRekberBot, MysqlAdapter } = require('@aldy11/rekber-bot')
const storage = new MysqlAdapter({
host: 'localhost',
user: 'root',
password: 'password',
database: 'rekber_bot'
})
const { sock } = await createRekberBot({
storage,
// ... opsi lain
})Custom Adapter
Kamu bisa buat adapter sendiri dengan meng-extend StorageAdapter:
const { StorageAdapter } = require('@aldy11/rekber-bot')
class RedisAdapter extends StorageAdapter {
async init() { /* koneksi Redis */ }
async close() { /* tutup koneksi */ }
async loadTransactions() { /* load dari Redis */ }
async saveSingleTransaction() { /* save ke Redis */ }
// ... implementasi method lainnya
}Method Umum Semua Adapter
// Statistik
console.log(await storage.getStats())
// Cari transaksi
const pending = await storage.findTransactions({ status: 'PENDING' })
const myTx = await storage.findTransactions({ buyer: '[email protected]' })
// Ambil satu transaksi
const tx = await storage.getTransaction('RKB-XXXXX')
// Cleanup TX lama > 30 hari
await storage.cleanup(30)
// Tutup koneksi (untuk Mongo/MySQL)
await storage.close()🔘 Interactive Message (Button, List, Carousel, dll)
Fitur buttonsMessage, listMessage, templateMessage lama sudah diblokir di WhatsApp versi terbaru. Package ini menyediakan InteractiveBuilder yang menggunakan format interactiveMessage + nativeFlowMessage yang didukung penuh di semua versi WA saat ini.
Tipe Button yang Didukung
| Tipe | Method | Keterangan |
|---|---|---|
| Quick Reply | addReplyButton(text, id) | Tombol balasan cepat |
| URL / Link | addUrlButton(text, url) | Buka link di browser |
| Copy Code | addCopyButton(text, copyCode) | Salin teks ke clipboard |
| Call / Telepon | addCallButton(text, phone) | Tombol telepon |
| Location Request | addLocationRequest(text) | Minta user kirim lokasi |
| Address | addAddressButton(text) | Minta user kirim alamat |
| List Menu | addListMenu(title, sections) | Popup menu pilihan |
| Custom / Raw | addRawButton(name, params) | Tipe button custom |
Contoh Lengkap
const { InteractiveBuilder } = require('@aldy11/rekber-bot')
// 1. Builder biasa (semua tipe tombol)
const builder = new InteractiveBuilder('Judul', 'Isi pesan', 'Footer')
.addReplyButton('Ping', '!ping')
.addUrlButton('Website', 'https://github.com')
.addCopyButton('Salin Kode', 'PROMO2024')
.addCallButton('Hubungi Admin', '+6281234567890')
.addLocationRequest('Kirim Lokasi')
.addListMenu('Pilih Menu', [
{
title: 'Kategori 1',
rows: [
{ title: 'Item 1', id: 'cmd_1', description: 'Deskripsi' }
]
}
])
// Kirim pakai sock.sendInteractive (cara termudah)
await sock.sendInteractive(chatJid, builder)
// Atau manual via relayMessage
const msg = builder.buildForRelay(chatJid)
await sock.relayMessage(chatJid, msg.message, { messageId: msg.key.id })Static Factory (Shortcut)
// Quick buttons
const b = InteractiveBuilder.buttons('Pilih:', [
{ text: 'Ya', id: 'yes' },
{ text: 'Tidak', id: 'no' }
], { header: 'Konfirmasi' })
// List
const l = InteractiveBuilder.list('Pilih layanan:', 'Lihat Menu', sections)
// URL
const u = InteractiveBuilder.url('Kunjungi website kami', 'Buka', 'https://...')
// Copy
const c = InteractiveBuilder.copy('Kode promo kamu:', 'Salin', 'DISKON50')Carousel (Kartu Swipe)
const { CarouselBuilder } = require('@aldy11/rekber-bot')
const carousel = new CarouselBuilder()
carousel.createCard('Akun Game', 'Jual beli akun aman', 'Mulai Rp 50k')
.addReplyButton('Beli', '!rekber')
.addUrlButton('Katalog', 'https://...')
carousel.createCard('Top Up', 'Diamond & voucher', 'Termurah')
.addReplyButton('Pesan', '!rekber')
.addCopyButton('Salin Promo', 'DISKON20')
await sock.sendInteractive(chatJid, carousel)Menangkap Response dari Button/List
const { InteractiveResponseParser } = require('@aldy11/rekber-bot')
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const msg of messages) {
const response = InteractiveResponseParser.parse(msg)
if (response) {
console.log(response.type) // 'button_reply' | 'list_reply' | 'native_flow'
console.log(response.id) // ID yang dipilih user
console.log(response.title) // Teks yang dipilih
}
}
})🧪 Menjalankan Test
npm test
# atau
node test/test.jsHasil: 45 passed, 0 failed
🎉 Semua test berhasil!📁 Struktur File
@aldy11/rekber-bot/
├── index.js ← Entry point & factory
├── package.json
├── src/
│ ├── lid/
│ │ └── LidConverter.js ← Konverter LID utama
│ ├── patches/
│ │ └── patchBaileysSock.js ← Inject ke Baileys socket
│ ├── rekber/
│ │ ├── RekberManager.js ← Engine transaksi rekber
│ │ └── RekberBot.js ← Handler command WhatsApp
│ └── utils/
│ ├── helpers.js ← Utility functions
│ └── RekberStorage.js ← Persistent storage
├── example/
│ └── bot.js ← Contoh bot siap pakai
└── test/
└── test.js ← Unit tests (45 test)📝 Lisensi
MIT — bebas digunakan dan dimodifikasi.
