fix: 修复插件解析
This commit is contained in:
parent
bfb44c589f
commit
baaf8a1cb7
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "miao-yunzai",
|
||||
"version": "4.0.0-rc.0",
|
||||
"version": "4.0.0",
|
||||
"author": "Yoimiya-Kokomi, Le-niao",
|
||||
"description": "QQ Group Bot",
|
||||
"main": "./index.js",
|
||||
|
|
|
@ -11,13 +11,13 @@ import cfg from './config/config.js'
|
|||
/**
|
||||
* 监听
|
||||
*/
|
||||
import ListenerLoader from './core/loader.js'
|
||||
import ListenerLoader from './core/events.loader.js'
|
||||
/**
|
||||
* 扩展
|
||||
*/
|
||||
import { Client } from 'icqq'
|
||||
|
||||
import { plugin } from './core/plugin.js'
|
||||
import { plugin } from './core/plugins/index.js'
|
||||
|
||||
/**
|
||||
* global
|
||||
|
@ -71,6 +71,6 @@ export class Yunzai extends Client {
|
|||
/** 全局变量 bot */
|
||||
global.Bot = bot
|
||||
/** 加载插件 */
|
||||
return await (await import('./core/plugins/loader.js')).default.load()
|
||||
return await (await import('./core/plugins.loader.js')).default.load()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import EventListener from '../listener.js'
|
||||
import cfg from '../../config/config.js'
|
||||
import { relpyPrivate } from '../common.js'
|
||||
import { relpyPrivate } from '../plugins/common.js'
|
||||
import { BOT_NAME } from '../../config/system.js'
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export * from './plugin.js'
|
||||
export * from './functional.js'
|
||||
export * from './types.js'
|
||||
export * from './plugins/index.js'
|
||||
export * from './plugins/functional.js'
|
||||
export * from './plugins/types.js'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import PluginsLoader from './plugins/loader.js'
|
||||
import PluginsLoader from './plugins.loader.js'
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import fs from 'node:fs/promises'
|
||||
import lodash from 'lodash'
|
||||
import cfg from '../../config/config.js'
|
||||
import cfg from '../config/config.js'
|
||||
import schedule from 'node-schedule'
|
||||
import { segment } from 'icqq'
|
||||
import chokidar from 'chokidar'
|
||||
import moment from 'moment'
|
||||
import path, { join } from 'node:path'
|
||||
import Runtime from './runtime.js'
|
||||
import Handler from './handler.js'
|
||||
|
||||
import path from 'node:path'
|
||||
import Runtime from './plugins/runtime.js'
|
||||
import Handler from './plugins/handler.js'
|
||||
|
||||
/**
|
||||
* 加载插件
|
||||
|
@ -19,7 +18,7 @@ class PluginsLoader {
|
|||
task = []
|
||||
|
||||
//
|
||||
dir = join(process.cwd(), 'plugins')
|
||||
dir = 'plugins'
|
||||
|
||||
/**
|
||||
* 命令冷却cd
|
||||
|
@ -35,9 +34,9 @@ class PluginsLoader {
|
|||
watcher = {}
|
||||
|
||||
eventMap = {
|
||||
message: ["post_type", "message_type", "sub_type"],
|
||||
notice: ["post_type", "notice_type", "sub_type"],
|
||||
request: ["post_type", "request_type", "sub_type"],
|
||||
message: ['post_type', 'message_type', 'sub_type'],
|
||||
notice: ['post_type', 'notice_type', 'sub_type'],
|
||||
request: ['post_type', 'request_type', 'sub_type']
|
||||
}
|
||||
|
||||
msgThrottle = {}
|
||||
|
@ -58,13 +57,13 @@ class PluginsLoader {
|
|||
if (val.isFile()) continue
|
||||
const tmp = {
|
||||
name: val.name,
|
||||
path: join(this.dir, val.name),
|
||||
path: `../../${this.dir}/${val.name}`
|
||||
}
|
||||
|
||||
try {
|
||||
const dir = join(tmp.path, 'index.js')
|
||||
const dir = `${this.dir}/${val.name}/index.js`
|
||||
if (await fs.stat(dir)) {
|
||||
tmp.path = dir
|
||||
tmp.path = `${tmp.path}/index.js`
|
||||
ret.push(tmp)
|
||||
continue
|
||||
}
|
||||
|
@ -72,20 +71,16 @@ class PluginsLoader {
|
|||
//
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const dir = join(this.dir, val.name)
|
||||
|
||||
const apps = await fs.readdir(dir, { withFileTypes: true })
|
||||
|
||||
//
|
||||
const apps = await fs.readdir(`${this.dir}/${val.name}`, {
|
||||
withFileTypes: true
|
||||
})
|
||||
for (const app of apps) {
|
||||
if (!app.isFile()) continue
|
||||
// .js .ts
|
||||
if (!/^(.js|.ts)$/.test(app.name)) continue
|
||||
// 解析js和ts
|
||||
if (!/(.js|.ts|.jsx|.tsx)$/.test(app.name)) continue
|
||||
ret.push({
|
||||
name: `${tmp.name}/${app.name}`,
|
||||
path: `${tmp.path}/${app.name}`,
|
||||
path: `${tmp.path}/${app.name}`
|
||||
})
|
||||
/** 监听热更新 */
|
||||
this.watch(val.name, app.name)
|
||||
|
@ -113,9 +108,9 @@ class PluginsLoader {
|
|||
this.pluginCount = 0
|
||||
const packageErr = []
|
||||
|
||||
await Promise.allSettled(files.map(file =>
|
||||
this.importPlugin(file, packageErr)
|
||||
))
|
||||
await Promise.allSettled(
|
||||
files.map(file => this.importPlugin(file, packageErr))
|
||||
)
|
||||
|
||||
this.packageTips(packageErr)
|
||||
this.createTask()
|
||||
|
@ -134,12 +129,10 @@ class PluginsLoader {
|
|||
*/
|
||||
async importPlugin(file, packageErr?: any) {
|
||||
try {
|
||||
let app = await import(`file://${file.path}`)
|
||||
let app = await import(file.path)
|
||||
if (app.apps) app = { ...app.apps }
|
||||
const pluginArray = []
|
||||
lodash.forEach(app, p =>
|
||||
pluginArray.push(this.loadPlugin(file, p))
|
||||
)
|
||||
lodash.forEach(app, p => pluginArray.push(this.loadPlugin(file, p)))
|
||||
for (const i of await Promise.allSettled(pluginArray))
|
||||
if (i?.status && i.status != 'fulfilled') {
|
||||
logger.error(`加载插件错误:${logger.red(file.name)}`)
|
||||
|
@ -164,10 +157,10 @@ class PluginsLoader {
|
|||
async loadPlugin(file, p) {
|
||||
if (!p?.prototype) return
|
||||
this.pluginCount++
|
||||
const plugin = new p
|
||||
const plugin = new p()
|
||||
logger.debug(`加载插件 [${file.name}][${plugin.name}]`)
|
||||
/** 执行初始化,返回 return 则跳过加载 */
|
||||
if (plugin.init && await plugin.init() == 'return') return
|
||||
if (plugin.init && (await plugin.init()) == 'return') return
|
||||
/** 初始化定时任务 */
|
||||
this.collectTask(plugin.task)
|
||||
this.priority.push({
|
||||
|
@ -201,7 +194,9 @@ class PluginsLoader {
|
|||
let pack = v.error.stack.match(/'(.+?)'/g)[0].replace(/'/g, '')
|
||||
logger.mark(`${v.file.name} 缺少依赖:${logger.red(pack)}`)
|
||||
logger.mark(`新增插件后请执行安装命令:${logger.red('pnpm i')} 安装依赖`)
|
||||
logger.mark(`如安装后仍未解决可联系插件作者将 ${logger.red(pack)} 依赖添加至插件的package.json dependencies中,或手工安装依赖`)
|
||||
logger.mark(
|
||||
`如安装后仍未解决可联系插件作者将 ${logger.red(pack)} 依赖添加至插件的package.json dependencies中,或手工安装依赖`
|
||||
)
|
||||
})
|
||||
// logger.error('或者使用其他包管理工具安装依赖')
|
||||
logger.mark('---------------------')
|
||||
|
@ -236,8 +231,7 @@ class PluginsLoader {
|
|||
const p = new i.class(e)
|
||||
p.e = e
|
||||
/** 判断是否启用功能,过滤事件 */
|
||||
if (this.checkDisable(p) && this.filtEvent(e, p))
|
||||
priority.push(p)
|
||||
if (this.checkDisable(p) && this.filtEvent(e, p)) priority.push(p)
|
||||
}
|
||||
|
||||
for (const plugin of priority) {
|
||||
|
@ -245,7 +239,7 @@ class PluginsLoader {
|
|||
if (!plugin.getContext) continue
|
||||
const context = {
|
||||
...plugin.getContext(),
|
||||
...plugin.getContext(false, true),
|
||||
...plugin.getContext(false, true)
|
||||
}
|
||||
if (!lodash.isEmpty(context)) {
|
||||
let ret
|
||||
|
@ -265,11 +259,11 @@ class PluginsLoader {
|
|||
// e.isSr = true,且命令标准化为 #星铁 开头
|
||||
Object.defineProperty(e, 'isSr', {
|
||||
get: () => e.game === 'sr',
|
||||
set: (v) => e.game = v ? 'sr' : 'gs'
|
||||
set: v => (e.game = v ? 'sr' : 'gs')
|
||||
})
|
||||
Object.defineProperty(e, 'isGs', {
|
||||
get: () => e.game === 'gs',
|
||||
set: (v) => e.game = v ? 'gs' : 'sr'
|
||||
set: v => (e.game = v ? 'gs' : 'sr')
|
||||
})
|
||||
if (this.srReg.test(e.msg)) {
|
||||
e.game = 'sr'
|
||||
|
@ -286,34 +280,39 @@ class PluginsLoader {
|
|||
|
||||
a: for (const plugin of priority) {
|
||||
/** 正则匹配 */
|
||||
if (plugin.rule) for (const v of plugin.rule) {
|
||||
/** 判断事件 */
|
||||
if (v.event && !this.filtEvent(e, v)) continue
|
||||
if (!new RegExp(v.reg).test(e.msg)) continue
|
||||
e.logFnc = `[${plugin.name}][${v.fnc}]`
|
||||
if (plugin.rule)
|
||||
for (const v of plugin.rule) {
|
||||
/** 判断事件 */
|
||||
if (v.event && !this.filtEvent(e, v)) continue
|
||||
if (!new RegExp(v.reg).test(e.msg)) continue
|
||||
e.logFnc = `[${plugin.name}][${v.fnc}]`
|
||||
|
||||
if (v.log !== false)
|
||||
logger.info(`${e.logFnc}${e.logText} ${lodash.truncate(e.msg, { length: 100 })}`)
|
||||
if (v.log !== false)
|
||||
logger.info(
|
||||
`${e.logFnc}${e.logText} ${lodash.truncate(e.msg, { length: 100 })}`
|
||||
)
|
||||
|
||||
/** 判断权限 */
|
||||
if (!this.filtPermission(e, v)) break a
|
||||
/** 判断权限 */
|
||||
if (!this.filtPermission(e, v)) break a
|
||||
|
||||
try {
|
||||
const start = Date.now()
|
||||
const res = plugin[v.fnc] && (await plugin[v.fnc](e))
|
||||
if (res !== false) {
|
||||
/** 设置冷却cd */
|
||||
this.setLimit(e)
|
||||
if (v.log !== false)
|
||||
logger.mark(`${e.logFnc} ${lodash.truncate(e.msg, { length: 100 })} 处理完成 ${Date.now() - start}ms`)
|
||||
try {
|
||||
const start = Date.now()
|
||||
const res = plugin[v.fnc] && (await plugin[v.fnc](e))
|
||||
if (res !== false) {
|
||||
/** 设置冷却cd */
|
||||
this.setLimit(e)
|
||||
if (v.log !== false)
|
||||
logger.mark(
|
||||
`${e.logFnc} ${lodash.truncate(e.msg, { length: 100 })} 处理完成 ${Date.now() - start}ms`
|
||||
)
|
||||
break a
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`${e.logFnc}`)
|
||||
logger.error(error.stack)
|
||||
break a
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`${e.logFnc}`)
|
||||
logger.error(error.stack)
|
||||
break a
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,19 +324,16 @@ class PluginsLoader {
|
|||
*/
|
||||
filtEvent(e, v) {
|
||||
if (!v.event) return false
|
||||
const event = v.event.split(".")
|
||||
const event = v.event.split('.')
|
||||
const eventMap = this.eventMap[e.post_type] || []
|
||||
const newEvent = []
|
||||
for (const i in event) {
|
||||
if (event[i] == "*")
|
||||
newEvent.push(event[i])
|
||||
else
|
||||
newEvent.push(e[eventMap[i]])
|
||||
if (event[i] == '*') newEvent.push(event[i])
|
||||
else newEvent.push(e[eventMap[i]])
|
||||
}
|
||||
return v.event == newEvent.join(".")
|
||||
return v.event == newEvent.join('.')
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断权限
|
||||
* @param e
|
||||
|
@ -400,7 +396,12 @@ class PluginsLoader {
|
|||
for (let val of e.message) {
|
||||
switch (val.type) {
|
||||
case 'text':
|
||||
e.msg = (e.msg || '') + (val.text || '').replace(/^\s*[#井#]+\s*/, '#').replace(/^\s*[\\*※*]+\s*/, '*').trim()
|
||||
e.msg =
|
||||
(e.msg || '') +
|
||||
(val.text || '')
|
||||
.replace(/^\s*[#井#]+\s*/, '#')
|
||||
.replace(/^\s*[\\*※*]+\s*/, '*')
|
||||
.trim()
|
||||
break
|
||||
case 'image':
|
||||
if (!e.img) {
|
||||
|
@ -423,9 +424,13 @@ class PluginsLoader {
|
|||
case 'file':
|
||||
e.file = { name: val.name, fid: val.fid }
|
||||
break
|
||||
case "xml":
|
||||
case "json":
|
||||
e.msg = (e.msg || "") + (typeof val.data == "string" ? val.data : JSON.stringify(val.data))
|
||||
case 'xml':
|
||||
case 'json':
|
||||
e.msg =
|
||||
(e.msg || '') +
|
||||
(typeof val.data == 'string'
|
||||
? val.data
|
||||
: JSON.stringify(val.data))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -475,7 +480,10 @@ class PluginsLoader {
|
|||
e.isGuild = true
|
||||
}
|
||||
|
||||
if (e.user_id && cfg.masterQQ.includes(String(e.user_id) || String(e.user_id))) {
|
||||
if (
|
||||
e.user_id &&
|
||||
cfg.masterQQ.includes(String(e.user_id) || String(e.user_id))
|
||||
) {
|
||||
e.isMaster = true
|
||||
}
|
||||
|
||||
|
@ -535,10 +543,8 @@ class PluginsLoader {
|
|||
text = lodash.truncate(text, { length: 10 })
|
||||
}
|
||||
|
||||
if (Array.isArray(msg))
|
||||
msg.unshift(segment.at(at, text), "\n")
|
||||
else
|
||||
msg = [segment.at(at, text), "\n", msg]
|
||||
if (Array.isArray(msg)) msg.unshift(segment.at(at, text), '\n')
|
||||
else msg = [segment.at(at, text), '\n', msg]
|
||||
}
|
||||
|
||||
let msgRes
|
||||
|
@ -551,15 +557,24 @@ class PluginsLoader {
|
|||
}
|
||||
logger.error(`发送消息错误:${msg}`)
|
||||
logger.error(err)
|
||||
if (cfg.bot.sendmsg_error) Bot[Bot.uin].pickUser(cfg.masterQQ[0]).sendMsg(`发送消息错误:${msg}`)
|
||||
if (cfg.bot.sendmsg_error)
|
||||
Bot[Bot.uin]
|
||||
.pickUser(cfg.masterQQ[0])
|
||||
.sendMsg(`发送消息错误:${msg}`)
|
||||
}
|
||||
|
||||
// 频道一下是不是频道
|
||||
if (!e.isGuild && recallMsg > 0 && msgRes?.message_id) {
|
||||
if (e.isGroup) {
|
||||
setTimeout(() => e.group.recallMsg(msgRes.message_id), recallMsg * 1000)
|
||||
setTimeout(
|
||||
() => e.group.recallMsg(msgRes.message_id),
|
||||
recallMsg * 1000
|
||||
)
|
||||
} else if (e.friend) {
|
||||
setTimeout(() => e.friend.recallMsg(msgRes.message_id), recallMsg * 1000)
|
||||
setTimeout(
|
||||
() => e.friend.recallMsg(msgRes.message_id),
|
||||
recallMsg * 1000
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,15 +586,18 @@ class PluginsLoader {
|
|||
if (!msg) return false
|
||||
this.count(e, msg)
|
||||
if (e.group_id) {
|
||||
return await e.group.sendMsg(msg).catch((err) => {
|
||||
return await e.group.sendMsg(msg).catch(err => {
|
||||
logger.warn(err)
|
||||
})
|
||||
} else {
|
||||
let friend = e.bot.fl.get(e.user_id)
|
||||
if (!friend) return
|
||||
return await e.bot.pickUser(e.user_id).sendMsg(msg).catch((err) => {
|
||||
logger.warn(err)
|
||||
})
|
||||
return await e.bot
|
||||
.pickUser(e.user_id)
|
||||
.sendMsg(msg)
|
||||
.catch(err => {
|
||||
logger.warn(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -655,11 +673,9 @@ class PluginsLoader {
|
|||
for (const i of this.task)
|
||||
i.job = schedule.scheduleJob(i?.cron, async () => {
|
||||
try {
|
||||
if (i.log == true)
|
||||
logger.mark(`开始定时任务:${i.name}`)
|
||||
if (i.log == true) logger.mark(`开始定时任务:${i.name}`)
|
||||
await i.fnc()
|
||||
if (i.log == true)
|
||||
logger.mark(`定时任务完成:${i.name}`)
|
||||
if (i.log == true) logger.mark(`定时任务完成:${i.name}`)
|
||||
} catch (error) {
|
||||
logger.error(`定时任务报错:${i.name}`)
|
||||
logger.error(error)
|
||||
|
@ -780,10 +796,16 @@ class PluginsLoader {
|
|||
|
||||
if (e.group_id) {
|
||||
/** 黑名单群 */
|
||||
if (other.blackGroup?.length && other.blackGroup.includes(Number(e.group_id) || String(e.group_id)))
|
||||
if (
|
||||
other.blackGroup?.length &&
|
||||
other.blackGroup.includes(Number(e.group_id) || String(e.group_id))
|
||||
)
|
||||
return false
|
||||
/** 白名单群 */
|
||||
if (other.whiteGroup?.length && !other.whiteGroup.includes(Number(e.group_id) || String(e.group_id)))
|
||||
if (
|
||||
other.whiteGroup?.length &&
|
||||
!other.whiteGroup.includes(Number(e.group_id) || String(e.group_id))
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -813,9 +835,12 @@ class PluginsLoader {
|
|||
let app = await import(`../../${this.dir}/${key}?${moment().format('x')}`)
|
||||
if (app.apps) app = { ...app.apps }
|
||||
lodash.forEach(app, p => {
|
||||
const plugin = new p
|
||||
const plugin = new p()
|
||||
for (const i in this.priority)
|
||||
if (this.priority[i].key == key && this.priority[i].name == plugin.name) {
|
||||
if (
|
||||
this.priority[i].key == key &&
|
||||
this.priority[i].name == plugin.name
|
||||
) {
|
||||
this.priority[i].class = p
|
||||
this.priority[i].priority = plugin.priority
|
||||
}
|
||||
|
@ -862,7 +887,6 @@ class PluginsLoader {
|
|||
this.watcher[`${dirName}.${appName}`] = watcher
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 监听文件夹更新
|
||||
* @param dirName
|
||||
|
@ -881,7 +905,7 @@ class PluginsLoader {
|
|||
const key = `${dirName}/${appName}`
|
||||
await this.importPlugin({
|
||||
name: key,
|
||||
path: `../../${this.dir}/${key}?${moment().format('X')}`,
|
||||
path: `../../${this.dir}/${key}?${moment().format('X')}`
|
||||
})
|
||||
/** 优先级排序 */
|
||||
this.priority = lodash.orderBy(this.priority, ['priority'], ['asc'])
|
||||
|
@ -890,8 +914,6 @@ class PluginsLoader {
|
|||
}, 10000)
|
||||
this.watcher[dirName] = watcher
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
|
@ -1,5 +1,5 @@
|
|||
import { MessageCallBackType } from './types.js'
|
||||
import { plugin } from './plugin.js'
|
||||
import { plugin } from './index.js'
|
||||
|
||||
/**
|
||||
* 插件super默认值
|
|
@ -1,4 +1,4 @@
|
|||
import { Common } from '../local.js'
|
||||
import { Common } from '../../local.js'
|
||||
import { EventType } from './types.js'
|
||||
|
||||
const stateArr = {}
|
|
@ -39,5 +39,5 @@
|
|||
"transpileOnly": true,
|
||||
"experimentalSpecifierResolution": "node"
|
||||
},
|
||||
"include": ["src", "image", "example"]
|
||||
"include": ["src", "image"]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue