From 124e01e93ae74ff78141b1c8093d63ef28d334ac Mon Sep 17 00:00:00 2001 From: whyour Date: Sat, 19 Apr 2025 01:38:43 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20QLAPI=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F=20remarks=EF=BC=8Cesm=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E6=9F=A5=E4=B8=8D=E5=88=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/api/system.ts | 1 + back/schedule/api.ts | 61 +++++++++++++++++++++++++++++----- shell/preload/sitecustomize.js | 53 ++++++++++++++++++++--------- shell/preload/sitecustomize.py | 60 +++++++++++++++++++++++---------- shell/share.sh | 12 ++++++- shell/update.sh | 25 ++++++++------ 6 files changed, 160 insertions(+), 52 deletions(-) diff --git a/back/api/system.ts b/back/api/system.ts index 7336d068..33f157a7 100644 --- a/back/api/system.ts +++ b/back/api/system.ts @@ -385,6 +385,7 @@ export default (app: Router) => { retries: Joi.number().optional(), twoFactorActivated: Joi.boolean().optional(), password: Joi.string().optional(), + username: Joi.string().optional(), }), }), async (req: Request, res: Response, next: NextFunction) => { diff --git a/back/schedule/api.ts b/back/schedule/api.ts index 09adec08..9b7ea28a 100644 --- a/back/schedule/api.ts +++ b/back/schedule/api.ts @@ -39,13 +39,6 @@ export const getEnvs = async ( callback: sendUnaryData, ) => { try { - if (!call.request.searchValue) { - return callback(null, { - code: 400, - data: [], - message: 'searchValue is required', - }); - } const envService = Container.get(EnvService); const data = await envService.envs(call.request.searchValue); callback(null, { @@ -79,9 +72,17 @@ export const updateEnv = async ( callback: sendUnaryData, ) => { try { + if (!call.request.env?.id) { + return callback(null, { + code: 400, + data: undefined, + message: 'id parameter is required', + }); + } + const envService = Container.get(EnvService); const data = await envService.update( - pick(call.request.env, ['id', 'name', 'value', 'remark']) as EnvItem, + pick(call.request.env, ['id', 'name', 'value', 'remarks']) as EnvItem, ); callback(null, { code: 200, data }); } catch (e: any) { @@ -94,6 +95,13 @@ export const deleteEnvs = async ( callback: sendUnaryData, ) => { try { + if (!call.request.ids || call.request.ids.length === 0) { + return callback(null, { + code: 400, + message: 'ids parameter is required', + }); + } + const envService = Container.get(EnvService); await envService.remove(call.request.ids); callback(null, { code: 200 }); @@ -107,6 +115,14 @@ export const moveEnv = async ( callback: sendUnaryData, ) => { try { + if (!call.request.id) { + return callback(null, { + code: 400, + data: undefined, + message: 'id parameter is required', + }); + } + const envService = Container.get(EnvService); const data = await envService.move(call.request.id, { fromIndex: call.request.fromIndex, @@ -123,6 +139,13 @@ export const disableEnvs = async ( callback: sendUnaryData, ) => { try { + if (!call.request.ids || call.request.ids.length === 0) { + return callback(null, { + code: 400, + message: 'ids parameter is required', + }); + } + const envService = Container.get(EnvService); await envService.disabled(call.request.ids); callback(null, { code: 200 }); @@ -136,6 +159,13 @@ export const enableEnvs = async ( callback: sendUnaryData, ) => { try { + if (!call.request.ids || call.request.ids.length === 0) { + return callback(null, { + code: 400, + message: 'ids parameter is required', + }); + } + const envService = Container.get(EnvService); await envService.enabled(call.request.ids); callback(null, { code: 200 }); @@ -149,6 +179,13 @@ export const updateEnvNames = async ( callback: sendUnaryData, ) => { try { + if (!call.request.ids || call.request.ids.length === 0) { + return callback(null, { + code: 400, + message: 'ids parameter is required', + }); + } + const envService = Container.get(EnvService); await envService.updateNames({ ids: call.request.ids, @@ -165,6 +202,14 @@ export const getEnvById = async ( callback: sendUnaryData, ) => { try { + if (!call.request.id) { + return callback(null, { + code: 400, + data: undefined, + message: 'id parameter is required', + }); + } + const envService = Container.get(EnvService); const data = await envService.getDb({ id: call.request.id }); callback(null, { diff --git a/shell/preload/sitecustomize.js b/shell/preload/sitecustomize.js index f80c57f8..8b89fc78 100644 --- a/shell/preload/sitecustomize.js +++ b/shell/preload/sitecustomize.js @@ -38,25 +38,48 @@ function run() { const splitStr = '__sitecustomize__'; const fileName = process.argv[1].replace(`${dir_scripts}/`, ''); - let command = `bash -c "source ${file_task_before} ${fileName}`; + const tempFile = `/tmp/env_${process.pid}.json`; + + const commands = [ + `source ${file_task_before} ${fileName}`, + task_before ? `eval '${task_before.replace(/'/g, "'\\''")}'` : null, + `echo -e '${splitStr}'`, + `node -e "require('fs').writeFileSync('${tempFile}', JSON.stringify(process.env))"`, + ].filter(Boolean); + if (task_before) { - const escapeTaskBefore = task_before - .replace(/"/g, '\\"') - .replace(/\$/g, '\\$'); - command = `${command} && eval '${escapeTaskBefore}'`; console.log('执行前置命令\n'); } - const res = execSync( - `${command} && echo -e '${splitStr}' && node -p 'JSON.stringify(process.env)'"`, - { - encoding: 'utf-8', - }, - ); - const [output, envStr] = res.split(splitStr); - const newEnvObject = JSON.parse(envStr.trim()); - for (const key in newEnvObject) { - process.env[key] = newEnvObject[key]; + + const res = execSync(commands.join(' && '), { + encoding: 'utf-8', + maxBuffer: 50 * 1024 * 1024, + shell: '/bin/bash', + }); + + const [output] = res.split(splitStr); + + try { + const envStr = require('fs').readFileSync(tempFile, 'utf-8'); + const newEnvObject = JSON.parse(envStr); + if (typeof newEnvObject === 'object' && newEnvObject !== null) { + for (const key in newEnvObject) { + if (Object.prototype.hasOwnProperty.call(newEnvObject, key)) { + process.env[key] = newEnvObject[key]; + } + } + } + require('fs').unlinkSync(tempFile); + } catch (jsonError) { + console.log( + '\ue926 Failed to parse environment variables:', + jsonError.message, + ); + try { + require('fs').unlinkSync(tempFile); + } catch (e) {} } + if (output) { console.log(output); } diff --git a/shell/preload/sitecustomize.py b/shell/preload/sitecustomize.py index 3d3626f7..6e1b95b2 100644 --- a/shell/preload/sitecustomize.py +++ b/shell/preload/sitecustomize.py @@ -43,35 +43,57 @@ def run(): split_str = "__sitecustomize__" file_name = sys.argv[0].replace(f"{os.getenv('dir_scripts')}/", "") - command = f'bash -c "source {os.getenv("file_task_before")} {file_name}' + + # 创建临时文件路径 + temp_file = f"/tmp/env_{os.getpid()}.json" + + # 构建命令数组 + commands = [ + f'source {os.getenv("file_task_before")} {file_name}' + ] + task_before = os.getenv("task_before") - if task_before: - escape_task_before = task_before.replace('"', '\\"').replace("$", "\\$") - command += f" && eval '{escape_task_before}'" + escaped_task_before = task_before.replace("'", "'\\''") + commands.append(f"eval '{escaped_task_before}'") print("执行前置命令\n") - - prev_pythonpath = os.getenv("PREV_PYTHONPATH", "") - python_command = ( - "python3 -c 'import os, json; print(json.dumps(dict(os.environ)))'" - ) - command += f" && echo -e '{split_str}' && {python_command}\"" + + commands.append(f"echo -e '{split_str}'") + + # 修改 Python 命令,使用单行并正确处理引号 + python_cmd = f"python3 -c 'import os,json; f=open(\\\"{temp_file}\\\",\\\"w\\\"); json.dump(dict(os.environ),f); f.close()'" + commands.append(python_cmd) + + command = " && ".join(cmd for cmd in commands if cmd) + command = f'bash -c "{command}"' res = subprocess.check_output(command, shell=True, encoding="utf-8") - output, env_str = res.split(split_str) + output = res.split(split_str)[0] - env_json = json.loads(env_str.strip()) + try: + with open(temp_file, 'r') as f: + env_json = json.loads(f.read()) - for key, value in env_json.items(): - os.environ[key] = value + for key, value in env_json.items(): + os.environ[key] = value + + os.unlink(temp_file) + except Exception as json_error: + print(f"\ue926 Failed to parse environment variables: {json_error}") + try: + os.unlink(temp_file) + except: + pass if len(output) > 0: print(output) if task_before: - print("执行前置命令结束") + print("执行前置命令结束\n") except subprocess.CalledProcessError as error: - print(f"run task before error: {error}") + print(f"\ue926 run task before error: {error}") + if task_before: + print("执行前置命令结束\n") except OSError as error: error_message = str(error) if "Argument list too long" not in error_message: @@ -81,9 +103,11 @@ def run(): "\ue926 The environment variable is too large. It is recommended to use task_before.py instead of task_before.sh\n" ) if task_before: - print("执行前置命令结束") + print("执行前置命令结束\n") except Exception as error: - print(f"run task before error: {error}") + print(f"\ue926 run task before error: {error}") + if task_before: + print("执行前置命令结束\n") import task_before diff --git a/shell/share.sh b/shell/share.sh index a63efd72..7bcc66fa 100755 --- a/shell/share.sh +++ b/shell/share.sh @@ -72,7 +72,17 @@ original_name=( ) init_env() { - export NODE_PATH=/usr/local/bin:/usr/local/pnpm-global/5/node_modules:/usr/local/lib/node_modules:/root/.local/share/pnpm/global/5/node_modules + local pnpm_global_path=$(pnpm root -g 2>/dev/null) + export NODE_PATH="/usr/local/bin:/usr/local/lib/node_modules${pnpm_global_path:+:${pnpm_global_path}}" + + # 如果存在 pnpm 全局路径,创建软链接 + if [[ -n "$pnpm_global_path" ]]; then + # 确保目标目录存在 + mkdir -p "${dir_root}/node_modules" + # 链接全局模块到项目的 node_modules + ln -sf "${pnpm_global_path}/"* "${dir_root}/node_modules/" 2>/dev/null || true + fi + export PYTHONUNBUFFERED=1 } diff --git a/shell/update.sh b/shell/update.sh index ef56db1c..6d161ad7 100755 --- a/shell/update.sh +++ b/shell/update.sh @@ -212,16 +212,18 @@ run_extra_shell() { ## 脚本用法 usage() { - echo -e "ql命令使用方法:" - echo -e "1. $cmd_update update # 更新并重启青龙" - echo -e "2. $cmd_update extra # 运行自定义脚本" - echo -e "3. $cmd_update raw # 更新单个脚本文件" - echo -e "4. $cmd_update repo # 更新单个仓库的脚本" - echo -e "5. $cmd_update rmlog # 删除旧日志" - echo -e "6. $cmd_update bot # 启动tg-bot" - echo -e "7. $cmd_update check # 检测青龙环境并修复" - echo -e "8. $cmd_update resetlet # 重置登录错误次数" - echo -e "9. $cmd_update resettfa # 禁用两步登录" + echo -e "$cmd_update 命令使用方法:" + echo -e "1. $cmd_update update # 更新并重启青龙" + echo -e "2. $cmd_update extra # 运行自定义脚本" + echo -e "3. $cmd_update raw # 更新单个脚本文件" + echo -e "4. $cmd_update repo # 更新单个仓库的脚本" + echo -e "5. $cmd_update rmlog # 删除旧日志" + echo -e "6. $cmd_update bot # 启动tg-bot" + echo -e "7. $cmd_update check # 检测青龙环境并修复" + echo -e "8. $cmd_update resetlet # 重置登录错误次数" + echo -e "9. $cmd_update resettfa # 禁用两步登录" + echo -e "10. $cmd_update resetpwd # 修改登录密码" + echo -e "11. $cmd_update resetname # 修改登录用户名" } reload_qinglong() { @@ -546,6 +548,9 @@ main() { resetpwd) eval update_auth_config "\\\"password\\\":\\\"$p2\\\"" "重置密码" $cmd ;; + resetname) + eval update_auth_config "\\\"username\\\":\\\"$p2\\\"" "重置用户名" $cmd + ;; *) eval echo -e "命令输入错误...\\\n" $cmd eval usage $cmd