diff --git a/package.json b/package.json index 70439c95..164ec422 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,8 @@ "devDependencies": { "@rollup/plugin-node-resolve": "^16.0.3", "@vitejs/plugin-react-swc": "^4.2.2", + "inversify": "^7.10.4", + "reflect-metadata": "^0.2.2", "typescript": "^5.3.0", "vite": "^6.4.1", "vite-plugin-cp": "^6.0.3" diff --git a/packages/napcat-common/src/event.ts b/packages/napcat-common/src/event.ts index 49543225..705d5b79 100644 --- a/packages/napcat-common/src/event.ts +++ b/packages/napcat-common/src/event.ts @@ -25,18 +25,18 @@ export class NTEventWrapper { private readonly listenerManager: Map = new Map(); // ListenerName-Unique -> Listener实例 private readonly EventTask = new Map>>(); // tasks ListenerMainName -> ListenerSubName-> uuid -> {timeout,createtime,func} - constructor ( + constructor( wrapperSession: NodeIQQNTWrapperSession ) { this.WrapperSession = wrapperSession; } - createProxyDispatch (ListenerMainName: string) { + createProxyDispatch(ListenerMainName: string) { const dispatcherListenerFunc = this.dispatcherListener.bind(this); return new Proxy( {}, { - get (target: any, prop: any, receiver: any) { + get(target: any, prop: any, receiver: any) { if (typeof target[prop] === 'undefined') { // 如果方法不存在,返回一个函数,这个函数调用existentMethod return (...args: any[]) => { @@ -54,7 +54,7 @@ export class NTEventWrapper { Service extends keyof ServiceNamingMapping, ServiceMethod extends FuncKeys, T extends (...args: any) => any = EnsureFunc - > (eventName: `${Service}/${ServiceMethod}`): T | undefined { + >(eventName: `${Service}/${ServiceMethod}`): T | undefined { const eventNameArr = eventName.split('/'); type eventType = { [key: string]: () => { [key: string]: (...params: Parameters) => Promise>; }; @@ -78,8 +78,8 @@ export class NTEventWrapper { return undefined; } - createListenerFunction> (listenerMainName: string, uniqueCode: string = ''): T { + createListenerFunction>(listenerMainName: string, uniqueCode: string = ''): T { const existListener = this.listenerManager.get(listenerMainName + uniqueCode); if (!existListener) { const Listener = this.createProxyDispatch(listenerMainName); @@ -97,7 +97,7 @@ export class NTEventWrapper { } // 统一回调清理事件 - async dispatcherListener (ListenerMainName: string, ListenerSubName: string, ...args: any[]) { + async dispatcherListener(ListenerMainName: string, ListenerSubName: string, ...args: any[]) { this.EventTask.get(ListenerMainName) ?.get(ListenerSubName) ?.forEach((task, uuid) => { @@ -115,7 +115,7 @@ export class NTEventWrapper { Service extends keyof ServiceNamingMapping, ServiceMethod extends FuncKeys, EventType extends (...args: any) => any = EnsureFunc - > ( + >( serviceAndMethod: `${Service}/${ServiceMethod}`, ...args: Parameters ): Promise>> { @@ -126,7 +126,7 @@ export class NTEventWrapper { Listener extends keyof ListenerNamingMapping, ListenerMethod extends FuncKeys, ListenerType extends (...args: any) => any = EnsureFunc - > ( + >( listenerAndMethod: `${Listener}/${ListenerMethod}`, checker: (...args: Parameters) => boolean, waitTimes = 1, @@ -140,7 +140,7 @@ export class NTEventWrapper { let complete = 0; let retData: Parameters | undefined; - function sendDataCallback () { + function sendDataCallback() { if (complete === 0) { reject(new Error(' ListenerName:' + listenerAndMethod + ' timeout')); } else { @@ -180,7 +180,7 @@ export class NTEventWrapper { ListenerMethod extends FuncKeys, EventType extends (...args: any) => any = EnsureFunc, ListenerType extends (...args: any) => any = EnsureFunc - > ( + >( serviceAndMethod: `${Service}/${ServiceMethod}`, listenerAndMethod: `${Listener}/${ListenerMethod}`, args: Parameters, @@ -194,7 +194,7 @@ export class NTEventWrapper { let retData: Parameters | undefined; let retEvent: any = {}; - function sendDataCallback (resolve: any, reject: any) { + function sendDataCallback(resolve: any, reject: any) { if (complete === 0) { reject( new Error( diff --git a/packages/napcat-core/index.ts b/packages/napcat-core/index.ts index 16709417..bf4c0c6c 100644 --- a/packages/napcat-core/index.ts +++ b/packages/napcat-core/index.ts @@ -31,6 +31,7 @@ import { NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/napcat-cor import { proxiedListenerOf } from 'napcat-common/src/proxy-handler'; import { NTQQPacketApi } from './apis/packet'; import { NativePacketHandler } from './packet/handler/client'; +import { container, ReceiverServiceRegistry } from './packet/handler/serviceRegister'; export * from './wrapper'; export * from './types/index'; export * from './services/index'; @@ -118,6 +119,15 @@ export class NapCatCore { UserApi: new NTQQUserApi(this.context, this), GroupApi: new NTQQGroupApi(this.context, this), }; + container.bind(NapCatCore).toConstantValue(this); + ReceiverServiceRegistry.forEach((ServiceClass, serviceName) => { + container.bind(ServiceClass).toSelf(); + console.log(`Registering service handler for: ${serviceName}`); + this.context.packetHandler.onCmd(serviceName, ({ seq, hex_data }) => { + const serviceInstance = container.get(ServiceClass); + return serviceInstance.handler(seq, hex_data); + }); + }); } async initCore () { diff --git a/packages/napcat-core/packet/handler/serviceRegister.ts b/packages/napcat-core/packet/handler/serviceRegister.ts new file mode 100644 index 00000000..08b9078d --- /dev/null +++ b/packages/napcat-core/packet/handler/serviceRegister.ts @@ -0,0 +1,24 @@ +import "reflect-metadata"; +import { Container, injectable } from "inversify"; +import { NapCatCore } from "../.."; + +export const container = new Container(); + +export const ReceiverServiceRegistry = new Map ServiceBase>(); + +export abstract class ServiceBase { + get core(): NapCatCore { + return container.get(NapCatCore); + } + + abstract handler(seq: number, hex_data: string): Promise | void; +} + +export function ReceiveService(serviceName: string) { + return function ServiceBase>(constructor: T) { + injectable()(constructor); + ReceiverServiceRegistry.set(serviceName, constructor); + return constructor; + }; +} + diff --git a/packages/napcat-core/protocol/OlpushSerivce.ts b/packages/napcat-core/protocol/OlpushSerivce.ts new file mode 100644 index 00000000..1d38b509 --- /dev/null +++ b/packages/napcat-core/protocol/OlpushSerivce.ts @@ -0,0 +1,8 @@ +import { ReceiveService, ServiceBase } from "../packet/handler/serviceRegister"; + +// @ReceiveService('trpc.msg.olpush.OlPushService.MsgPush') +// export class OlPushService extends ServiceBase { +// async handler(seq: number, hex_data: string) { +// console.log(`OlPushService handler called with seq: ${seq} and data: ${hex_data}`); +// } +// } \ No newline at end of file diff --git a/packages/napcat-framework/vite.config.ts b/packages/napcat-framework/vite.config.ts index 84965458..65dab29c 100644 --- a/packages/napcat-framework/vite.config.ts +++ b/packages/napcat-framework/vite.config.ts @@ -16,6 +16,7 @@ const nodeModules = [...builtinModules, builtinModules.map((m) => `node:${m}`)]. const FrameworkBaseConfigPlugin: PluginOption[] = [ autoIncludeTSPlugin({ entries: [ + { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-core/protocol') }, { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-onebot/action/test') } ] }), diff --git a/packages/napcat-shell/vite.config.ts b/packages/napcat-shell/vite.config.ts index 72f801e1..66609067 100644 --- a/packages/napcat-shell/vite.config.ts +++ b/packages/napcat-shell/vite.config.ts @@ -19,6 +19,7 @@ const ShellBaseConfigPlugin: PluginOption[] = [ react({ tsDecorators: true }), autoIncludeTSPlugin({ entries: [ + { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-core/protocol') }, { entry: 'napcat.ts', dir: path.resolve(__dirname, '../napcat-onebot/action/test') } ] }), diff --git a/packages/napcat-vite/vite-auto-include.js b/packages/napcat-vite/vite-auto-include.js index 34402f67..20c91129 100644 --- a/packages/napcat-vite/vite-auto-include.js +++ b/packages/napcat-vite/vite-auto-include.js @@ -12,6 +12,9 @@ export function autoIncludeTSPlugin(options) { async buildStart() { tsFilesMap = {}; for (const { entry, dir } of entries) { + if (!tsFilesMap[entry]) { + tsFilesMap[entry] = []; + } const fullDir = path.resolve(dir); const allTsFiles = await findTSFiles(fullDir); @@ -29,7 +32,7 @@ export function autoIncludeTSPlugin(options) { } }); - tsFilesMap[entry] = validFiles; + tsFilesMap[entry].push(...validFiles); } },