arizukocomponents › whapd

whapd

What it is

whapd is the WhatsApp channel adapter. It speaks WhatsApp Web through the Baileys socket library (TypeScript / Node, the only non-Go adapter in the core), posts inbound to gated, and sends outbound through the same socket. JID prefix is whatsapp:; per-conversation JIDs are whatsapp:<jid> where jid is the Baileys-native form (phone-number@s.whatsapp.net or group-id@g.us).

Why it exists

WhatsApp has no usable consumer API. The official Cloud API is partner-gated and quota-limited; everyone else uses a WhatsApp Web client. Baileys has no Go port, so whapd lives in TypeScript. Pairing credentials persist in $WHATSAPP_AUTH_DIR/creds.json with an atomic .bak rotation; a fresh install requires pairing.

How it fits

WhatsApp (web.whatsapp.com socket)
        |  Baileys multi-device socket
        v
      whapd     (LISTEN_ADDR=:8080, Node runtime)
        |  POST /v1/messages    (signed by CHANNEL_SECRET)
        v
      gated
        |  POST /v1/send         (callback to whapd)
        v
      whapd     (sock.sendMessage / reactMessage / delete)
        |
        v
      WhatsApp

Wired verbs (whapd/src/server.ts): send (sendMessage(jid, {text}), honours reply_to via Baileys quoted), send_file (image / video / audio / document by mime sniff), typing (composing / paused presence with refresher), like (reaction; emoji selectable via reaction field, default 👍), edit (own messages, 15-min window), delete (own-message redaction), forward (best-effort — synthesizes forwarded text since Baileys only gives source_msg_id). quote, repost, dislike, post are 501-with-hint — dislike redirects to like(reaction='👎').

No fetch_history: Baileys’ history sync is unreliable across the LID/JID translation Meta introduced in 2024; the gateway falls back to its local cache.

Pairing

Two paths, both token-less:

Lose creds.json and the device is unlinked — re-pair. whapd backs up to creds.json.bak on every save and recovers from it on a crash. The outbound queue is persisted to disk and auto-resumes on reconnect.

Standalone usage

export ROUTER_URL=http://gated:8080
export CHANNEL_SECRET=$(grep ^CHANNEL_SECRET .env | cut -d= -f2)
export LISTEN_ADDR=:8080
export WHATSAPP_AUTH_DIR=/srv/data/store/whatsapp-auth
export DATA_DIR=/srv/data/arizuko_demo
node dist/main.js

GET /health returns 503 while waiting for QR / pairing-code scan and while the Baileys socket is disconnected. The container log carries the QR; sudo docker logs arizuko-<inst>-whapd-1 on the host.

Go deeper