fix: 执行顺序

This commit is contained in:
ningmengchongshui 2024-06-13 22:57:21 +08:00
parent cd29445387
commit 47ba0fee14
21 changed files with 225 additions and 258 deletions

1
plugins/system Submodule

@ -0,0 +1 @@
Subproject commit c052a84f274b4ed9fd924afd682a359ec4fde2f2

View File

@ -1,13 +1,18 @@
import { PuppeteerLaunchOptions } from 'puppeteer';
import Puppeteer from './lib/puppeteer.js' import Puppeteer from './lib/puppeteer.js'
/** /**
* *
* @param config config.yaml的配置内容 * @param config
* @returns renderer * @returns renderer
* @returns renderer.id IDrenderer中选择的id * @returns renderer.id IDrenderer中选择的id
* @returns renderer.type image * @returns renderer.type image
* @returns renderer.render * @returns renderer.render
*/ */
export default function (config) { export default function (config?: PuppeteerLaunchOptions & {
chromiumPath: string;
puppeteerWS: any;
puppeteerTimeout: any;
}) {
// TODO Puppeteer待简化重构 // TODO Puppeteer待简化重构
return new Puppeteer(config) return new Puppeteer(config)
} }

View File

@ -4,6 +4,22 @@ import { join } from 'node:path'
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync } from 'node:fs' import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync } from 'node:fs'
import { CONFIG_DEFAULT_PATH, CONFIG_INIT_PATH } from './system.js' import { CONFIG_DEFAULT_PATH, CONFIG_INIT_PATH } from './system.js'
export function configInit() {
const path = CONFIG_INIT_PATH
const pathDef = CONFIG_DEFAULT_PATH
const files = readdirSync(pathDef).filter(file => file.endsWith('.yaml'))
mkdirSync(join(process.cwd(), path), {
'recursive': true
})
for (let file of files) {
if (!existsSync(`${path}${file}`)) {
copyFileSync(`${pathDef}${file}`, `${path}${file}`)
}
}
if (!existsSync("data")) mkdirSync("data")
if (!existsSync("resources")) mkdirSync("resources")
}
/** /**
* ******** * ********
* *
@ -21,30 +37,6 @@ class ConfigController {
*/ */
watcher = { config: {}, defSet: {} } watcher = { config: {}, defSet: {} }
/**
*
*/
constructor() {
this.initCfg()
}
/**
*
*/
initCfg() {
const path = CONFIG_INIT_PATH
const pathDef = CONFIG_DEFAULT_PATH
const files = readdirSync(pathDef).filter(file => file.endsWith('.yaml'))
for (let file of files) {
if (!existsSync(`${path}${file}`)) {
copyFileSync(`${pathDef}${file}`, `${path}${file}`)
}
}
if (!existsSync("data")) mkdirSync("data")
if (!existsSync("resources")) mkdirSync("resources")
}
/** /**
* qq号 * qq号
*/ */
@ -238,8 +230,7 @@ class ConfigController {
* *
*/ */
async change_bot() { async change_bot() {
const { setLogger } = await import('./log.js') //
setLogger && setLogger()
} }
} }

View File

@ -1,8 +1,7 @@
import log4js from 'log4js' import log4js from 'log4js'
import chalk from 'chalk' import chalk from 'chalk'
import cfg from './config.js' import cfg from './config.js'
import fs from 'node:fs' import { mkdirSync } from 'node:fs'
/** /**
* *
@ -86,27 +85,18 @@ function createLog() {
/** /**
* *
*/ */
export function setLogger() { export function loggerInit() {
/** /**
* *
*/ */
let file = './logs' mkdirSync('./logs', {
'recursive': true
/** })
*
*/
if (!fs.existsSync(file)) {
fs.mkdirSync(file, {
'recursive': true
})
}
/** /**
* logger * logger
*/ */
global.logger = createLog() as any global.logger = createLog() as any
logger.chalk = chalk logger.chalk = chalk
logger.red = chalk.red logger.red = chalk.red
logger.green = chalk.green logger.green = chalk.green

View File

@ -11,7 +11,7 @@ export default class messageEvent extends EventListener {
/** /**
* *
*/ */
super({ event: 'message', prefix: undefined, once: undefined }) super({ event: 'message' })
} }
/** /**

View File

@ -11,7 +11,7 @@ export default class noticeEvent extends EventListener {
/** /**
* *
*/ */
super({ event: 'notice', prefix: undefined, once: undefined }) super({ event: 'notice' })
} }
/** /**

View File

@ -14,7 +14,7 @@ export default class offlineEvent extends EventListener {
/** /**
* *
*/ */
super({ event: 'system.offline', prefix: undefined, once: undefined }) super({ event: 'system.offline' })
} }
/** /**

View File

@ -16,8 +16,7 @@ export default class onlineEvent extends EventListener {
*/ */
super({ super({
event: 'system.online', event: 'system.online',
once: true, once: true
prefix: undefined
}) })
} }

View File

@ -11,7 +11,7 @@ export default class requestEvent extends EventListener {
/** /**
* *
*/ */
super({ event: 'request', prefix: undefined, once: undefined }) super({ event: 'request' })
} }
/** /**

View File

@ -29,7 +29,15 @@ export default class EventListener {
* @param data.event * @param data.event
* @param data.once * @param data.once
*/ */
constructor({ prefix, event, once }) { constructor({
prefix,
event,
once
}: {
prefix?: string
event?: any
once?: any
}) {
prefix && (this.prefix = prefix) prefix && (this.prefix = prefix)
once && (this.once = once) once && (this.once = once)
this.event = event this.event = event

View File

@ -10,9 +10,9 @@
* @param msg * @param msg
* @param uin bot发送Bot * @param uin bot发送Bot
*/ */
export async function relpyPrivate(userId, msg, uin = Bot.uin) { export async function relpyPrivate(userId: number | string, msg, uin = Bot.uin) {
userId = Number(userId) userId = Number(userId)
let friend = Bot.fl.get(userId) const friend = Bot.fl.get(userId)
if (friend) { if (friend) {
logger.mark(`发送好友消息[${friend.nickname}](${userId})`) logger.mark(`发送好友消息[${friend.nickname}](${userId})`)
return await Bot[uin] return await Bot[uin]
@ -58,13 +58,13 @@ export async function makeForwardMsg(
let forwardMsg: let forwardMsg:
| { | {
user_id: number user_id: number
nickname: string nickname: string
message: any message: any
}[] }[]
| { | {
data: any data: any
} = [] } = []
/** /**
* *

View File

@ -6,6 +6,10 @@ interface EventTypeBase {
* *
*/ */
isMaster: boolean; isMaster: boolean;
/**
*
*/
// isAdmin: boolean;
/** /**
* *
*/ */
@ -21,11 +25,9 @@ interface EventTypeBase {
*/ */
reply: (...arg: any[]) => Promise<any>; reply: (...arg: any[]) => Promise<any>;
/** /**
* @deprecated
*/ */
file: any; file: any;
/** /**
* @deprecated
*/ */
bot: typeof Client.prototype; bot: typeof Client.prototype;
/** /**
@ -49,7 +51,11 @@ interface EventTypeGroup extends EventTypeBase, GroupMessage {
*/ */
group_id: number; group_id: number;
/** /**
* @deprecated *
*/
group_name:string
/**
*
*/ */
group: { group: {
is_owner: any; is_owner: any;

View File

@ -1,124 +1,42 @@
import fs, { promises } from 'node:fs' import { existsSync } from 'fs'
import { join } from 'path'
import { configInit } from './config/config'
import { loggerInit } from './config/log'
import { BOT_NAME } from './config'
import { redisInit } from './config/redis'
import { promises } from 'node:fs'
import yaml from 'yaml' import yaml from 'yaml'
import { join } from 'node:path' import { CONFIG_INIT_PATH } from './config/system.js'
/**
*
*/
import { BOT_NAME, CONFIG_INIT_PATH } from './config/system.js'
import { createQQ } from './config/qq.js'
import { setLogger } from './config/log.js'
import { redisInit } from './config/redis.js'
import { checkRun } from './config/check.js' import { checkRun } from './config/check.js'
/** /**
* * node_modules
*/ */
async function UpdateTitle() { if (!existsSync(join(process.cwd(), './node_modules'))) {
/** console.log('未安装依赖。。。。')
* console.log('请先运行命令pnpm install -P 安装依赖')
*/ process.exit()
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
} }
/** /**
* *
*/ */
export async function checkInit() { configInit()
/**
* node_modules
*/
if (!fs.existsSync(join(process.cwd(), './node_modules'))) {
console.log('未安装依赖。。。。')
console.log('请先运行命令pnpm install -P 安装依赖')
process.exit()
}
/** /**
* node_modules/icqq *
*/ */
if (!fs.existsSync(join(process.cwd(), './node_modules/icqq'))) { loggerInit()
console.log('未安装icqq。。。。')
console.log('请先运行命令pnpm install -P 安装依赖')
process.exit()
}
/** /**
* qq.yaml *
*/ */
await createQQ() logger.mark(`${BOT_NAME} 启动中...`)
/** /**
* *
*/ */
setLogger() await redisInit()
/**
*
*/
logger.mark(`${BOT_NAME} 启动中...`)
/**
*
*/
await redisInit()
/**
*
*/
await checkRun()
/**
*
*/
await UpdateTitle()
}
/** /**
* *
@ -166,6 +84,58 @@ process.on('exit', async () => {
}) })
/** /**
* *
*/ */
await checkInit() 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()

View File

@ -1,14 +1,7 @@
/**
* **********
*
* **********
*/
import './init.js' import './init.js'
/**
*
*/
import { plugin, segment, Client } from './core/index.js' import { plugin, segment, Client } from './core/index.js'
import { Renderer } from './utils/index.js' import { Renderer } from './utils/index.js'
import { createQQ } from './config/qq.js'
/** /**
* global.plugin * global.plugin
*/ */
@ -22,6 +15,12 @@ global.segment = segment
*/ */
global.Renderer = Renderer global.Renderer = Renderer
/** /**
* run *
*/ */
await Client.run() setTimeout(async () => {
await createQQ()
/**
* run
*/
await Client.run()
}, 0)

View File

@ -3,24 +3,16 @@ export * from './puppeteer.js'
export * from './types.js' export * from './types.js'
export * from './common.js' export * from './common.js'
export * from './component.js' export * from './component.js'
/** /**
* *
*/ */
import puppeteer from './puppeteer/puppeteer.js' import puppeteer from './puppeteer/puppeteer.js'
export { puppeteer } export { puppeteer }
/**
* ********
*
* **********
*/
import renderer from './renderer/loader.js' import renderer from './renderer/loader.js'
import Renderer from './renderer/Renderer.js' import Renderer from './renderer/Renderer.js'
import renderers from './renderers/index.js' import renderers from './renderers/index.js'
import Renderers from './renderers/puppeteer.js' import Renderers from './renderers/puppeteer.js'
export { Renderers, renderers, Renderer, renderer } export { Renderers, renderers, Renderer, renderer }
/** /**
* puppeteer/ * puppeteer/
* renderer/ * renderer/

View File

@ -1,13 +1,16 @@
import Renderer from '../renderer/loader.js' import Renderer from '../renderer/loader.js'
/**
* @deprecated
*/
const renderer = Renderer.getRenderer() const renderer = Renderer.getRenderer()
renderer.screenshot = async (name, data) => { renderer.screenshot = async (name, data) => {
let img = await renderer.render(name, data) const img = await renderer.render(name, data)
return img ? segment.image(img) : img return img ? segment.image(img) : img
} }
renderer.screenshots = async (name, data) => { renderer.screenshots = async (name, data) => {
data.multiPage = true data.multiPage = true
let imgs = (await renderer.render(name, data)) || [] const imgs = (await renderer.render(name, data)) || []
let ret = [] const ret = []
for (let img of imgs) { for (let img of imgs) {
ret.push(img ? segment.image(img) : img) ret.push(img ? segment.image(img) : img)
} }

View File

@ -1,8 +1,12 @@
import template from 'art-template' import template from 'art-template'
import chokidar from 'chokidar' import chokidar from 'chokidar'
import path from 'node:path' import path from 'node:path'
import fs from 'node:fs' import fs, { writeFileSync } from 'node:fs'
/**
*
* @deprecated
*/
export default class Renderer { export default class Renderer {
id = null id = null
type = null type = null
@ -10,14 +14,13 @@ export default class Renderer {
dir = './temp/html' dir = './temp/html'
html = {} html = {}
watcher = {} watcher = {}
/** /**
* *
* @param data.id ID * @param data.id ID
* @param data.type * @param data.type
* @param data.render * @param data.render
*/ */
constructor(data) { constructor(data?: { id?: any; type?: any; render?: any }) {
/** 渲染器ID */ /** 渲染器ID */
this.id = data.id || 'renderer' this.id = data.id || 'renderer'
/** 渲染器类型 */ /** 渲染器类型 */
@ -26,13 +29,12 @@ export default class Renderer {
this.render = this[data.render || 'render'] this.render = this[data.render || 'render']
this.createDir(this.dir) this.createDir(this.dir)
} }
/** /**
* *
* @param dirname * @param dirname
* @returns * @returns
*/ */
createDir(dirname) { createDir(dirname: string) {
if (fs.existsSync(dirname)) { if (fs.existsSync(dirname)) {
return true return true
} else { } else {
@ -42,7 +44,6 @@ export default class Renderer {
} }
} }
} }
/** /**
* *
* @param name * @param name
@ -50,8 +51,8 @@ export default class Renderer {
* @returns * @returns
*/ */
dealTpl(name, data) { dealTpl(name, data) {
let { tplFile, saveId = name } = data const { tplFile, saveId = name } = data
let savePath = `./temp/html/${name}/${saveId}.html` const savePath = `./temp/html/${name}/${saveId}.html`
/** 读取html模板 */ /** 读取html模板 */
if (!this.html[tplFile]) { if (!this.html[tplFile]) {
this.createDir(`./temp/html/${name}`) this.createDir(`./temp/html/${name}`)
@ -63,18 +64,14 @@ export default class Renderer {
} }
this.watch(tplFile) this.watch(tplFile)
} }
data.resPath = `./resources/` data.resPath = `./resources/`
/** 替换模板 */ /** 替换模板 */
let tmpHtml = template.render(this.html[tplFile], data) const tmpHtml = template.render(this.html[tplFile], data)
/** 保存模板 */ /** 保存模板 */
fs.writeFileSync(savePath, tmpHtml) writeFileSync(savePath, tmpHtml)
logger.debug(`[图片生成][使用模板] ${savePath}`) logger.debug(`[图片生成][使用模板] ${savePath}`)
return savePath return savePath
} }
/** /**
* *
* @param tplFile * @param tplFile

View File

@ -1,23 +0,0 @@
# 如需自定义,复制此文件为 config.yaml 进行配置
# 更新配置后需要重启
# chromium 地址可填写系统的edge/chromium路径例如根据实际情况调整
# chromiumPath: C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
chromiumPath:
# puppeteer websocket 地址。连接单独存在的 chromium。
# puppeteerWS: 'ws://browserless:3000'
puppeteerWS:
# headless
headless: 'new'
# puppeteer启动args注意args的--前缀
args:
- --disable-gpu
- --disable-setuid-sandbox
- --no-sandbox
- --no-zygote
# puppeteer截图超时时间
puppeteerTimeout:

View File

@ -2,26 +2,25 @@ import fs from 'node:fs'
import yaml from 'yaml' import yaml from 'yaml'
import lodash from 'lodash' import lodash from 'lodash'
import { ConfigController as cfg } from '../../config/index.js' import { ConfigController as cfg } from '../../config/index.js'
import { join } from 'node:path'
/** /**
* *
* @deprecated
*/ */
class RendererLoader { class RendererLoader {
/** /**
* *
*/ */
renderers = new Map() renderers = new Map()
/** /**
* *
*/ */
dir = './renderers' dir = './renderers'
/** /**
* *
*/ */
watcher = {} watcher = {}
/** /**
* *
* @returns * @returns
@ -31,7 +30,6 @@ class RendererLoader {
await render.load() await render.load()
return render return render
} }
/** /**
* *
*/ */
@ -39,15 +37,20 @@ class RendererLoader {
const subFolders = fs const subFolders = fs
.readdirSync(this.dir, { withFileTypes: true }) .readdirSync(this.dir, { withFileTypes: true })
.filter(dirent => dirent.isDirectory()) .filter(dirent => dirent.isDirectory())
for (let subFolder of subFolders) { for (const subFolder of subFolders) {
let name = subFolder.name const name = subFolder.name
try { try {
const rendererFn = await import('../renderers/index.js') const rendererFn = await import('../renderers/index.js')
let configFile = `./config.yaml` const configFile = join(
let rendererCfg = fs.existsSync(configFile) process.cwd(),
'config',
'config',
'puppeteer.yaml'
)
const rendererCfg = fs.existsSync(configFile)
? yaml.parse(fs.readFileSync(configFile, 'utf8')) ? yaml.parse(fs.readFileSync(configFile, 'utf8'))
: {} : {}
let renderer = rendererFn.default(rendererCfg) const renderer = rendererFn.default(rendererCfg)
if ( if (
!renderer.id || !renderer.id ||
!renderer.type || !renderer.type ||
@ -64,7 +67,6 @@ class RendererLoader {
} }
} }
} }
/** /**
* *
* @param name * @param name
@ -74,10 +76,12 @@ class RendererLoader {
// TODO 渲染器降级 // TODO 渲染器降级
return this.renderers.get(name) return this.renderers.get(name)
} }
/** /**
* *
*/ */
} }
/**
*
* @deprecated
*/
export default await RendererLoader.init() export default await RendererLoader.init()

View File

@ -1,13 +1,19 @@
import { PuppeteerLaunchOptions } from 'puppeteer';
import Puppeteer from './puppeteer.js' import Puppeteer from './puppeteer.js'
/** /**
* *
* @param config config.yaml的配置内容 * @deprecated
* @param config
* @returns renderer * @returns renderer
* @returns renderer.id IDrenderer中选择的id * @returns renderer.id IDrenderer中选择的id
* @returns renderer.type image * @returns renderer.type image
* @returns renderer.render * @returns renderer.render
*/ */
export default function (config) { export default function (config?: PuppeteerLaunchOptions & {
chromiumPath: string;
puppeteerWS: any;
puppeteerTimeout: any;
}) {
// TODO Puppeteer待简化重构 // TODO Puppeteer待简化重构
return new Puppeteer(config) return new Puppeteer(config)
} }

View File

@ -1,15 +1,30 @@
import Renderer from "../renderer/Renderer.js"
import os from "node:os" import os from "node:os"
import lodash from "lodash" import lodash from "lodash"
import puppeteer, { Browser } from "puppeteer" import puppeteer, { Browser, PuppeteerLaunchOptions } from "puppeteer"
// 暂时保留对原config的兼容 /**
*
*/
import Renderer from "../renderer/Renderer.js"
/**
* config的兼容
*/
import { ConfigController as cfg } from "../../config/index.js" import { ConfigController as cfg } from "../../config/index.js"
/**
*
*/
const _path = process.cwd() const _path = process.cwd()
// mac地址
/**
* mac地址
*/
let mac = "" let mac = ""
/**
*
* @deprecated
*/
export default class Puppeteer extends Renderer { export default class Puppeteer extends Renderer {
browser: false | Browser = false browser: false | Browser = false
lock = false lock = false
@ -27,7 +42,11 @@ export default class Puppeteer extends Renderer {
* *
* @param config * @param config
*/ */
constructor(config) { constructor(config?: PuppeteerLaunchOptions & {
chromiumPath: string
puppeteerWS: any
puppeteerTimeout: any
}) {
/** /**
* *
*/ */
@ -182,16 +201,16 @@ export default class Puppeteer extends Renderer {
* @param data.pageGotoParams goto时的参数 * @param data.pageGotoParams goto时的参数
* @return img segment包裹 * @return img segment包裹
*/ */
async screenshot(name, data: any = {}) { async screenshot(name:string, data: any = {}) {
if (!await this.browserInit()) if (!await this.browserInit())
return false return false
const pageHeight = data.multiPageHeight || 4000 const pageHeight = data.multiPageHeight || 4000
let savePath = this.dealTpl(name, data) const savePath = this.dealTpl(name, data)
if (!savePath) return false if (!savePath) return false
let buff: any = "" let buff: any = ""
let start = Date.now() const start = Date.now()
let ret = [] let ret = []
this.shoting.push(name) this.shoting.push(name)
@ -213,16 +232,16 @@ export default class Puppeteer extends Renderer {
try { try {
const page = await this.browser.newPage() const page = await this.browser.newPage()
let pageGotoParams = lodash.extend({ timeout: 120000 }, data.pageGotoParams || {}) const pageGotoParams = lodash.extend({ timeout: 120000 }, data.pageGotoParams || {})
await page.goto(`file://${_path}${lodash.trim(savePath, ".")}`, pageGotoParams) await page.goto(`file://${_path}${lodash.trim(savePath, ".")}`, pageGotoParams)
let body = await page.$("#container") || await page.$("body") const body = await page.$("#container") || await page.$("body")
// 计算页面高度 // 计算页面高度
const boundingBox = await body.boundingBox() const boundingBox = await body.boundingBox()
// 分页数 // 分页数
let num = 1 let num = 1
let randData = { const randData = {
type: data.imgType || "jpeg", type: data.imgType || "jpeg",
omitBackground: data.omitBackground || false, omitBackground: data.omitBackground || false,
quality: data.quality || 90, quality: data.quality || 90,
@ -322,10 +341,10 @@ export default class Puppeteer extends Renderer {
} }
/** /**
* *
* @param browser * @param browser
*/ */
async stop(browser) { async stop(browser: Browser) {
try { try {
await browser.close() await browser.close()
} catch (err) { } catch (err) {