5.9 KiB
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:3000in dit document zijn historisch en niet meer actueel. De correcte poort is3001. Zie.env.examplevoor 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 indiensten/dienst-tijden.json - dienst-tijden.json: Array van objecten met
dienstnummer(4 cijfers),startTime,endTime, enpaginas(array metbestandsnaamvoor 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:
- wwebjs-api (bestaand) - met
BASE_WEBHOOK_URL=http://localhost:3002/webhookgeconfigureerd - 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 groepfromMe:trueals het bericht van de bot zelf komtmentionedJidList: array van genoemde contact-IDs
Berichtverwerking (Core Logic)
- Filter op dataType: negeer alles behalve
dataType === "message" - Filter op afzender: negeer als
fromMe === true(bot's eigen berichten) - Filter op groep: negeer als
from !== ALLOWED_GROUP - Check mention: controleer of het bot-nummer voorkomt in
mentionedJidListOF of de tekst@EdGpt(case-insensitive) bevat - Extract dienstnummer: regex
\b(\d{4})\bop message body - neem het eerste match - Lookup: zoek dienstnummer in
dienst-tijden.json, krijg lijst met PNG bestandsnamen - Stuur PNGs: voor elke PNG, stuur privé naar afzender via wwebjs-api
Afbeelding Versturen
Per PNG bestand:
- Lees file van schijf uit
DIENSTEN_PNGdirectory - Converteer naar base64
- 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
/webhookendpoint - Laadt
.enven start server - Delegeert verwerking naar
messageHandler
src/messageHandler.js
handleWebhook(payload): hoofdfunctie, voert alle filterstappen uit- Parse message body voor dienstnummer
- Roept
dienstServiceaan voor lookup - Stuurt PNGs of foutmelding via wwebjs-api
src/dienstService.js
loadDiensten(): laadt en cachedienst-tijden.jsonfindDienst(nummer): retourneer dienst-object of nullgetPngFiles(dienst): retourneer array van absolute bestandspaden
Dependencies
express- HTTP server voor webhook endpointdotenv- .env variabelen ladenaxios- HTTP client voor wwebjs-api callsfs- 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