whatsapp-hybrid-gateway/SETUPVPS.md

12 KiB
Raw Permalink Blame History

Setup Bot WhatsApp di Ubuntu VPS - Step by Step

1. Update Sistem & Install Dependencies

# Update package list dan upgrade sistem
apt update && apt upgrade -y

# Install curl, wget, dan tools penting lainnya
apt install -y curl wget git unzip software-properties-common build-essential

# Install Node.js versi terbaru (LTS)
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
apt install -y nodejs

# Verifikasi instalasi
node --version
npm --version
# Buat user baru
adduser botuser

# Tambahkan ke grup sudo
usermod -aG sudo botuser

# Switch ke user baru
su - botuser

3. Setup Project Bot WhatsApp

# Buat direktori project
mkdir ~/whatsapp-bot
cd ~/whatsapp-bot

# Inisialisasi npm project
npm init -y

# Install dependencies
npm install @whiskeysockets/baileys qrcode-terminal

# Buat struktur folder
mkdir session
mkdir logs

4. Buat File Bot

Buat file bot.js:

nano bot.js

Copy paste kode berikut:

const { default: makeWASocket, DisconnectReason, useMultiFileAuthState } = require('@whiskeysockets/baileys')
const fs = require('fs')

// Fungsi untuk log dengan timestamp
function log(message) {
    const timestamp = new Date().toISOString()
    const logMessage = `[${timestamp}] ${message}`
    console.log(logMessage)
    
    // Simpan ke file log
    fs.appendFileSync('./logs/bot.log', logMessage + '\n')
}

async function startBot() {
    try {
        // Setup authentikasi
        const { state, saveCreds } = await useMultiFileAuthState('./session')
        
        // Buat koneksi WhatsApp
        const sock = makeWASocket({
            auth: state,
            printQRInTerminal: true,
            browser: ['Bot WhatsApp', 'Chrome', '1.0.0']
        })
        
        // Event ketika koneksi berubah
        sock.ev.on('connection.update', async (update) => {
            const { connection, lastDisconnect, qr } = update
            
            if (qr) {
                log('📱 QR Code generated! Scan dengan WhatsApp Anda.')
            }
            
            if (connection === 'close') {
                const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut
                log(<>Œ Koneksi terputus: ${lastDisconnect?.error?.output?.statusCode}`)
                
                if (shouldReconnect) {
                    log('🔄 Mencoba reconnect dalam 5 detik...')
                    setTimeout(() => startBot(), 5000)
                } else {
                    log('ðŸ”<C5B8> Bot logout. Perlu scan QR lagi.')
                }
            } else if (connection === 'open') {
                log('✅ Bot WhatsApp berhasil terhubung!')
                
                // Kirim pesan ke diri sendiri sebagai test
                const myNumber = sock.user?.id
                if (myNumber) {
                    await sock.sendMessage(myNumber, { 
                        text: '🤖 Bot WhatsApp berhasil online!\n\nBot siap menerima pesan.' 
                    })
                }
            }
        })
        
        // Simpan kredensial ketika berubah
        sock.ev.on('creds.update', saveCreds)
        
        // Event ketika ada pesan masuk
        sock.ev.on('messages.upsert', async (messageUpdate) => {
            try {
                const messages = messageUpdate.messages
                
                for (const message of messages) {
                    // Skip pesan dari bot sendiri
                    if (message.key.fromMe) continue
                    
                    // Skip status updates
                    if (message.key.remoteJid === 'status@broadcast') continue
                    
                    // Ambil informasi pesan
                    const text = message.message?.conversation || 
                               message.message?.extendedTextMessage?.text || ''
                    
                    if (!text) continue
                    
                    const sender = message.key.remoteJid
                    const senderName = message.pushName || 'Unknown'
                    const isGroup = sender.endsWith('@g.us')
                    
                    log(`📩 Pesan ${isGroup ? 'grup' : 'pribadi'} dari ${senderName}: ${text}`)
                    
                    // Handle pesan
                    await handleMessage(sock, sender, text.toLowerCase().trim(), senderName, isGroup)
                }
            } catch (error) {
                log(<>Œ Error processing messages: ${error.message}`)
            }
        })
        
        return sock
        
    } catch (error) {
        log(<>Œ Error starting bot: ${error.message}`)
        log('🔄 Restart bot dalam 10 detik...')
        setTimeout(() => startBot(), 10000)
    }
}

// Fungsi untuk menangani pesan
async function handleMessage(sock, sender, message, senderName, isGroup) {
    try {
        let response = ''
        
        // Perintah bot
        switch (message) {
            case '/start':
            case '/help':
                response = `🤖 *Bot WhatsApp Server*\n\n` +
                          `Halo ${senderName}! Bot berjalan di Ubuntu VPS.\n\n` +
                          `*Perintah tersedia:*\n` +
                          `🆘 /help - Menu bantuan\n` +
                          <>° /time - Waktu server\n` +
                          `📊 /status - Status server\n` +
                          `🎲 /random - Angka random\n` +
                          `ðŸ“<C5B8> /ping - Test koneksi\n` +
                          `ℹï¸<C3AF> /info - Info bot`
                break
                
            case '/time':
                const now = new Date().toLocaleString('id-ID', { 
                    timeZone: 'Asia/Jakarta',
                    dateStyle: 'full',
                    timeStyle: 'medium'
                })
                response = <>° *Waktu Server*\n${now}\n\nðŸ“<C5B8> Timezone: Asia/Jakarta (WIB)`
                break
                
            case '/status':
                const uptime = process.uptime()
                const uptimeFormatted = Math.floor(uptime / 3600) + 'h ' + 
                                     Math.floor((uptime % 3600) / 60) + 'm ' + 
                                     Math.floor(uptime % 60) + 's'
                
                const memUsage = process.memoryUsage()
                const memUsed = Math.round(memUsage.heapUsed / 1024 / 1024)
                
                response = `📊 *Status Server*\n\n` +
                          `🟢 Status: Online\n` +
                          <>±ï¸<C3AF> Uptime: ${uptimeFormatted}\n` +
                          `💾 Memory: ${memUsed} MB\n` +
                          `ðŸ¥ï¸<C3AF> OS: Ubuntu 24.04 LTS\n` +
                          `âš¡ Node.js: ${process.version}`
                break
                
            case '/ping':
                const startTime = Date.now()
                response = `ðŸ<C3B0>“ *Pong!*\n\nâš¡ Latency: ${Date.now() - startTime}ms\n🟢 Bot responsive`
                break
                
            case '/random':
                const randomNum = Math.floor(Math.random() * 100) + 1
                response = `🎲 *Random Number*\n\nAngka untuk ${senderName}: *${randomNum}*`
                break
                
            case '/info':
                response = `ℹï¸<C3AF> *Bot Information*\n\n` +
                          `🤖 Bot WhatsApp Server\n` +
                          `ðŸ¥ï¸<C3AF> Platform: Ubuntu VPS\n` +
                          `📡 API: Baileys WhatsApp\n` +
                          `âš¡ Runtime: Node.js\n` +
                          `🔧 Status: Production Ready\n` +
                          `📅 Started: ${new Date().toLocaleDateString('id-ID')}`
                break
                
            default:
                // Auto-reply untuk pesan umum
                if (message.includes('halo') || message.includes('hai') || message.includes('hello')) {
                    response = `👋 Halo ${senderName}!\n\nBot berjalan dari Ubuntu VPS. Ketik /help untuk melihat perintah tersedia.`
                } else if (message.includes('bot')) {
                    response = `🤖 Ya, saya bot WhatsApp yang berjalan di server Ubuntu!\n\nKetik /help untuk menu lengkap.`
                } else if (message.includes('terima kasih') || message.includes('thanks')) {
                    response = `ðŸ™<C5B8> Sama-sama ${senderName}! Senang bisa membantu.`
                } else {
                    // Respon default dengan rate limiting
                    if (!isGroup) { // Hanya reply di chat pribadi
                        response = `ðŸ“<C5B8> Pesan diterima: "${message}"\n\n✨ Ketik /help untuk melihat perintah yang tersedia!`
                    }
                }
        }
        
        // Kirim respon (jika ada)
        if (response) {
            // Delay untuk avoid spam detection
            await new Promise(resolve => setTimeout(resolve, 1000))
            
            await sock.sendMessage(sender, { text: response })
            log(`✅ Respon terkirim ke ${senderName}`)
        }
        
    } catch (error) {
        log(<>Œ Error handling message: ${error.message}`)
        
        // Kirim pesan error ke user
        try {
            await sock.sendMessage(sender, { 
                text: 'âš ï¸<C3AF> Terjadi error saat memproses pesan. Tim teknis sudah diberitahu.' 
            })
        } catch (sendError) {
            log(<>Œ Error sending error message: ${sendError.message}`)
        }
    }
}

// Graceful shutdown
process.on('SIGINT', () => {
    log('🛑 Bot dihentikan oleh user (SIGINT)')
    process.exit(0)
})

process.on('SIGTERM', () => {
    log('🛑 Bot dihentikan oleh sistem (SIGTERM)')
    process.exit(0)
})

// Handle unhandled errors
process.on('uncaughtException', (error) => {
    log(`💥 Uncaught Exception: ${error.message}`)
    log('🔄 Restarting bot...')
    setTimeout(() => startBot(), 5000)
})

process.on('unhandledRejection', (error) => {
    log(`💥 Unhandled Rejection: ${error.message}`)
})

// Mulai bot
log('🚀 Starting WhatsApp Bot on Ubuntu VPS...')
startBot()

Simpan dengan Ctrl+X, lalu Y, lalu Enter.

5. Install PM2 untuk Production

# Install PM2 globally
sudo npm install -g pm2

# Buat file konfigurasi PM2
nano ecosystem.config.js

Isi file ecosystem.config.js:

module.exports = {
  apps: [{
    name: 'whatsapp-bot',
    script: 'bot.js',
    instances: 1,
    autorestart: true,
    watch: false,
    max_memory_restart: '500M',
    error_file: './logs/err.log',
    out_file: './logs/out.log',
    log_file: './logs/combined.log',
    time: true,
    env: {
      NODE_ENV: 'production'
    }
  }]
}

6. Menjalankan Bot

# Test jalankan sekali untuk scan QR
node bot.js

# Setelah berhasil scan QR, hentikan dengan Ctrl+C
# Lalu jalankan dengan PM2
pm2 start ecosystem.config.js

# Lihat status
pm2 status

# Lihat logs real-time
pm2 logs whatsapp-bot

# Auto-start saat server restart
pm2 startup
pm2 save
# Enable UFW firewall
sudo ufw enable

# Allow SSH
sudo ufw allow ssh

# Allow specific ports jika perlu
# sudo ufw allow 3000/tcp

# Check status
sudo ufw status

8. Monitoring dan Maintenance

# Restart bot
pm2 restart whatsapp-bot

# Stop bot
pm2 stop whatsapp-bot

# Delete bot dari PM2
pm2 delete whatsapp-bot

# Monitor resource usage
pm2 monit

# View logs
pm2 logs whatsapp-bot --lines 100

# Rotate logs
pm2 install pm2-logrotate

9. Backup Session (Penting!)

# Buat backup session
tar -czf session-backup.tar.gz session/

# Restore session
tar -xzf session-backup.tar.gz

10. Troubleshooting

Jika QR Code tidak muncul:

# Install font untuk QR display
sudo apt install fonts-liberation2

# Atau gunakan external QR generator
npm install qrcode

Jika ada masalah permission:

# Fix ownership
sudo chown -R botuser:botuser ~/whatsapp-bot

# Fix permissions
chmod +x bot.js

Jika bot crash terus:

# Check logs
pm2 logs whatsapp-bot

# Clear session dan scan ulang
rm -rf session/*
pm2 restart whatsapp-bot

✅ Checklist Setup

  • Update Ubuntu & install dependencies
  • Install Node.js & npm
  • Buat project directory
  • Copy kode bot
  • Install PM2
  • Test run bot & scan QR
  • Setup PM2 production
  • Enable auto-restart
  • Backup session

Bot WhatsApp Anda siap production di Ubuntu VPS! 🎉