const {
default: makeWASocket,
DisconnectReason,
useMultiFileAuthState,
fetchLatestBaileysVersion
} = require('@whiskeysockets/baileys');
const QRCode = require('qrcode-terminal');
const qrcode = require('qrcode');
const axios = require('axios');
const crypto = require('crypto'); // TAMBAHIN INI
const fs = require('fs');
const express = require('express');
const pino = require('pino');
const app = express();
const PORT = process.env.PORT || 7860;
const HF_TOKEN = process.env.HF_TOKEN || 'hf_LMbsGCSfszThllrjJzi';
let sock = null;
let qrCodeData = null;
let pairingCode = null;
let status = 'connecting';
// Web UI
app.get('/', async (req, res) => {
// Kalau connected
if (status === 'connected') {
res.send(`
ā
Bot Connected!
Siap menerima pesan WhatsApp
`);
return;
}
// Kalau ada pairing code
if (pairingCode) {
res.send(`
š¢ Pairing Code
${pairingCode}
Cara pakai:
- Buka WhatsApp
- Menu ā Linked Devices
- Link with phone number
- Masukin kode di atas
Atau tunggu QR code di bawah...
`);
return;
}
// Kalau ada QR
if (qrCodeData) {
const qr = await qrcode.toDataURL(qrCodeData);
res.send(`
š· Scan QR Code
WhatsApp ā Menu ā Linked Devices ā Scan
`);
return;
}
// Loading
res.send(`
ā³ Status: ${status}
Menyiapkan koneksi...
Refresh dalam 5 detik
`);
});
app.listen(PORT, () => console.log(`š Web: http://localhost:${PORT}`));
// Bot
async function startBot() {
console.log('š Starting bot...');
const { state, saveCreds } = await useMultiFileAuthState('./auth');
const { version } = await fetchLatestBaileysVersion();
sock = makeWASocket({
version,
logger: pino({ level: 'silent' }),
printQRInTerminal: true,
auth: state,
browser: ['Ubuntu', 'Chrome', '20.0.04'],
});
// Pairing code (dengan error handling)
if (!state.creds.registered) {
setTimeout(async () => {
try {
// Coba pairing code
const code = await sock.requestPairingCode('6282117207534'); // GANTI NOMOR!
pairingCode = code;
console.log('\nš¢ PAIRING CODE:', code);
console.log('š Masukin ke WhatsApp ā Linked Devices ā Link with phone number\n');
} catch (e) {
console.log('ā ļø Pairing code gagal, pake QR aja');
console.log('š Tunggu QR code muncul...\n');
// QR akan muncul otomatis di event connection.update
}
}, 3000);
}
sock.ev.on('connection.update', async (update) => {
const { connection, lastDisconnect, qr } = update;
if (qr) {
qrCodeData = qr;
status = 'qr_ready';
console.log('\nš„ QR CODE READY');
console.log('š Scan pakai WhatsApp\n');
QRCode.generate(qr, { small: true });
}
if (connection === 'open') {
status = 'connected';
qrCodeData = null;
pairingCode = null;
console.log('\nā
CONNECTED!');
console.log('š± Bot siap dipake\n');
try {
await sock.sendMessage(sock.user.id, {
text: 'š¤ *Bot Aktif!*\n\nKetik !help untuk bantuan'
});
} catch (e) {}
}
else if (connection === 'close') {
const statusCode = lastDisconnect?.error?.output?.statusCode;
const shouldReconnect = statusCode !== DisconnectReason.loggedOut;
console.log('\nā Disconnected:', statusCode);
status = 'disconnected';
qrCodeData = null;
pairingCode = null;
if (shouldReconnect) {
console.log('š Reconnecting in 5s...\n');
setTimeout(startBot, 5000);
}
}
});
sock.ev.on('creds.update', saveCreds);
sock.ev.on('messages.upsert', async ({ messages, type }) => {
if (type !== 'notify') return;
const msg = messages[0];
if (!msg.message || msg.key.fromMe) return;
const sender = msg.key.remoteJid;
const text = msg.message.conversation || msg.message.extendedTextMessage?.text || '';
if (!text.startsWith('!')) return;
const cmd = text.slice(1).split(' ')[0].toLowerCase();
const args = text.slice(1).split(' ').slice(1).join(' ');
if (cmd === 'ai' && args) {
await sock.sendMessage(sender, { text: 'ā³ AI mikir...' });
try {
const res = await axios.post(
'/static-proxy?url=https%3A%2F%2Fapi-inference.huggingface.co%2Fmodels%2Fmistralai%2FMistral-7B-Instruct-v0.2',
{ inputs: `[INST] ${args} [/INST]`, parameters: { max_new_tokens: 500 } },
{ headers: { 'Authorization': `Bearer ${HF_TOKEN}` }, timeout: 30000 }
);
let reply = res.data[0]?.generated_text || 'Gagal';
reply = reply.replace(/\[INST\].*?\[\/INST\]\s*/, '');
await sock.sendMessage(sender, { text: reply.substring(0, 1000) });
} catch (e) {
await sock.sendMessage(sender, { text: 'ā AI sibuk, coba lagi' });
}
}
else if (cmd === 'help') {
await sock.sendMessage(sender, { text: '!ai [tanya] - Tanya AI\n!status - Cek status' });
}
else if (cmd === 'status') {
await sock.sendMessage(sender, { text: `Status: ${status}` });
}
});
}
startBot();