import { assertConfig, config } from './config.js'; import { createBot } from './bot/panel.js'; import { openDb, purgeOld } from './core/db.js'; import { loadModules } from './core/loader.js'; import { logger } from './core/logger.js'; import { runHook } from './core/registry.js'; import { createContext } from './business/context.js'; import { wireBusiness } from './business/events.js'; // Бизнес-апдейты Telegram по умолчанию не приходят — их нужно запросить явно. const ALLOWED_UPDATES = [ 'message', 'callback_query', 'business_connection', 'business_message', 'edited_business_message', 'deleted_business_messages', ]; // 1. Конфиг и БД — падаем понятной ошибкой, если что-то не задано. try { assertConfig(); } catch (err) { logger.error(err.message); process.exit(1); } openDb(); // 2. Бот (единственный UI и приёмник бизнес-апдейтов) — запускаем в фоне. const bot = createBot(); bot .start({ allowed_updates: ALLOWED_UPDATES, onStart: ({ username }) => logger.info(`Панель поднята: @${username}`), }) .catch((err) => { logger.error('Бот не запустился (проверьте BOT_TOKEN):', err.message); process.exit(1); }); // 3. Модули: грузим и раздаём им бизнес-апдейты через хуки. const registry = await loadModules(); const ctx = createContext({ bot, registry }); await runHook(registry, 'setup', undefined, ctx); wireBusiness(bot, registry, ctx); logger.info(`Готово. Активных модулей: ${registry.list().map((m) => m.name).join(', ')}`); // 4. Периодическая чистка по сроку хранения. if (config.retentionDays > 0) { const timer = setInterval(() => { const { messages, captures } = purgeOld(); if (messages || captures) logger.info(`Чистка: удалено сообщений ${messages}, перехватов ${captures}`); }, 6 * 3600 * 1000); timer.unref(); } // 5. Аккуратная остановка. for (const signal of ['SIGINT', 'SIGTERM']) { process.once(signal, async () => { logger.info('Останавливаюсь…'); await bot.stop().catch(() => {}); process.exit(0); }); }