123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- const express = require('express');
- const cors = require('cors');
- const helmet = require('helmet');
- const compression = require('compression');
- require('dotenv').config();
- const logger = require('./utils/logger');
- const sequelize = require('./config/database');
- const routes = require('./api/routes');
- const Scheduler = require('./core/scheduler');
- const MultiSubscriptionManager = require('./core/multiSubscriptionManager');
- const BotManager = require('./core/botManager');
- const app = express();
- const PORT = process.env.PORT || 3000;
- // 中间件
- app.use(helmet({
- contentSecurityPolicy: {
- directives: {
- defaultSrc: ["'self'"],
- styleSrc: ["'self'", "'unsafe-inline'", "https://cdn.jsdelivr.net"],
- scriptSrc: ["'self'", "'unsafe-inline'", "https://cdn.jsdelivr.net"],
- scriptSrcAttr: ["'unsafe-inline'"],
- fontSrc: ["'self'", "https://cdn.jsdelivr.net", "data:"],
- imgSrc: ["'self'", "data:", "https:"],
- mediaSrc: ["'self'", "data:"],
- connectSrc: ["'self'"],
- frameSrc: ["'none'"],
- objectSrc: ["'none'"],
- upgradeInsecureRequests: []
- }
- }
- }));
- app.use(compression());
- app.use(cors());
- app.use(express.json({ limit: '10mb' }));
- app.use(express.urlencoded({ extended: true, limit: '10mb' }));
- // 静态文件服务
- app.use(express.static('public'));
- // 请求日志中间件 - 只记录重要请求
- app.use((req, res, next) => {
- // 只记录重要的API请求,不记录频繁的自动刷新请求
- if (req.path.startsWith('/api/') &&
- !req.path.includes('/favicon') &&
- !req.path.includes('/sw.js') &&
- !req.path.includes('/stats') &&
- !req.path.includes('/test/results')) {
- logger.info(`${req.method} ${req.path}`);
- }
- next();
- });
- // API路由
- app.use('/api', routes);
- // 健康检查
- app.get('/health', (req, res) => {
- res.json({
- status: 'ok',
- timestamp: new Date().toISOString(),
- uptime: process.uptime()
- });
- });
- // 根路径
- app.get('/', (req, res) => {
- res.json({
- name: 'Clash Speed Test',
- version: '1.0.0',
- description: 'Clash节点测速工具,支持定时监控和Telegram通知',
- endpoints: {
- health: '/health',
- api: '/api'
- }
- });
- });
- // 错误处理中间件
- app.use((err, req, res, next) => {
- logger.error('未处理的错误', {
- error: err.message,
- stack: err.stack,
- path: req.path,
- method: req.method
- });
- res.status(500).json({
- success: false,
- error: process.env.NODE_ENV === 'production' ? '服务器内部错误' : err.message
- });
- });
- // 404处理
- app.use('*', (req, res) => {
- res.status(404).json({
- success: false,
- error: '接口不存在'
- });
- });
- // 处理未捕获的Promise拒绝
- process.on('unhandledRejection', (reason, promise) => {
- logger.error('未处理的Promise拒绝', {
- reason: {
- code: reason.code,
- message: reason.message
- },
- promise: {
- isFulfilled: promise.isFulfilled,
- isRejected: promise.isRejected,
- rejectionReason: promise.rejectionReason
- }
- });
- });
- // 启动应用
- async function startApp() {
- try {
- // 测试数据库连接
- await sequelize.authenticate();
- logger.info('数据库连接成功');
- // 同步数据库模型
- await sequelize.sync({ alter: true });
- logger.info('数据库模型同步完成');
- // 启动调度器
- const scheduler = new Scheduler();
- scheduler.start();
- app.set('scheduler', scheduler);
- // 启动多订阅管理器
- const subscriptionManager = new MultiSubscriptionManager();
- subscriptionManager.startAutoUpdate();
-
- // 设置测速触发器
- subscriptionManager.setSpeedTestTrigger(() => {
- scheduler.runSpeedTest().catch(error => {
- logger.error('订阅更新后自动测速失败', { error: error.message });
- });
- });
-
- app.set('subscriptionManager', subscriptionManager);
- // 启动Telegram机器人管理器
- const botManager = new BotManager();
- app.set('botManager', botManager);
- // 检查是否启用启动时立即测速
- const enableStartupSpeedTest = process.env.ENABLE_SCHEDULED_SPEED_TEST !== 'false';
-
- if (enableStartupSpeedTest) {
- // 立即开始测速
- setTimeout(async () => {
- try {
- logger.info('应用启动后立即开始测速');
- await scheduler.runSpeedTest();
- } catch (error) {
- logger.error('启动测速失败', { error: error.message });
- }
- }, 3000); // 延迟3秒开始,确保应用完全启动
- } else {
- logger.info('启动时立即测速功能已禁用');
- }
- // 启动服务器
- app.listen(PORT, () => {
- logger.info(`服务器启动成功,端口: ${PORT}`);
- logger.info(`前端界面: http://localhost:${PORT}`);
- });
- } catch (error) {
- logger.error('应用启动失败', { error: error.message });
- process.exit(1);
- }
- }
- // 优雅关闭
- process.on('SIGTERM', async () => {
- logger.info('收到SIGTERM信号,开始优雅关闭');
-
- const scheduler = app.get('scheduler');
- if (scheduler) {
- scheduler.stop();
- }
-
- const subscriptionManager = app.get('subscriptionManager');
- if (subscriptionManager) {
- subscriptionManager.stopAutoUpdate();
- }
-
- const botManager = app.get('botManager');
- if (botManager) {
- botManager.stop();
- }
-
- await sequelize.close();
- logger.info('应用已关闭');
- process.exit(0);
- });
- process.on('SIGINT', async () => {
- logger.info('收到SIGINT信号,开始优雅关闭');
-
- const scheduler = app.get('scheduler');
- if (scheduler) {
- scheduler.stop();
- }
-
- const subscriptionManager = app.get('subscriptionManager');
- if (subscriptionManager) {
- subscriptionManager.stopAutoUpdate();
- }
-
- const botManager = app.get('botManager');
- if (botManager) {
- botManager.stop();
- }
-
- await sequelize.close();
- logger.info('应用已关闭');
- process.exit(0);
- });
- // 未捕获的异常处理
- process.on('uncaughtException', (error) => {
- logger.error('未捕获的异常', { error: error.message, stack: error.stack });
- process.exit(1);
- });
- process.on('unhandledRejection', (reason, promise) => {
- logger.error('未处理的Promise拒绝', { reason, promise });
- process.exit(1);
- });
- // 启动应用
- startApp();
|