dienst_echo_whatsappgroep/docs/superpowers/specs/2025-05-11-dienst-bot-design.md

5.9 KiB

Dienst Bot - WhatsApp Dienstnummer Bot

⚠️ Poort-wijziging: De wwebjs-api is verhuisd van poort 3000 naar poort 3001 (juni 2026). Alle referenties naar localhost:3000 in dit document zijn historisch en niet meer actueel. De correcte poort is 3001. Zie .env.example voor de actuele configuratie.

Samenvatting

Een Node.js webhook service die luistert naar berichten in een WhatsApp groep via de wwebjs-api. Wanneer een groepsllid EdGpt noemt (@EdGpt) met een 4-cijferig dienstnummer, zoekt de bot de bijbehorende PNG-afbeeldingen op en stuurt deze privé terug naar de afzender.

Context

  • wwebjs-api: REST API wrapper voor whatsapp-web.js, draait op localhost:3000
  • Sessie: EdGpt, actief in WhatsApp groep TestGpt
  • Diensten: Gescande dienstschema's opgeslagen als PNG in diensten/png/, met metadata in diensten/dienst-tijden.json
  • dienst-tijden.json: Array van objecten met dienstnummer (4 cijfers), startTime, endTime, en paginas (array met bestandsnaam voor PNG)

Architectuur

WhatsApp groep bericht ("@EdGpt 4001")
  → wwebjs-api (localhost:3000)
    → webhook POST naar dienst-bot (localhost:3002/webhook)
      → bericht parsing: @EdGpt + 4-cijferig dienstnummer
      → lookup PNGs via dienst-tijden.json
      → stuur PNGs privé via wwebjs-api REST endpoint

Twee componenten:

  1. wwebjs-api (bestaand) - met BASE_WEBHOOK_URL=http://localhost:3002/webhook geconfigureerd
  2. dienst-bot (nieuw) - Express.js webhook receiver op poort 3002

Webhook Payload

wwebjs-api stuurt per message event een POST naar de webhook URL:

{
  "dataType": "message",
  "sessionId": "EdGpt",
  "data": {
    "message": {
      "from": "120363407356808413@g.us",
      "author": "31620248011@c.us",
      "body": "@EdGpt 4001",
      "fromMe": false,
      "hasMedia": false,
      "_data": {
        "mentionedJidList": ["31620248011@c.us"]
      }
    }
  }
}

Belangrijke velden:

  • from: groep-ID bij groepsberichten (eindigt op @g.us)
  • author: de afzender van het bericht binnen de groep
  • fromMe: true als het bericht van de bot zelf komt
  • mentionedJidList: array van genoemde contact-IDs

Berichtverwerking (Core Logic)

  1. Filter op dataType: negeer alles behalve dataType === "message"
  2. Filter op afzender: negeer als fromMe === true (bot's eigen berichten)
  3. Filter op groep: negeer als from !== ALLOWED_GROUP
  4. Check mention: controleer of het bot-nummer voorkomt in mentionedJidList OF of de tekst @EdGpt (case-insensitive) bevat
  5. Extract dienstnummer: regex \b(\d{4})\b op message body - neem het eerste match
  6. Lookup: zoek dienstnummer in dienst-tijden.json, krijg lijst met PNG bestandsnamen
  7. Stuur PNGs: voor elke PNG, stuur privé naar afzender via wwebjs-api

Afbeelding Versturen

Per PNG bestand:

  1. Lees file van schijf uit DIENSTEN_PNG directory
  2. Converteer naar base64
  3. Stuur via wwebjs-api endpoint:
POST {WHATSAPP_API_ENDPOINT}/client/sendMessage/EdGpt
Content-Type: application/json

{
  "chatId": "{author}",
  "contentType": "MessageMedia",
  "content": {
    "mimetype": "image/png",
    "data": "{base64_string}",
    "filename": "{bestandsnaam}.png"
  }
}

Elke PNG wordt als apart privébericht verstuurd.

Foutafhandeling

Situatie Actie
Ongeldig dienstnummer (niet in JSON) Stuur privé bericht: "Dienstnummer XXXX niet gevonden."
Geen PNGs gevonden voor dienst Stuur privé bericht: "Geen pagina's gevonden voor dienst XXXX."
Geen dienstnummer in bericht Negeer stil (geen actie)
Fout bij verzenden PNG Log error + stuur WhatsApp foutmelding naar admin
Webhook verwerking fout Log error + stuur WhatsApp foutmelding naar admin, return 500 naar wwebjs-api

Configuratie

.env (dienst-bot project)

# WhatsApp API Configuration
WHATSAPP_API_ENDPOINT=http://localhost:3000
WHATSAPP_SESSION=EdGpt

# Webhook Configuration
WEBHOOK_PORT=3002
ALLOWED_GROUP=120363407356808413@g.us
BOT_NAME=EdGpt

# Paths
DIENSTEN_JSON=./diensten/dienst-tijden.json
DIENSTEN_PNG=./diensten/png

# Admin notifications
ADMIN_NUMBER=31620248011@c.us

wwebjs-api .env (toevoeging)

BASE_WEBHOOK_URL=http://localhost:3002/webhook

Bestandsstructuur

dienst_echo_whatsappgroep/
├── .env                        # configuratie
├── package.json                # dependencies: express, dotenv, axios
├── src/
│   ├── index.js                # Express server, webhook endpoint
│   ├── messageHandler.js       # bericht parsing + dienst lookup + dispatch
│   └── dienstService.js        # JSON laden + PNG file reading
├── diensten/                   # bestaande data
│   ├── dienst-tijden.json
│   └── png/
└── docs/
    └── superpowers/
        └── specs/
            └── 2025-05-11-dienst-bot-design.md

Modules

src/index.js

  • Express server op WEBHOOK_PORT
  • POST /webhook endpoint
  • Laadt .env en start server
  • Delegeert verwerking naar messageHandler

src/messageHandler.js

  • handleWebhook(payload): hoofdfunctie, voert alle filterstappen uit
  • Parse message body voor dienstnummer
  • Roept dienstService aan voor lookup
  • Stuurt PNGs of foutmelding via wwebjs-api

src/dienstService.js

  • loadDiensten(): laadt en cache dienst-tijden.json
  • findDienst(nummer): retourneer dienst-object of null
  • getPngFiles(dienst): retourneer array van absolute bestandspaden

Dependencies

  • express - HTTP server voor webhook endpoint
  • dotenv - .env variabelen laden
  • axios - HTTP client voor wwebjs-api calls
  • fs - file reading voor PNG bestanden (built-in)
  • path - pad constructie (built-in)

Operationeel

  • Starten: pm2 start src/index.js --name dienst-bot
  • Loggen: pm2 logs dienst-bot
  • Herstarten: pm2 restart dienst-bot
  • Stoppen: pm2 stop dienst-bot