revert runtime-merge/pacing: delivery stuurt json-bestand as-is (whatsappdienst pre-rendert 1 lange JPEG per dienst)

This commit is contained in:
Eddy de Vink 2026-10-05 21:58:06 +02:00
commit 391aa5998d
4 changed files with 24 additions and 97 deletions

View file

@ -2,46 +2,6 @@ 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 { execFile } = require('child_process')
const { promisify } = require('util')
const path = require('path')
const os = require('os')
const fs = require('fs')
const crypto = require('crypto')
const execFileP = promisify(execFile)
// Merge-helper: combineer alle pagina's tot één lange afbeelding en stuur die als
// EÉN image. De staged-ghost is een "2e pagina van een paar verliest" (RCA
// 2026-09-26; gemeten 2026-10-05: ook JPEG, delay en ack-gate lossen het niet op);
// één enkele send van een samengevoegde afbeelding komt deterministisch aan.
const MAGICK_BIN = process.env.MAGICK_BIN || 'magick'
const MERGE_PAGES = process.env.MERGE_PAGES !== 'false'
async function mergePages(filePaths, dienstnummer) {
const out = path.join(os.tmpdir(), `dienst-${dienstnummer}-${crypto.randomBytes(4).toString('hex')}.jpg`)
try {
await execFileP(MAGICK_BIN, [...filePaths, '-append', out])
return out
} catch (err) {
console.error(`magick merge failed for ${dienstnummer}: ${err.message}`)
return null
}
}
// Pauze tussen opeenvolgende pagina-sends. De staged-ghost-race (RCA 2026-09-26)
// treedt op als de 2e pagina start terwijl de 1e nog écht transmetteert — de bot
// wacht per pagina alleen op het optimistische brug-signaal (staging), en de
// bridge-delay (MEDIA_SEND_DELAY_MS) wacht óók op staging (delay loss effect).
// Een bot-side wacht maakt van elke pagina een effectief losse send: die komen
// empirisch wél aan (enkele sends falen nooit).
const PAGE_SEND_DELAY_MS = (() => {
const parsed = parseInt(process.env.PAGE_SEND_DELAY_MS, 10)
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 15000
})()
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
const ALLOWED_GROUP = process.env.ALLOWED_GROUP
const ALLOWED_GROUP_NAMES = (process.env.ALLOWED_GROUP_NAME || '')
@ -100,27 +60,17 @@ async function handleWebhook(payload) {
return
}
// Strategie: meerpagina-diensten als EEN lange afbeelding (merge) sturen — zie
// onder. pngPaths = de bronbestanden (nu .jpg, bestandsnaam uit json).
// 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
}
// Merge alle pagina's tot één lange afbeelding (één send) — elimineert de
// staged-ghost (2e pagina van een paar verliest; zie RCA 2026-09-26 + verificatie
// 2026-10-05). 1 pagina = as-is sturen; bij merge-falen valt terug op per-pagina.
let sendPaths = pngPaths
let tempMerged = null
if (MERGE_PAGES && pngPaths.length > 1) {
tempMerged = await mergePages(pngPaths, dienstnummer)
if (tempMerged) sendPaths = [tempMerged]
}
for (let i = 0; i < sendPaths.length; i++) {
const pngPath = sendPaths[i]
const filename = tempMerged ? `${dienstnummer}.jpg` : pngPath.split('/').pop()
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) {
@ -128,15 +78,6 @@ async function handleWebhook(payload) {
console.error(errorMsg)
await notifyAdmin(errorMsg)
}
// Wacht vóór de volgende pagina (alleen bij niet-gemerge pagina-sends);
// 0 zet de pauze uit.
if (!tempMerged && i < sendPaths.length - 1 && PAGE_SEND_DELAY_MS > 0) {
await sleep(PAGE_SEND_DELAY_MS)
}
}
if (tempMerged) {
fs.unlink(tempMerged, () => {})
}
}