From bcd4e84807bbe0e0fba67aa0a63b139f7fba96b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=8C=8C?= Date: Sun, 15 Oct 2023 14:09:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20handler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/plugins/handler.js | 70 ++++++++++++++++++++++++++++++++++++++++++ lib/plugins/loader.js | 40 ++++++++++++++++++------ lib/plugins/plugin.js | 42 ++++++++++++++++++------- lib/plugins/runtime.js | 7 +++++ package.json | 2 +- 5 files changed, 140 insertions(+), 21 deletions(-) create mode 100644 lib/plugins/handler.js diff --git a/lib/plugins/handler.js b/lib/plugins/handler.js new file mode 100644 index 0000000..52ddb6a --- /dev/null +++ b/lib/plugins/handler.js @@ -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][Reg]: [${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][Reject]: [${obj.ns}][${key}] ${msg}`) + } + done = false + } + ret = fn(e, args, reject) + if (ret) { + await ret + } + if (done && !allHandler) { + logger.mark(`[Handler][Done]: [${obj.ns}][${key}]`) + return ret + } + } + return ret + }, + has (key) { + return !!events[key] + } +} +export default Handler + diff --git a/lib/plugins/loader.js b/lib/plugins/loader.js index ceeccac..b63880e 100644 --- a/lib/plugins/loader.js +++ b/lib/plugins/loader.js @@ -10,6 +10,7 @@ import moment from "moment" import path from "node:path" import common from "../common/common.js" import Runtime from "./runtime.js" +import Handler from './handler.js' /** 全局变量 plugin */ global.plugin = plugin @@ -21,6 +22,7 @@ global.segment = segment class PluginsLoader { constructor() { this.priority = [] + this.handler = {} this.task = [] this.dir = "./plugins" @@ -56,11 +58,13 @@ class PluginsLoader { for (let File of files) { try { let tmp = await import(File.path) - if (tmp.apps) tmp = { ...tmp.apps } - let isAdd = false - lodash.forEach(tmp, (p, i) => { + let apps = tmp + if (tmp.apps) { + apps = { ...tmp.apps } + } + lodash.forEach(apps, (p, i) => { if (!p.prototype) return - isAdd = true + pluCount++ /* eslint-disable new-cap */ let plugin = new p() logger.debug(`载入插件 [${File.name}][${plugin.name}]`) @@ -74,8 +78,17 @@ class PluginsLoader { name: plugin.name, 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) { if (error.stack.includes("Cannot find package")) { packageErr.push({ error, File }) @@ -94,7 +107,6 @@ class PluginsLoader { /** 优先级排序 */ this.priority = lodash.orderBy(this.priority, ["priority"], ["asc"]) - // console.log(this.priority) } async runInit(plugin) { @@ -281,6 +293,7 @@ class PluginsLoader { /** 过滤事件 */ filtEvent(e, v) { + if (!v.event) return false let event = v.event.split(".") let eventMap = { message: ["post_type", "message_type", "sub_type"], @@ -297,9 +310,7 @@ class PluginsLoader { }) newEvent = newEvent.join(".") - if (v.event == newEvent) return true - - return false + return v.event === newEvent } /** 判断权限 */ @@ -759,6 +770,17 @@ class PluginsLoader { 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"]) diff --git a/lib/plugins/plugin.js b/lib/plugins/plugin.js index 0c43488..b4874ba 100644 --- a/lib/plugins/plugin.js +++ b/lib/plugins/plugin.js @@ -4,24 +4,39 @@ export default class plugin { /** * @param name 插件名称 * @param dsc 插件描述 + * @param handler handler配置 + * @param handler.key handler支持的事件key + * @param handler.fn handler的处理func + * @param namespace namespace,设置handler时建议设置 * @param event 执行事件,默认message * @param priority 优先级,数字越小优先级越高 + * @param rule * @param rule.reg 命令正则 * @param rule.fnc 命令执行方法 * @param rule.event 执行事件,默认message * @param rule.log false时不显示执行日志 * @param rule.permission 权限 master,owner,admin,all + * @param task * @param task.name 定时任务名称 * @param task.cron 定时任务cron表达式 * @param task.fnc 定时任务方法名 * @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.dsc = dsc - /** 监听事件,默认message */ + /** 监听事件,默认message https://oicqjs.github.io/oicq/#events */ this.event = event /** 优先级 */ this.priority = priority @@ -36,20 +51,25 @@ export default class plugin { } /** 命令规则 */ this.rule = rule + + if (handler) { + this.handler = handler + this.namespace = namespace || '' + } } /** * @param msg 发送的消息 * @param quote 是否引用回复 - * @param data.recallMsg 是否撤回消息,0-120秒,0不撤回 - * @param data.at 是否提及用户 + * @param data.recallMsg 群聊是否撤回消息,0-120秒,0不撤回 + * @param data.at 是否at用户 */ - reply(msg = '', quote = false, data = {}) { + reply (msg = '', quote = false, data = {}) { if (!this.e.reply || !msg) return false return this.e.reply(msg, quote, data) } - conKey(isGroup = false) { + conKey (isGroup = false) { if (isGroup) { return `${this.name}.${this.e.group_id}` } else { @@ -62,7 +82,7 @@ export default class plugin { * @param isGroup 是否群聊 * @param time 操作时间,默认120秒 */ - setContext(type, isGroup = false, time = 120) { + setContext (type, isGroup = false, time = 120) { let key = this.conKey(isGroup) if (!stateArr[key]) stateArr[key] = {} stateArr[key][type] = this.e @@ -77,12 +97,12 @@ export default class plugin { } } - getContext() { + getContext () { let key = this.conKey() return stateArr[key] } - getContextGroup() { + getContextGroup () { let key = this.conKey(true) return stateArr[key] } @@ -91,9 +111,9 @@ export default class plugin { * @param type 执行方法 * @param isGroup 是否群聊 */ - finish(type, isGroup = false) { + finish (type, isGroup = false) { if (stateArr[this.conKey(isGroup)] && stateArr[this.conKey(isGroup)][type]) { delete stateArr[this.conKey(isGroup)][type] } } -} \ No newline at end of file +} diff --git a/lib/plugins/runtime.js b/lib/plugins/runtime.js index 83d379a..21b2d46 100644 --- a/lib/plugins/runtime.js +++ b/lib/plugins/runtime.js @@ -15,6 +15,7 @@ import puppeteer from '../puppeteer/puppeteer.js' import { Version } from '#miao' import NoteUser from '../../plugins/genshin/model/mys/NoteUser.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) { this.e = e this._mysInfo = {} + + this.handler = { + has: Handler.has, + call: Handler.call, + callAll: Handler.callAll + } } get uid () { diff --git a/package.json b/package.json index 8a83d9f..d5ce248 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "sequelize": "^6.33.0", "sqlite3": "^5.1.6", "ws": "^8.14.2", - "yaml": "^2.3.2" + "yaml": "^2.3.3" }, "devDependencies": { "eslint": "^8.51.0",