# 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: ```json { "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) ```env # 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) ```env 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`