diff --git a/src/whatsappApi.js b/src/whatsappApi.js index e5b0534..b797eb7 100644 --- a/src/whatsappApi.js +++ b/src/whatsappApi.js @@ -19,6 +19,19 @@ async function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)) } +// Media-send seriële keten: de wwebjs-media-pipeline is EÉN chromium-tab. Zonder +// serialisatie overlappen opeenvolgende media-sends — pagina's van één dienst óf +// afbeeldingen naar verschillende ontvangers bij gelijktijdige webhook-requests. +// Daarom loopt élke media-send door deze ene keten en eindigt elke send met +// MEDIA_SEND_DELAY_MS, zodat de tab tussen twee sends rust krijgt. +let mediaSendChain = Promise.resolve() + +function enqueueSend(run) { + const job = mediaSendChain.then(run, run) + mediaSendChain = job.catch(() => {}) // keten levend houden, ook als een send faalt + return job +} + function isRetryableError(error) { if (error.response) { const status = error.response.status @@ -56,6 +69,10 @@ async function sendTextMessage(chatId, text) { } async function sendImageMessage(chatId, filePath, filename) { + return enqueueSend(() => sendImageMessageInner(chatId, filePath, filename)) +} + +async function sendImageMessageInner(chatId, filePath, filename) { return withRetry(async () => { const fileBuffer = fs.readFileSync(filePath) const base64Data = fileBuffer.toString('base64') @@ -71,7 +88,7 @@ async function sendImageMessage(chatId, filePath, filename) { }) const messageId = response.data?.message?._data?.id?.id registerSend(messageId, chatId, filename) - // Pacing na élke media-send: de wwebjs-media-pipeline is EEN chromium-tab. Twee + // Pacing ná élke media-send: de wwebjs-media-pipeline is EEN chromium-tab. Twee // opeenvolgende media-sends (pagina's van één dienst óf afbeeldingen naar // verschillende ontvangers) mogen niet overlappen — dat veroorzaakt de staged- // ghost-race (2e send verliest). Wacht dus altijd MEDIA_SEND_DELAY_MS ná een send.