98 lines
3.7 KiB
JavaScript
98 lines
3.7 KiB
JavaScript
import { loadDotEnv, APP_HOST, APP_PORT, paths, telegramConfig } from '../src/env.mjs';
|
|
import { createTelegramAlerter } from '../src/alerts/telegram.mjs';
|
|
import {
|
|
hasCampaignsPausedByRestart,
|
|
notifyStartupState,
|
|
startInitialWhatsAppReconnect
|
|
} from '../src/alerts/runtime-alerts.mjs';
|
|
import { openDb, ensureSeeds, recoverPendingOutreach, updateOutreachMessageStatus } from '../src/db.mjs';
|
|
import { createJobManager, recoverOrphans } from '../src/jobs/manager.mjs';
|
|
import { createAppServer } from '../src/server/index.mjs';
|
|
import { startOutreachScheduler } from '../src/outreach/scheduler.mjs';
|
|
import { pauseCampaignsAfterRestart, recoverReservedCampaignQueue } from '../src/outreach/campaign-worker.mjs';
|
|
import { recordInboundReply } from '../src/outreach/inbound.mjs';
|
|
import { createWhatsAppManager, hasWhatsAppSession } from '../src/whatsapp/manager.mjs';
|
|
|
|
// Servidor local da Maquina Comercial Pessoal.
|
|
|
|
await loadDotEnv();
|
|
|
|
const log = (message) => console.log(`[servidor] ${message}`);
|
|
|
|
const db = openDb();
|
|
await ensureSeeds(db, { log });
|
|
recoverOrphans(db, log);
|
|
recoverPendingOutreach(db);
|
|
pauseCampaignsAfterRestart(db);
|
|
const campaignsPausedByRestart = hasCampaignsPausedByRestart(db);
|
|
recoverReservedCampaignQueue(db);
|
|
|
|
const tg = telegramConfig();
|
|
const alerter = createTelegramAlerter({ enabled: tg.enabled, token: tg.botToken, chatId: tg.chatId, log });
|
|
|
|
const jobs = createJobManager({ db });
|
|
const whatsapp = createWhatsAppManager({
|
|
authDir: paths.whatsappAuth,
|
|
log,
|
|
onMessageStatus: (event) => updateOutreachMessageStatus(db, event),
|
|
onInboundMessage: (event) => recordInboundReply(db, event)
|
|
});
|
|
void notifyStartupState({ alerter, whatsappStatus: whatsapp.getStatus().state, campaignsPausedByRestart, log });
|
|
await startInitialWhatsAppReconnect({
|
|
hasSession: () => hasWhatsAppSession(paths.whatsappAuth),
|
|
whatsapp,
|
|
alerter,
|
|
log
|
|
});
|
|
const server = createAppServer({ db, jobs, whatsapp, log });
|
|
const stopScheduler = startOutreachScheduler({ db, whatsapp, log });
|
|
|
|
const port = APP_PORT;
|
|
server.listen(port, APP_HOST, () => {
|
|
log(`Maquina Comercial Pessoal rodando em http://${APP_HOST}:${port}`);
|
|
if (APP_HOST === '127.0.0.1') log('somente este computador tem acesso (127.0.0.1). Ctrl+C para encerrar.');
|
|
else log('modo container/rede: proteja o acesso com proxy HTTPS e senha forte.');
|
|
});
|
|
|
|
let shuttingDown = false;
|
|
async function shutdown() {
|
|
if (shuttingDown) return;
|
|
shuttingDown = true;
|
|
log('encerrando...');
|
|
const watchdog = setTimeout(() => process.exit(1), 30_000);
|
|
watchdog.unref();
|
|
|
|
const shutdownTasks = [
|
|
stopScheduler().catch((error) => log(`outreach: falha ao encerrar scheduler: ${error.message}`)),
|
|
jobs.close().catch((error) => log(`jobs: falha ao encerrar: ${error.message}`)),
|
|
whatsapp.close().catch((error) => log(`whatsapp: falha ao encerrar: ${error.message}`))
|
|
];
|
|
let resourceTimer;
|
|
const resourcesTimedOut = await Promise.race([
|
|
Promise.allSettled(shutdownTasks).then(() => false),
|
|
new Promise((resolve) => {
|
|
resourceTimer = setTimeout(() => resolve(true), 20_000);
|
|
resourceTimer.unref();
|
|
})
|
|
]);
|
|
clearTimeout(resourceTimer);
|
|
if (resourcesTimedOut) log('encerramento dos recursos excedeu o prazo; prosseguindo');
|
|
|
|
recoverOrphans(db, log);
|
|
let httpTimer;
|
|
const httpTimedOut = await Promise.race([
|
|
new Promise((resolve) => server.close(resolve)).then(() => false),
|
|
new Promise((resolve) => {
|
|
httpTimer = setTimeout(() => resolve(true), 5_000);
|
|
httpTimer.unref();
|
|
})
|
|
]);
|
|
clearTimeout(httpTimer);
|
|
if (httpTimedOut) log('encerramento HTTP excedeu o prazo; prosseguindo');
|
|
db.close();
|
|
process.exit(0);
|
|
}
|
|
|
|
process.on('SIGINT', shutdown);
|
|
process.on('SIGTERM', shutdown);
|