const express = require('express'); const cors = require('cors'); const path = require('path'); const fs = require('fs'); // 导入logger const { defaultLogger } = require('./utils/logger'); // 导入中间件 const { errorHandler } = require('./middleware/errorHandler'); const { loggerMiddleware } = require('./middleware/logger'); const { corsMiddleware } = require('./middleware/cors'); const { bodyParserMiddleware } = require('./middleware/bodyParser'); const { staticFilesMiddleware } = require('./middleware/staticFiles'); const { backendInjector } = require('./middleware/backendInjector'); // 导入路由配置 const { setupRoutes } = require('./routes'); // 导入核心模块 const PixivBackend = require('./core'); const proxyConfig = require('./config'); // 创建logger实例 const logger = defaultLogger.child('Server'); class PixivServer { constructor() { this.server = null; this.backend = null; } /** * 加载配置文件 */ loadConfig() { // 检测是否在pkg打包环境中运行 const isPackaged = process.pkg !== undefined; // 在打包环境中,配置文件在当前工作目录;在开发环境中,配置文件在上级目录 const configPath = isPackaged ? path.join(process.cwd(), 'config.json') // 打包环境:当前工作目录 : path.join(__dirname, '..', 'config.json'); // 开发环境:上级目录 let config = { server: { port: 3000, autoOpenBrowser: true }, proxy: { port: null, enabled: false }, logging: { level: "INFO" }, system: { threadPoolSize: 16 } }; try { logger.info(`检测环境: ${isPackaged ? '打包环境' : '开发环境'}`); logger.info(`配置文件路径: ${configPath}`); if (fs.existsSync(configPath)) { const configData = fs.readFileSync(configPath, 'utf8'); const userConfig = JSON.parse(configData); // 合并配置,用户配置覆盖默认配置 config = { ...config, server: { ...config.server, ...userConfig.server }, proxy: { ...config.proxy, ...userConfig.proxy }, logging: { ...config.logging, ...userConfig.logging }, system: { ...config.system, ...userConfig.system } }; logger.info('已加载配置文件'); } else { // 如果配置文件不存在,创建默认配置文件 fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8'); logger.info('已创建默认配置文件:', configPath); } } catch (error) { logger.error('读取配置文件失败,使用默认配置:', error.message); } return config; } /** * 应用配置到环境变量 */ applyConfig(config) { // 设置线程池大小 if (!process.env.UV_THREADPOOL_SIZE) { process.env.UV_THREADPOOL_SIZE = config.system.threadPoolSize.toString(); } // 设置环境变量 process.env.NODE_ENV = process.env.NODE_ENV || 'development'; // 设置日志级别环境变量 if (config.logging.level) { process.env.LOG_LEVEL = config.logging.level.toLowerCase(); } // 如果配置了代理,设置环境变量 if (config.proxy.enabled === true || (config.proxy.enabled === "auto" && config.proxy.port)) { // 显式配置代理端口 if (config.proxy.port) { process.env.PROXY_PORT = config.proxy.port.toString(); logger.info(`代理端口已设置为: ${config.proxy.port}`); } } else if (config.proxy.enabled === "auto") { // 自动检测系统代理 const systemProxy = process.env.HTTP_PROXY || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.https_proxy; if (systemProxy) { logger.info(`检测到系统代理: ${systemProxy}`); // 从系统代理URL中提取端口 const match = systemProxy.match(/http:\/\/127\.0\.0\.1:(\d+)/); if (match) { process.env.PROXY_PORT = match[1]; logger.info(`自动设置代理端口为: ${match[1]}`); } } else { logger.info('未检测到系统代理,将尝试使用系统代理环境变量'); } } // 设置服务器端口 if (config.server.port) { process.env.PORT = config.server.port.toString(); logger.info(`服务器端口已设置为: ${config.server.port}`); } // 设置自动打开浏览器选项 if (config.server.autoOpenBrowser !== undefined) { process.env.AUTO_OPEN_BROWSER = config.server.autoOpenBrowser.toString(); logger.info(`自动打开浏览器: ${config.server.autoOpenBrowser ? '启用' : '禁用'}`); } logger.info(`日志级别: ${config.logging.level}`); } /** * 初始化服务器 */ async init() { this.app = express(); this.port = parseInt(process.env.PORT) || 3000; this.logLevel = process.env.LOG_LEVEL || 'info'; this.isVerboseMode = ['debug', 'trace'].includes(this.logLevel.toLowerCase()); logger.info('初始化 Pixiv 服务器...'); logger.info(`服务器端口: ${this.port}`); logger.info(`日志级别: ${this.logLevel}`); // 初始化后端核心 this.backend = new PixivBackend(); await this.backend.init(); // 设置中间件 this.setupMiddleware(); // 设置路由 this.setupRoutes(); logger.info('服务器初始化完成'); } /** * 配置中间件 */ setupMiddleware() { // 自定义日志中间件 this.app.use(loggerMiddleware); // CORS 中间件 this.app.use(corsMiddleware()); // Body Parser 中间件 this.app.use(bodyParserMiddleware()); // 静态文件服务中间件 const staticMiddlewares = staticFilesMiddleware(); this.app.use('/downloads', staticMiddlewares[0]); // 下载文件静态服务 this.app.use(staticMiddlewares[1]); // 前端静态文件服务 // 后端实例注入中间件 this.app.use(backendInjector(this.backend)); // 将服务器实例保存到app.locals中,供路由使用 this.app.locals.serverInstance = this; } /** * 配置路由 */ setupRoutes() { setupRoutes(this.app, this.backend); } /** * 配置错误处理 */ setupErrorHandling() { this.app.use(errorHandler); } /** * 启动服务器 */ start() { this.server = this.app.listen(this.port, () => { logger.info('Pixiv 后端服务器已启动2'); logger.info(`服务地址: http://localhost:${this.port}`); logger.info(`健康检查: http://localhost:${this.port}/health`); logger.info(`登录状态: ${this.backend.isLoggedIn ? '已登录' : '未登录'}`); if (this.backend.isLoggedIn) { logger.info(`用户: ${this.backend.config.user?.account}`); } if (this.isVerboseMode) { logger.info(`日志级别: ${this.logLevel.toUpperCase()}`); logger.debug(`服务器端口: ${this.port}`); logger.debug(`代理端口: ${process.env.PROXY_PORT || '未设置'}`); } logger.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); // 自动打开浏览器 if (process.env.AUTO_OPEN_BROWSER === 'true') { this.openBrowser(); } }); } /** * 打开浏览器 */ openBrowser() { const url = `http://localhost:${this.port}`; logger.info(`正在打开浏览器: ${url}`); const { spawn } = require('child_process'); const os = require('os'); const fs = require('fs'); const platform = os.platform(); // 在服务器环境中直接跳过打开浏览器 if (platform === 'linux') { // 直接跳过 Linux 服务器环境的浏览器打开 logger.info('在 Linux 服务器环境中,跳过打开浏览器'); return; } let command; let args = [url]; switch (platform) { case 'win32': command = 'cmd'; args = ['/c', 'start', '""', url]; break; case 'darwin': command = 'open'; break; default: logger.warn('不支持的操作系统,无法自动打开浏览器'); return; } try { const child = spawn(command, args, { detached: true, stdio: 'ignore', }); // 添加错误处理 child.on('error', (err) => { logger.warn('打开浏览器失败:', err.message); }); child.unref(); logger.info('浏览器打开命令已执行'); } catch (error) { logger.warn('打开浏览器失败:', error.message); } } /** * 重启服务器 */ async restart() { logger.info('正在重启服务器...'); try { // 关闭当前服务器 if (this.server) { await new Promise((resolve) => { this.server.close(() => { logger.info('HTTP服务器已关闭'); resolve(); }); }); } // 清理后端实例 if (this.backend) { await this.backend.cleanup?.(); } // 重新加载配置文件 const config = this.loadConfig(); // 重新应用配置到环境变量 this.applyConfig(config); // 重新初始化并启动 await this.init(); await this.start(); logger.info('服务器重启成功'); return { success: true, message: '服务器重启成功' }; } catch (error) { logger.error('服务器重启失败:', error); throw error; } } /** * 优雅关闭 */ async shutdown() { logger.info('正在关闭服务器...'); logger.info('服务器已关闭'); process.exit(0); } } // 如果直接运行此文件 if (require.main === module) { const server = new PixivServer(); // 处理进程信号 process.on('SIGINT', () => server.shutdown()); process.on('SIGTERM', () => server.shutdown()); // 启动服务器 server .init() .then(() => server.start()) .catch((error) => logger.error('服务器启动失败', error)); } module.exports = PixivServer;