增加对Handler调用的支持

This commit is contained in:
Kokomi 2023-10-15 05:35:17 +08:00
parent 74a3101a5f
commit ed6ec3f309
6 changed files with 146 additions and 24 deletions

70
lib/plugins/handler.js Normal file
View File

@ -0,0 +1,70 @@
import lodash from 'lodash'
let events = {}
let Handler = {
add (cfg) {
let { ns, fn, property = 50 } = cfg
let key = cfg.key || cfg.event
if (!key || !fn) {
return
}
Handler.del(ns, key)
logger.mark(`[Handler]注册Handler: ${ns} - ${key}`)
events[key] = events[key] || []
events[key].push({
property,
fn,
ns,
key
})
events[key] = lodash.orderBy(events[key], ['priority'], ['asc'])
},
del (ns, key = '') {
if (!key) {
for (let key in events) {
Handler.del(ns, key)
}
return
}
if (!events[key]) {
return
}
for (let idx = 0; idx < events[key].length; idx++) {
let handler = events[key][idx]
if (handler.ns === ns) {
events[key].splice(idx, 1)
events[key] = lodash.orderBy(events[key], ['priority'], ['asc'])
}
}
},
async callAll (key, e, args) {
return await Handler.callAll(key, e, args, true)
},
async call (key, e, args, allHandler = false) {
let ret
for (let obj of events[key]) {
let fn = obj.fn
let done = true
let reject = (msg = '') => {
if (msg) {
logger.mark(`[Handler][${key}][Reject] ${msg}`)
}
done = false
}
ret = fn(e, args, reject)
if (ret) {
await ret
}
if (done && !allHandler) {
logger.mark(`[Handler][${key}][Done]`)
return ret
}
}
return ret
},
has (key) {
return !!events[key]
}
}
export default Handler

View File

@ -10,6 +10,7 @@ import moment from 'moment'
import path from 'node:path' import path from 'node:path'
import common from '../common/common.js' import common from '../common/common.js'
import Runtime from './runtime.js' import Runtime from './runtime.js'
import Handler from './handler.js'
/** 全局变量 plugin */ /** 全局变量 plugin */
global.plugin = plugin global.plugin = plugin
@ -21,6 +22,7 @@ global.segment = segment
class PluginsLoader { class PluginsLoader {
constructor () { constructor () {
this.priority = [] this.priority = []
this.handler = {}
this.task = [] this.task = []
this.dir = './plugins' this.dir = './plugins'
@ -55,14 +57,17 @@ class PluginsLoader {
for (let File of files) { for (let File of files) {
try { try {
let tmp = await import(File.path) let tmp = await import(File.path)
if (tmp.apps) tmp = { ...tmp.apps } let apps = tmp
let isAdd = false if (tmp.apps) {
lodash.forEach(tmp, (p, i) => { apps = { ...tmp.apps }
}
lodash.forEach(apps, (p, i) => {
if (!p.prototype) return if (!p.prototype) return
isAdd = true pluCount++
/* eslint-disable new-cap */ /* eslint-disable new-cap */
let plugin = new p() let plugin = new p()
logger.debug(`载入插件 [${File.name}][${plugin.name}]`) logger.debug(`载入插件 [${File.name}][${plugin.name}]`)
console.log(File.name, plugin.name)
/** 执行初始化 */ /** 执行初始化 */
this.runInit(plugin) this.runInit(plugin)
/** 初始化定时任务 */ /** 初始化定时任务 */
@ -73,8 +78,17 @@ class PluginsLoader {
name: plugin.name, name: plugin.name,
priority: plugin.priority priority: plugin.priority
}) })
if (plugin.handler) {
lodash.forEach(plugin.handler, ({ fn, key, priority }) => {
Handler.add({
ns: plugin.namespace || File.name,
key: key,
property: priority || plugin.priority || 500,
fn: plugin[fn]
})
})
}
}) })
if (isAdd) pluCount++
} catch (error) { } catch (error) {
if (error.stack.includes('Cannot find package')) { if (error.stack.includes('Cannot find package')) {
packageErr.push({ error, File }) packageErr.push({ error, File })
@ -94,7 +108,6 @@ class PluginsLoader {
/** 优先级排序 */ /** 优先级排序 */
this.priority = lodash.orderBy(this.priority, ['priority'], ['asc']) this.priority = lodash.orderBy(this.priority, ['priority'], ['asc'])
// console.log(this.priority)
} }
async runInit (plugin) { async runInit (plugin) {
@ -289,6 +302,9 @@ class PluginsLoader {
/** 过滤事件 */ /** 过滤事件 */
filtEvent (e, v) { filtEvent (e, v) {
if (!v.event) {
return false
}
let event = v.event.split('.') let event = v.event.split('.')
let eventMap = { let eventMap = {
message: ['post_type', 'message_type', 'sub_type'], message: ['post_type', 'message_type', 'sub_type'],
@ -305,9 +321,7 @@ class PluginsLoader {
}) })
newEvent = newEvent.join('.') newEvent = newEvent.join('.')
if (v.event == newEvent) return true return v.event === newEvent
return false
} }
/** 判断权限 */ /** 判断权限 */
@ -770,11 +784,23 @@ class PluginsLoader {
/* eslint-disable new-cap */ /* eslint-disable new-cap */
let plugin = new p() let plugin = new p()
for (let i in this.priority) { for (let i in this.priority) {
if (this.priority[i].key == key) { if (this.priority[i].key === key) {
this.priority[i].class = p this.priority[i].class = p
this.priority[i].priority = plugin.priority this.priority[i].priority = plugin.priority
} }
} }
if (plugin.handler) {
lodash.forEach(plugin.handler, ({ fn, key, priority }) => {
Handler.add({
ns: plugin.namespace || File.name,
key: key,
property: priority || plugin.priority || 500,
fn: plugin[fn]
})
})
}
}) })
this.priority = lodash.orderBy(this.priority, ['priority'], ['asc']) this.priority = lodash.orderBy(this.priority, ['priority'], ['asc'])

View File

@ -1,23 +1,37 @@
let stateArr = {} let stateArr = {}
export default class plugin { export default class plugin {
/** /**
* @param name 插件名称 * @param name 插件名称
* @param dsc 插件描述 * @param dsc 插件描述
* @param handler handler配置
* @param handler.key handler支持的事件key
* @param handler.fn handler的处理func
* @param namespace namespace设置handler时建议设置
* @param event 执行事件默认message * @param event 执行事件默认message
* @param priority 优先级数字越小优先级越高 * @param priority 优先级数字越小优先级越高
* @param rule
* @param rule.reg 命令正则 * @param rule.reg 命令正则
* @param rule.fnc 命令执行方法 * @param rule.fnc 命令执行方法
* @param rule.event 执行事件默认message * @param rule.event 执行事件默认message
* @param rule.log false时不显示执行日志 * @param rule.log false时不显示执行日志
* @param rule.permission 权限 master,owner,admin,all * @param rule.permission 权限 master,owner,admin,all
* @param task
* @param task.name 定时任务名称 * @param task.name 定时任务名称
* @param task.cron 定时任务cron表达式 * @param task.cron 定时任务cron表达式
* @param task.fnc 定时任务方法名 * @param task.fnc 定时任务方法名
* @param task.log false时不显示执行日志 * @param task.log false时不显示执行日志
*/ */
constructor({ name = 'your-plugin', dsc = '无', event = 'message', priority = 5000, task = { fnc: '', cron: '' }, rule = [] }) { constructor ({
name = 'your-plugin',
dsc = '无',
handler,
namespace,
event = 'message',
priority = 5000,
task = { fnc: '', cron: '' },
rule = []
}) {
/** 插件名称 */ /** 插件名称 */
this.name = name this.name = name
/** 插件描述 */ /** 插件描述 */
@ -37,14 +51,19 @@ export default class plugin {
} }
/** 命令规则 */ /** 命令规则 */
this.rule = rule this.rule = rule
if (handler) {
this.handler = handler
this.namespace = namespace || ''
}
} }
/** /**
* @param msg 发送的消息 * @param msg 发送的消息
* @param quote 是否引用回复 * @param quote 是否引用回复
* @param data.recallMsg 群聊是否撤回消息0-1200不撤回 * @param data.recallMsg 群聊是否撤回消息0-1200不撤回
* @param data.at 是否at用户 * @param data.at 是否at用户
*/ */
reply (msg = '', quote = false, data = {}) { reply (msg = '', quote = false, data = {}) {
if (!this.e.reply || !msg) return false if (!this.e.reply || !msg) return false
return this.e.reply(msg, quote, data) return this.e.reply(msg, quote, data)

View File

@ -15,6 +15,7 @@ import puppeteer from '../puppeteer/puppeteer.js'
import { Version } from '#miao' import { Version } from '#miao'
import NoteUser from '../../plugins/genshin/model/mys/NoteUser.js' import NoteUser from '../../plugins/genshin/model/mys/NoteUser.js'
import MysUser from '../../plugins/genshin/model/mys/MysUser.js' import MysUser from '../../plugins/genshin/model/mys/MysUser.js'
import Handler from './handler.js'
/** /**
* 常用的处理方法 * 常用的处理方法
@ -24,6 +25,12 @@ export default class Runtime {
constructor (e) { constructor (e) {
this.e = e this.e = e
this._mysInfo = {} this._mysInfo = {}
this.handler = {
has: Handler.has,
call: Handler.call,
callAll: Handler.callAll
}
} }
get uid () { get uid () {

View File

@ -119,10 +119,6 @@ export default class MysApi {
return false return false
} }
/* if (res.retcode !== 0 && this.option.log) {
logger.debug(`[米游社接口][请求参数] ${url} ${JSON.stringify(param)}`)
} */
res.api = type res.api = type
if (cached) this.cache(res, cacheKey) if (cached) this.cache(res, cacheKey)

View File

@ -419,9 +419,13 @@ export default class MysInfo {
if (res.api === 'detail') res.retcode = 0 if (res.api === 'detail') res.retcode = 0
break break
case 1034: case 1034:
try { let handler = this.e.runtime?.handler || {}
res = await Gtest.getvali(mysApi, type, data, this.gtest)
} catch (error) { } // 如果有注册的mys.req.err调用
if (handler.has('mys.req.err')) {
logger.mark(`[米游社查询][uid:${this.uid}][qq:${this.userId}] 遇到验证码,尝试调用 Handler mys.req.err`)
res = await handler.call('mys.req.err', this.e, { mysApi, type, res, data, mysInfo: this }) || res
}
if (!res || res?.retcode == 1034) { if (!res || res?.retcode == 1034) {
logger.mark(`[米游社查询失败][uid:${this.uid}][qq:${this.userId}] 遇到验证码`) logger.mark(`[米游社查询失败][uid:${this.uid}][qq:${this.userId}] 遇到验证码`)