diff --git a/src/common/utils/eventTask.ts b/src/common/utils/eventTask.ts deleted file mode 100644 index 2c84e03..0000000 --- a/src/common/utils/eventTask.ts +++ /dev/null @@ -1,234 +0,0 @@ -import { NodeIQQNTWrapperSession } from '@/ntqqapi/wrapper' -import { randomUUID } from 'node:crypto' - -interface Internal_MapKey { - timeout: number - createtime: number - func: (...arg: any[]) => unknown - checker?: (...args: any[]) => boolean -} - -export class ListenerClassBase { - [key: string]: string -} - -export interface ListenerIBase { - new(listener: unknown): ListenerClassBase -} - -// forked from https://github.com/NapNeko/NapCatQQ/blob/6f6b258f22d7563f15d84e7172c4d4cbb547f47e/src/common/utils/EventTask.ts#L20 -export class NTEventWrapper { - private ListenerMap: { [key: string]: ListenerIBase } | undefined//ListenerName-Unique -> Listener构造函数 - private WrapperSession: NodeIQQNTWrapperSession | undefined//WrapperSession - private ListenerManger: Map = new Map() //ListenerName-Unique -> Listener实例 - private EventTask = new Map>>()//tasks ListenerMainName -> ListenerSubName-> uuid -> {timeout,createtime,func} - public initialised = false - - constructor() { - } - - createProxyDispatch(ListenerMainName: string) { - const current = this - return new Proxy({}, { - get(target: any, prop: string, receiver: unknown) { - // console.log('get', prop, typeof target[prop]) - if (typeof target[prop] === 'undefined') { - // 如果方法不存在,返回一个函数,这个函数调用existentMethod - return (...args: unknown[]) => { - current.dispatcherListener.apply(current, [ListenerMainName, prop, ...args]).then() - } - } - // 如果方法存在,正常返回 - return Reflect.get(target, prop, receiver) - } - }) - } - - init({ ListenerMap, WrapperSession }: { ListenerMap: { [key: string]: typeof ListenerClassBase }, WrapperSession: NodeIQQNTWrapperSession }) { - this.ListenerMap = ListenerMap - this.WrapperSession = WrapperSession - this.initialised = true - } - - createEventFunction unknown>(eventName: string): T | undefined { - const eventNameArr = eventName.split('/') - type eventType = { - [key: string]: () => { [key: string]: (...params: Parameters) => Promise> } - } - if (eventNameArr.length > 1) { - const serviceName = 'get' + eventNameArr[0].replace('NodeIKernel', '') - const eventName = eventNameArr[1] - //getNodeIKernelGroupListener,GroupService - //console.log('2', eventName) - const services = (this.WrapperSession as unknown as eventType)[serviceName]() - let event = services[eventName] - //重新绑定this - event = event.bind(services) - if (event) { - return event as T - } - return undefined - } - } - - createListenerFunction(listenerMainName: string, uniqueCode: string = ''): T { - const ListenerType = this.ListenerMap![listenerMainName] - let Listener = this.ListenerManger.get(listenerMainName + uniqueCode) - if (!Listener && ListenerType) { - Listener = new ListenerType(this.createProxyDispatch(listenerMainName)) - const ServiceSubName = listenerMainName.match(/^NodeIKernel(.*?)Listener$/)![1] - const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener' - const addfunc = this.createEventFunction<(listener: T) => number>(Service) - addfunc!(Listener as T) - //console.log(addfunc!(Listener as T)) - this.ListenerManger.set(listenerMainName + uniqueCode, Listener) - } - return Listener as T - } - - //统一回调清理事件 - async dispatcherListener(ListenerMainName: string, ListenerSubName: string, ...args: unknown[]) { - //console.log("[EventDispatcher]",ListenerMainName, ListenerSubName, ...args) - this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.forEach((task, uuid) => { - //console.log(task.func, uuid, task.createtime, task.timeout) - if (task.createtime + task.timeout < Date.now()) { - this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.delete(uuid) - return - } - if (task.checker && task.checker(...args)) { - task.func(...args) - } - }) - } - - async CallNoListenerEvent Promise>(EventName = '', timeout: number = 3000, ...args: Parameters) { - return new Promise>>(async (resolve, reject) => { - const EventFunc = this.createEventFunction(EventName) - let complete = false - const Timeouter = setTimeout(() => { - if (!complete) { - reject(new Error('NTEvent EventName:' + EventName + ' timeout')) - } - }, timeout) - const retData = await EventFunc!(...args) - complete = true - resolve(retData) - }) - } - - async RegisterListen void>(ListenerName = '', waitTimes = 1, timeout = 5000, checker: (...args: Parameters) => boolean) { - return new Promise>((resolve, reject) => { - const ListenerNameList = ListenerName.split('/') - const ListenerMainName = ListenerNameList[0] - const ListenerSubName = ListenerNameList[1] - const id = randomUUID() - let complete = 0 - let retData: Parameters | undefined = undefined - const databack = () => { - if (complete == 0) { - reject(new Error(' ListenerName:' + ListenerName + ' timeout')) - } else { - resolve(retData!) - } - } - const Timeouter = setTimeout(databack, timeout) - const eventCallbak = { - timeout: timeout, - createtime: Date.now(), - checker: checker, - func: (...args: Parameters) => { - complete++ - retData = args - if (complete >= waitTimes) { - clearTimeout(Timeouter) - databack() - } - } - } - if (!this.EventTask.get(ListenerMainName)) { - this.EventTask.set(ListenerMainName, new Map()) - } - if (!(this.EventTask.get(ListenerMainName)?.get(ListenerSubName))) { - this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map()) - } - this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak) - this.createListenerFunction(ListenerMainName) - }) - } - - async CallNormalEvent Promise, ListenerType extends (...args: any[]) => void> - (EventName = '', ListenerName = '', waitTimes = 1, timeout: number = 3000, checker: (...args: Parameters) => boolean, ...args: Parameters) { - return new Promise<[EventRet: Awaited>, ...Parameters]>(async (resolve, reject) => { - const id = randomUUID() - let complete = 0 - let retData: Parameters | undefined = undefined - let retEvent = {} - const databack = () => { - if (complete == 0) { - reject(new Error('Timeout: NTEvent EventName:' + EventName + ' ListenerName:' + ListenerName + ' EventRet:\n' + JSON.stringify(retEvent, null, 4) + '\n')) - } else { - resolve([retEvent as Awaited>, ...retData!]) - } - } - - const ListenerNameList = ListenerName.split('/') - const ListenerMainName = ListenerNameList[0] - const ListenerSubName = ListenerNameList[1] - - const Timeouter = setTimeout(databack, timeout) - - const eventCallbak = { - timeout: timeout, - createtime: Date.now(), - checker: checker, - func: (...args: unknown[]) => { - complete++ - //console.log('func', ...args) - retData = args as Parameters - if (complete >= waitTimes) { - clearTimeout(Timeouter) - databack() - } - } - } - if (!this.EventTask.get(ListenerMainName)) { - this.EventTask.set(ListenerMainName, new Map()) - } - if (!(this.EventTask.get(ListenerMainName)?.get(ListenerSubName))) { - this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map()) - } - this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak) - this.createListenerFunction(ListenerMainName) - const EventFunc = this.createEventFunction(EventName) - retEvent = await EventFunc!(...args) - }) - } -} - -export const NTEventDispatch = new NTEventWrapper() - -// 示例代码 快速创建事件 -// let NTEvent = new NTEventWrapper() -// let TestEvent = NTEvent.CreatEventFunction<(force: boolean) => Promise>('NodeIKernelProfileLikeService/GetTest') -// if (TestEvent) { -// TestEvent(true) -// } - -// 示例代码 快速创建监听Listener类 -// let NTEvent = new NTEventWrapper() -// NTEvent.CreatListenerFunction('NodeIKernelMsgListener', 'core') - - -// 调用接口 -//let NTEvent = new NTEventWrapper() -//let ret = await NTEvent.CallNormalEvent<(force: boolean) => Promise, (data1: string, data2: number) => void>('NodeIKernelProfileLikeService/GetTest', 'NodeIKernelMsgListener/onAddSendMsg', 1, 3000, true) - -// 注册监听 解除监听 -// NTEventDispatch.RigisterListener('NodeIKernelMsgListener/onAddSendMsg','core',cb) -// NTEventDispatch.UnRigisterListener('NodeIKernelMsgListener/onAddSendMsg','core') - -// let GetTest = NTEventDispatch.CreatEvent('NodeIKernelProfileLikeService/GetTest','NodeIKernelMsgListener/onAddSendMsg',Mode) -// GetTest('test') - -// always模式 -// NTEventDispatch.CreatEvent('NodeIKernelProfileLikeService/GetTest','NodeIKernelMsgListener/onAddSendMsg',Mode,(...args:any[])=>{ console.log(args) }) \ No newline at end of file diff --git a/src/ntqqapi/api/file.ts b/src/ntqqapi/api/file.ts index e17bd57..6599064 100644 --- a/src/ntqqapi/api/file.ts +++ b/src/ntqqapi/api/file.ts @@ -21,7 +21,6 @@ import { Peer } from '@/ntqqapi/types/msg' import { calculateFileMD5 } from '@/common/utils/file' import { fileTypeFromFile } from 'file-type' import fsPromise from 'node:fs/promises' -import { NTEventDispatch } from '@/common/utils/eventTask' import { OnRichMediaDownloadCompleteParams } from '@/ntqqapi/listeners' import { Time } from 'cosmokit' import { Service, Context } from 'cordis' @@ -143,76 +142,32 @@ export class NTQQFileApi extends Service { return sourcePath } } - let filePath: string - if (NTEventDispatch.initialised) { - const data = await NTEventDispatch.CallNormalEvent< - ( - params: { - fileModelId: string, - downloadSourceType: number, - triggerType: number, - msgId: string, - chatType: ChatType, - peerUid: string, - elementId: string, - thumbSize: number, - downloadType: number, - filePath: string - }) => Promise, - (fileTransNotifyInfo: OnRichMediaDownloadCompleteParams) => void - >( - 'NodeIKernelMsgService/downloadRichMedia', - 'NodeIKernelMsgListener/onRichMediaDownloadComplete', - 1, - timeout, - (arg: OnRichMediaDownloadCompleteParams) => { - if (arg.msgId === msgId) { - return true - } - return false - }, + const data = await invoke<{ notifyInfo: OnRichMediaDownloadCompleteParams }>( + 'nodeIKernelMsgService/downloadRichMedia', + [ { - fileModelId: '0', - downloadSourceType: 0, - triggerType: 1, - msgId: msgId, - chatType: chatType, - peerUid: peerUid, - elementId: elementId, - thumbSize: 0, - downloadType: 1, - filePath: thumbPath - } - ) - filePath = data[1].filePath - } else { - const data = await invoke<{ notifyInfo: OnRichMediaDownloadCompleteParams }>( - 'nodeIKernelMsgService/downloadRichMedia', - [ - { - getReq: { - fileModelId: '0', - downloadSourceType: 0, - triggerType: 1, - msgId: msgId, - chatType: chatType, - peerUid: peerUid, - elementId: elementId, - thumbSize: 0, - downloadType: 1, - filePath: thumbPath, - }, + getReq: { + fileModelId: '0', + downloadSourceType: 0, + triggerType: 1, + msgId: msgId, + chatType: chatType, + peerUid: peerUid, + elementId: elementId, + thumbSize: 0, + downloadType: 1, + filePath: thumbPath, }, - null, - ], - { - cbCmd: ReceiveCmdS.MEDIA_DOWNLOAD_COMPLETE, - cmdCB: payload => payload.notifyInfo.msgId === msgId, - timeout - } - ) - filePath = data.notifyInfo.filePath - } + }, + null, + ], + { + cbCmd: ReceiveCmdS.MEDIA_DOWNLOAD_COMPLETE, + cmdCB: payload => payload.notifyInfo.msgId === msgId, + timeout + } + ) + let filePath = data.notifyInfo.filePath if (filePath.startsWith('\\')) { const downloadPath = TEMP_DIR filePath = path.join(downloadPath, filePath) @@ -238,7 +193,7 @@ export class NTQQFileApi extends Service { const url: string = element.originImageUrl! // 没有域名 const md5HexStr = element.md5HexStr const fileMd5 = element.md5HexStr - + if (url) { const parsedUrl = new URL(IMAGE_HTTP_HOST + url) //临时解析拼接 const imageAppid = parsedUrl.searchParams.get('appid') diff --git a/src/ntqqapi/api/friend.ts b/src/ntqqapi/api/friend.ts index ba68c49..b0a37a8 100644 --- a/src/ntqqapi/api/friend.ts +++ b/src/ntqqapi/api/friend.ts @@ -2,8 +2,7 @@ import { Friend, FriendV2, SimpleInfo, CategoryFriend } from '../types' import { ReceiveCmdS } from '../hook' import { invoke, NTMethod, NTClass } from '../ntcall' import { getSession } from '@/ntqqapi/wrapper' -import { BuddyListReqType, NodeIKernelProfileService } from '../services' -import { NTEventDispatch } from '@/common/utils/eventTask' +import { BuddyListReqType } from '../services' import { Dict, pick } from 'cosmokit' import { Service, Context } from 'cordis' @@ -75,9 +74,7 @@ export class NTQQFriendApi extends Service { const buddyService = session.getBuddyService() const buddyListV2 = await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) uids.push(...buddyListV2.data.flatMap(item => item.buddyUids)) - const data = await NTEventDispatch.CallNoListenerEvent( - 'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids - ) + const data = await session.getProfileService().getCoreAndBaseInfo('nodeStore', uids) return Array.from(data.values()) } else { const data = await invoke<{ @@ -106,12 +103,10 @@ export class NTQQFriendApi extends Service { const session = getSession() if (session) { const uids: string[] = [] - const buddyService = session?.getBuddyService() + const buddyService = session.getBuddyService() const buddyListV2 = await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) uids.push(...buddyListV2.data.flatMap(item => item.buddyUids)) - const data = await NTEventDispatch.CallNoListenerEvent( - 'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids - ) + const data = await session.getProfileService().getCoreAndBaseInfo('nodeStore', uids) for (const [, item] of data) { if (retMap.size > 5000) { break @@ -155,9 +150,7 @@ export class NTQQFriendApi extends Service { }) return item.buddyUids })) - const data = await NTEventDispatch.CallNoListenerEvent( - 'NodeIKernelProfileService/getCoreAndBaseInfo', 5000, 'nodeStore', uids - ) + const data = await session.getProfileService().getCoreAndBaseInfo('nodeStore', uids) return Array.from(data).map(([key, value]) => { const category = categoryMap.get(key) return category ? { ...value, categoryId: category.categoryId, categroyName: category.categroyName } : value diff --git a/src/ntqqapi/api/group.ts b/src/ntqqapi/api/group.ts index 93a78b7..0e7a8de 100644 --- a/src/ntqqapi/api/group.ts +++ b/src/ntqqapi/api/group.ts @@ -1,5 +1,5 @@ import { ReceiveCmdS } from '../hook' -import { Group, GroupMember, GroupMemberRole, GroupNotifies, GroupRequestOperateTypes, GroupNotify, GetFileListParam } from '../types' +import { Group, GroupMember, GroupMemberRole, GroupNotifies, GroupRequestOperateTypes, GetFileListParam } from '../types' import { invoke, NTClass, NTMethod } from '../ntcall' import { GeneralCallResult } from '../services' import { NTQQWindows } from './window' diff --git a/src/ntqqapi/core.ts b/src/ntqqapi/core.ts index e1524f2..4f38fce 100644 --- a/src/ntqqapi/core.ts +++ b/src/ntqqapi/core.ts @@ -2,8 +2,6 @@ import fs from 'node:fs' import { Service, Context } from 'cordis' import { registerCallHook, registerReceiveHook, ReceiveCmdS } from './hook' import { MessageUnique } from '../common/utils/messageUnique' -import { NTEventDispatch } from '../common/utils/eventTask' -import { wrapperConstructor, getSession } from './wrapper' import { Config as LLOBConfig } from '../common/types' import { llonebotError } from '../common/globalVars' import { isNumeric } from '../common/utils/misc' @@ -45,10 +43,6 @@ class Core extends Service { public start() { llonebotError.otherError = '' - const WrapperSession = getSession() - if (WrapperSession) { - NTEventDispatch.init({ ListenerMap: wrapperConstructor, WrapperSession }) - } MessageUnique.init(selfInfo.uin) this.registerListener() this.ctx.logger.info(`LLOneBot/${version}`)