// src/conversations.js — Log de conversas comprimido (gzip streaming), ocupa pouquíssimo espaço. // Um arquivo por dia: AAAA-MM-DD.log.gz. Cada linha: epoch \t telefone \t u|b \t texto. // Usa um único stream gzip por dia com Z_SYNC_FLUSH: mantém o dicionário de // compressão entre mensagens (ótima taxa) e grava na hora (sem perder em queda). import { createWriteStream, mkdirSync } from 'node:fs'; import zlib from 'node:zlib'; const DIR = process.env.AUTH_DIR ? '/data/conversations' : new URL('../data/conversations', import.meta.url).pathname; let gz = null; // stream gzip atual let day = null; // dia (YYYY-MM-DD) do stream aberto function today() { return new Date().toISOString().slice(0, 10); } function ensureStream() { const d = today(); if (gz && d === day) return; if (gz) gz.end(); // vira o dia → fecha o gzip anterior (flush final) day = d; mkdirSync(DIR, { recursive: true }); const out = createWriteStream(`${DIR}/${d}.log.gz`, { flags: 'a' }); // append: membros gzip concatenados gz = zlib.createGzip({ level: 9 }); gz.on('error', (e) => console.error('conv gzip erro:', e.message)); gz.pipe(out); } // dir: 'u' (usuário) ou 'b' (bot) export function logMessage(jid, dir, text) { try { ensureStream(); const ts = Math.floor(Date.now() / 1000); const phone = String(jid).split('@')[0]; const clean = String(text).replace(/\s+/g, ' ').trim(); if (!clean) return; gz.write(`${ts}\t${phone}\t${dir}\t${clean}\n`); gz.flush(zlib.constants.Z_SYNC_FLUSH); // grava já, sem resetar o dicionário } catch (e) { console.error('log conversa falhou:', e.message); } } export function conversationsDir() { return DIR; } function close() { try { gz?.end(); } catch { /* noop */ } } process.on('SIGTERM', () => { close(); process.exit(0); }); process.on('SIGINT', () => { close(); process.exit(0); });