engine-whatsapp adalah WhatsApp gateway ekosistem Dazo — jembatan antara akun WhatsApp dan backend Dazo. Service ini mengelola sesi login (QR), mengirim pesan/media/lokasi, menerima pesan masuk, lalu meneruskannya ke backend via webhook dan ke frontend via Socket.IO secara realtime.
Dibangun dengan Baileys (multi-device, tanpa browser), Express 5, MongoDB, dan Socket.IO. Satu proses Node dapat menjalankan banyak sesi WhatsApp sekaligus (single process, multi-device).
Peran di ekosistem
| Aspek | Penjelasan |
|---|---|
| Identitas | Package engine-whatsapp, repo engine-whatsapp |
| Posisi | Antara akun WhatsApp (via Baileys) dan backend-go/dazoapp/frontend |
| Tenant | instanceId (UUID per device) — bukan store_id sebagai identitas utama |
| Datastore | MongoDB (DB dazo lokal / remote) untuk data device dan riwayat chat |
| Sesi | Kredensial Baileys persisten di filesystem (session/auth/<instanceId>), bukan MongoDB |
| Realtime | Socket.IO — event QR, status device, pesan masuk, status ACK |
| Auth | ❌ Tidak ada — semua endpoint public |
| Bahasa | TypeScript ESM |
Arsitektur
┌──────────────────────────────┐
WhatsApp ◄───►│ Baileys (WhatsAppService) │
│ sesi per instanceId (UUID) │
└───────────┬──────────────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌──────────────────┐ ┌────────────────┐
│ REST API │ │ Webhook │ │ Socket.IO │
│ /api/* │ │ → Backend Dazo │ │ → Frontend │
└───────────────┘ └──────────────────┘ └────────────────┘
│
▼
┌────────────────┐
│ MongoDB │
└────────────────┘Tiga jalur keluar-masuk data:
| Jalur | Arah | Kegunaan |
|---|---|---|
REST API (/api/*) | Backend → Engine | Perintah: buat sesi, kirim pesan, kelola grup, relay notif |
| Webhook | Engine → Backend | Lapor pesan masuk & perubahan status pesan (POST {WEBHOOK_URL}/callback_message) |
| Socket.IO | Engine → Frontend | Realtime: QR, status device, bubble chat, notifikasi |
Alur utama
- Login — Client hit
POST /api/new, engine membuat socket Baileys, QR dikirim realtime lewat eventqrcode. - Pesan masuk — Baileys
messages.upsert→ media diunduh kepublic/files→ payload dikirim ke webhook backend → hasil di-emit ke frontend. - Pesan keluar — Backend hit
POST /api/send-message→ Baileys kirim → status ACK dipantau lewatmessages.update→ diteruskan ke webhook + socket. - Persistensi — Kredensial sesi disimpan di filesystem (
session/auth/<instanceId>), bukan di MongoDB. MongoDB dipakai untuk data device dan riwayat chat.
Stack teknologi
| Lapisan | Teknologi | Versi |
|---|---|---|
| Runtime | Node.js | diuji v20–v23 (disarankan ≥ 20) |
| Bahasa | TypeScript | 5.9.3 (ESM) |
| Web framework | Express | 5.2.1 |
| WhatsApp engine | @whiskeysockets/baileys | 7.0.0-rc.9 |
| Realtime | Socket.IO | 4.8.3 |
| Database | MongoDB via Mongoose | 9.1.4 |
| Logging | Pino + pino-pretty | 10.1.0 / 13.1.3 |
| Dev runner | tsx | 4.21.0 |
| HTTP client | Axios | 1.13.2 |
| Lainnya | qrcode, link-preview-js, @hapi/boom, cors, uuid, dotenv | — |
Struktur direktori
engine-whatsapp/
├── .github/workflows/ # CI/CD: deploy staging & production
├── public/files/ # Media hasil download pesan masuk (disajikan via /files)
├── session/auth/<uuid>/ # Kredensial Baileys per instance
├── src/
│ ├── app.ts # Entry: Express + HTTP + Socket.IO + Mongo + restore sesi
│ ├── config/
│ │ ├── config.ts # Loader env var
│ │ └── database.ts # Koneksi MongoDB
│ ├── controller/ # Validasi request + bentuk response
│ │ ├── SessionController.ts
│ │ ├── MessageController.ts
│ │ ├── GroupController.ts
│ │ └── NotificationController.ts
│ ├── middleware/
│ │ └── errorHandler.ts
│ ├── model/ # 4 skema Mongoose
│ │ ├── devices.model.ts
│ │ ├── admin_devices.model.ts
│ │ ├── chatInbox.model.ts
│ │ └── chatHistory.model.ts
│ ├── routes/itemRoutes.ts # SATU-SATUNYA tempat definisi route (prefix /api)
│ ├── service/
│ │ ├── whatsappService.ts # Inti Baileys: sesi, kirim, event (~886 baris)
│ │ ├── incomingMessageService.ts # Pipeline pesan masuk
│ │ ├── socketService.ts # Singleton Socket.IO
│ │ ├── notificationService.ts # Push notif, chatlist, team chat, pixel
│ │ ├── chatHistory/chatHistoryService.ts
│ │ └── devices/deviceServices.ts
│ └── utils/
│ ├── helper.ts # Webhook, format nomor, download media, enkripsi
│ └── responseHandler.ts # sendSuccess / sendError
├── wa-logs.txt # Output log Pino (dibuat otomatis saat runtime)
└── package.jsonAlur lapisan: routes → controller → service → (model | Baileys | webhook | socket).
whatsappService.ts (~886 baris) adalah pusat gravitasi repo. Perubahan di sana berdampak luas — baca dulu keseluruhan fungsi terkait sebelum mengedit.
Komponen utama
| Komponen | Lokasi | Catatan |
|---|---|---|
| HTTP server | src/app.ts (53 baris) | Express, CORS, Socket.IO, Mongo, restore sesi saat boot |
| Routes | src/routes/itemRoutes.ts | Semua endpoint /api + static /files |
| Session controller | src/controller/SessionController.ts | new, qrcode, logout, device-info |
| Message controller | src/controller/MessageController.ts | send-message, send-media, send-location, send-broadcast |
| Group controller | src/controller/GroupController.ts | create, info, participants |
| Notification controller | src/controller/NotificationController.ts | push-notif, update-chatlist, update-teamchat, submit-pixel |
| WhatsApp service | src/service/whatsappService.ts | Inti: sesi, kirim pesan, event listener Baileys |
| Incoming message service | src/service/incomingMessageService.ts | Pipeline pesan masuk: media, content, webhook, socket |
| Socket service | src/service/socketService.ts | Singleton — rooms per instanceId dan store_id |
| Notification service | src/service/notificationService.ts | Relay notif + Facebook Pixel |
| Helper | src/utils/helper.ts | sendWebhook, formatNumber, handleMedia, extractContent, AES-256-CBC |
| Response handler | src/utils/responseHandler.ts | sendSuccess/sendError standar |
Endpoint ringkas
| Grup | Endpoint |
|---|---|
| Session | POST /api/new, GET /api/qrcode, GET /api/logout, GET /api/device-info |
| Messaging | POST /api/send-message, POST /api/send-media, POST /api/send-location, POST /api/send-broadcast |
| Group | POST /api/group/create, GET /api/group/info, POST /api/group/participants |
| Notification | POST /api/push-notif, POST /api/update-chatlist, POST /api/update-teamchat, POST /api/submit-pixel |
| Static | GET /files/:filename |
Detail per-endpoint di API Reference.
Cara kerja singkat
Inbound (pesan masuk): messages.upsert → IncomingMessageService.handle → processMessage — skip broadcast/newsletter, normalisasi @lid, ambil metadata grup, unduh media, ekstrak content, buat chat_histories bila belum aktif, ambil foto profil, kirim webhook report: false, emit message_upsert.
Outbound (pesan keluar): backend hit POST /api/send-message → WhatsAppService.sendTextMessage → validasi onWhatsApp, simulasi presence (composing/recording lalu paused), kirim, emit sendmessage(+_bubble). Status ACK dipantau via messages.update → webhook report: true.
Status ACK: messages.update → mapping 1..5 → pending|sent|delivered|viewed|played → dedupe via Set per sesi → cari temp_id di chat_inbox → webhook report: true.
Detail alur di Session Lifecycle, Message Flow, dan Realtime Events.
Konsep inti
instanceId
Identitas sebuah device/sesi WhatsApp, berupa UUID. Nilai ini dipakai konsisten sebagai:
- nama folder kredensial:
session/auth/<instanceId> - key sesi di memory (
Map) - nama room Socket.IO
- kolom
idpada koleksidevices/admin_devices
Konsistensi keempatnya wajib dijaga.
Sesi bersifat in-memory
private static sessions = new Map<string, SessionData>(). Konsekuensi yang harus diingat:
- Tidak bisa PM2 cluster mode atau scaling horizontal tanpa mengubah arsitektur.
- Kredensial persisten di filesystem, bukan di MongoDB.
- Restart = semua sesi dimuat ulang dari disk (dengan jeda 2 detik antar sesi).
Status sesi
Status internal: CONNECTING, QR_READY, CONNECTED, DISCONNECTED. Untuk konsumsi luar, status dinormalisasi menjadi open / close (atau NOT_FOUND bila sesi tidak ada di memory).
Yang TIDAK boleh diubah tanpa koordinasi
| Area | Lokasi |
|---|---|
| Bentuk payload webhook | utils/helper.ts — sendWebhook — POST {WEBHOOK_URL}/callback_message |
| Event Socket.IO | service/socketService.ts, service/notificationService.ts — frontend adalah konsumen eksternal |
Field instanceId konsistensi | nama folder, key Map, room Socket.IO, kolom id device |
WEBHOOK_URL | config/config.ts — base URL backend Dazo |
Langkah berikutnya
- Baru mulai? Baca Setup Environment —
.envmemegang seluruh URL service. - Sudah punya env? Lanjut ke Local Development.
- Akan deploy? Baca Deployment — PM2, single process.
- Engineer baru wajib baca Session Lifecycle sebelum menyentuh
whatsappService.ts.