From 54aa32d0e4af5a97cf0cba8e210781dca791543c Mon Sep 17 00:00:00 2001 From: ningmengchongshui <916415899@qq.com> Date: Sat, 15 Jun 2024 09:27:19 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/pm2/pm2.json | 10 ---- image/main.ts | 3 +- pm2.config.cjs | 20 +++++++- src/config/check.ts | 37 --------------- src/config/log.ts | 107 ------------------------------------------- src/config/redis.ts | 76 ------------------------------ src/config/utils.ts | 37 +-------------- src/init.ts | 103 +---------------------------------------- src/init/logger.ts | 103 ++++++++++++++++++++++++++++++++++++++++- src/init/modules.ts | 11 ----- src/init/process.ts | 94 ++++++++++++++++++++++++++++++++++++++ src/init/redis.ts | 71 ++++++++++++++++++++++++++++- src/init/run.ts | 67 +++++++++++++++++++++++++++ trss.js | 109 -------------------------------------------- 14 files changed, 354 insertions(+), 494 deletions(-) delete mode 100644 config/pm2/pm2.json delete mode 100644 src/config/check.ts delete mode 100644 src/config/log.ts delete mode 100644 src/config/redis.ts delete mode 100644 src/init/modules.ts create mode 100644 src/init/process.ts create mode 100644 src/init/run.ts delete mode 100644 trss.js diff --git a/config/pm2/pm2.json b/config/pm2/pm2.json deleted file mode 100644 index e3c9548..0000000 --- a/config/pm2/pm2.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "apps": [ - { - "name": "Miao-Yunzai", - "script": "./index.js", - "max_memory_restart": "512M", - "restart_delay": 60000 - } - ] -} \ No newline at end of file diff --git a/image/main.ts b/image/main.ts index e0c3da2..8c00547 100644 --- a/image/main.ts +++ b/image/main.ts @@ -1,6 +1,5 @@ -import '../src/init/modules.js' -import '../src/init/logger.js' import '../src/init/config.js' +import '../src/init/logger.js' import '../src/init/redis.js' import './tailwindcss.js' import Koa from 'koa' diff --git a/pm2.config.cjs b/pm2.config.cjs index 1729e56..bbadccc 100644 --- a/pm2.config.cjs +++ b/pm2.config.cjs @@ -5,8 +5,24 @@ module.exports = { name: 'Miao-Yunzai', script: './index.js', args: argv, - max_memory_restart: '512M', - restart_delay: 60000 + // 超时时间内进程仍未终止,则 PM2 将强制终止该进程 + kill_timeout: 5000, + // 发送意外重启 + autorestart: true, + // 进程到达指定内存时重启 + max_memory_restart: '2G', + // 进程重启之间的延迟时间 + restart_delay: 5000, + // 进程重启之间的最大延迟时间 + restart_delay_max: 10000, + // 将 PM2 进程列表自动保存到文件中 + autodump: true, + // 不监听文件变化 + watch: false, + env: { + NODE_ENV: 'production' + } } ] } +console.log('module.exports', module.exports) diff --git a/src/config/check.ts b/src/config/check.ts deleted file mode 100644 index 939094f..0000000 --- a/src/config/check.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { execAsync, readJSON } from "./utils.js" - -/** - * 校验运行 - * @returns - */ -export async function checkRun() { - /** - * - */ - if (process.argv[1].includes('pm2')) return - /** - * - */ - if (process.argv[1].includes('test')) return - /** - * - */ - const cfg = readJSON('./config/pm2/pm2.json') - /** - * - */ - if (!cfg) return - /** - * - */ - execAsync(`pm2 show ${cfg.apps[0].name}`).then((status) => { - /** - * - */ - if (status.stdout.includes('online')) { - logger.mark('检测到后台正在运行') - logger.mark('已停止后台进程,防止重复运行') - execAsync(`pm2 stop ${cfg.apps[0].name}`).catch(logger.error) - } - }).catch(() => { }) -} \ No newline at end of file diff --git a/src/config/log.ts b/src/config/log.ts deleted file mode 100644 index 6930f6d..0000000 --- a/src/config/log.ts +++ /dev/null @@ -1,107 +0,0 @@ -import log4js from 'log4js' -import chalk from 'chalk' -import cfg from './config.js' -import { mkdirSync } from 'node:fs' - -/** - * 创建日志 - * @returns - */ -function createLog() { - // log4js.levels.levels[5].level = Number.MAX_VALUE - // log4js.levels.levels.sort((a, b) => a.level - b.level) - log4js.configure({ - appenders: { - console: { - type: 'console', - layout: { - type: 'pattern', - pattern: '%[[MYZ-V4][%d{hh:mm:ss.SSS}][%4.4p]%] %m' - } - }, - command: { - type: 'dateFile', // 可以是console,dateFile,file,Logstash等 - filename: 'logs/command', // 将会按照filename和pattern拼接文件名 - pattern: 'yyyy-MM-dd.log', - numBackups: 15, - alwaysIncludePattern: true, - layout: { - type: 'pattern', - pattern: '[%d{hh:mm:ss.SSS}][%4.4p] %m' - } - }, - error: { - type: 'file', - filename: 'logs/error.log', - alwaysIncludePattern: true, - layout: { - type: 'pattern', - pattern: '[%d{hh:mm:ss.SSS}][%4.4p] %m' - } - } - }, - categories: { - default: { appenders: ['console'], level: cfg.bot.log_level }, - command: { appenders: ['console', 'command'], level: 'warn' }, - error: { appenders: ['console', 'command', 'error'], level: 'error' } - } - }) - - const defaultLogger = log4js.getLogger('message') - const commandLogger = log4js.getLogger('command') - const errorLogger = log4js.getLogger('error') - - - /** - * 调整error日志等级 - */ - const logger = { - trace() { - defaultLogger.trace.call(defaultLogger, ...arguments) - }, - debug() { - defaultLogger.debug.call(defaultLogger, ...arguments) - }, - info() { - defaultLogger.info.call(defaultLogger, ...arguments) - }, - // warn及以上的日志采用error策略 - warn() { - commandLogger.warn.call(defaultLogger, ...arguments) - }, - error() { - errorLogger.error.call(errorLogger, ...arguments) - }, - fatal() { - errorLogger.fatal.call(errorLogger, ...arguments) - }, - mark() { - errorLogger.mark.call(commandLogger, ...arguments) - } - } - return logger -} - -/** -* 设置日志样式 -*/ -export function loggerInit() { - /** - * - */ - mkdirSync('./logs', { - 'recursive': true - }) - - /** - * 全局变量 logger - */ - global.logger = createLog() as any - logger.chalk = chalk - logger.red = chalk.red - logger.green = chalk.green - logger.yellow = chalk.yellow - logger.blue = chalk.blue - logger.magenta = chalk.magenta - logger.cyan = chalk.cyan -} \ No newline at end of file diff --git a/src/config/redis.ts b/src/config/redis.ts deleted file mode 100644 index 31bf32f..0000000 --- a/src/config/redis.ts +++ /dev/null @@ -1,76 +0,0 @@ -import cfg from "./config.js" -import { execAsync, sleep } from "./utils.js" -import { createClient } from "redis" - -/** - * 初始化全局redis客户端 - * @returns - */ -export async function redisInit() { - const rc = cfg.redis - const redisUn = rc.username || "" - let redisPw = rc.password ? `:${rc.password}` : "" - if (rc.username || rc.password) { - redisPw += "@" - } - const redisUrl = `redis://${redisUn}${redisPw}${rc.host}:${rc.port}/${rc.db}` - let client = createClient({ url: redisUrl }) - - try { - logger.info(`正在连接 ${logger.blue(redisUrl)}`) - await client.connect() - } catch (err) { - logger.error(`Redis 错误:${logger.red(err)}`) - - const cmd = "redis-server --save 900 1 --save 300 10 --daemonize yes" + await aarch64() - logger.info("正在启动 Redis...") - - await execAsync(cmd) - - await sleep(1000) - - try { - client = createClient({ url: redisUrl }) - await client.connect() - } catch (err) { - logger.error(`Redis 错误:${logger.red(err)}`) - logger.error(`请先启动 Redis:${logger.blue(cmd)}`) - process.exit() - } - } - - client.on("error", async err => { - logger.error(`Redis 错误:${logger.red(err)}`) - const cmd = "redis-server --save 900 1 --save 300 10 --daemonize yes" + await aarch64() - logger.error(`请先启动 Redis:${cmd}`) - process.exit() - }) - - /** 全局变量 redis */ - global.redis = client as any - - logger.info("Redis 连接成功") - return client -} - -/** - * - * @returns - */ -async function aarch64() { - if (process.platform == "win32") return "" - return await execAsync("uname -m").then(async arch => { - if (arch.stdout && arch.stdout.includes("aarch64")) { - /** 判断redis版本 */ - let v = await execAsync("redis-server -v") - if (v.stdout) { - const data = v.stdout.match(/v=(\d)./) - /** 忽略arm警告 */ - if (data && Number(data[1]) >= 6) { - return " --ignore-warnings ARM64-COW-BUG" - } - } - } - return '' - }) -} \ No newline at end of file diff --git a/src/config/utils.ts b/src/config/utils.ts index cf63909..707b911 100644 --- a/src/config/utils.ts +++ b/src/config/utils.ts @@ -1,42 +1,7 @@ -import fs from 'node:fs' -import { exec } from 'child_process' -import { join } from 'path' - /** * 休眠函数 * @param ms 毫秒 */ export function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)) -} - -/** - * - * @param cmd - * @returns - */ -export function execAsync(cmd: string): Promise<{ - stdout: string - stderr: string -}> { - return new Promise((resolve, reject) => { - exec(cmd, (error, stdout, stderr) => { - if (error) reject(error) - resolve({ stdout, stderr }) - }) - }) -} - -/** - * - * @param dir - * @returns - */ -export function readJSON(dir: string) { - try { - const cfg = fs.readFileSync(join(process.cwd(), dir), 'utf-8') - return JSON.parse(cfg) - } catch { - return false - } -} +} \ No newline at end of file diff --git a/src/init.ts b/src/init.ts index ffbd448..90c35d1 100644 --- a/src/init.ts +++ b/src/init.ts @@ -1,104 +1,5 @@ -import './init/modules.js' import './init/config.js' import './init/logger.js' import './init/redis.js' -import { promises } from 'node:fs' -import yaml from 'yaml' -import { BOT_NAME } from './config' -import { CONFIG_INIT_PATH } from './config/system.js' -import { checkRun } from './config/check.js' -/** - * - */ -logger.mark(`${BOT_NAME} 启动中...`) -/** - * 设置标题 - */ -process.title = BOT_NAME -/** - * 设置时区 - */ -process.env.TZ = 'Asia/Shanghai' -/** - * - */ -process.on('SIGHUP', () => process.exit()) -/** - * 捕获未处理的错误 - */ -process.on('uncaughtException', error => { - if (typeof logger == 'undefined') console.log(error) - else logger.error(error) -}) -/** - * 捕获未处理的Promise错误 - */ -process.on('unhandledRejection', error => { - if (typeof logger == 'undefined') console.log(error) - else logger.error(error) -}) -/** - * 退出事件 - */ -process.on('exit', async () => { - if (typeof redis != 'undefined') { - await redis.save() - } - if (typeof logger == 'undefined') { - console.log(`${BOT_NAME} 已停止运行`) - } else { - logger.mark(logger.magenta(`${BOT_NAME} 已停止运行`)) - } -}) -/** - * 添加一些多余的标题内容 - */ -let title = BOT_NAME -// -const qq = await promises - .readFile(`./${CONFIG_INIT_PATH}qq.yaml`, 'utf-8') - .then(yaml.parse) - .catch(() => null) -/** - * - */ -if (qq) { - title += `@${qq.qq || ''}` - switch (qq.platform) { - case 1: { - title += ' 安卓手机' - break - } - case 2: { - title += ' aPad' - break - } - case 3: { - title += ' 安卓手表' - break - } - case 4: { - title += ' MacOS' - break - } - case 5: { - title += ' iPad' - break - } - case 6: { - title += ' Tim' - break - } - default: { - break - } - } -} -/** - * 设置标题 - */ -process.title = title -/** - * 检查程序 - */ -await checkRun() +import './init/process.js' +import './init/run.js' diff --git a/src/init/logger.ts b/src/init/logger.ts index 840eedb..28fdc84 100644 --- a/src/init/logger.ts +++ b/src/init/logger.ts @@ -1,2 +1,101 @@ -import { loggerInit } from '../config/log' -loggerInit() +import log4js from 'log4js' +import chalk from 'chalk' +import cfg from '../config/config.js' +import { mkdirSync } from 'node:fs' + +/** + * 创建日志 + * @returns + */ +function createLog() { + // log4js.levels.levels[5].level = Number.MAX_VALUE + // log4js.levels.levels.sort((a, b) => a.level - b.level) + log4js.configure({ + appenders: { + console: { + type: 'console', + layout: { + type: 'pattern', + pattern: '%[[MYZ-V4][%d{hh:mm:ss.SSS}][%4.4p]%] %m' + } + }, + command: { + type: 'dateFile', // 可以是console,dateFile,file,Logstash等 + filename: 'logs/command', // 将会按照filename和pattern拼接文件名 + pattern: 'yyyy-MM-dd.log', + numBackups: 15, + alwaysIncludePattern: true, + layout: { + type: 'pattern', + pattern: '[%d{hh:mm:ss.SSS}][%4.4p] %m' + } + }, + error: { + type: 'file', + filename: 'logs/error.log', + alwaysIncludePattern: true, + layout: { + type: 'pattern', + pattern: '[%d{hh:mm:ss.SSS}][%4.4p] %m' + } + } + }, + categories: { + default: { appenders: ['console'], level: cfg.bot.log_level }, + command: { appenders: ['console', 'command'], level: 'warn' }, + error: { appenders: ['console', 'command', 'error'], level: 'error' } + } + }) + + const defaultLogger = log4js.getLogger('message') + const commandLogger = log4js.getLogger('command') + const errorLogger = log4js.getLogger('error') + + /** + * 调整error日志等级 + */ + const logger = { + trace() { + defaultLogger.trace.call(defaultLogger, ...arguments) + }, + debug() { + defaultLogger.debug.call(defaultLogger, ...arguments) + }, + info() { + defaultLogger.info.call(defaultLogger, ...arguments) + }, + // warn及以上的日志采用error策略 + warn() { + commandLogger.warn.call(defaultLogger, ...arguments) + }, + error() { + errorLogger.error.call(errorLogger, ...arguments) + }, + fatal() { + errorLogger.fatal.call(errorLogger, ...arguments) + }, + mark() { + errorLogger.mark.call(commandLogger, ...arguments) + } + } + return logger +} + +/** + * + */ +mkdirSync('./logs', { + recursive: true +}) + +/** + * 全局变量 logger + */ +global.logger = createLog() as any +logger.chalk = chalk +logger.red = chalk.red +logger.green = chalk.green +logger.yellow = chalk.yellow +logger.blue = chalk.blue +logger.magenta = chalk.magenta +logger.cyan = chalk.cyan diff --git a/src/init/modules.ts b/src/init/modules.ts deleted file mode 100644 index cc0cc4e..0000000 --- a/src/init/modules.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { existsSync } from 'fs' -import { join } from 'path' -const node_modules = join(process.cwd(), './node_modules') -/** - * 检查node_modules - */ -if (!existsSync(node_modules)) { - console.log('未安装依赖。。。。') - console.log('请先运行命令:pnpm install -P 安装依赖') - process.exit() -} diff --git a/src/init/process.ts b/src/init/process.ts new file mode 100644 index 0000000..b263782 --- /dev/null +++ b/src/init/process.ts @@ -0,0 +1,94 @@ +import { promises } from 'node:fs' +import yaml from 'yaml' +import { BOT_NAME, CONFIG_INIT_PATH } from '../config/system.js' +/** + * + */ +logger.mark(`${BOT_NAME} 启动中...`) +/** + * 设置标题 + */ +process.title = BOT_NAME +/** + * 设置时区 + */ +process.env.TZ = 'Asia/Shanghai' +/** + * + */ +process.on('SIGHUP', () => process.exit()) +/** + * 捕获未处理的错误 + */ +process.on('uncaughtException', error => { + if (typeof logger == 'undefined') console.log(error) + else logger.error(error) +}) +/** + * 捕获未处理的Promise错误 + */ +process.on('unhandledRejection', error => { + if (typeof logger == 'undefined') console.log(error) + else logger.error(error) +}) +/** + * 退出事件 + */ +process.on('exit', async () => { + if (typeof redis != 'undefined') { + await redis.save() + } + if (typeof logger == 'undefined') { + console.log(`${BOT_NAME} 已停止运行`) + } else { + logger.mark(logger.magenta(`${BOT_NAME} 已停止运行`)) + } +}) +/** + * 添加一些多余的标题内容 + */ +let title = BOT_NAME +// +const qq = await promises + .readFile(`./${CONFIG_INIT_PATH}qq.yaml`, 'utf-8') + .then(yaml.parse) + .catch(() => null) +/** + * + */ +if (qq) { + title += `@${qq.qq || ''}` + switch (qq.platform) { + case 1: { + title += ' 安卓手机' + break + } + case 2: { + title += ' aPad' + break + } + case 3: { + title += ' 安卓手表' + break + } + case 4: { + title += ' MacOS' + break + } + case 5: { + title += ' iPad' + break + } + case 6: { + title += ' Tim' + break + } + default: { + break + } + } +} +/** + * 设置标题 + */ +process.title = title diff --git a/src/init/redis.ts b/src/init/redis.ts index 6794d16..f0902ec 100644 --- a/src/init/redis.ts +++ b/src/init/redis.ts @@ -1,2 +1,71 @@ -import { redisInit } from '../config/redis' +import cfg from '../config/config.js' +import { execAsync, sleep } from '../utils/common.js' +import { createClient } from 'redis' +/** + * 初始化全局redis客户端 + * @returns + */ +async function redisInit() { + const rc = cfg.redis + const redisUn = rc.username || '' + let redisPw = rc.password ? `:${rc.password}` : '' + if (rc.username || rc.password) { + redisPw += '@' + } + const redisUrl = `redis://${redisUn}${redisPw}${rc.host}:${rc.port}/${rc.db}` + let client = createClient({ url: redisUrl }) + try { + logger.info(`正在连接 ${logger.blue(redisUrl)}`) + await client.connect() + } catch (err) { + logger.error(`Redis 错误:${logger.red(err)}`) + const cmd = + 'redis-server --save 900 1 --save 300 10 --daemonize yes' + + (await aarch64()) + logger.info('正在启动 Redis...') + await execAsync(cmd) + await sleep(1000) + try { + client = createClient({ url: redisUrl }) + await client.connect() + } catch (err) { + logger.error(`Redis 错误:${logger.red(err)}`) + logger.error(`请先启动 Redis:${logger.blue(cmd)}`) + process.exit() + } + } + client.on('error', async err => { + logger.error(`Redis 错误:${logger.red(err)}`) + const cmd = + 'redis-server --save 900 1 --save 300 10 --daemonize yes' + + (await aarch64()) + logger.error(`请先启动 Redis:${cmd}`) + process.exit() + }) + /** 全局变量 redis */ + global.redis = client as any + logger.info('Redis 连接成功') + return client +} +/** + * + * @returns + */ +async function aarch64() { + if (process.platform == 'win32') return '' + return await execAsync('uname -m').then(async arch => { + if (arch.stdout && arch.stdout.includes('aarch64')) { + /** 判断redis版本 */ + let v = await execAsync('redis-server -v') + if (v.stdout) { + const data = v.stdout.match(/v=(\d)./) + /** 忽略arm警告 */ + if (data && Number(data[1]) >= 6) { + return ' --ignore-warnings ARM64-COW-BUG' + } + } + } + return '' + }) +} await redisInit() diff --git a/src/init/run.ts b/src/init/run.ts new file mode 100644 index 0000000..2b642f6 --- /dev/null +++ b/src/init/run.ts @@ -0,0 +1,67 @@ +import { join } from 'path' +import { createRequire } from 'module' +import { existsSync } from 'fs' +import pm2 from 'pm2' +const require = createRequire(import.meta.url) +/** + * 校验运行 + * @returns + */ +export function checkRun() { + return new Promise((resolve, reject) => { + if (process.argv[1].includes('pm2')) { + resolve(true) + } + if (process.argv[1].includes('test')) { + resolve(true) + } + // 不是生产运行 + if (process.env.NODE_ENV != 'production') { + const dir = join(process.cwd(), 'pm2.config.cjs') + if (!existsSync(dir)) { + reject(false) + } + const cfg = require('../../pm2.config.cjs') + pm2.connect(err => { + if (err) { + reject(err) + return + } + // + pm2.list((err, processList) => { + if (err) { + pm2.disconnect() + reject(err) + return + } + const app = processList.find(p => p.name === cfg.apps[0].name) + if (app && app.pm2_env.status === 'online') { + console.log('检测到后台正在运行') + // 关闭 + pm2.stop(cfg.apps[0].name, err => { + if (err) { + reject(err) + } else { + console.log('已停止后台进程,防止重复运行') + } + pm2.disconnect() + resolve(true) + }) + } else { + // 断开连接 + pm2.disconnect() + resolve(true) + } + }) + }) + } else { + resolve(true) + } + }) +} +await checkRun().catch(err => { + // 打印错误 + console.error(err) + // 关闭进程 + process.exit(2) +}) diff --git a/trss.js b/trss.js deleted file mode 100644 index 9256eae..0000000 --- a/trss.js +++ /dev/null @@ -1,109 +0,0 @@ -console.log("正迁移到 TRSS-Yunzai") - -import fs from "node:fs" -import { execSync } from "child_process" -import YAML from "yaml" - -function exec(cmd) { try { - console.log(`执行命令 [${cmd}]`) - console.log(execSync(cmd).toString()) - return true -} catch (err) { - console.error("执行", cmd, "失败", err) - return false -}} - -function rm(file) { try { - if (!fs.existsSync(file)) return true - return process.platform == "win32" ? - exec(`rd /s /q "${file.replace(/\//g, "\\")}"`) : - exec(`rm -rf "${file}"`) -} catch (err) { - console.error("删除", file, "错误", err) - return false -}} - -function mv(file, target) { try { - if (!fs.existsSync(file)) return false - if (fs.existsSync(target)) rm(target) - return fs.renameSync(file, target) -} catch (err) { - console.error("移动", file, target, "错误", err) - return false -}} - -function readYaml(file) { try { - if (!fs.existsSync(file)) return {} - return YAML.parse(fs.readFileSync(file, "utf-8")) -} catch (err) { - console.error("读取", file, "错误", err) - return {} -}} - -function writeYaml(file, data) { try { - return fs.writeFileSync(file, YAML.stringify(data), "utf-8") -} catch (err) { - console.error("写入", file, "错误", err) - return false -}} - -const bot = readYaml("config/config/bot.yaml") -const qq = readYaml("config/config/qq.yaml") - -exec("git remote add trss https://gitee.com/TimeRainStarSky/Yunzai") -exec("git fetch trss main") -exec("git clean -df") -mv("config/config", "config/config_miao") -exec("git reset --hard") -exec("git checkout --track trss/main") -rm("plugins/ICQQ-Plugin") -exec("git clone --depth 1 --single-branch https://gitee.com/TimeRainStarSky/Yunzai-ICQQ-Plugin plugins/ICQQ-Plugin") -if (qq.qq) writeYaml("config/ICQQ.yaml", { bot, token: [`${qq.qq}:${qq.pwd}:${qq.platform}`] }) -rm("plugins/genshin") -exec("git clone --depth 1 --single-branch https://gitee.com/TimeRainStarSky/Yunzai-genshin plugins/genshin") -exec("pnpm install --force") - -console.log("迁移完成,请查看教程 启动协议端\nhttps://gitee.com/TimeRainStarSky/Yunzai\n输入 node miao 回 Miao-Yunzai") -fs.writeFileSync("miao.js", `console.log("正迁移到 Miao-Yunzai") - -import fs from "node:fs" -import { execSync } from "child_process" - -function exec(cmd) { try { - console.log(\`执行命令 [\${cmd}]\`) - console.log(execSync(cmd).toString()) - return true -} catch (err) { - console.error("执行", cmd, "失败", err) - return false -}} - -function rm(file) { try { - if (!fs.existsSync(file)) return true - return process.platform == "win32" ? - exec(\`rd /s /q "\${file.replace(/\\//g, "\\\\")}"\`) : - exec(\`rm -rf "\${file}"\`) -} catch (err) { - console.error("删除", file, "错误", err) - return false -}} - -function mv(file, target) { try { - if (!fs.existsSync(file)) return false - if (fs.existsSync(target)) rm(target) - return fs.renameSync(file, target) -} catch (err) { - console.error("移动", file, target, "错误", err) - return false -}} - -mv("config/config_miao", "config/config") -exec("git reset --hard") -exec("git clean -df") -rm("plugins/ICQQ-Plugin") -rm("plugins/genshin") -exec("git checkout master") -exec("git branch -D main") -exec("pnpm install --force") - -console.log("迁移完成")`, "utf-8") \ No newline at end of file