106 lines
3.7 KiB
JavaScript
106 lines
3.7 KiB
JavaScript
const { findDienst, getPngFilePaths } = require('./dienstService')
|
|
const { sendTextMessage, sendImageMessage, notifyAdmin, sendChatSeen } = require('./whatsappApi')
|
|
const { checkLimit, increment, MAX_REQUESTS_PER_DAY } = require('./rateLimiter')
|
|
const { increment: incrementDaily } = require('./dailyStats')
|
|
|
|
const ALLOWED_GROUP = process.env.ALLOWED_GROUP
|
|
const ALLOWED_GROUP_NAMES = (process.env.ALLOWED_GROUP_NAME || '')
|
|
.split(',')
|
|
.map(name => name.trim())
|
|
.filter(Boolean)
|
|
const ALLOWED_CHAT_IDS = new Set([ALLOWED_GROUP, ...ALLOWED_GROUP_NAMES].filter(Boolean))
|
|
|
|
// WuzAPI-webhook-payload-mapping. WuzAPI stuurt (WEBHOOK_FORMAT=json) het volledig
|
|
// whatsmeow-event als { "event": {...}, "type": "Message", ... }. De relevante
|
|
// velden (uit whatsmeow-types): event.Info.Chat/Sender = {User, Server},
|
|
// event.Info.IsFromMe (bool), event.Info.ID, event.Message.conversation.
|
|
function jidFromObject(jid) {
|
|
// whatsmeow-JID serialiseert als {User, RawAgent, Device, Integrator, Server}
|
|
if (!jid || typeof jid !== 'object') return String(jid || '')
|
|
const server = jid.Server || 's.whatsapp.net'
|
|
const device = jid.Device ? `:${jid.Device}` : ''
|
|
return `${jid.User}${device}@${server}`
|
|
}
|
|
|
|
function normalizeChatId(chatId) {
|
|
return (chatId || '')
|
|
.replace(/^\u200e/, '')
|
|
.replace(/\s*\(\d+ berichten?\)$/, '')
|
|
.trim()
|
|
}
|
|
|
|
function extractDienstnummer(body) {
|
|
const match = body.match(/^\s*(\d{4,5})\s*$/)
|
|
return match ? match[1] : null
|
|
}
|
|
|
|
async function handleWebhook(payload) {
|
|
if (payload.type !== 'Message') return
|
|
|
|
const event = payload.event
|
|
if (!event || !event.Info) return
|
|
|
|
const chatId = jidFromObject(event.Info.Chat)
|
|
const author = jidFromObject(event.Info.Sender)
|
|
if (event.Info.IsFromMe) return
|
|
if (!ALLOWED_CHAT_IDS.has(normalizeChatId(chatId))) return
|
|
|
|
const messageId = event.Info.ID
|
|
// Tekst: conversation of extendedTextMessage.text; protobuf-veldnamen kunnen
|
|
// zowel lowerCamel (protojson) als Go-vorm (Conversation) zijn — beide afdekken.
|
|
const msg = event.Message || {}
|
|
const body = msg.conversation || msg.Conversation ||
|
|
msg.extendedTextMessage?.text || msg.ExtendedTextMessage?.Text || ''
|
|
|
|
const dienstnummer = extractDienstnummer(body)
|
|
if (!dienstnummer) return
|
|
|
|
incrementDaily()
|
|
|
|
if (messageId) {
|
|
sendChatSeen(chatId, messageId).catch(err =>
|
|
console.error('Failed to mark chat as seen:', err.message)
|
|
)
|
|
}
|
|
|
|
console.log(`Processing dienst ${dienstnummer} for ${author}`)
|
|
|
|
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)
|
|
if (!dienst) {
|
|
await sendTextMessage(author, `Dienstnummer ${dienstnummer} niet gevonden.`)
|
|
return
|
|
}
|
|
|
|
// Media-pacing voor opeenvolgende sends gebeurt bridge-breed (wwebjs-api
|
|
// serialiseert + throttle de media-sends; MEDIA_SEND_DELAY_MS in bridge-.env).
|
|
const pngPaths = getPngFilePaths(dienst)
|
|
if (!pngPaths || pngPaths.length === 0) {
|
|
await sendTextMessage(author, `Geen pagina's gevonden voor dienst ${dienstnummer}.`)
|
|
return
|
|
}
|
|
|
|
for (let i = 0; i < pngPaths.length; i++) {
|
|
const pngPath = pngPaths[i]
|
|
const filename = pngPath.split('/').pop()
|
|
try {
|
|
await sendImageMessage(author, pngPath, filename)
|
|
} catch (err) {
|
|
const errorMsg = `Fout bij verzenden ${filename} naar ${author}: ${err.message}`
|
|
console.error(errorMsg)
|
|
await notifyAdmin(errorMsg)
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = { handleWebhook, extractDienstnummer }
|