D
Pendahuluan

Overview

Engine WhatsApp adalah WhatsApp gateway multi-device ekosistem Dazo — menjembatani akun WhatsApp dengan backend via REST API, webhook, dan Socket.IO realtime. Dibangun di atas Baileys 7 + Express 5 + MongoDB, single process multi-device.

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

AspekPenjelasan
IdentitasPackage engine-whatsapp, repo engine-whatsapp
PosisiAntara akun WhatsApp (via Baileys) dan backend-go/dazoapp/frontend
TenantinstanceId (UUID per device) — bukan store_id sebagai identitas utama
DatastoreMongoDB (DB dazo lokal / remote) untuk data device dan riwayat chat
SesiKredensial Baileys persisten di filesystem (session/auth/<instanceId>), bukan MongoDB
RealtimeSocket.IO — event QR, status device, pesan masuk, status ACK
Auth❌ Tidak ada — semua endpoint public
BahasaTypeScript ESM

Arsitektur

text
                  ┌──────────────────────────────┐
   WhatsApp  ◄───►│  Baileys (WhatsAppService)   │
                  │  sesi per instanceId (UUID)  │
                  └───────────┬──────────────────┘
                              │
        ┌─────────────────────┼─────────────────────┐
        │                     │                     │
        ▼                     ▼                     ▼
┌───────────────┐   ┌──────────────────┐   ┌────────────────┐
│  REST API     │   │  Webhook         │   │  Socket.IO     │
│  /api/*       │   │  → Backend Dazo  │   │  → Frontend    │
└───────────────┘   └──────────────────┘   └────────────────┘
                              │
                              ▼
                     ┌────────────────┐
                     │    MongoDB     │
                     └────────────────┘

Tiga jalur keluar-masuk data:

JalurArahKegunaan
REST API (/api/*)Backend → EnginePerintah: buat sesi, kirim pesan, kelola grup, relay notif
WebhookEngine → BackendLapor pesan masuk & perubahan status pesan (POST {WEBHOOK_URL}/callback_message)
Socket.IOEngine → FrontendRealtime: QR, status device, bubble chat, notifikasi

Alur utama

  1. Login — Client hit POST /api/new, engine membuat socket Baileys, QR dikirim realtime lewat event qrcode.
  2. Pesan masuk — Baileys messages.upsert → media diunduh ke public/files → payload dikirim ke webhook backend → hasil di-emit ke frontend.
  3. Pesan keluar — Backend hit POST /api/send-message → Baileys kirim → status ACK dipantau lewat messages.update → diteruskan ke webhook + socket.
  4. Persistensi — Kredensial sesi disimpan di filesystem (session/auth/<instanceId>), bukan di MongoDB. MongoDB dipakai untuk data device dan riwayat chat.

Stack teknologi

LapisanTeknologiVersi
RuntimeNode.jsdiuji v20–v23 (disarankan ≥ 20)
BahasaTypeScript5.9.3 (ESM)
Web frameworkExpress5.2.1
WhatsApp engine@whiskeysockets/baileys7.0.0-rc.9
RealtimeSocket.IO4.8.3
DatabaseMongoDB via Mongoose9.1.4
LoggingPino + pino-pretty10.1.0 / 13.1.3
Dev runnertsx4.21.0
HTTP clientAxios1.13.2
Lainnyaqrcode, link-preview-js, @hapi/boom, cors, uuid, dotenv—

Struktur direktori

text
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.json

Alur 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

KomponenLokasiCatatan
HTTP serversrc/app.ts (53 baris)Express, CORS, Socket.IO, Mongo, restore sesi saat boot
Routessrc/routes/itemRoutes.tsSemua endpoint /api + static /files
Session controllersrc/controller/SessionController.tsnew, qrcode, logout, device-info
Message controllersrc/controller/MessageController.tssend-message, send-media, send-location, send-broadcast
Group controllersrc/controller/GroupController.tscreate, info, participants
Notification controllersrc/controller/NotificationController.tspush-notif, update-chatlist, update-teamchat, submit-pixel
WhatsApp servicesrc/service/whatsappService.tsInti: sesi, kirim pesan, event listener Baileys
Incoming message servicesrc/service/incomingMessageService.tsPipeline pesan masuk: media, content, webhook, socket
Socket servicesrc/service/socketService.tsSingleton — rooms per instanceId dan store_id
Notification servicesrc/service/notificationService.tsRelay notif + Facebook Pixel
Helpersrc/utils/helper.tssendWebhook, formatNumber, handleMedia, extractContent, AES-256-CBC
Response handlersrc/utils/responseHandler.tssendSuccess/sendError standar

Endpoint ringkas

GrupEndpoint
SessionPOST /api/new, GET /api/qrcode, GET /api/logout, GET /api/device-info
MessagingPOST /api/send-message, POST /api/send-media, POST /api/send-location, POST /api/send-broadcast
GroupPOST /api/group/create, GET /api/group/info, POST /api/group/participants
NotificationPOST /api/push-notif, POST /api/update-chatlist, POST /api/update-teamchat, POST /api/submit-pixel
StaticGET /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 id pada koleksi devices / 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

AreaLokasi
Bentuk payload webhookutils/helper.ts — sendWebhook — POST {WEBHOOK_URL}/callback_message
Event Socket.IOservice/socketService.ts, service/notificationService.ts — frontend adalah konsumen eksternal
Field instanceId konsistensinama folder, key Map, room Socket.IO, kolom id device
WEBHOOK_URLconfig/config.ts — base URL backend Dazo

Langkah berikutnya