153 lines
4.9 KiB
Markdown
153 lines
4.9 KiB
Markdown
# Dienst Bot
|
|
|
|
> Dit project is gemaakt door middel van vibecoding met [OpenCode 1.14.40](https://opencode.ai).
|
|
|
|
WhatsApp bot die dienstschema's (PNG) privé verstuurt op basis van een 4-cijferig dienstnummer, gepost in een speciale WhatsApp groep.
|
|
|
|
## Hoe het werkt
|
|
|
|
1. Iemand stuurt een **4-cijferig dienstnummer** in de groep (bijv. `4002`)
|
|
2. De bot zoekt het dienstschema op in `dienst-tijden.json`
|
|
3. De bijbehorende PNG-bestanden worden **privé** naar de afzender gestuurd
|
|
4. Via een **vastgezet welkomstbericht** in de groep staat uitleg over het gebruik
|
|
|
|
De bot gebruikt een **speciale groep** (Dienst opvragen EdGPT-EBS) waarin **elk bericht dat uit exact 4 cijfers bestaat** wordt verwerkt. Geen @mention nodig.
|
|
|
|
## Vereisten
|
|
|
|
- [Node.js](https://nodejs.org/) 18+
|
|
- [wwebjs-api](https://github.com/pedroslopez/whatsapp-web.js) Docker container op nextcloud (poort 3001)
|
|
- WhatsApp sessie "EdGpt" actief in wwebjs-api
|
|
|
|
## Installatie
|
|
|
|
```bash
|
|
git clone <repo-url>
|
|
cd dienst_echo_whatsappgroep
|
|
npm install
|
|
```
|
|
|
|
## Configuratie
|
|
|
|
Kopieer `.env.example` naar `.env` en vul de waarden in:
|
|
|
|
```env
|
|
# WhatsApp API
|
|
WHATSAPP_API_ENDPOINT=http://192.168.5.252:3001
|
|
WHATSAPP_SESSION=EdGpt
|
|
|
|
# Webhook
|
|
WEBHOOK_PORT=3002
|
|
ALLOWED_GROUP=120363407613652082@g.us
|
|
|
|
# Bestanden
|
|
DIENSTEN_JSON=./diensten/dienst-tijden.json
|
|
DIENSTEN_PNG=./diensten/png
|
|
|
|
# Admin
|
|
ADMIN_NUMBER=31620248011@c.us
|
|
```
|
|
|
|
### wwebjs-api webhook config
|
|
|
|
In de `.env` van wwebjs-api:
|
|
|
|
```env
|
|
BASE_WEBHOOK_URL=http://192.168.5.252:3002/webhook
|
|
ENABLE_LOCAL_CALLBACK_EXAMPLE=FALSE
|
|
ENABLE_WEBHOOK=TRUE
|
|
```
|
|
|
|
Belangrijk: gebruik **`docker compose up -d`** (niet `docker restart`) om `.env` wijzigingen door te voeren.
|
|
|
|
## Data
|
|
|
|
De map `diensten/` bevat:
|
|
|
|
- `dienst-tijden.json` — array met dienstmetadata:
|
|
```json
|
|
[
|
|
{
|
|
"dienstnummer": "4002",
|
|
"startTime": "09:30",
|
|
"endTime": "10:30",
|
|
"paginas": [
|
|
{ "bestandsnaam": "4002-001.png" },
|
|
{ "bestandsnaam": "4002-002.png" }
|
|
]
|
|
}
|
|
]
|
|
```
|
|
- `png/` — PNG bestanden met dienstschema's (bijv. `4002-001.png`)
|
|
|
|
Beide zijn uitgesloten van git via `.gitignore`.
|
|
|
|
## Gebruik
|
|
|
|
### Starten (nextcloud — huidig)
|
|
|
|
De bot draait op **nextcloud** via **systemd** (gemigreerd van Mac Mini LaunchDaemon → PM2, nu systemd).
|
|
|
|
```bash
|
|
# Status
|
|
ssh aiaiaiaiagent@nextcloud "sudo -A systemctl status dienst-bot"
|
|
|
|
# Herstarten
|
|
ssh aiaiaiaiagent@nextcloud "sudo -A systemctl restart dienst-bot"
|
|
|
|
# Logs volgen
|
|
ssh aiaiaiaiagent@nextcloud "sudo -A journalctl -u dienst-bot -n 50 -f"
|
|
```
|
|
|
|
### Oude Mac Mini (niet meer actief)
|
|
|
|
Plist: `/Library/LaunchDaemons/nl.eddydevink.dienst-bot.plist` → `.disabled`
|
|
Wrapper: `run-dienst-bot.sh` (codesign fix voor Homebrew Node)
|
|
|
|
## Projectstructuur
|
|
|
|
```
|
|
src/
|
|
index.js # Express webhook server + cron job
|
|
messageHandler.js # Berichtverwerking en filtering
|
|
rateLimiter.js # Spam protectie (max 5 per dag)
|
|
dailyStats.js # Dagelijkse aanvraag-teller
|
|
dienstService.js # JSON lookup en PNG bestandspaden
|
|
whatsappApi.js # WhatsApp API client (bericht + afbeelding)
|
|
pinnedMessageService.js # Vastgezet welkomstbericht beheer
|
|
```
|
|
|
|
## Welkomstbericht
|
|
|
|
De groep heeft een **vastgezet welkomstbericht** dat automatisch door EdGpt wordt herplaatst als het is verlopen (30 dagen). De tekst luidt:
|
|
|
|
> *Welkom in Dienst opvragen EdGpt-EBS. Stuur hier je 4 cijferige dienstnummer en EdGpt zal het prive naar je toe sturen, alleen 4 cijfers meer niet.*
|
|
|
|
Bij elke interactie met de groep controleert de bot of het pinned bericht nog bestaat en plaatst het opnieuw indien nodig.
|
|
|
|
## Foutafhandeling
|
|
|
|
- **Ongeldig dienstnummer**: de bot stuurt een melding terug naar de afzender
|
|
- **Fout bij verzenden tekst/PNG**: maximaal 3 pogingen met exponential backoff (1s, 2s, 4s) voor 5xx HTTP-fouten en connectieproblemen (ECONNRESET, ECONNREFUSED, ETIMEDOUT). Bij definitieve fout krijgt de admin een WhatsApp-melding.
|
|
- **EADDRINUSE (poort 3002 in gebruik)**: de server wacht 5 seconden en herhaalt de bind-poging, met `SO_REUSEADDR` om TIME_WAIT te omzeilen
|
|
- **Graceful shutdown**: de server handelt SIGTERM en SIGINT af door actieve connecties netjes te sluiten (10s timeout)
|
|
- **Restart-loop preventie**: de LaunchDaemon heeft `ThrottleInterval=10` — maximaal 1 herstart per 10 seconden
|
|
- **Webhook fout**: wordt gelogd in de logs
|
|
|
|
## Spam protectie
|
|
|
|
Elke gebruiker kan maximaal `MAX_REQUESTS_PER_DAY` (standaard 5) diensten per dag opvragen. Bij overschrijding krijgt de gebruiker een melding. De teller wordt dagelijks automatisch gereset (bij de eerste request na middernacht).
|
|
|
|
## Dagelijkse samenvatting
|
|
|
|
Elke dag om **10:00** stuurt de bot een WhatsApp-bericht naar `ADMIN_NUMBER` met het totaal aantal **alle** 4-cijferige berichten van de vorige dag (00:00 t/m 23:59).
|
|
|
|
```
|
|
📊 Aantal dienstaanvragen gisteren: N
|
|
```
|
|
|
|
De teller wordt bijgehouden in memory door `dailyStats.js` en gereset na verzending van de samenvatting. De scheduling gebruikt `node-cron` (`0 10 * * *`).
|
|
|
|
## Licentie
|
|
|
|
Public Domain
|