diff --git a/.gitignore b/.gitignore index 3cf4c4e..288a359 100644 --- a/.gitignore +++ b/.gitignore @@ -11,8 +11,9 @@ data/ # 用户配置文件 backend/config/user-config.json -# 自己的启动文件 +# 自己的配置文件 start_me.bat +config.json #打包文件夹 dist/ diff --git a/README.md b/README.md index 73d7154..c879f6b 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Pixiv 下载浏览管理器是一个基于 Web 的应用程序,提供以下功 ### 便携版下载(如果不想自义定或者是懒) -如果懒得配置环境,可以直接下载便携版(日,我自己用怎么还被当成木马了,算了忽略一下,不放心就自己打包(npm bp运行一下即可,全局装个pkg)): +如果懒得配置环境,可以直接下载便携版(日,我自己用怎么还被当成木马了,算了忽略一下,不放心就自己打包(npm bp运行一下即可)): **方式一:直接下载(可能比较慢,服务器带宽有限辣)** - **下载链接**: [点我下载](https://sywb.top/Staticfiles/p%E4%B8%8B%E8%BD%BD%E5%99%A8.rar) @@ -40,7 +40,7 @@ Pixiv 下载浏览管理器是一个基于 Web 的应用程序,提供以下功 **方式二:发行版下载** - **发行版** : [点我跳转](https://github.com/kjqwer/pixiv-D/releases) -**使用说明**: 下载后解压,记事本打开start.bat配置代理(看readme有介绍),双击 `start.bat` 即可启动,打开网站,按照教程登录即可 +**使用说明**: 下载后解压,如需修改配置可编辑 `config.json` 文件(通常自动检测代理即可),双击 `pixiv-manager.exe` 即可启动,打开网站,按照教程登录即可 ### 环境要求 @@ -66,27 +66,46 @@ Pixiv 下载浏览管理器是一个基于 Web 的应用程序,提供以下功 ``` 4. **启动应用** - - 修改代理端口,请用记事本打开 `start.bat` 文件,修改PROXY_PORT端口号 - - 修改服务器端口,请用记事本打开 `start.bat` 文件,修改SERVER_PORT端口号(默认3000) - - 双击 `start.bat` 文件启动 + ```bash + # 在项目根目录执行 + node backend/start.js + ``` 5. **访问应用** - - 打开浏览器访问:http://localhost:3000 (默认端口,可修改) + - 打开浏览器访问:http://localhost:3001 (默认端口,可在 config.json 中修改) ## 🌐 代理配置 -当然既然能上P站,怎么上网就不多说了,代理别忘了配置,可以去软件里看(一定要改): +应用现在支持自动检测系统代理,通常情况下无需手动配置。如果你使用 Clash、V2Ray 等代理软件并已设置为系统代理,应用会自动使用。 -**修改代理端口**: -1. 用记事本打开 `start.bat` 文件 -2. 找到:`set PROXY_PORT=xxxx` -3. 将 `xxxx` 改为你的代理端口号 +### 自动代理检测(推荐) +- 应用会自动检测系统环境变量中的代理设置 +- 支持 HTTP_PROXY、HTTPS_PROXY 等标准环境变量 +- 无需手动配置,开箱即用 -**常见代理端口**: -- Clash: 7890 -- V2Ray: 10809 -- Shadowsocks: 1080 -- 其他代理软件请查看其设置页面获取端口号 +### 手动配置(可选) +如果自动检测不工作,可以手动配置: + +1. **修改配置文件**: + - 编辑项目根目录下的 `config.json` 文件 + - 设置 `proxy.enabled` 为具体端口号(如 7890) + - 设置 `proxy.port` 为对应端口 + +2. **常见代理端口**: + - Clash: 7890 + - V2Ray: 10809 + - Shadowsocks: 1080 + - 其他代理软件请查看其设置页面获取端口号 + +**配置示例**: +```json +{ + "proxy": { + "port": 7890, + "enabled": true + } +} +``` ## 🔐 登录认证 @@ -149,7 +168,8 @@ Pixiv 下载浏览管理器是一个基于 Web 的应用程序,提供以下功 │ └── src/ # 前端源码 ├── downloads/ # 下载目录 ├── data/ # 数据存储 -└── start.bat # 启动脚本 +├── config.json # 配置文件 +└── config.json.example # 配置文件示例 ``` ## 🤝 贡献 @@ -158,4 +178,4 @@ Pixiv 下载浏览管理器是一个基于 Web 的应用程序,提供以下功 ## 许可证 -MIT License \ No newline at end of file +MIT License \ No newline at end of file diff --git a/backend/server.js b/backend/server.js index 0527088..559698f 100644 --- a/backend/server.js +++ b/backend/server.js @@ -25,63 +25,33 @@ const logger = defaultLogger.child('Server'); class PixivServer { constructor() { - this.app = express(); + this.server = null; this.backend = null; - this.server = null; // 添加server实例引用 - this.port = 3000; // 默认端口,会在init时重新设置 - this.logLevel = process.env.LOG_LEVEL || 'info'; // 获取日志级别 - this.isVerboseMode = ['debug', 'trace'].includes(this.logLevel.toLowerCase()); // 检查是否为详细模式 - - // 保存启动时的命令行参数和环境变量 - this.startupArgs = { - argv: [...process.argv], // 复制命令行参数 - env: { - PORT: process.env.PORT, - PROXY_PORT: process.env.PROXY_PORT, - LOG_LEVEL: process.env.LOG_LEVEL, - NODE_ENV: process.env.NODE_ENV, - AUTO_OPEN_BROWSER: process.env.AUTO_OPEN_BROWSER, - UV_THREADPOOL_SIZE: process.env.UV_THREADPOOL_SIZE - } - }; } /** * 初始化服务器 */ async init() { - logger.info('正在初始化 Pixiv 后端服务器...'); + 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()); - // 重新设置端口(从环境变量获取) - this.port = process.env.PORT || 3000; + logger.info('初始化 Pixiv 服务器...'); + logger.info(`服务器端口: ${this.port}`); + logger.info(`日志级别: ${this.logLevel}`); - // 如果启用了详细模式,输出调试信息 - if (this.isVerboseMode) { - logger.info(`详细模式已启用 (日志级别: ${this.logLevel.toUpperCase()})`); - logger.debug('环境变量:', { - NODE_ENV: process.env.NODE_ENV, - PORT: process.env.PORT, - PROXY_PORT: process.env.PROXY_PORT, - LOG_LEVEL: process.env.LOG_LEVEL - }); - } - - // 设置代理 - proxyConfig.setEnvironmentVariables(); - - // 初始化 Pixiv 后端 + // 初始化后端核心 this.backend = new PixivBackend(); await this.backend.init(); - // 配置中间件 + // 设置中间件 this.setupMiddleware(); - // 配置路由 + // 设置路由 this.setupRoutes(); - // 配置错误处理 - this.setupErrorHandling(); - logger.info('服务器初始化完成'); } @@ -216,41 +186,11 @@ class PixivServer { await this.backend.cleanup?.(); } - logger.info('正在使用原始启动参数重新启动服务器...'); - - // 使用spawn重新启动进程,保持原始参数 - const { spawn } = require('child_process'); - const path = require('path'); - - // 构建启动命令 - const nodeExecutable = process.execPath; - const startScript = path.join(__dirname, 'start.js'); - - // 获取原始命令行参数(排除node和脚本路径) - const originalArgs = this.startupArgs.argv.slice(2); - - logger.info('重启命令:', nodeExecutable, [startScript, ...originalArgs]); - - // 启动新进程 - const child = spawn(nodeExecutable, [startScript, ...originalArgs], { - detached: true, - stdio: 'inherit', - env: { - ...process.env, - ...this.startupArgs.env // 恢复原始环境变量 - } - }); - - // 分离子进程 - child.unref(); - - logger.info('新进程已启动,当前进程即将退出'); - - // 延迟退出当前进程 - setTimeout(() => { - process.exit(0); - }, 500); + // 重新初始化并启动 + await this.init(); + await this.start(); + logger.info('服务器重启成功'); return { success: true, message: '服务器重启成功' }; } catch (error) { diff --git a/backend/start.js b/backend/start.js index c48b02d..f4971ef 100644 --- a/backend/start.js +++ b/backend/start.js @@ -4,110 +4,133 @@ * Pixiv 后端服务器启动脚本 */ +const fs = require('fs'); +const path = require('path'); + +// 加载配置文件 +function 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 { + console.log(`检测环境: ${isPackaged ? '打包环境' : '开发环境'}`); + console.log(`配置文件路径: ${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 } + }; + console.log('已加载配置文件'); + } else { + // 如果配置文件不存在,创建默认配置文件 + fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8'); + console.log('已创建默认配置文件:', configPath); + } + } catch (error) { + console.error('读取配置文件失败,使用默认配置:', error.message); + } + + return config; +} +// 加载配置 +const config = loadConfig(); + // 重要:必须在任何其他模块导入之前设置线程池大小 // 解决多个下载任务时的SSH连接阻塞问题 if (!process.env.UV_THREADPOOL_SIZE) { - process.env.UV_THREADPOOL_SIZE = '16'; // 增加到16个线程 + process.env.UV_THREADPOOL_SIZE = config.system.threadPoolSize.toString(); } -const PixivServer = require('./server'); - -// 解析命令行参数 -function parseArguments() { - const args = process.argv.slice(2); - const options = {}; - - for (let i = 0; i < args.length; i++) { - const arg = args[i]; - - // 处理 --key=value 格式 - if (arg.startsWith('--proxy-port=')) { - const port = parseInt(arg.split('=')[1]); - if (!isNaN(port)) { - options.proxyPort = port; - } - } else if (arg.startsWith('--server-port=')) { - const port = parseInt(arg.split('=')[1]); - if (!isNaN(port)) { - options.serverPort = port; - } - } else if (arg.startsWith('--log-level=')) { - const level = arg.split('=')[1].toUpperCase(); - if (['ERROR', 'WARN', 'INFO', 'DEBUG', 'TRACE'].includes(level)) { - options.logLevel = level; - } - } else if (arg.startsWith('--auto-open-browser=')) { - const value = arg.split('=')[1].toLowerCase(); - options.autoOpenBrowser = value === 'true'; - } - // 处理 --key value 格式(向后兼容) - else if (arg === '--proxy-port' && i + 1 < args.length) { - const port = parseInt(args[i + 1]); - if (!isNaN(port)) { - options.proxyPort = port; - } - i++; // 跳过下一个参数 - } else if (arg === '--server-port' && i + 1 < args.length) { - const port = parseInt(args[i + 1]); - if (!isNaN(port)) { - options.serverPort = port; - } - i++; // 跳过下一个参数 - } else if (arg === '--log-level' && i + 1 < args.length) { - const level = args[i + 1].toUpperCase(); - if (['ERROR', 'WARN', 'INFO', 'DEBUG', 'TRACE'].includes(level)) { - options.logLevel = level; - } - i++; // 跳过下一个参数 - } else if (arg === '--auto-open-browser' && i + 1 < args.length) { - const value = args[i + 1].toLowerCase(); - options.autoOpenBrowser = value === 'true'; - i++; // 跳过下一个参数 - } - } - - return options; -} - -// 获取命令行参数 -const cliOptions = parseArguments(); - // 设置环境变量 process.env.NODE_ENV = process.env.NODE_ENV || 'development'; // 设置日志级别环境变量 -if (cliOptions.logLevel) { - process.env.LOG_LEVEL = cliOptions.logLevel.toLowerCase(); +if (config.logging.level) { + process.env.LOG_LEVEL = config.logging.level.toLowerCase(); } -// 在设置环境变量后导入logger +// 在设置环境变量后导入logger和服务器 const { defaultLogger } = require('./utils/logger'); const logger = defaultLogger.child('Start'); +const PixivServer = require('./server'); -// 如果提供了代理端口,设置环境变量 -if (cliOptions.proxyPort) { - process.env.PROXY_PORT = cliOptions.proxyPort.toString(); - logger.info(`代理端口已设置为: ${cliOptions.proxyPort}`); +// 如果配置了代理,设置环境变量 +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 (cliOptions.serverPort) { - process.env.PORT = cliOptions.serverPort.toString(); - logger.info(`服务器端口已设置为: ${cliOptions.serverPort}`); +// 设置服务器端口 +if (config.server.port) { + process.env.PORT = config.server.port.toString(); + logger.info(`服务器端口已设置为: ${config.server.port}`); } // 输出日志级别信息 -if (cliOptions.logLevel) { - logger.info(`日志级别: ${cliOptions.logLevel}`); -} +logger.info(`日志级别: ${config.logging.level}`); // 设置自动打开浏览器选项 -if (cliOptions.autoOpenBrowser !== undefined) { - process.env.AUTO_OPEN_BROWSER = cliOptions.autoOpenBrowser.toString(); - logger.info(`自动打开浏览器: ${cliOptions.autoOpenBrowser ? '启用' : '禁用'}`); +if (config.server.autoOpenBrowser !== undefined) { + process.env.AUTO_OPEN_BROWSER = config.server.autoOpenBrowser.toString(); + logger.info(`自动打开浏览器: ${config.server.autoOpenBrowser ? '启用' : '禁用'}`); } logger.info('启动 Pixiv 后端服务器...'); +// logger.info('配置信息:', { +// serverPort: config.server.port, +// proxyMode: config.proxy.enabled, +// proxyPort: config.proxy.enabled === true && config.proxy.port ? config.proxy.port : +// (config.proxy.enabled === "auto" ? '自动检测' : '未启用'), +// logLevel: config.logging.level, +// autoOpenBrowser: config.server.autoOpenBrowser, +// threadPoolSize: config.system.threadPoolSize +// }); // 创建服务器实例 const server = new PixivServer(); diff --git a/backend/utils/logger.js b/backend/utils/logger.js index dfcd4ff..02a6163 100644 --- a/backend/utils/logger.js +++ b/backend/utils/logger.js @@ -60,6 +60,7 @@ const ModuleColors = { 'UpdateRoute': '\x1b[93m', // 亮黄色 'ArtistService': '\x1b[95m', // 亮紫色 'DownloadService': '\x1b[96m', // 亮青色 + 'AbortControllerManager': '\x1b[94m', // 亮蓝色 'Default': '\x1b[39m' // 默认颜色 }; diff --git a/config.json.example b/config.json.example new file mode 100644 index 0000000..a316111 --- /dev/null +++ b/config.json.example @@ -0,0 +1,16 @@ +{ + "server": { + "port": 3001, + "autoOpenBrowser": false + }, + "proxy": { + "port": null, + "enabled": "auto" + }, + "logging": { + "level": "INFO" + }, + "system": { + "threadPoolSize": 16 + } +} \ No newline at end of file diff --git a/scripts/create-portable.js b/scripts/create-portable.js index 7081ada..38dc290 100644 --- a/scripts/create-portable.js +++ b/scripts/create-portable.js @@ -21,107 +21,99 @@ async function createPortable() { await fs.copy(exePath, path.join(portableDir, exeName)); } - // 创建启动脚本 - const startScript = `@echo off - -title Pixiv Manager - -REM ======================================== -REM Proxy Configuration - Modify port according to your proxy software -REM Common ports: Clash=7890, V2Ray=10809, Shadowsocks=1080 -REM ======================================== -set PROXY_PORT=7890 - -REM ======================================== -REM Server Port Configuration - Default 3000 -REM ======================================== -set SERVER_PORT=3000 - -REM ======================================== -REM Log Level Configuration - Options: ERROR, WARN, INFO, DEBUG, TRACE -REM ERROR: Show only error messages -REM WARN: Show warning and above level messages -REM INFO: Show general information and above level messages (default) -REM DEBUG: Show debug information and above level messages -REM TRACE: Show all level messages (most detailed) -REM ======================================== -set LOG_LEVEL=INFO - -REM ======================================== -REM Auto Open Browser Configuration - Options: true, false -REM true: Automatically open browser when server starts (default) -REM false: Do not automatically open browser -REM ======================================== -set AUTO_OPEN_BROWSER=true - -echo. -echo ======================================== -echo Pixiv Manager Starting... -echo ======================================== -echo. - -cd /d "%~dp0" - -echo Current proxy port: %PROXY_PORT% -echo Current server port: %SERVER_PORT% -echo Log level: %LOG_LEVEL% -echo To modify settings, edit this file with notepad -echo. - -echo Starting backend server... -echo Access URL: http://localhost:%SERVER_PORT% -echo. -echo Tip: Press Ctrl+C to stop server -echo. - -REM Start server and pass proxy port, server port and log level -if "%PROXY_PORT%"=="" ( - pixiv-manager.exe --server-port=%SERVER_PORT% --log-level=%LOG_LEVEL% --auto-open-browser=%AUTO_OPEN_BROWSER% -) else ( - pixiv-manager.exe --proxy-port=%PROXY_PORT% --server-port=%SERVER_PORT% --log-level=%LOG_LEVEL% --auto-open-browser=%AUTO_OPEN_BROWSER% -) - -echo. -echo Server stopped -pause -`; + // 创建配置文件 + const config = { + server: { + port: 3000, + autoOpenBrowser: true + }, + proxy: { + port: null, + enabled: "auto" + }, + logging: { + level: "INFO" + }, + system: { + threadPoolSize: 16 + } + }; - await fs.writeFile(path.join(portableDir, 'start.bat'), startScript, 'utf8'); + await fs.writeFile(path.join(portableDir, 'config.json'), JSON.stringify(config, null, 2), 'utf8'); // 创建README const readme = `# Pixiv Manager 便携版 ## 使用说明 -1. 双击 \`start.bat\` 启动程序 +1. 双击 \`pixiv-manager.exe\` 启动程序 2. 在浏览器中访问 http://localhost:3000 3. 按 Ctrl+C 停止服务器 ## 配置设置 -如需修改配置,请用记事本编辑 \`start.bat\` 文件: +如需修改配置,请用记事本编辑 \`config.json\` 文件: ### 代理设置(重要) -修改(PROXY_PORT=xxxx)的端口号: +修改 proxy 部分: +\`\`\`json +{ + "proxy": { + "port": null, // 代理端口号(auto模式下可为null) + "enabled": "auto" // 代理模式:true/false/"auto" + } +} +\`\`\` + +代理模式说明: +- \`"auto"\`: 自动检测系统代理(推荐) +- \`true\`: 启用指定端口的代理 +- \`false\`: 禁用代理 + +常见代理端口: - Clash: 7890 - V2Ray: 10809 - Shadowsocks: 1080 +**推荐使用 "auto" 模式**,程序会自动检测 Clash 等代理软件的系统代理设置。 + ### 服务器端口设置 -修改(SERVER_PORT=xxxx)的端口号,默认为3000 +修改 server 部分: +\`\`\`json +{ + "server": { + "port": 3000, // 服务器端口,默认3000 + "autoOpenBrowser": true // 是否自动打开浏览器 + } +} +\`\`\` ### 日志级别设置 -修改(LOG_LEVEL=xxxx)的日志级别,可选值: +修改 logging 部分: +\`\`\`json +{ + "logging": { + "level": "INFO" // 日志级别 + } +} +\`\`\` + +可选的日志级别: - ERROR: 只显示错误信息 - WARN: 显示警告及以上级别信息 - INFO: 显示一般信息及以上级别信息(默认) - DEBUG: 显示调试信息及以上级别信息 - TRACE: 显示所有级别信息(最详细) -### 自动打开浏览器设置 -修改(AUTO_OPEN_BROWSER=xxxx)的值来启用或禁用自动打开浏览器功能: -- true: 启动服务器后自动打开浏览器(默认) -- false: 不自动打开浏览器 +### 系统设置 +修改 system 部分: +\`\`\`json +{ + "system": { + "threadPoolSize": 16 // 线程池大小,影响下载性能 + } +} +\`\`\` ## 注意事项 @@ -129,6 +121,7 @@ pause - 程序会在当前目录创建数据文件夹 - 没代理或者代理设置错误无法成功登录,注意仔细检查,获取code的时间比较短,记得快速操作 - 支持Windows 10/11 64位系统 +- 修改配置文件后需要重启程序才能生效 `; await fs.writeFile(path.join(portableDir, 'README.txt'), readme, 'utf8'); diff --git a/start.bat b/start.bat deleted file mode 100644 index ff7480b..0000000 --- a/start.bat +++ /dev/null @@ -1,52 +0,0 @@ -@echo off -chcp 65001 >nul - -REM ======================================== -REM 代理配置 - 请根据你的代理软件修改端口号 -REM 常见端口: Clash=7890, V2Ray=10809, Shadowsocks=1080 -REM ======================================== -set PROXY_PORT= - -REM ======================================== -REM 服务器端口配置 - 默认3000 -REM ======================================== -set SERVER_PORT=3000 - -REM ======================================== -REM 日志级别配置 - 可选值: ERROR, WARN, INFO, DEBUG, TRACE -REM ERROR: 只显示错误信息 -REM WARN: 显示警告及以上级别信息 -REM INFO: 显示一般信息及以上级别信息 (默认) -REM DEBUG: 显示调试信息及以上级别信息 -REM TRACE: 显示所有级别信息 (最详细) -REM ======================================== -set LOG_LEVEL=DEBUG - -echo. -echo Pixiv Manager 启动中... -echo. - -cd /d "%~dp0" - -echo 当前代理端口: %PROXY_PORT% -echo 当前服务器端口: %SERVER_PORT% -echo 日志级别: %LOG_LEVEL% -echo 如需修改端口或日志级别,请用记事本打开此文件,修改对应的配置 -echo. - -echo 启动后端服务器... -echo 访问地址: http://localhost:%SERVER_PORT% -echo. -echo 提示: 按 Ctrl+C 停止服务器 -echo. - -REM 启动服务器并传递代理端口、服务器端口和日志级别 -if "%PROXY_PORT%"=="" ( - node backend/start.js --server-port=%SERVER_PORT% --log-level=%LOG_LEVEL% -) else ( - node backend/start.js --proxy-port=%PROXY_PORT% --server-port=%SERVER_PORT% --log-level=%LOG_LEVEL% -) - -echo. -echo 服务器已停止 -pause \ No newline at end of file