191 lines
4.9 KiB
TypeScript
191 lines
4.9 KiB
TypeScript
import { Plugin } from 'yunzai/core'
|
|
import fetch from 'node-fetch'
|
|
import net from 'net'
|
|
import fs from 'fs'
|
|
import YAML from 'yaml'
|
|
import { exec } from 'child_process'
|
|
|
|
/**
|
|
* tudo
|
|
*/
|
|
|
|
/**
|
|
*
|
|
* @param port
|
|
* @returns
|
|
*/
|
|
const isPortTaken = async (port) => {
|
|
return new Promise((resolve) => {
|
|
const tester = net.createServer()
|
|
.once('error', () => resolve(true))
|
|
.once('listening', () => tester.once('close', () => resolve(false)).close())
|
|
.listen(port);
|
|
});
|
|
};
|
|
|
|
/**
|
|
*
|
|
*/
|
|
export class Restart extends Plugin {
|
|
key = 'Yz:restart'
|
|
|
|
/**
|
|
*
|
|
* @param e
|
|
*/
|
|
constructor() {
|
|
/**
|
|
name: '重启',
|
|
dsc: '#重启',
|
|
*/
|
|
super()
|
|
this.priority = 10
|
|
this.rule = [
|
|
{
|
|
reg: /^#重启$/,
|
|
fnc: this.restart.name,
|
|
permission: 'master'
|
|
},
|
|
{
|
|
reg: /^#(停机|关机)$/,
|
|
fnc: this.stop.name,
|
|
permission: 'master'
|
|
}
|
|
]
|
|
}
|
|
|
|
async init() {
|
|
const data = await redis.get(this.key)
|
|
if (data) {
|
|
const restart = JSON.parse(data)
|
|
const uin = restart?.uin || Bot.uin
|
|
let time = restart.time || new Date().getTime()
|
|
time = (new Date().getTime() - time) / 1000
|
|
|
|
let msg = `重启成功:耗时${time.toFixed(2)}秒`
|
|
try {
|
|
if (restart.isGroup) {
|
|
Bot[uin].pickGroup(restart.id).sendMsg(msg)
|
|
} else {
|
|
Bot[uin].pickUser(restart.id).sendMsg(msg)
|
|
}
|
|
} catch (error) {
|
|
/** 不发了,发不出去... */
|
|
logger.debug(error)
|
|
}
|
|
redis.del(this.key)
|
|
}
|
|
}
|
|
|
|
async restart() {
|
|
let restart_port
|
|
try {
|
|
restart_port = YAML.parse(fs.readFileSync(`./config/config/bot.yaml`, `utf-8`))
|
|
restart_port = restart_port.restart_port || 27881
|
|
} catch { }
|
|
await this.e.reply('开始执行重启,请稍等...')
|
|
logger.mark(`${this.e.logFnc} 开始执行重启,请稍等...`)
|
|
|
|
let data = JSON.stringify({
|
|
uin: this.e?.self_id || this.e.bot.uin,
|
|
isGroup: !!this.e.isGroup,
|
|
id: this.e.isGroup ? this.e.group_id : this.e.user_id,
|
|
time: new Date().getTime()
|
|
})
|
|
|
|
let npm = await this.checkPnpm()
|
|
await redis.set(this.key, data, { EX: 120 })
|
|
if (await isPortTaken(restart_port || 27881)) {
|
|
try {
|
|
let result = await fetch(`http://localhost:${restart_port || 27881}/restart`)
|
|
result = await result.text()
|
|
if (result !== `OK`) {
|
|
redis.del(this.key)
|
|
this.e.reply(`操作失败!`)
|
|
logger.error(`重启失败`)
|
|
}
|
|
} catch (error) {
|
|
redis.del(this.key)
|
|
this.e.reply(`操作失败!\n${error}`)
|
|
}
|
|
} else {
|
|
try {
|
|
let cm = `${npm} start`
|
|
if (process.argv[1].includes('pm2')) {
|
|
cm = `${npm} run restart`
|
|
}
|
|
|
|
exec(cm, { windowsHide: true }, (error, stdout, stderr) => {
|
|
if (error) {
|
|
redis.del(this.key)
|
|
this.e.reply(`操作失败!\n${error.stack}`)
|
|
logger.error(`重启失败\n${error.stack}`)
|
|
} else if (stdout) {
|
|
logger.mark('重启成功,运行已由前台转为后台')
|
|
logger.mark(`查看日志请用命令:${npm} run log`)
|
|
logger.mark(`停止后台运行命令:${npm} stop`)
|
|
process.exit()
|
|
}
|
|
})
|
|
} catch (error) {
|
|
redis.del(this.key)
|
|
let e = error.stack ?? error
|
|
this.e.reply(`操作失败!\n${e}`)
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
async checkPnpm() {
|
|
let npm = 'npm'
|
|
let ret = await this.execSync('pnpm -v')
|
|
if (ret.stdout) npm = 'pnpm'
|
|
return npm
|
|
}
|
|
|
|
async execSync(cmd) {
|
|
return new Promise((resolve, reject) => {
|
|
exec(cmd, { windowsHide: true }, (error, stdout, stderr) => {
|
|
resolve({ error, stdout, stderr })
|
|
})
|
|
})
|
|
}
|
|
|
|
async stop() {
|
|
let restart_port
|
|
try {
|
|
restart_port = YAML.parse(fs.readFileSync(`./config/config/bot.yaml`, `utf-8`))
|
|
restart_port = restart_port.restart_port || 27881
|
|
} catch { }
|
|
if (await isPortTaken(restart_port || 27881)) {
|
|
try {
|
|
logger.mark('关机成功,已停止运行')
|
|
await this.e.reply(`关机成功,已停止运行`)
|
|
await fetch(`http://localhost:${restart_port || 27881}/exit`)
|
|
return
|
|
} catch (error) {
|
|
this.e.reply(`操作失败!\n${error}`)
|
|
logger.error(`关机失败\n${error}`)
|
|
}
|
|
}
|
|
|
|
if (!process.argv[1].includes('pm2')) {
|
|
logger.mark('关机成功,已停止运行')
|
|
await this.e.reply('关机成功,已停止运行')
|
|
process.exit()
|
|
}
|
|
|
|
logger.mark('关机成功,已停止运行')
|
|
await this.e.reply('关机成功,已停止运行')
|
|
|
|
let npm = await this.checkPnpm()
|
|
exec(`${npm} stop`, { windowsHide: true }, (error, stdout, stderr) => {
|
|
if (error) {
|
|
this.e.reply(`操作失败!\n${error.stack}`)
|
|
logger.error(`关机失败\n${error.stack}`)
|
|
}
|
|
})
|
|
}
|
|
}
|