Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7176f09387 | ||
|
|
100b2af449 | ||
|
|
3d933c96a6 | ||
|
|
52c51fbf3f |
4 changed files with 50 additions and 0 deletions
|
|
@ -11,5 +11,8 @@ BOT_NAME=EdGpt
|
||||||
DIENSTEN_JSON=./diensten/dienst-tijden.json
|
DIENSTEN_JSON=./diensten/dienst-tijden.json
|
||||||
DIENSTEN_PNG=./diensten/png
|
DIENSTEN_PNG=./diensten/png
|
||||||
|
|
||||||
|
# Rate limiting
|
||||||
|
MAX_REQUESTS_PER_DAY=5
|
||||||
|
|
||||||
# Admin notifications
|
# Admin notifications
|
||||||
ADMIN_NUMBER=31612345678@c.us
|
ADMIN_NUMBER=31612345678@c.us
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ npx pm2 logs dienst-bot
|
||||||
src/
|
src/
|
||||||
index.js # Express webhook server
|
index.js # Express webhook server
|
||||||
messageHandler.js # Berichtverwerking en filtering
|
messageHandler.js # Berichtverwerking en filtering
|
||||||
|
rateLimiter.js # Spam protectie (max 5 per dag)
|
||||||
dienstService.js # JSON lookup en PNG bestandspaden
|
dienstService.js # JSON lookup en PNG bestandspaden
|
||||||
whatsappApi.js # WhatsApp API client (bericht + afbeelding)
|
whatsappApi.js # WhatsApp API client (bericht + afbeelding)
|
||||||
```
|
```
|
||||||
|
|
@ -124,6 +125,10 @@ src/
|
||||||
- **Fout bij verzenden PNG**: de admin krijgt een WhatsApp melding
|
- **Fout bij verzenden PNG**: de admin krijgt een WhatsApp melding
|
||||||
- **Webhook fout**: wordt gelogd in PM2 logs
|
- **Webhook fout**: wordt gelogd in PM2 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).
|
||||||
|
|
||||||
## Licentie
|
## Licentie
|
||||||
|
|
||||||
Privé project — niet voor distributie.
|
Privé project — niet voor distributie.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
const { findDienst, getPngFilePaths } = require('./dienstService')
|
const { findDienst, getPngFilePaths } = require('./dienstService')
|
||||||
const { sendTextMessage, sendImageMessage, notifyAdmin } = require('./whatsappApi')
|
const { sendTextMessage, sendImageMessage, notifyAdmin } = require('./whatsappApi')
|
||||||
|
const { checkLimit, increment, MAX_REQUESTS_PER_DAY } = require('./rateLimiter')
|
||||||
|
|
||||||
const BOT_NAME = (process.env.BOT_NAME || 'EdGpt').toLowerCase()
|
const BOT_NAME = (process.env.BOT_NAME || 'EdGpt').toLowerCase()
|
||||||
const ALLOWED_GROUP = process.env.ALLOWED_GROUP
|
const ALLOWED_GROUP = process.env.ALLOWED_GROUP
|
||||||
|
|
@ -40,6 +41,15 @@ async function handleWebhook(payload) {
|
||||||
const author = message.author
|
const author = message.author
|
||||||
if (!author) return
|
if (!author) return
|
||||||
|
|
||||||
|
const limit = checkLimit(author)
|
||||||
|
if (!limit.allowed) {
|
||||||
|
await sendTextMessage(author, `Je hebt vandaag het maximum van ${limit.max} diensten bereikt. Probeer het morgen opnieuw.`)
|
||||||
|
console.log(`Rate limit reached for ${author} (${limit.count}/${limit.max})`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
increment(author)
|
||||||
|
|
||||||
const dienst = findDienst(dienstnummer)
|
const dienst = findDienst(dienstnummer)
|
||||||
if (!dienst) {
|
if (!dienst) {
|
||||||
await sendTextMessage(author, `Dienstnummer ${dienstnummer} niet gevonden.`)
|
await sendTextMessage(author, `Dienstnummer ${dienstnummer} niet gevonden.`)
|
||||||
|
|
|
||||||
32
src/rateLimiter.js
Normal file
32
src/rateLimiter.js
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
const MAX_REQUESTS_PER_DAY = parseInt(process.env.MAX_REQUESTS_PER_DAY, 10) || 5
|
||||||
|
|
||||||
|
const userCounts = new Map()
|
||||||
|
let currentDate = new Date().toDateString()
|
||||||
|
|
||||||
|
function resetIfNeeded() {
|
||||||
|
const today = new Date().toDateString()
|
||||||
|
if (today !== currentDate) {
|
||||||
|
userCounts.clear()
|
||||||
|
currentDate = today
|
||||||
|
console.log('Rate limiter: daily counters reset')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkLimit(userId) {
|
||||||
|
resetIfNeeded()
|
||||||
|
const count = userCounts.get(userId) || 0
|
||||||
|
return {
|
||||||
|
allowed: count < MAX_REQUESTS_PER_DAY,
|
||||||
|
count,
|
||||||
|
max: MAX_REQUESTS_PER_DAY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function increment(userId) {
|
||||||
|
resetIfNeeded()
|
||||||
|
const count = (userCounts.get(userId) || 0) + 1
|
||||||
|
userCounts.set(userId, count)
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { checkLimit, increment, MAX_REQUESTS_PER_DAY }
|
||||||
Loading…
Reference in a new issue