import express from 'express'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import { createLogger } from './utils/logger.js'; import { config, validateConfig } from './config/index.js'; import { notionClient } from './services/NotionClient.js'; import { streamManager } from './services/StreamManager.js'; import { proxyPool } from './ProxyPool.js'; import { proxyServer } from './ProxyServer.js'; import { requestLogger, errorHandler, requestLimits } from './middleware/auth.js'; import apiRouter from './routes/api.js'; // 获取当前目录 const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const logger = createLogger('App'); /** * 应用程序类 * 负责初始化和管理整个应用 */ class Application { constructor() { this.app = express(); this.server = null; } /** * 配置Express中间件 */ configureMiddleware() { // 请求体解析 this.app.use(express.json(requestLimits.json)); this.app.use(express.urlencoded(requestLimits.urlencoded)); // 静态文件服务 const publicPath = join(dirname(__dirname), 'public'); this.app.use(express.static(publicPath)); // 管理界面路由 this.app.get('/admin', (req, res) => { res.sendFile(join(publicPath, 'admin.html')); }); // 请求日志 this.app.use(requestLogger); // API路由 this.app.use(apiRouter); // 错误处理(必须放在最后) this.app.use(errorHandler); } /** * 初始化服务 */ async initializeServices() { // 验证配置 const configErrors = validateConfig(); if (configErrors.length > 0) { throw new Error(`配置错误:\n${configErrors.join('\n')}`); } // 初始化代理服务器 if (config.proxy.enableServer) { try { await proxyServer.start(); logger.success('代理服务器启动成功'); } catch (error) { logger.error(`启动代理服务器失败: ${error.message}`); // 代理服务器启动失败不应该阻止应用启动 } } // 初始化Notion客户端 await notionClient.initialize(); // 初始化代理池 if (config.proxy.useNativePool) { logger.info('正在初始化本地代理池...'); proxyPool.logLevel = 'info'; proxyPool.showProgressBar = true; proxyPool.setCountry(config.proxy.country); await proxyPool.initialize(); logger.success(`代理池初始化完成,当前代理国家: ${proxyPool.proxyCountry}`); } } /** * 启动应用 */ async start() { try { // 初始化服务 await this.initializeServices(); // 配置中间件 this.configureMiddleware(); // 启动服务器 this.server = this.app.listen(config.server.port, () => { logger.info(`服务已启动 - 端口: ${config.server.port}`); logger.info(`访问地址: http://localhost:${config.server.port}`); logger.info(`管理界面: http://localhost:${config.server.port}/admin`); const status = notionClient.getStatus(); if (status.initialized) { logger.success('系统初始化状态: ✅'); logger.success(`可用cookie数量: ${status.validCookies}`); } else { logger.warning('系统初始化状态: ❌'); logger.warning('警告: 系统未成功初始化,API调用将无法正常工作'); logger.warning('请检查NOTION_COOKIE配置是否有效'); } }); } catch (error) { logger.error(`应用启动失败: ${error.message}`, error); process.exit(1); } } /** * 优雅关闭应用 */ async shutdown() { logger.info('正在关闭应用...'); // 关闭所有活跃流 streamManager.closeAll(); // 关闭代理服务器 if (proxyServer) { try { proxyServer.stop(); logger.info('代理服务器已关闭'); } catch (error) { logger.error(`关闭代理服务器时出错: ${error.message}`); } } // 关闭Express服务器 if (this.server) { await new Promise((resolve) => { this.server.close(resolve); }); logger.info('HTTP服务器已关闭'); } logger.success('应用已优雅关闭'); } } // 创建应用实例 const application = new Application(); // 注册进程信号处理 process.on('SIGINT', handleShutdown); process.on('SIGTERM', handleShutdown); process.on('SIGQUIT', handleShutdown); async function handleShutdown(signal) { logger.info(`收到${signal}信号,正在关闭应用...`); await application.shutdown(); process.exit(0); } // 处理未捕获的异常 process.on('uncaughtException', (error) => { logger.error('未捕获的异常:', error); process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { logger.error('未处理的Promise拒绝:', reason); process.exit(1); }); application.start(); export { application };