diff --git a/src/core/karin.ts b/src/core/karin.ts index 12640fa..451b107 100644 --- a/src/core/karin.ts +++ b/src/core/karin.ts @@ -1,8 +1,10 @@ import PluginApp from './plugin.app' import { common } from 'karin/utils' +import { render } from 'karin/render' +import { stateArr } from './plugin' +import { listener } from './listener' import { KarinMessage } from 'karin/event/message' import { Permission, PluginApps, KarinElement, contact, KarinRenderType } from 'karin/types' -import { render } from 'karin/render' type FncFunction = (e: KarinMessage) => Promise type FncElement = string | KarinElement | Array @@ -222,4 +224,45 @@ export class Karin { render (options: KarinRenderType) { return render.render(options) } + + /** + * - 上下文 + * @param e - 消息事件 + */ + async ctx (e: KarinMessage, options?: { + /** + * - 指定用户id触发下文 不指定则使用默认e.user_id + */ + userId?: string + /** + * - 超时时间 默认120秒 + */ + time?: number + /** + * - 超时后是否回复 + */ + reply?: boolean + /** + * - 超时回复文本 默认为'操作超时已取消' + */ + replyMsg?: string + }): Promise { + const time = options?.time || 120 + const userId = options?.userId || e.user_id + const key = e.group_id ? `${e.group_id}.${userId}` : userId + stateArr[key] = { type: 'ctx' } + // 返回promise 设置超时时间 + return new Promise((resolve, reject) => { + setTimeout(() => { + if (stateArr[key]) { + delete stateArr[key] + if (options?.reply) e.reply(options.replyMsg || '操作超时已取消') + reject(new Error('操作超时已取消')) + return true + } + }, time * 1000) + + listener.once(`ctx:${key}`, (e: KarinMessage) => resolve(e)) + }) + } } diff --git a/src/core/plugin.ts b/src/core/plugin.ts index b5d1222..c88c807 100644 --- a/src/core/plugin.ts +++ b/src/core/plugin.ts @@ -1,4 +1,4 @@ -import { PluginType, KarinElement, KarinNodeElement, EventType, KarinNoticeEvent, KarinRequestEvent } from 'karin/types' +import { PluginType, KarinElement, KarinNodeElement, EventType, KarinNoticeEvent, KarinRequestEvent, stateArrType } from 'karin/types' /** * 插件基类 @@ -178,7 +178,7 @@ export class Plugin implements PluginType { /** * @param fnc - 执行方法 */ - fnc: string, + fnc: string | Function, /** * @param reply - 超时后是否回复 */ @@ -189,7 +189,13 @@ export class Plugin implements PluginType { time = 120 ) { const key = this.conKey() - stateArr[key] = { plugin: this, fnc } + + if (typeof fnc === 'string') { + stateArr[key] = { type: 'class', fnc: this, name: fnc } + } else { + stateArr[key] = { type: 'fnc', fnc } + } + /** 操作时间 */ this.timeout = setTimeout(() => { if (stateArr[key]) { @@ -202,7 +208,7 @@ export class Plugin implements PluginType { /** * 获取上下文状态 */ - getContext (): { plugin: Plugin, fnc: string } { + getContext (): stateArrType[string] { const key = this.conKey() return stateArr[key] } @@ -223,18 +229,7 @@ export class Plugin implements PluginType { /** * 上下文状态 */ -export const stateArr: { - [key: string]: { - /** - * @param plugin - 插件实例 - */ - plugin: Plugin - /** - * @param fnc - 执行方法名称 - */ - fnc: string - } -} = {} +export const stateArr: stateArrType = {} /** * 通知事件 插件类型 diff --git a/src/event/message.handler.ts b/src/event/message.handler.ts index 4112e72..d8eb58f 100644 --- a/src/event/message.handler.ts +++ b/src/event/message.handler.ts @@ -233,14 +233,33 @@ export class MessageHandler extends EventHandler { const key = this.e.isGroup ? `${this.e.group_id}.${this.e.user_id}` : this.e.user_id const App = stateArr[key] if (App) { - const { plugin, fnc } = App - this.e.logFnc = `[${plugin.name}][${fnc}]` - /** 计算插件处理时间 */ - const start = Date.now() - plugin.e = this.e - await (plugin[fnc as keyof typeof plugin] as Function)() - logger.bot('mark', this.e.self_id, `${this.e.logFnc} 上下文处理完成 ${Date.now() - start}ms`) - return true + switch (App.type) { + case 'ctx': { + listener.emit(`ctx:${key}`, this.e) + delete stateArr[key] + return true + } + case 'class': { + const { fnc, name } = App + this.e.logFnc = `[${fnc.name}][${name}]` + /** 计算插件处理时间 */ + const start = Date.now() + fnc.e = this.e + await (fnc[name as keyof typeof fnc] as Function)() + logger.bot('mark', this.e.self_id, `${this.e.logFnc} 上下文处理完成 ${Date.now() - start}ms`) + return true + } + case 'fnc': { + const { fnc } = App + this.e.logFnc = `[${fnc.name}]` + /** 计算插件处理时间 */ + const start = Date.now() + await fnc(this.e) + logger.bot('mark', this.e.self_id, `${this.e.logFnc} 上下文处理完成 ${Date.now() - start}ms`) + delete stateArr[key] + return true + } + } } return false } diff --git a/src/types/plugin.ts b/src/types/plugin.ts index 1895c45..8ba5180 100644 --- a/src/types/plugin.ts +++ b/src/types/plugin.ts @@ -1,6 +1,7 @@ import schedule from 'node-schedule' import { Reply, replyCallback, replyForward } from './reply' import { EventType, Event, Permission, SubEvent, KarinMessageEvent, KarinNoticeEvent, KarinRequestEvent } from './event' +import { Plugin } from 'karin/core' /** * - 插件根目录名称 @@ -14,6 +15,16 @@ export type dirName = `karin-plugin-${string}` */ export type fileName = `${string}.js` | `${string}.ts` +/** + * 上下文状态 + */ +export interface stateArrType { + [key: string]: + | { type: 'fnc', fnc: Function } + | { type: 'class', fnc: Plugin, name: string } + | { type: 'ctx' } +} + /** * - 插件规则 */ @@ -211,16 +222,7 @@ export interface PluginType { /** * - 获取上下文状态 */ - getContext: () => { - /** - * - 插件实例 - */ - plugin: PluginType - /** - * - 执行方法名称 - */ - fnc: string - } + getContext: () => stateArrType[string] /** * - accept标准方法 给通知、请求事件使用 @@ -228,16 +230,6 @@ export interface PluginType { accept?(e: EventType): Promise } -/** - * 上下文状态 - */ -export interface stateArrType { - [key: string]: { - plugin: PluginType - fnc: string - } -} - /** * - Apps */